Fix VoucherAdjustmentsService.calculate so we can call it mutiple time

It now uses `order.pre_discount_total` to make any calculation, that
means you can call it multiple time and you will still get the same
adjustment amount, included_tax and tax adjustment when needed. This
is assuming nothing changed on the order.
This commit is contained in:
Gaetan Craig-Riou
2023-06-26 14:30:10 +10:00
parent 60c0c54eb2
commit 87790b29ae
2 changed files with 34 additions and 30 deletions

View File

@@ -10,7 +10,7 @@ class VoucherAdjustmentsService
# We only support one voucher per order right now, we could just loop on voucher_adjustments
adjustment = order.voucher_adjustments.first
# Recalculate value
# Calculate value
amount = adjustment.originator.compute_amount(order)
# It is quite possible to have an order with both tax included in and tax excluded from price.
@@ -23,33 +23,35 @@ class VoucherAdjustmentsService
handle_tax_included_in_price(order, amount)
else
adjustment.amount = amount
adjustment.save
end
# Move to closed state
adjustment.close
end
def self.handle_tax_excluded_from_price(order, amount)
voucher_rate = amount / order.total
voucher_rate = amount / order.pre_discount_total
adjustment = order.voucher_adjustments.first
# Adding the voucher tax part
tax_amount = voucher_rate * order.additional_tax_total
adjustment = order.voucher_adjustments.first
adjustment_attributes = {
amount: tax_amount,
originator: adjustment.originator,
order: order,
label: "Tax #{adjustment.label}",
mandatory: false,
state: 'closed',
state: 'open',
tax_category: nil,
included_tax: 0
}
order.adjustments.create(adjustment_attributes)
# Update the amount if tax adjustment already exist, create if not
tax_adjustment = order.adjustments.find_or_initialize_by(adjustment_attributes)
tax_adjustment.amount = tax_amount
tax_adjustment.save
# Update the adjustment amount
amount = voucher_rate * (order.total - order.additional_tax_total)
amount = voucher_rate * (order.pre_discount_total - order.additional_tax_total)
adjustment.update_columns(
amount: amount,
@@ -58,7 +60,7 @@ class VoucherAdjustmentsService
end
def self.handle_tax_included_in_price(order, amount)
voucher_rate = amount / order.total
voucher_rate = amount / order.pre_discount_total
included_tax = voucher_rate * order.included_tax_total
# Update Adjustment

View File

@@ -22,7 +22,7 @@ describe VoucherAdjustmentsService do
end
end
context 'with price included in order price' do
context 'with tax included in order price' do
subject { order.voucher_adjustments.first }
let(:order) do
@@ -51,18 +51,14 @@ describe VoucherAdjustmentsService do
it 'updates the adjustment included_tax' do
# voucher_rate = amount / order.total
# -10 / 150 = -0.066666667
# -10 / 160 = -0.0625
# included_tax = voucher_rate * order.included_tax_total
# -0.66666666 * 10 = -0.67
expect(subject.included_tax.to_f).to eq(-0.67)
end
it 'moves the adjustment state to closed' do
expect(subject.state).to eq('closed')
# -0.0625 * 10 = -0.625
expect(subject.included_tax.to_f).to eq(-0.63)
end
end
context 'with price not included in order price' do
context 'with tax not included in order price' do
let(:order) do
create(
:order_with_taxes,
@@ -87,28 +83,34 @@ describe VoucherAdjustmentsService do
VoucherAdjustmentsService.calculate(order)
end
it 'includes amount withou tax' do
it 'includes amount without tax' do
adjustment = order.voucher_adjustments.first
# voucher_rate = amount / order.total
# -10 / 161 = -0.062111801
# -10 / 171 = -0.058479532
# amount = voucher_rate * (order.total - order.additional_tax_total)
# -0.062111801 * (161 -11) = -9.32
expect(adjustment.amount.to_f).to eq(-9.32)
# -0.058479532 * (171 -11) = -9.36
expect(adjustment.amount.to_f).to eq(-9.36)
end
it 'creates a tax adjustment' do
# voucher_rate = amount / order.total
# -10 / 161 = -0.062111801
# -10 / 171 = -0.058479532
# amount = voucher_rate * order.additional_tax_total
# -0.0585 * 11 = -0.68
# -0.058479532 * 11 = -0.64
tax_adjustment = order.voucher_adjustments.second
expect(tax_adjustment.amount.to_f).to eq(-0.68)
expect(tax_adjustment.amount.to_f).to eq(-0.64)
expect(tax_adjustment.label).to match("Tax")
end
it 'moves the adjustment state to closed' do
adjustment = order.voucher_adjustments.first
expect(adjustment.state).to eq('closed')
context "when re calculating" do
it "updates the tax adjustment" do
order.update_columns(item_total: 200)
tax_adjustment = order.voucher_adjustments.second
expect do
VoucherAdjustmentsService.calculate(order)
end.to change { tax_adjustment.reload.amount }
end
end
end