mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Make weight calculator work for SubscriptionLineItems by making it test if line_item responds to final_weight_volume field (final_weight_volume_present?)
We also add logic to weight_per_variant so that we use variant.unit_value if final_weight_volume is not available but variant_unit is weight Adapt some test case to test unit_value (in grams) instead of weight (in kgs)
This commit is contained in:
@@ -25,7 +25,7 @@ module Calculator
|
||||
end
|
||||
|
||||
def line_item_weight(line_item)
|
||||
if line_item.final_weight_volume.present?
|
||||
if final_weight_volume_present?(line_item)
|
||||
weight_per_final_weight_volume(line_item)
|
||||
else
|
||||
weight_per_variant(line_item) * line_item.quantity
|
||||
@@ -33,13 +33,18 @@ module Calculator
|
||||
end
|
||||
|
||||
def weight_per_variant(line_item)
|
||||
line_item.variant.andand.weight || 0
|
||||
if variant_unit(line_item) == 'weight'
|
||||
# The calculator price is per_kg so we need to convert unit_value to kg
|
||||
convert_g_to_kg(line_item.variant.andand.unit_value)
|
||||
else
|
||||
line_item.variant.andand.weight || 0
|
||||
end
|
||||
end
|
||||
|
||||
def weight_per_final_weight_volume(line_item)
|
||||
if line_item.variant.product.andand.variant_unit == 'weight'
|
||||
# Divided by 1000 because grams is the base weight unit and the calculator price is per_kg
|
||||
line_item.final_weight_volume / 1000.0
|
||||
if variant_unit(line_item) == 'weight'
|
||||
# The calculator price is per_kg so we need to convert final_weight_volume to kg
|
||||
convert_g_to_kg(line_item.final_weight_volume)
|
||||
else
|
||||
weight_per_variant(line_item) * quantity_implied_in_final_weight_volume(line_item)
|
||||
end
|
||||
@@ -51,5 +56,19 @@ module Calculator
|
||||
def quantity_implied_in_final_weight_volume(line_item)
|
||||
(1.0 * line_item.final_weight_volume / line_item.variant.unit_value).round(3)
|
||||
end
|
||||
|
||||
def final_weight_volume_present?(line_item)
|
||||
line_item.respond_to?(:final_weight_volume) && line_item.final_weight_volume.present?
|
||||
end
|
||||
|
||||
def variant_unit(line_item)
|
||||
line_item.variant.product.andand.variant_unit
|
||||
end
|
||||
|
||||
def convert_g_to_kg(value)
|
||||
return 0 unless value
|
||||
|
||||
value / 1000
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,9 +4,9 @@ describe Calculator::Weight do
|
||||
it_behaves_like "a model using the LocalizedNumber module", [:preferred_per_kg]
|
||||
|
||||
it "computes shipping cost for an order by total weight" do
|
||||
variant1 = build(:variant, weight: 10)
|
||||
variant2 = build(:variant, weight: 20)
|
||||
variant3 = build(:variant, weight: nil)
|
||||
variant1 = build(:variant, unit_value: 10_000)
|
||||
variant2 = build(:variant, unit_value: 20_000)
|
||||
variant3 = build(:variant, unit_value: nil)
|
||||
|
||||
line_item1 = build(:line_item, variant: variant1, quantity: 1)
|
||||
line_item2 = build(:line_item, variant: variant2, quantity: 3)
|
||||
@@ -14,39 +14,40 @@ describe Calculator::Weight do
|
||||
|
||||
order = double(:order, line_items: [line_item1, line_item2, line_item3])
|
||||
|
||||
subject.set_preference(:per_kg, 10)
|
||||
expect(subject.compute(order)).to eq((10 * 1 + 20 * 3) * 10)
|
||||
subject.set_preference(:per_kg, 5)
|
||||
expect(subject.compute(order)).to eq(350) # (10 * 1 + 20 * 3) * 5
|
||||
end
|
||||
|
||||
describe "line item with variant weight" do
|
||||
let(:variant) { build(:variant, weight: 10) }
|
||||
describe "line item with variant_unit weight and variant unit_value" do
|
||||
let(:variant) { build(:variant, unit_value: 10_000) }
|
||||
let(:line_item) { build(:line_item, variant: variant, quantity: 2) }
|
||||
|
||||
before { subject.set_preference(:per_kg, 10) }
|
||||
before { subject.set_preference(:per_kg, 5) }
|
||||
|
||||
it "computes shipping cost for a line item" do
|
||||
expect(subject.compute(line_item)).to eq(10 * 2 * 10)
|
||||
expect(subject.compute(line_item)).to eq(100) # 10 * 2 * 5
|
||||
end
|
||||
|
||||
describe "and with final_weight_volume defined" do
|
||||
before { line_item.update_attribute :final_weight_volume, '18000' }
|
||||
|
||||
it "computes fee using final_weight_volume, not the variant weight" do
|
||||
expect(subject.compute(line_item)).to eq(10 * 18)
|
||||
expect(subject.compute(line_item)).to eq(90) # 18 * 5
|
||||
end
|
||||
|
||||
context "where variant unit is not weight" do
|
||||
it "uses both final_weight_volume and weight to calculate fee" do
|
||||
line_item.variant.update_attribute :weight, 7
|
||||
line_item.variant.product.update_attribute :variant_unit, 'items'
|
||||
expect(subject.compute(line_item)).to eq(180)
|
||||
expect(subject.compute(line_item)).to eq(63) # 7 * (18000/10000) * 5
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "computes shipping cost for an object with an order" do
|
||||
variant1 = build(:variant, weight: 10)
|
||||
variant2 = build(:variant, weight: 5)
|
||||
variant1 = build(:variant, unit_value: 10_000)
|
||||
variant2 = build(:variant, unit_value: 20_000)
|
||||
|
||||
line_item1 = build(:line_item, variant: variant1, quantity: 1)
|
||||
line_item2 = build(:line_item, variant: variant2, quantity: 2)
|
||||
@@ -54,8 +55,8 @@ describe Calculator::Weight do
|
||||
order = double(:order, line_items: [line_item1, line_item2])
|
||||
object_with_order = double(:object_with_order, order: order)
|
||||
|
||||
subject.set_preference(:per_kg, 10)
|
||||
expect(subject.compute(object_with_order)).to eq((10 * 1 + 5 * 2) * 10)
|
||||
subject.set_preference(:per_kg, 5)
|
||||
expect(subject.compute(object_with_order)).to eq(250) # (10 * 1 + 20 * 2) * 5
|
||||
end
|
||||
|
||||
context "when line item final_weight_volume is set" do
|
||||
@@ -77,7 +78,7 @@ describe Calculator::Weight do
|
||||
it "is correct" do
|
||||
expect(line_item.final_weight_volume).to eq(600) # 600g
|
||||
line_item.final_weight_volume = 700 # 700g
|
||||
expect(calculator.compute(line_item)).to eq(4.2)
|
||||
expect(calculator.compute(line_item)).to eq(4.2) # 0.7 * 6
|
||||
end
|
||||
end
|
||||
|
||||
@@ -88,7 +89,7 @@ describe Calculator::Weight do
|
||||
it "is correct" do
|
||||
expect(line_item.final_weight_volume).to eq(6_000) # 6kg
|
||||
line_item.final_weight_volume = 7_000 # 7kg
|
||||
expect(calculator.compute(line_item)).to eq(42)
|
||||
expect(calculator.compute(line_item)).to eq(42) # 7 * 6
|
||||
end
|
||||
end
|
||||
|
||||
@@ -99,7 +100,7 @@ describe Calculator::Weight do
|
||||
it "is correct" do
|
||||
expect(line_item.final_weight_volume).to eq(6_000_000) # 6T
|
||||
line_item.final_weight_volume = 7_000_000 # 7T
|
||||
expect(calculator.compute(line_item)).to eq(42_000)
|
||||
expect(calculator.compute(line_item)).to eq(42_000) # 7000 * 6
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -112,7 +113,7 @@ describe Calculator::Weight do
|
||||
it "is correct" do
|
||||
expect(line_item.final_weight_volume).to eq(0.6) # 600mL
|
||||
line_item.final_weight_volume = 0.7 # 700mL
|
||||
expect(calculator.compute(line_item)).to eq(3.50)
|
||||
expect(calculator.compute(line_item)).to eq(3.50) # 0.25 * (0.7/0.3) * 6
|
||||
end
|
||||
end
|
||||
|
||||
@@ -123,7 +124,7 @@ describe Calculator::Weight do
|
||||
it "is correct" do
|
||||
expect(line_item.final_weight_volume).to eq(6) # 6L
|
||||
line_item.final_weight_volume = 7 # 7L
|
||||
expect(calculator.compute(line_item)).to eq(35.00)
|
||||
expect(calculator.compute(line_item)).to eq(35.00) # 2.5 * (7/3) * 6
|
||||
end
|
||||
end
|
||||
|
||||
@@ -134,7 +135,7 @@ describe Calculator::Weight do
|
||||
it "is correct" do
|
||||
expect(line_item.final_weight_volume).to eq(6_000) # 6kL
|
||||
line_item.final_weight_volume = 7_000 # 7kL
|
||||
expect(calculator.compute(line_item)).to eq(34_995)
|
||||
expect(calculator.compute(line_item)).to eq(34_995) # 2_500 * round(7_000/3_000) * 6
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -146,7 +147,7 @@ describe Calculator::Weight do
|
||||
it "is correct" do
|
||||
expect(line_item.final_weight_volume).to eq(6) # 6 pcs
|
||||
line_item.final_weight_volume = 7 # 7 pcs
|
||||
expect(calculator.compute(line_item)).to eq(35.0)
|
||||
expect(calculator.compute(line_item)).to eq(35.0) # 2.5 * (7/3) * 6
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user