mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-29 21:17:17 +00:00
355 lines
11 KiB
Ruby
355 lines
11 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
|
|
RSpec.describe VoucherAdjustmentsService do
|
|
describe '#update' do
|
|
let(:enterprise) { build(:enterprise) }
|
|
|
|
context 'with a flat rate voucher' do
|
|
let(:voucher) do
|
|
create(:voucher_flat_rate, code: 'new_code', enterprise:, amount: 10)
|
|
end
|
|
|
|
context 'when voucher covers the order total' do
|
|
subject { order.voucher_adjustments.first }
|
|
|
|
let(:order) { create(:order_with_totals) }
|
|
|
|
it 'updates the adjustment amount to -order.total' do
|
|
voucher.create_adjustment(voucher.code, order)
|
|
order.update_columns(item_total: 6)
|
|
|
|
VoucherAdjustmentsService.new(order).update
|
|
|
|
expect(subject.amount.to_f).to eq(-6.0)
|
|
end
|
|
end
|
|
|
|
context 'with tax included in order price' do
|
|
subject { order.voucher_adjustments.first }
|
|
|
|
let(:order) do
|
|
create(
|
|
:order_with_taxes,
|
|
distributor: enterprise,
|
|
ship_address: create(:address),
|
|
product_price: 110,
|
|
tax_rate_amount: 0.10,
|
|
included_in_price: true,
|
|
tax_rate_name: "Tax 1"
|
|
)
|
|
end
|
|
|
|
before do
|
|
add_voucher(order, voucher)
|
|
|
|
VoucherAdjustmentsService.new(order).update
|
|
end
|
|
|
|
it 'updates the adjustment included_tax' do
|
|
# voucher_rate = amount / order.total
|
|
# -10 / 160 = -0.0625
|
|
# included_tax = voucher_rate * order.included_tax_total
|
|
# -0.625 * 10 = -0.63
|
|
expect(subject.included_tax.to_f).to eq(-0.63)
|
|
end
|
|
|
|
context "when re calculating" do
|
|
it "does not update the adjustment amount" do
|
|
expect do
|
|
VoucherAdjustmentsService.new(order).update
|
|
end.not_to change { subject.reload.amount }
|
|
end
|
|
|
|
it "does not update the tax adjustment" do
|
|
expect do
|
|
VoucherAdjustmentsService.new(order).update
|
|
end.not_to change { subject.reload.included_tax }
|
|
end
|
|
|
|
context "when the order changed" do
|
|
before do
|
|
order.update_columns(item_total: 200)
|
|
end
|
|
|
|
it "does update the adjustment amount" do
|
|
expect do
|
|
VoucherAdjustmentsService.new(order).update
|
|
end.not_to change { subject.reload.amount }
|
|
end
|
|
|
|
it "updates the tax adjustment" do
|
|
expect do
|
|
VoucherAdjustmentsService.new(order).update
|
|
end.to change { subject.reload.included_tax }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'with tax not included in order price' do
|
|
let(:order) do
|
|
create(
|
|
:order_with_taxes,
|
|
distributor: enterprise,
|
|
ship_address: create(:address),
|
|
product_price: 110,
|
|
tax_rate_amount: 0.10,
|
|
included_in_price: false,
|
|
tax_rate_name: "Tax 1"
|
|
)
|
|
end
|
|
let(:adjustment) { order.voucher_adjustments.first }
|
|
let(:tax_adjustment) { order.voucher_adjustments.second }
|
|
|
|
before do
|
|
add_voucher(order, voucher)
|
|
|
|
VoucherAdjustmentsService.new(order).update
|
|
end
|
|
|
|
it 'includes amount without tax' do
|
|
# voucher_rate = amount / order.total
|
|
# -10 / 171 = -0.058479532
|
|
# amount = voucher_rate * (order.total - order.additional_tax_total)
|
|
# -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 / 171 = -0.058479532
|
|
# amount = voucher_rate * order.additional_tax_total
|
|
# -0.058479532 * 11 = -0.64
|
|
expect(tax_adjustment.amount.to_f).to eq(-0.64)
|
|
expect(tax_adjustment.label).to match("Tax")
|
|
|
|
expect(tax_adjustment.metadata.enterprise_id).to eq(
|
|
tax_adjustment.originator.enterprise.id
|
|
)
|
|
expect(tax_adjustment.metadata.fee_name).to eq("Tax")
|
|
expect(tax_adjustment.metadata.fee_type).to eq("Voucher")
|
|
end
|
|
|
|
context "when re calculating" do
|
|
it "does not update the adjustment amount" do
|
|
expect do
|
|
VoucherAdjustmentsService.new(order).update
|
|
end.not_to change { adjustment.reload.amount }
|
|
end
|
|
|
|
it "does not update the tax adjustment" do
|
|
expect do
|
|
VoucherAdjustmentsService.new(order).update
|
|
end.not_to change { tax_adjustment.reload.amount }
|
|
end
|
|
|
|
context "when the order changed" do
|
|
before do
|
|
order.update_columns(item_total: 200)
|
|
end
|
|
|
|
it "updates the adjustment amount" do
|
|
expect do
|
|
VoucherAdjustmentsService.new(order).update
|
|
end.to change { adjustment.reload.amount }
|
|
end
|
|
|
|
it "updates the tax adjustment" do
|
|
expect do
|
|
VoucherAdjustmentsService.new(order).update
|
|
end.to change { tax_adjustment.reload.amount }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'with a percentage rate voucher' do
|
|
let(:voucher) do
|
|
create(:voucher_percentage_rate, code: 'new_code', enterprise:, amount: 10)
|
|
end
|
|
let(:adjustment) { order.voucher_adjustments.first }
|
|
let(:tax_adjustment) { order.voucher_adjustments.second }
|
|
|
|
context 'when voucher covers the order total' do
|
|
subject { order.voucher_adjustments.first }
|
|
|
|
let(:voucher) do
|
|
create(:voucher_percentage_rate, code: 'new_code', enterprise:, amount: 100)
|
|
end
|
|
let(:order) { create(:order_with_totals) }
|
|
|
|
it 'updates the adjustment amount to -order.total' do
|
|
voucher.create_adjustment(voucher.code, order)
|
|
|
|
order.update_columns(item_total: 150)
|
|
|
|
VoucherAdjustmentsService.new(order).update
|
|
|
|
expect(subject.amount.to_f).to eq(-150.0)
|
|
end
|
|
end
|
|
|
|
context 'with tax included in order price' do
|
|
subject { order.voucher_adjustments.first }
|
|
|
|
let(:order) do
|
|
create(
|
|
:order_with_taxes,
|
|
distributor: enterprise,
|
|
ship_address: create(:address),
|
|
product_price: 110,
|
|
tax_rate_amount: 0.10,
|
|
included_in_price: true,
|
|
tax_rate_name: "Tax 1"
|
|
)
|
|
end
|
|
|
|
before do
|
|
add_voucher(order, voucher)
|
|
|
|
VoucherAdjustmentsService.new(order).update
|
|
end
|
|
|
|
it 'updates the adjustment included_tax' do
|
|
# voucher_rate = voucher.amount / 100
|
|
# 10 / 100 = 0.1
|
|
# included_tax = -voucher_rate * included_tax_total
|
|
# -0.1 * 10 = -1
|
|
expect(subject.included_tax.to_f).to eq(-1)
|
|
end
|
|
end
|
|
|
|
context 'with tax not included in order price' do
|
|
let(:order) do
|
|
create(
|
|
:order_with_taxes,
|
|
distributor: enterprise,
|
|
ship_address: create(:address),
|
|
product_price: 110,
|
|
tax_rate_amount: 0.10,
|
|
included_in_price: false,
|
|
tax_rate_name: "Tax 1"
|
|
)
|
|
end
|
|
|
|
before do
|
|
add_voucher(order, voucher)
|
|
|
|
VoucherAdjustmentsService.new(order).update
|
|
end
|
|
|
|
it 'includes amount without tax' do
|
|
adjustment = order.voucher_adjustments.first
|
|
# voucher_rate = voucher.amount / 100
|
|
# 10 / 100 = 0.1
|
|
# amount = -voucher_rate * (order.total - order.additional_tax_total)
|
|
# -0.1 * (171 -11) = -16.0
|
|
expect(adjustment.amount.to_f).to eq(-16.0)
|
|
end
|
|
|
|
it 'creates a tax adjustment' do
|
|
# voucher_rate = voucher.amount / 100
|
|
# 10 / 100 = 0.1
|
|
# amount = -voucher_rate * order.additional_tax_total
|
|
# -0.1 * 11 = -1.1
|
|
tax_adjustment = order.voucher_adjustments.second
|
|
expect(tax_adjustment.amount.to_f).to eq(-1.1)
|
|
expect(tax_adjustment.label).to match("Tax")
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when no order given' do
|
|
it "doesn't blow up" do
|
|
expect { VoucherAdjustmentsService.new(nil).update }.not_to raise_error
|
|
end
|
|
end
|
|
|
|
context 'when no voucher used on the given order' do
|
|
let(:order) { create(:order_with_line_items, line_items_count: 1, distributor: enterprise) }
|
|
|
|
it "doesn't blow up" do
|
|
expect { VoucherAdjustmentsService.new(order).update }.not_to raise_error
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#voucher_included_tax" do
|
|
subject(:voucher_included_tax) { VoucherAdjustmentsService.new(order).voucher_included_tax }
|
|
|
|
let(:order) { create(:order_with_totals) }
|
|
let(:enterprise) { build(:enterprise) }
|
|
let(:voucher) do
|
|
create(:voucher_flat_rate, code: 'new_code', enterprise:, amount: 10)
|
|
end
|
|
|
|
it "returns included tax from voucher adjusment" do
|
|
voucher_adjustment = voucher.create_adjustment(voucher.code, order)
|
|
# Manually update included tax, so we don't have to do a big data setup to be able to use
|
|
# VoucherAdjustmentsService.update
|
|
voucher_adjustment.update(included_tax: 0.5)
|
|
|
|
expect(voucher_included_tax).to eq(0.5)
|
|
end
|
|
|
|
context "When no voucher adjustment linked to the order" do
|
|
it "returns 0.0" do
|
|
expect(voucher_included_tax).to eq(0.0)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#voucher_excluded_tax" do
|
|
subject(:voucher_excluded_tax) { VoucherAdjustmentsService.new(order).voucher_excluded_tax }
|
|
let(:order) do
|
|
create(
|
|
:order_with_taxes,
|
|
distributor: enterprise,
|
|
ship_address: create(:address),
|
|
product_price: 110,
|
|
tax_rate_amount: 0.10,
|
|
included_in_price: false,
|
|
tax_rate_name: "Tax 1"
|
|
)
|
|
end
|
|
let(:enterprise) { build(:enterprise) }
|
|
let(:voucher) do
|
|
create(:voucher_flat_rate, code: 'new_code', enterprise:, amount: 10)
|
|
end
|
|
|
|
it "returns the amount from the tax voucher adjustment" do
|
|
add_voucher(order, voucher)
|
|
|
|
VoucherAdjustmentsService.new(order).update
|
|
|
|
expect(voucher_excluded_tax).to eq(-0.64)
|
|
end
|
|
|
|
context "when no voucher adjustment tax" do
|
|
it "returns 0" do
|
|
voucher_adjustment = voucher.create_adjustment(voucher.code, order)
|
|
|
|
expect(voucher_excluded_tax).to eq(0.0)
|
|
end
|
|
end
|
|
|
|
context "when no voucher adjustment linked to the order" do
|
|
it "returns 0.0" do
|
|
expect(voucher_excluded_tax).to eq(0.0)
|
|
end
|
|
end
|
|
end
|
|
|
|
def add_voucher(order, voucher)
|
|
voucher.create_adjustment(voucher.code, order)
|
|
|
|
# Update taxes
|
|
order.create_tax_charge!
|
|
order.update_shipping_fees!
|
|
order.update_order!
|
|
end
|
|
end
|