Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions backend/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ group :development, :test do

# Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/]
gem "rubocop-rails-omakase", require: false

# Load environment variables from .env file
gem "dotenv-rails"
end


8 changes: 8 additions & 0 deletions backend/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ GEM
debug (1.10.0)
irb (~> 1.10)
reline (>= 0.3.8)
dotenv (3.2.0)
dotenv-rails (3.2.0)
dotenv (= 3.2.0)
railties (>= 6.1)
drb (2.2.1)
erubi (1.13.1)
globalid (1.2.1)
Expand Down Expand Up @@ -127,6 +131,8 @@ GEM
nio4r (2.7.4)
nokogiri (1.18.8-aarch64-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.8-x86_64-linux-gnu)
racc (~> 1.4)
parallel (1.27.0)
parser (3.3.8.0)
ast (~> 2.4.1)
Expand Down Expand Up @@ -239,11 +245,13 @@ GEM

PLATFORMS
aarch64-linux
x86_64-linux

DEPENDENCIES
bootsnap
brakeman
debug
dotenv-rails
pg (~> 1.1)
puma (>= 5.0)
rack-cors
Expand Down
18 changes: 18 additions & 0 deletions backend/app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,20 @@
class ApplicationController < ActionController::API
rescue_from ActiveRecord::RecordNotFound, with: :handle_not_found
rescue_from ActiveRecord::RecordInvalid, with: :handle_invalid_record
rescue_from StandardError, with: :handle_other_errors

private

def handle_not_found
render json: {error: "Record not found"}, status: :not_found
end

def handle_invalid_record(e)
render json: {errors: e.record.errors}, status: :unprocessable_entity
end

def handle_other_errors(e)
render json: {errors: e.message}, status: :internal_server_error
end

end
28 changes: 28 additions & 0 deletions backend/app/controllers/orders_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class OrdersController < ApplicationController
def index
orders = ::OrderService.list_orders
render json: orders, status: :ok
end

def create
new_order = ::OrderService.create_order(order_params)
render json: new_order, status: :created
end

def destroy
::OrderService.delete_order(params[:id])
render status: :ok
end

def update
updated_order = ::OrderService.update_order(params[:id], order_params)
render json: updated_order, status: :ok
end

private

def order_params
params.require(:order).permit(:title, :description, :due, :status, :client)
end

end
8 changes: 8 additions & 0 deletions backend/app/mailers/order_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class OrderMailer < ApplicationMailer
default from: "notifications@example.com"

def order_created_email
@order = params[:order]
mail(to: "admin@ordersapp.com", subject: "Order has been created")
end
end
4 changes: 4 additions & 0 deletions backend/app/models/order.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Order < ApplicationRecord
validates :title, presence: true
enum :status, {:pending=>0, :processing=>1, :completed=>2, :cancelled=>3}
end
23 changes: 23 additions & 0 deletions backend/app/services/order_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class OrderService
def self.create_order(order_params)
order = Order.new(order_params)
order.save!
OrderMailer.with(order: order).order_created_email.deliver_later
order
end

def self.update_order(order_id, order_params)
order = Order.find(order_id)
order.update!(order_params)
order
end

def self.delete_order(order_id)
order = Order.find(order_id)
order.destroy!
end

def self.list_orders
Order.all.order(created_at: :desc)
end
end
13 changes: 13 additions & 0 deletions backend/app/views/order_mailer/order_created_email.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<h1>New order created</h1>
<p>
A new order has been created in the Orders app.<br>
Order info:<br>
Title: <%= @order.title %>.<br>
Client: <%= @order.client %>.<br>
Description: <%= @order.description %>.<br>
Due date: <%= @order.due %>.<br>

</p>
<p>
You can see the new order in the orders app
</p>
12 changes: 12 additions & 0 deletions backend/app/views/order_mailer/order_created_email.text.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
New Order Created
================

A new order has been created in the Orders app.

Order Info:
- Title: <%= @order.title %>
- Client: <%= @order.client %>
- Description: <%= @order.description %>
- Due date: <%= @order.due %>

You can see the new order in the orders app.
14 changes: 13 additions & 1 deletion backend/config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,25 @@
config.active_storage.service = :local

# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
config.action_mailer.raise_delivery_errors = true

# Disable caching for Action Mailer templates even if Action Controller
# caching is enabled.
config.action_mailer.perform_caching = false

config.action_mailer.default_url_options = { host: "localhost", port: 3000 }

