Created
November 21, 2017 19:36
-
-
Save nsave/524810c50651d510d5b0fd983ff5a0bd to your computer and use it in GitHub Desktop.
Rails code example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # == Schema Information | |
| # | |
| # Table name: orders | |
| # | |
| # id :integer not null, primary key | |
| # eid :string(255) | |
| # location_id :integer | |
| # customer_id :integer | |
| # created_at :datetime | |
| # creator_client_id :integer | |
| # created_by :string(255) | |
| # service_type :string(255) | |
| # expected_time :datetime | |
| # confirmed_time :datetime | |
| # status :string(255) | |
| # customer_notes :text(65535) | |
| # total :string(255) | |
| # total_discrepancy :string(255) | |
| # c_email :string(255) | |
| # c_first_name :string(255) | |
| # c_last_name :string(255) | |
| # c_company_name :string(255) | |
| # c_phone :string(255) | |
| # c_address_1 :string(255) | |
| # c_address_2 :string(255) | |
| # c_postal_code :string(255) | |
| # c_city :string(255) | |
| # c_state :string(255) | |
| # c_country :string(255) | |
| # c_latitude :decimal(9, 6) | |
| # c_longitude :decimal(9, 6) | |
| # c_delivery_notes :text(65535) | |
| # payment_discrepancy :string(255) | |
| # | |
| # Indexes | |
| # | |
| # index_orders_on_customer_id (customer_id) | |
| # index_orders_on_location_id (location_id) | |
| # | |
| class HrOrder < HrModel | |
| self.table_name = 'orders' | |
| STATUSES = [ | |
| NEW_STATUS = 'new', | |
| RECEIVED_STATUS = 'received', | |
| ACCEPTED_STATUS = 'accepted', | |
| IN_PREPARATION_STATUS = 'in_preparation', | |
| AWAITING_SHIPMENT_STATUS = 'awaiting_shipment', | |
| AWAITING_COLLECTION_STATUS = 'awaiting_collection', | |
| IN_DELIVERY_STATUS = 'in_delivery', | |
| COMPLETED_STATUS = 'completed', | |
| REJECTED_STATUS = 'rejected', | |
| CANCELLED_STATUS = 'cancelled', | |
| DELIVERY_FAILED_STATUS = 'delivery_failed', | |
| ] | |
| belongs_to :hr_location, foreign_key: :location_id | |
| belongs_to :hr_customer, foreign_key: :customer_id | |
| has_one :hr_account, through: :hr_location | |
| with_options foreign_key: :order_id, dependent: :destroy, inverse_of: :hr_order do | |
| has_many :hr_order_deals | |
| has_many :hr_order_items | |
| has_many :hr_order_charges | |
| has_many :hr_order_discounts | |
| has_many :hr_order_payments | |
| has_many :hr_loyalty_operations | |
| has_many :hr_private_refs, class_name: HrOrderPrivateRef | |
| end | |
| has_many :hr_connection_logs, as: :resource | |
| belongs_to :hr_client, foreign_key: :creator_client_id | |
| accepts_nested_attributes_for :hr_order_items, | |
| :hr_order_charges, | |
| :hr_order_deals, | |
| :hr_order_discounts, | |
| :hr_order_payments, | |
| :hr_private_refs, | |
| :hr_loyalty_operations | |
| money_accessor :total | |
| money_accessor :total_discrepancy | |
| money_accessor :payment_discrepancy | |
| validates :total, money: true | |
| validates_presence_of :hr_location | |
| validates_inclusion_of :status, in: STATUSES | |
| validates_length_of :c_email, | |
| :c_first_name, | |
| :c_last_name, | |
| :c_company_name, | |
| :c_phone, | |
| :c_address_1, | |
| :c_address_2, | |
| :c_postal_code, | |
| :c_city, | |
| :c_state, | |
| :c_country, maximum: 255 | |
| validates_length_of :customer_notes, | |
| :c_delivery_notes, maximum: 65355 | |
| include PrivateReferable | |
| scope :with_private_ref, ->(hr_client, hr_location, private_ref) { | |
| joins(:hr_private_refs).where( | |
| 'order_private_refs.client_id = ? && order_private_refs.location_id = ? && order_private_refs.private_ref = ?', | |
| hr_client.id, hr_location.id, private_ref | |
| ) | |
| } | |
| delegate :hr_observing_callbacks, to: :hr_location | |
| delegate :currency, to: :hr_account | |
| def recalculate_total | |
| items_total = hr_order_items.map(&:subtotal_m).inject(hr_location.hr_account.null_money, &:+) | |
| charges_total = hr_order_charges.map(&:charge_price_m).inject(hr_location.hr_account.null_money, &:+) | |
| total = items_total + charges_total | |
| final_total = hr_order_discounts.inject(total) do |total, hr_order_discount| | |
| hr_order_discount.discount.apply(total) | |
| end | |
| self.total = final_total.to_s | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'rails_helper' | |
| describe Parsers::HrOrder::ParserCreate do | |
| let(:hr_account) { create(:hr_account, :with_resources, owner: create(:hr_user), locations_count: 2) } | |
| let(:hr_account_2) { create(:hr_account, :with_resources, owner: create(:hr_user), locations_count: 2) } | |
| let(:hr_location_1) { hr_account.hr_locations.first } | |
| let(:hr_location_2) { hr_account.hr_locations.second } | |
| let(:hr_catalog_1) { hr_account.hr_all_catalogs.first } | |
| let(:hr_product_1_1) { hr_catalog_1.hr_products.first } | |
| let(:hr_sku_1_1_1) { hr_product_1_1.hr_skus.first } | |
| let(:hr_sku_1_1_2) { hr_product_1_1.hr_skus.last } | |
| let(:hr_charge_1) { hr_catalog_1.hr_charges.first } | |
| let(:hr_catalog_2) { hr_account_2.hr_all_catalogs.first } | |
| let(:hr_product_2_1) { hr_catalog_2.hr_products.first } | |
| let(:hr_sku_2_1_1) { hr_product_2_1.hr_skus.first } | |
| let(:hr_charge_2) { hr_catalog_2.hr_charges.first } | |
| let(:hr_customer_list_1) { hr_account.hr_customer_lists.first } | |
| let(:hr_customer_list_2) { hr_account_2.hr_customer_lists.first } | |
| let(:hr_customer_1) { create(:hr_customer, hr_customer_list: hr_customer_list_1) } | |
| let(:hr_customer_2) { create(:hr_customer, hr_customer_list: hr_customer_list_2) } | |
| let(:hr_client) { create(:hr_client) } | |
| let(:catalogs_repository) { HrCatalog::CatalogsRepository.new(hr_account.hr_all_catalogs) } | |
| let(:customers_repository) { HrCustomer::CustomersRepository.new(hr_account.hr_all_customer_lists) } | |
| def service | |
| Parsers::HrOrder::ParserCreate.new( | |
| hr_location_1, hr_client, catalogs_repository, customers_repository | |
| ) | |
| end | |
| it 'builds order' do | |
| new_hr_order = service.build( | |
| status: 'new' | |
| ) | |
| expect(new_hr_order).to be_valid | |
| end | |
| describe 'validation' do | |
| it 'fails if private_ref is not uniq in scope of client and location' do | |
| hr_order_1 = create(:hr_order, hr_location: hr_location_1, hr_customer: hr_customer_1) | |
| ref_1 = generate_ref | |
| hr_order_1.hr_private_refs.create(hr_client: hr_client, hr_location: hr_order_1.hr_location, private_ref: ref_1) | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: ref_1 | |
| ) | |
| expect(new_hr_order).to_not be_valid | |
| end | |
| end | |
| describe 'total field' do | |
| it 'assigns total from request' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| total: '100 EUR' | |
| ) | |
| expect(new_hr_order.total_m.cents).to eq(100_00) | |
| end | |
| it 'records dif of totals in total_discrepancy' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| total: '100 EUR' | |
| ) | |
| expect(new_hr_order.total_discrepancy_m.cents).to eq(-100_00) | |
| end | |
| it 'fails if total is wrong currency' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| total: '100 USD' | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| end | |
| end | |
| describe 'with customer' do | |
| it 'fails if customer is out of scope' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| customer_id: hr_customer_2.encoded_id | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| end | |
| it 'assigns customer by id' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| customer_id: hr_customer_1.encoded_id | |
| ) | |
| expect(new_hr_order.customer_id).to eq(hr_customer_1.id) | |
| end | |
| it 'assigns customer by customer_list_id and private_ref' do | |
| private_ref = generate_ref | |
| hr_customer_1.hr_private_refs.create!(private_ref: private_ref, hr_customer_list: hr_customer_1.hr_customer_list, hr_client: hr_client) | |
| new_hr_order = service.build( | |
| status: 'new', | |
| customer_list_id: hr_customer_1.hr_customer_list.encoded_id, | |
| customer_private_ref: private_ref | |
| ) | |
| expect(new_hr_order.customer_id).to eq(hr_customer_1.id) | |
| end | |
| it 'fails if customer_id passed with customer_list_id and customer_private_ref' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| customer_id: hr_customer_1.encoded_id, | |
| customer_list_id: hr_customer_1.hr_customer_list.encoded_id, | |
| customer_private_ref: generate_ref | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| end | |
| it 'fails if customer_private_ref passed without customer_list_id' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| customer_private_ref: generate_ref | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| end | |
| it 'copies customer fileds to new order' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| customer_id: hr_customer_1.encoded_id | |
| ) | |
| expect(new_hr_order.c_first_name).to eq(hr_customer_1.first_name) | |
| expect(new_hr_order.c_last_name).to eq(hr_customer_1.last_name) | |
| end | |
| end | |
| describe 'with items' do | |
| subject(:new_hr_order) do | |
| service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| price: '10 EUR', | |
| quantity: 2, | |
| points_earned: 10 | |
| }, | |
| { | |
| product_name: 'New product', | |
| price: '5.00 EUR', | |
| quantity: 1, | |
| points_used: 15 | |
| } | |
| ] | |
| ) | |
| end | |
| it 'builds order with items' do | |
| aggregate_failures do | |
| expect(new_hr_order).to be_valid | |
| expect(new_hr_order.hr_order_items.size).to eq(2) | |
| expect(new_hr_order.total).to eq('25.00 EUR') | |
| expect(new_hr_order.hr_order_items.first.points_earned).to eq(10) | |
| expect(new_hr_order.hr_order_items.last.points_used).to eq(15) | |
| end | |
| end | |
| it 'fails with invalid item price currency' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| price: '10 GBP', | |
| quantity: 2, | |
| points_earned: 10 | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| end | |
| it 'ignores order item subtotal' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| price: hr_sku_1_1_1.price, | |
| quantity: 1, | |
| subtotal: (hr_sku_1_1_1.price_m * 2).to_s | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order.hr_order_items.first.subtotal_m.cents).to eq(hr_sku_1_1_1.price_m.cents) | |
| end | |
| it 'builds order items with options' do | |
| hr_option = hr_sku_1_1_1.hr_option_lists.take.hr_options.take | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| price: '10.00 EUR', | |
| quantity: 1, | |
| options: [ | |
| { | |
| ref: hr_option.ref, | |
| name: hr_option.name, | |
| option_list_name: hr_option.hr_option_list.name, | |
| price: hr_option.price, | |
| removed: 'true' | |
| } | |
| ] | |
| } | |
| ] | |
| ) | |
| hr_order_item_option = new_hr_order.hr_order_items.first.hr_order_item_options.first | |
| expect(hr_order_item_option.price).to eq(hr_option.price) | |
| expect(hr_order_item_option.option_list_name).to eq(hr_option.hr_option_list.name) | |
| end | |
| it 'fails with invalid options currency' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| price: '10.00 EUR', | |
| quantity: 1, | |
| options: [ | |
| { | |
| option_list_name: 'Colors', | |
| name: 'Black', | |
| price: '1 GBP' | |
| } | |
| ] | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| end | |
| it 'adds option price to order total' do | |
| price = '1 EUR' | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| price: hr_sku_1_1_1.price, | |
| quantity: 1, | |
| options: [ | |
| { | |
| option_list_name: 'Colors', | |
| name: 'Black', | |
| price: price | |
| } | |
| ] | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order.total_m).to eq(hr_sku_1_1_1.price_m + Util::Money.from_string(price)) | |
| end | |
| it 'fails if item is invalid' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| product_ref: generate_ref, | |
| quantity: 2, | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| end | |
| end | |
| describe 'with charges' do | |
| it 'fails without charge name' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| charges: [ | |
| { | |
| type: HrCharge::DELIVERY_TYPE, | |
| price: '10 EUR' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| expect(new_hr_order.hr_order_charges.first).to be_invalid | |
| end | |
| it 'fails without charge type' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| charges: [ | |
| { | |
| name: "Carge #{generate_ref}", | |
| price: '10 EUR' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| expect(new_hr_order.hr_order_charges.first).to be_invalid | |
| end | |
| it 'fails without charge price' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| charges: [ | |
| { | |
| type: HrCharge::DELIVERY_TYPE, | |
| name: "Charge #{generate_ref}" | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| expect(new_hr_order.hr_order_charges.first).to be_invalid | |
| end | |
| it 'failes with invalid charge currency' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| charges: [ | |
| { | |
| name: "Charge #{generate_ref}", | |
| type: HrCharge::DELIVERY_TYPE, | |
| price: '10 GBP' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| end | |
| it 'builds order charge' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| charges: [ | |
| { | |
| name: "Charge #{generate_ref}", | |
| type: HrCharge::DELIVERY_TYPE, | |
| price: '10 EUR' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to_not be_invalid | |
| expect(new_hr_order.hr_order_charges.first).to_not be_invalid | |
| end | |
| end | |
| describe 'with discounts' do | |
| it 'fails with invalid discount' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| discounts: [ | |
| { | |
| pricing_effect: HrDiscount::Discount::PRICING_EFFECT_PERCENTAGE_OFF, | |
| pricing_value: '10' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| expect(new_hr_order.hr_order_discounts.first).to be_invalid | |
| end | |
| it 'builds order discount' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| discounts: [ | |
| { | |
| name: 'DISCOUNT', | |
| pricing_effect: HrDiscount::Discount::PRICING_EFFECT_PERCENTAGE_OFF, | |
| pricing_value: '10' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to_not be_invalid | |
| expect(new_hr_order.hr_order_discounts.first).to_not be_invalid | |
| end | |
| it 'applies percentage discount' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| price: '10 EUR', | |
| quantity: 2 | |
| } | |
| ], | |
| discounts: [ | |
| { | |
| name: 'DISCOUNT', | |
| pricing_effect: HrDiscount::Discount::PRICING_EFFECT_PERCENTAGE_OFF, | |
| pricing_value: 10 | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order.total_m.cents).to eq(1800) | |
| end | |
| it 'applies fixed discount' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| price: '10 EUR', | |
| quantity: 2 | |
| } | |
| ], | |
| discounts: [ | |
| { | |
| name: 'DISCOUNT', | |
| pricing_effect: HrDiscount::Discount::PRICING_EFFECT_PRICE_OFF, | |
| pricing_value: '3 EUR' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order.total_m.cents).to eq(1700) | |
| end | |
| it 'fails with invalid discount currency' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| price: '10 EUR', | |
| quantity: 2 | |
| } | |
| ], | |
| discounts: [ | |
| { | |
| name: 'DISCOUNT', | |
| pricing_effect: HrDiscount::Discount::PRICING_EFFECT_PRICE_OFF, | |
| pricing_value: '3 GBP' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| end | |
| end | |
| describe 'with deals' do | |
| it 'builds order deals' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| deals: { | |
| 'some_deal_key' => { | |
| name: 'Some deal', | |
| ref: 'Some ref' | |
| } | |
| } | |
| ) | |
| expect(new_hr_order).to be_valid | |
| expect(new_hr_order.hr_order_deals.size).to eq(1) | |
| end | |
| it 'builds order deal lines' do | |
| deal_key = 'some_deal_key' | |
| # call #run in this example to save to db for testing relations after saving | |
| new_hr_order = service.run( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| price: '10 EUR', | |
| quantity: 1, | |
| deal_line: { | |
| deal_key: deal_key, | |
| pricing_effect: HrDealLine::DealLine::PRICING_EFFECT_PRICE_OFF, | |
| pricing_value: '1 EUR' | |
| } | |
| } | |
| ], | |
| deals: { | |
| deal_key => { | |
| name: 'Some deal', | |
| ref: 'Some ref' | |
| } | |
| } | |
| ) | |
| new_hr_order.reload | |
| expect(new_hr_order).to be_valid | |
| expect(new_hr_order.hr_order_deals.size).to eq(1) | |
| expect(new_hr_order.hr_order_items.first.hr_order_deal).to_not be_nil | |
| end | |
| it 'applies order deals to total' do | |
| deal_key = 'some_deal_key' | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| items: [ | |
| { | |
| product_name: 'Margarita', | |
| price: '10 EUR', | |
| quantity: 1, | |
| deal_line: { | |
| deal_key: deal_key, | |
| pricing_effect: HrDealLine::DealLine::PRICING_EFFECT_UNCHANGED | |
| } | |
| }, | |
| { | |
| product_name: 'Margarita', | |
| price: '10 EUR', | |
| quantity: 1, | |
| deal_line: { | |
| deal_key: deal_key, | |
| pricing_effect: HrDealLine::DealLine::PRICING_EFFECT_FIXED_PRICE, | |
| pricing_value: '8 EUR' | |
| } | |
| }, | |
| { | |
| product_name: 'Margarita', | |
| price: '10 EUR', | |
| quantity: 1, | |
| deal_line: { | |
| deal_key: deal_key, | |
| pricing_effect: HrDealLine::DealLine::PRICING_EFFECT_PRICE_OFF, | |
| pricing_value: '1 EUR' | |
| } | |
| }, | |
| { | |
| product_name: 'Margarita', | |
| price: '10 EUR', | |
| quantity: 1, | |
| deal_line: { | |
| deal_key: deal_key, | |
| pricing_effect: HrDealLine::DealLine::PRICING_EFFECT_PERCENTAGE_OFF, | |
| pricing_value: '20' | |
| } | |
| } | |
| ], | |
| deals: { | |
| deal_key => { | |
| name: 'Some deal', | |
| ref: 'Some ref' | |
| } | |
| } | |
| ) | |
| expect(new_hr_order.total_m.cents).to eq(3500) | |
| end | |
| end | |
| describe 'with payments' do | |
| it 'builds nested payments' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| payments: [ | |
| { | |
| type: HrOrderPayment::PAYMENT_TYPES.sample, | |
| amount: '10 EUR' | |
| }, | |
| { | |
| type: HrOrderPayment::PAYMENT_TYPES.sample, | |
| amount: '20 EUR' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_valid | |
| expect(new_hr_order.hr_order_payments.size).to eq(2) | |
| end | |
| it 'sets payment_discrepancy if payments total is different from order total' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| payments: [ | |
| { | |
| type: HrOrderPayment::PAYMENT_TYPES.sample, | |
| amount: '10 EUR' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order.payment_discrepancy_m).to eq(Util::Money.from_string('-10 EUR')) | |
| end | |
| it 'sets payment_discrepancy to zero if there are no discrepancy' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref | |
| ) | |
| expect(new_hr_order.payment_discrepancy_m).to eq(Util::Money.from_string('0 EUR')) | |
| end | |
| it 'fails if payment is invalid' do | |
| new_hr_order = service.build( | |
| status: 'new', | |
| private_ref: generate_ref, | |
| payments: [ | |
| { | |
| type: HrOrderPayment::PAYMENT_TYPES.sample, | |
| amount: '10 USD' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| end | |
| end | |
| describe 'with loyalty operations' do | |
| it 'builds loyalty operation' do | |
| hr_loyalty_card = hr_customer_1.hr_loyalty_cards.take | |
| new_hr_order = service.build( | |
| status: 'new', | |
| customer_id: hr_customer_1.encoded_id, | |
| loyalty_operations: [ | |
| { | |
| name: hr_loyalty_card.name, | |
| delta: 10, | |
| reason: 'Order' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order.hr_loyalty_operations.size).to be(1) | |
| expect(new_hr_order.hr_loyalty_operations.first.loyalty_card_id).to eq(hr_loyalty_card.id) | |
| end | |
| it 'updates loyalty card balance' do | |
| hr_loyalty_card = hr_customer_1.hr_loyalty_cards.take | |
| delta = 10 | |
| expect { | |
| new_hr_order = service.build( | |
| status: 'new', | |
| customer_id: hr_customer_1.encoded_id, | |
| loyalty_operations: [ | |
| { | |
| name: hr_loyalty_card.name, | |
| delta: delta, | |
| reason: 'Order' | |
| } | |
| ] | |
| ) | |
| }.to change{hr_loyalty_card.reload.balance}.by(delta) | |
| end | |
| it 'builds new loyalty card with operation' do | |
| delta = 10 | |
| expect { | |
| new_hr_order = service.build( | |
| status: 'new', | |
| customer_id: hr_customer_1.encoded_id, | |
| loyalty_operations: [ | |
| { | |
| name: "NewCard#{generate_ref}", | |
| delta: delta, | |
| reason: 'Order' | |
| } | |
| ] | |
| ) | |
| hr_loyalty_card = new_hr_order.hr_loyalty_operations.first.hr_loyalty_card | |
| expect(hr_loyalty_card.balance).to eq(delta) | |
| }.to change{hr_customer_1.hr_loyalty_cards.size}.by(1) | |
| end | |
| it 'fails if loyalty operation is invalid' do | |
| hr_loyalty_card = hr_customer_1.hr_loyalty_cards.take | |
| new_hr_order = service.build( | |
| status: 'new', | |
| customer_id: hr_customer_1.encoded_id, | |
| loyalty_operations: [ | |
| { | |
| name: hr_loyalty_card.name, | |
| reason: 'Order' | |
| } | |
| ] | |
| ) | |
| expect(new_hr_order).to be_invalid | |
| end | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module V1 | |
| class OrdersController < BaseController | |
| before_action :authorize_access_level! | |
| before_action :ensure_hr_location_found!, except: [:account_orders_index] | |
| before_action :ensure_hr_account_found!, only: [:account_orders_index] | |
| before_action :ensure_hr_order_found!, except: [:index, :account_orders_index, :create] | |
| before_action :ensure_filter_params_valid!, only: [:index, :account_orders_index] | |
| def index | |
| if policy(current_hr_location).read_orders? | |
| respond_with_resources!( | |
| filter_orders(current_hr_location.hr_orders) | |
| ) | |
| else | |
| respond_with_error!(:forbidden, message: "A 'orders' read scope is required") | |
| end | |
| end | |
| def account_orders_index | |
| if policy(current_hr_account).read_orders? | |
| respond_with_resources!( | |
| filter_orders(current_hr_account.hr_orders) | |
| ) | |
| else | |
| respond_with_error!(:forbidden, message: "A 'orders' read scope is required") | |
| end | |
| end | |
| def show | |
| if policy(current_hr_order).read? | |
| respond_with_resource!(current_hr_order) | |
| else | |
| respond_with_error!(:forbidden, message: "A 'orders' read scope is required") | |
| end | |
| end | |
| def create | |
| if policy(current_hr_location).create_order? | |
| hr_order = HrOrder.create_from_json( | |
| current_hr_location, | |
| current_hr_client, | |
| curent_catalogs_repository, | |
| curent_customers_repository, | |
| params | |
| ) | |
| if hr_order.valid? | |
| events_manager.detect_resource_create_events(current_hr_client, hr_order) | |
| HrApiCounter.find_or_create_for(current_hr_location, HrApiCounter::NAME_CREATE_ORDER).count! | |
| if hr_customer = hr_order.hr_customer | |
| events_manager.detect_resource_update_events(current_hr_client, hr_customer) do | |
| hr_customer.handle_new_order!(hr_order) | |
| end | |
| end | |
| end | |
| respond_with_modified_resource!(hr_order) | |
| else | |
| respond_with_error!(:forbidden, message: "A 'orders' write scope is required") | |
| end | |
| end | |
| def update | |
| if policy(current_hr_order).write? | |
| events_manager.detect_resource_update_events(current_hr_client, current_hr_order) do | |
| current_hr_order.update_from_json(current_hr_client, params) | |
| end | |
| respond_with_modified_resource!(current_hr_order) | |
| else | |
| respond_with_error!(:forbidden, message: "A 'orders' write scope is required") | |
| end | |
| end | |
| protected | |
| def filter_orders(hr_orders_relation) | |
| OrdersFilter.process(hr_orders_relation, orders_filter_params, | |
| hr_client: current_hr_client, | |
| hr_location: current_hr_location | |
| ) | |
| end | |
| def orders_filter_params | |
| @orders_filter_params ||= OrdersFilter::Params.from_h(params) | |
| end | |
| def ensure_filter_params_valid! | |
| if orders_filter_params.invalid? | |
| respond_with_error!(:unprocessable_entity, message: orders_filter_params.errors.full_messages.first) | |
| end | |
| end | |
| def curent_catalogs_repository | |
| HrCatalog::CatalogsRepository.new( | |
| policy_scope(current_hr_location.hr_all_catalogs) | |
| ) | |
| end | |
| def curent_customers_repository | |
| HrCustomer::CustomersRepository.new( | |
| policy_scope(current_hr_location.hr_all_customer_lists) | |
| ) | |
| end | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment