diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index 1ab58d530c..a663b9b9c8 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -624,6 +624,16 @@ module Spree @send_shipment_email end + # @return [BigDecimal] The rate of the voucher if applied to the order + def applied_voucher_rate + # As an order can have only one voucher, + # hence using +take+ as each voucher adjustment will have the same voucher + return BigDecimal(0) unless (voucher_adjustment = voucher_adjustments.take) + + voucher = voucher_adjustment.originator + voucher.rate(self) + end + private def reapply_tax_on_changed_address diff --git a/lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_order.rb b/lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_order.rb index a502d34d96..e035a2d469 100644 --- a/lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_order.rb +++ b/lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_order.rb @@ -158,7 +158,8 @@ module Reporting end def enterprise_fees_sum(order) - enterprise_fees(order).sum(:amount) + amount = enterprise_fees(order).sum(:amount) + apply_voucher_on_amount(order, amount) end def enterprise_fees(order) @@ -181,7 +182,8 @@ module Reporting query = order.all_adjustments.tax query = query.inclusive if included == true query = query.additional if added == true - query.where(adjustable: enterprise_fees(order)).sum(:amount) + amount = query.where(adjustable: enterprise_fees(order)).sum(:amount) + apply_voucher_on_amount(order, amount) end def distributor(query_result_row) @@ -221,23 +223,25 @@ module Reporting end def total_excl_tax(query_result_row) + order = order(query_result_row) amount = Spree::Adjustment.enterprise_fee - .where(order: order(query_result_row)) + .where(order:) .where(originator_id: enterprise_fee_id(query_result_row)) .pick("sum(amount)") || 0 - amount - tax(query_result_row, all: true, included: true) + apply_voucher_on_amount(order, amount) - tax(query_result_row, all: true, included: true) end def tax(query_result_row, all: false, included: nil) - order_id = order(query_result_row).id + order = order(query_result_row) adjustment_ids = enterprise_fee_adjustment_ids(query_result_row) query = Spree::Adjustment.tax query = query.where(included: true) unless included.nil? query = query.where(originator_id: tax_rate_id(query_result_row)) unless all == true - query.where(order_id:) + tax_amount = query.where(order:) .where(adjustable_type: 'Spree::Adjustment') .where(adjustable_id: adjustment_ids) .pick("sum(amount)") || 0 + apply_voucher_on_amount(order, tax_amount) end def total_incl_tax(query_result_row) @@ -299,6 +303,12 @@ module Reporting def keys(query_result_row) query_result_row.first end + + def apply_voucher_on_amount(order, amount) + rate = order.applied_voucher_rate + result = amount + (amount * rate) + BigDecimal(result.to_s).round(2, BigDecimal::ROUND_HALF_UP) + end end end end diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index 030eb3704f..8049cf4f42 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -1544,4 +1544,52 @@ describe Spree::Order do expect(order.voucher_adjustments).to eq(expected_adjustments) end end + + describe '#applied_voucher_rate' do + let(:distributor) { create(:distributor_enterprise) } + let(:order) { create(:order, user:, distributor:) } + + context 'when the order has no voucher adjustment' do + it 'returns the BigDecimal 0 value' do + actual = order.applied_voucher_rate + expect(actual.class).to eq(BigDecimal) + # below expectation gets passed if 0 (Integer) is returned regardless of BigDecimal 0 + # Hence adding the expectation for the class as well + expect(actual).to eq(BigDecimal(0)) + end + end + + context "given that the order has voucher adjustment and pre_discount_total is 20" do + before do + voucher.create_adjustment(voucher.code, order) + allow(order).to receive(:pre_discount_total).and_return(BigDecimal(20)) + end + + context "when order has voucher_flat_rate adjustment" do + let(:voucher) { create(:voucher_flat_rate, enterprise: order.distributor, amount: 10) } + + it 'returns the BigDecimal 0 value' do + actual = order.applied_voucher_rate + expect(actual.class).to eq(BigDecimal) + # below expectation gets passed if 0 (Integer) is returned regardless of BigDecimal 0 + # Hence adding the expectation for the class as well + expect(actual).to eq(-BigDecimal('0.5')) + end + end + + context "when order has voucher_percentage_rate adjustment" do + let(:voucher) do + create(:voucher_percentage_rate, enterprise: order.distributor, amount: 10) + end + + it 'returns the BigDecimal 0 value' do + actual = order.applied_voucher_rate + expect(actual.class).to eq(BigDecimal) + # below expectation gets passed if 0 (Integer) is returned regardless of BigDecimal 0 + # Hence adding the expectation for the class as well + expect(actual).to eq(-BigDecimal('0.1')) + end + end + end + end end