mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-05 22:26:07 +00:00
Round FlatPercentItemTotal calcs per-item before summing full quantity
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
Spree::Calculator::FlatPercentItemTotal.class_eval do
|
||||
# Spree's calculator sums all amounts, and then calculates a percentage on them.
|
||||
# In the cart, we display line item individual amounts rounded, so to have consistent
|
||||
# calculations we do the same internally. Here, we round adjustments at the individual
|
||||
# item level first, then multiply by the item quantity.
|
||||
|
||||
|
||||
def compute(object)
|
||||
line_items_for(object).sum do |li|
|
||||
unless li.price.present? && li.quantity.present?
|
||||
raise ArgumentError, "object must respond to #price and #quantity"
|
||||
end
|
||||
|
||||
value = (li.price * BigDecimal(self.preferred_flat_percent.to_s) / 100.0).round(2)
|
||||
value * li.quantity
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -13,16 +13,35 @@ feature "full-page cart", js: true do
|
||||
let!(:order_cycle) { create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], coordinator: create(:distributor_enterprise), variants: [product_tax.variants.first, product_fee.variants.first]) }
|
||||
let(:enterprise_fee) { create(:enterprise_fee, amount: 11.00, tax_category: product_tax.tax_category) }
|
||||
let(:product_tax) { create(:taxed_product, supplier: supplier, zone: zone, price: 110.00, tax_rate_amount: 0.1) }
|
||||
let(:product_fee) { create(:simple_product, supplier: supplier, price: 0.86) }
|
||||
let(:product_fee) { create(:simple_product, supplier: supplier, price: 0.86, on_hand: 100) }
|
||||
let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor) }
|
||||
|
||||
before do
|
||||
add_enterprise_fee enterprise_fee
|
||||
set_order order
|
||||
end
|
||||
|
||||
describe "fees" do
|
||||
let(:percentage_fee) { create(:enterprise_fee, calculator: Spree::Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 20)) }
|
||||
|
||||
before do
|
||||
add_enterprise_fee percentage_fee
|
||||
add_product_to_cart order, product_fee, quantity: 8
|
||||
visit spree.cart_path
|
||||
end
|
||||
|
||||
it "rounds fee calculations correctly" do
|
||||
# $0.86 + 20% = $1.032
|
||||
# Fractional cents should be immediately rounded down and not carried through
|
||||
expect(page).to have_selector '.cart-item-price', text: '$1.03'
|
||||
expect(page).to have_selector '.cart-item-total', text: '$8.24'
|
||||
expect(page).to have_selector '.order-total.item-total', text: '$8.24'
|
||||
expect(page).to have_selector '.order-total.grand-total', text: '$8.24'
|
||||
end
|
||||
end
|
||||
|
||||
describe "tax" do
|
||||
before do
|
||||
add_enterprise_fee enterprise_fee
|
||||
add_product_to_cart order, product_tax
|
||||
visit spree.cart_path
|
||||
end
|
||||
|
||||
15
spec/models/spree/calculator/flat_percent_item_total_spec.rb
Normal file
15
spec/models/spree/calculator/flat_percent_item_total_spec.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
module Spree
|
||||
describe Calculator::FlatPercentItemTotal do
|
||||
let(:calculator) { Calculator::FlatPercentItemTotal.new preferred_flat_percent: 20 }
|
||||
|
||||
it "calculates for a simple line item" do
|
||||
line_item = LineItem.new price: 50, quantity: 2
|
||||
expect(calculator.compute(line_item)).to eq 20
|
||||
end
|
||||
|
||||
it "rounds fractional cents before summing" do
|
||||
line_item = LineItem.new price: 0.86, quantity: 8
|
||||
expect(calculator.compute(line_item)).to eq 1.36
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -16,9 +16,9 @@ module ShopWorkflow
|
||||
ApplicationController.any_instance.stub(:session).and_return({order_id: order.id, access_token: order.token})
|
||||
end
|
||||
|
||||
def add_product_to_cart(order, product)
|
||||
def add_product_to_cart(order, product, quantity: 1)
|
||||
populator = Spree::OrderPopulator.new(order, order.currency)
|
||||
populator.populate(variants: {product.variants.first.id => 1})
|
||||
populator.populate(variants: {product.variants.first.id => quantity})
|
||||
|
||||
# Recalculate fee totals
|
||||
order.update_distribution_charge!
|
||||
|
||||
Reference in New Issue
Block a user