# Configuración SMTP para Gmail
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'gmail.com',
user_name: ENV['GMAIL_USERNAME'],
password: ENV['GMAIL_APP_PASSWORD'],
authentication: 'plain',
enable_starttls_auto: true
}

# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
Expand Down
18 changes: 9 additions & 9 deletions backend/config/initializers/cors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

# Read more: https://github.com/cyu/rack-cors

# Rails.application.config.middleware.insert_before 0, Rack::Cors do
# allow do
# origins "example.com"
#
# resource "*",
# headers: :any,
# methods: [:get, :post, :put, :patch, :delete, :options, :head]
# end
# end
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "*"

resource "*",
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
2 changes: 2 additions & 0 deletions backend/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@

# Defines the root path route ("/")
# root "posts#index"

resources :orders
end
12 changes: 12 additions & 0 deletions backend/db/migrate/20251218161810_create_orders.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateOrders < ActiveRecord::Migration[7.2]
def change
create_table :orders do |t|
t.string :title
t.text :description
t.date :due
t.integer :status, default: 0, null: false

t.timestamps
end
end
end
5 changes: 5 additions & 0 deletions backend/db/migrate/20251219160000_add_client_to_orders.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddClientToOrders < ActiveRecord::Migration[7.2]
def change
add_column :orders, :client, :string
end
end
11 changes: 10 additions & 1 deletion backend/db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 73 additions & 6 deletions backend/db/seeds.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,76 @@
# This file should ensure the existence of records required to run the application in every environment (production,
# development, test). The code here should be idempotent so that it can be executed at any point in every environment.
# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup).
#
# Example:
#
# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name|
# MovieGenre.find_or_create_by!(name: genre_name)
# end

Order.create!([
{
title: "Website Redesign",
client: "Tech Corp",
description: "Complete redesign of company website with modern UI/UX",
due: Date.today + 30.days,
status: :pending
},
{
title: "Mobile App Development",
client: "StartupXYZ",
description: "Build iOS and Android apps for food delivery service",
due: Date.today + 45.days,
status: :processing
},
{
title: "Database Migration",
client: "Enterprise Solutions",
description: "Migrate legacy database to PostgreSQL",
due: Date.today - 5.days,
status: :completed
},
{
title: "API Integration",
client: "FinTech Inc",
description: "Integrate payment gateway API",
due: Date.today + 15.days,
status: :processing
},
{
title: "Marketing Campaign",
client: "Fashion Brand",
description: "Social media marketing campaign for summer collection",
due: Date.today + 60.days,
status: :pending
},
{
title: "Server Maintenance",
client: "Cloud Services",
description: "Routine server maintenance and security updates",
due: Date.today - 10.days,
status: :cancelled
},
{
title: "E-commerce Platform",
client: "Retail Chain",
description: "Build custom e-commerce platform with inventory management",
due: Date.today + 90.days,
status: :pending
},
{
title: "Data Analytics Dashboard",
client: "Analytics Pro",
description: "Create interactive dashboard for sales data visualization",
due: Date.today + 20.days,
status: :processing
},
{
title: "Security Audit",
client: "BankCorp",
description: "Comprehensive security audit of banking application",
due: Date.today - 2.days,
status: :completed
},
{
title: "Logo Design",
client: "New Startup",
description: "Design modern logo and brand identity",
due: nil,
status: :pending
}
])
45 changes: 45 additions & 0 deletions backend/test/controllers/orders_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require "test_helper"

class OrdersControllerTest < ActionDispatch::IntegrationTest
fixtures :orders

test "should get index" do
get orders_url
assert_response :success

json_response = JSON.parse(response.body)
assert_equal 2, json_response.length
end

test "should get index in order created_at desc" do
get orders_url
assert_response :success

json_response = JSON.parse(response.body)
timestamps = json_response.map { |t| t["created_at"]}
assert_equal timestamps.sort.reverse, timestamps
end

test "should create order" do
assert_difference("Order.count", 1) do
post orders_url, params: {order:{title:"A new order", status: "pending"}}
end
assert_response :created
end

test "should delete order" do
assert_difference("Order.count", -1) do
delete order_url(1)
end
assert_response :success
end

test "should update order" do
patch order_url(2), params: {order:{title:"Updated Title"}}
assert_response :success

json_response = JSON.parse(response.body)
assert_equal "Updated Title", json_response["title"]
end

end
Loading