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
2 changes: 0 additions & 2 deletions app/controllers/orders_payment_methods_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ def create

if @order_payment_method.valid?
@order_payment_method.save!
@order.reload
@order.process_payment!

render json: @order_payment_method, status: :created
else
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/payment_methods_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def index
@payment_methods = PaymentMethod.page(pagination_params[:page]).per(pagination_params[:limit])

with_pagination_options @payment_methods do |options|
render json: PaymentMethodsSerializer.new(@payment_methods, options), status: :ok
render json: PaymentMethodSerializer.new(@payment_methods, options), status: :ok
end
end
end
27 changes: 27 additions & 0 deletions app/controllers/payments_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

class PaymentsController < ApplicationController
before_action :authenticate

def create
@order = Order.find params[:order_id]
@payment = @order.build_payment create_params

if @payment.valid?
@payment.save!
@order.reload
@order.process_payment!

render json: PaymentSerializer.new(@payment), status: :created

else
render json: @payment.errors, status: :unprocessable_entity
end
end

private

def create_params
params.require(:payment).permit(:amount)
end
end
12 changes: 6 additions & 6 deletions app/models/order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ class Order < ApplicationRecord
belongs_to :shipping_address
has_one :orders_payment_methods, class_name: 'OrdersPaymentMethod', dependent: :destroy
has_one :payment_method, through: :orders_payment_methods
has_one :payment, dependent: :destroy

has_many :items, class_name: 'OrderItem', dependent: :destroy

validates :cart, cart_items: true
validates :cart, cart_items: true, if: proc { |order| order.cart.present? }

aasm :status do
state :pending, initial: true
Expand All @@ -35,8 +36,7 @@ class Order < ApplicationRecord
state :void

event :process_payment do
transitions from: :pending, to: :payment_processing, guard: :verify_payment_method?
transitions from: :pending, to: :order_packaging
transitions from: :delivered, to: :payment_processing, guard: :payment_received?
end

event :confirm_payment do
Expand All @@ -56,11 +56,11 @@ def pay_on_delivery?
payment_method.name == PAYMENT_METHODS[:pay_on_delivery]
end

def verify_payment_method?
!pay_on_delivery?
def payment_received?
pay_on_delivery? && payment.present?
end

def payment_confirmed?
return true if pay_on_delivery?
false
end
end
1 change: 1 addition & 0 deletions app/models/payment.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

class Payment < ApplicationRecord
belongs_to :order
has_one :payments_payment_methods, class_name: 'PaymentsPaymentMethod', dependent: :destroy
has_one :payment_method, through: :payments_payment_methods
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

class PaymentMethodsSerializer
class PaymentMethodSerializer
include JSONAPI::Serializer

attributes :name, :description
Expand Down
9 changes: 9 additions & 0 deletions app/serializers/payment_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

class PaymentSerializer
include JSONAPI::Serializer

attributes :amount, :order_id

has_one :payment_method
end
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
get 'payments/create'
post 'auth', to: 'auth#create'
resources :users do
resources :shipping_addresses, only: %i[create index]
Expand All @@ -16,5 +17,6 @@
resources :payment_methods, only: :index
resources :orders, only: :show do
resources :orders_payment_methods, only: :create, as: :payment_methods
resources :payments, only: :create
end
end
5 changes: 5 additions & 0 deletions db/migrate/20230121042740_add_order_to_payments.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddOrderToPayments < ActiveRecord::Migration[6.0]
def change
add_reference :payments, :order, null: false, foreign_key: true
end
end
5 changes: 4 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2023_01_20_141624) do
ActiveRecord::Schema.define(version: 2023_01_21_042740) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -164,6 +164,8 @@
t.decimal "amount", precision: 8, scale: 2
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.bigint "order_id", null: false
t.index ["order_id"], name: "index_payments_on_order_id"
end

create_table "payments_payment_methods", force: :cascade do |t|
Expand Down Expand Up @@ -274,6 +276,7 @@
add_foreign_key "orders", "shipping_addresses"
add_foreign_key "orders_payment_methods", "orders"
add_foreign_key "orders_payment_methods", "payment_methods"
add_foreign_key "payments", "orders"
add_foreign_key "payments_payment_methods", "payment_methods"
add_foreign_key "payments_payment_methods", "payments"
add_foreign_key "products", "brands"
Expand Down
1 change: 1 addition & 0 deletions spec/models/order_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

context 'Associations' do
specify { should have_one(:payment_method).through :orders_payment_methods }
specify { should have_one(:payment) }
specify { should belong_to(:shipping_address) }
end
end
1 change: 1 addition & 0 deletions spec/models/payment_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
RSpec.describe Payment, type: :model do
context 'Associations' do
specify { should have_one(:payment_method).through :payments_payment_methods }
specify { should belong_to(:order) }
end
end
47 changes: 47 additions & 0 deletions spec/requests/orders/payments/create_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'POST /orders/:order_id/payments', type: :request do
let(:user) { create :user }
let(:cart) { create :cart, :with_items, user: user, items_count: 1 }
let(:order) { create :order, cart: cart }
let(:payment_method) { create :payment_method, name: 'Pay on Delivery' }

context 'When unauthorized' do
before { post order_payments_path(order), params: {} }

it_should_behave_like 'unauthorized request'
end

context 'With pay on delivery payment method' do
let(:cart) { create :cart, user: user }
let(:product) { create :product, :with_master, stock: 10 }
let(:product2) { create :product, :with_master, stock: 1 }
let(:cart_item1) { create :cart_item, product: product, sku: product.master.sku, cart: cart }
let(:cart_item2) { create :cart_item, product: product2, sku: product2.master.sku, cart: cart }
let(:amount) { cart.items.select(:amount).collect(&:amount).reduce(&:+).to_f }

before do
cart.items << [cart_item1, cart_item2]
order.payment_method = payment_method
order.status = :delivered
order.save!
post order_payments_path(order), params: { payment: { amount: amount } },
headers: authorization_header(user.email)
end

it_behaves_like 'created resource request'

it 'returns payment data' do
expect(response.parsed_body['data']['type']).to eq 'payment'
expect(response.parsed_body['data']['attributes']['order_id']).to eql order.id
expect(response.parsed_body['data']['attributes']['amount'].to_f).to eql amount.to_f
end

it 'updates order status to payment processing' do
order.reload
expect(order.status).to eql :payment_processing.to_s
end
end
end
12 changes: 12 additions & 0 deletions spec/requests/payments_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'Payments', type: :request do
describe 'GET /create' do
it 'returns http success' do
get '/payments/create'
expect(response).to have_http_status(:success)
end
end
end