diff --git a/app/models/concerns/balance.rb b/app/models/concerns/balance.rb new file mode 100644 index 0000000000..5de06109d5 --- /dev/null +++ b/app/models/concerns/balance.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'active_support/concern' + +# Contains the methods to compute an order balance form the point of view of the enterprise and not +# the individual shopper. +module Balance + FINALIZED_NON_SUCCESSFUL_STATES = %w(canceled returned).freeze + + # Returns the order balance by considering the total as money owed to the order distributor aka. + # the shop, and as a positive balance of said enterprise. If the customer pays it all, they + # distributor and customer are even. + # + # Note however, this is meant to be used only in the context of a single order object. When + # working with a collection of orders, such an index controller action, please consider using + # `app/queries/oustanding_balance.rb` instead so we avoid potential N+1s. + def outstanding_balance + if state.in?(FINALIZED_NON_SUCCESSFUL_STATES) + -payment_total + else + total - payment_total + end + end + + def outstanding_balance? + !outstanding_balance.zero? + end + + def display_outstanding_balance + Spree::Money.new(outstanding_balance, currency: currency) + end +end diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index 3d8559af35..19e617e26b 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -9,7 +9,9 @@ require 'concerns/order_shipment' module Spree class Order < ActiveRecord::Base prepend OrderShipment + include Checkout + include Balance checkout_flow do go_to_state :address @@ -136,7 +138,6 @@ module Spree # All the states an order can be in after completing the checkout FINALIZED_STATES = %w(complete canceled resumed awaiting_return returned).freeze - FINALIZED_NON_SUCCESSFUL_STATES = %w(canceled returned).freeze scope :finalized, -> { where(state: FINALIZED_STATES) } @@ -173,10 +174,6 @@ module Spree self[:currency] || Spree::Config[:currency] end - def display_outstanding_balance - Spree::Money.new(outstanding_balance, currency: currency) - end - def display_item_total Spree::Money.new(item_total, currency: currency) end @@ -394,18 +391,6 @@ module Spree Spree::TaxRate.adjust(self) end - def outstanding_balance - if state.in?(FINALIZED_NON_SUCCESSFUL_STATES) - -payment_total - else - total - payment_total - end - end - - def outstanding_balance? - outstanding_balance != 0 - end - def name address = bill_address || ship_address return unless address diff --git a/app/queries/outstanding_balance.rb b/app/queries/outstanding_balance.rb index ce4d4d78f4..48ee451009 100644 --- a/app/queries/outstanding_balance.rb +++ b/app/queries/outstanding_balance.rb @@ -8,6 +8,9 @@ # cases. # # See CompleteOrdersWithBalance or CustomersWithBalance as examples. +# +# Note this query object and `app/models/concerns/balance.rb` should implement the same behavior +# until we find a better way. If you change one, please, change the other too. class OutstandingBalance # All the states of a finished order but that shouldn't count towards the balance (the customer # didn't get the order for whatever reason). Note it does not include complete diff --git a/spec/models/spree/order/outstanding_balance_spec.rb b/spec/models/concerns/balance_spec.rb similarity index 99% rename from spec/models/spree/order/outstanding_balance_spec.rb rename to spec/models/concerns/balance_spec.rb index 4963fe273d..8e60eeae89 100644 --- a/spec/models/spree/order/outstanding_balance_spec.rb +++ b/spec/models/concerns/balance_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe Spree::Order do - +describe Balance do context "#outstanding_balance" do context 'when orders are in cart state' do let(:order) { build(:order, total: 100, payment_total: 10, state: 'cart') }