From e9e6aa77d88ebc6d93277d85bbc2e4eca1f558d2 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 6 Dec 2019 18:14:35 +0000 Subject: [PATCH] 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) --- app/models/calculator/weight.rb | 29 ++++++++++++++--- spec/models/calculator/weight_spec.rb | 45 ++++++++++++++------------- 2 files changed, 47 insertions(+), 27 deletions(-) diff --git a/app/models/calculator/weight.rb b/app/models/calculator/weight.rb index e30e78a1e8..cff4dba4fa 100644 --- a/app/models/calculator/weight.rb +++ b/app/models/calculator/weight.rb @@ -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 diff --git a/spec/models/calculator/weight_spec.rb b/spec/models/calculator/weight_spec.rb index 799d0ba0f0..94f7d1b498 100644 --- a/spec/models/calculator/weight_spec.rb +++ b/spec/models/calculator/weight_spec.rb @@ -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