diff --git a/app/controllers/spree/admin/shipping_methods_controller.rb b/app/controllers/spree/admin/shipping_methods_controller.rb index 5fa427772e..b68dca98e3 100644 --- a/app/controllers/spree/admin/shipping_methods_controller.rb +++ b/app/controllers/spree/admin/shipping_methods_controller.rb @@ -88,7 +88,7 @@ module Spree :require_ship_address, :tag_list, :calculator_type, distributor_ids: [], calculator_attributes: [ - :id, :preferred_currency, :preferred_amount, :preferred_per_kg, :preferred_flat_percent, + :id, :preferred_currency, :preferred_amount, :preferred_unit, :preferred_per_unit, :preferred_flat_percent, :preferred_first_item, :preferred_additional_item, :preferred_max_items, :preferred_minimal_amount, :preferred_normal_amount, :preferred_discount_amount ] diff --git a/app/models/calculator/weight.rb b/app/models/calculator/weight.rb index bb1f70c030..abdf626d05 100644 --- a/app/models/calculator/weight.rb +++ b/app/models/calculator/weight.rb @@ -3,8 +3,9 @@ require 'spree/localized_number' module Calculator class Weight < Spree::Calculator extend Spree::LocalizedNumber - preference :per_kg, :decimal, default: 0.0 - localize_number :preferred_per_kg + preference :per_unit, :decimal, default: 0.0 + preference :unit, :string, default: "kg" + localize_number :preferred_per_unit def self.description I18n.t('spree.weight') @@ -12,7 +13,7 @@ module Calculator def compute(object) line_items = line_items_for object - (total_weight(line_items) * preferred_per_kg).round(2) + (total_weight(line_items) * preferred_per_unit).round(2) end private @@ -33,8 +34,8 @@ module Calculator def weight_per_variant(line_item) 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) + # Convert unit_value to the preferred unit + convert_weight(line_item.variant.andand.unit_value) else line_item.variant.andand.weight || 0 end @@ -42,8 +43,8 @@ module Calculator def weight_per_final_weight_volume(line_item) 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) + # Convert final_weight_volume to the preferred unit + convert_weight(line_item.final_weight_volume) else weight_per_variant(line_item) * quantity_implied_in_final_weight_volume(line_item) end @@ -66,10 +67,16 @@ module Calculator line_item.variant.product.andand.variant_unit end - def convert_g_to_kg(value) + def convert_weight(value) return 0 unless value - - value / 1000 + if preferences[:unit] == "kg" + value / 1000 + elsif preferences[:unit] == "lb" + value / 453.6 + else + #TODO: handle this case without crashing? + raise "Unknown unit preference" + end end end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 6cbd131c09..de5e0ffe4a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3126,7 +3126,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using inventory_error_flash_for_insufficient_quantity: "An item in your cart has become unavailable." inventory: Inventory zipcode: Postcode - weight: Weight (per kg) + weight: Weight (per kg or lb) error_user_destroy_with_orders: "Users with completed orders may not be deleted" cannot_create_payment_without_payment_methods: "You cannot create a payment for an order without any payment methods defined." please_define_payment_methods: "Please define some payment methods first." diff --git a/spec/controllers/spree/admin/shipping_methods_controller_spec.rb b/spec/controllers/spree/admin/shipping_methods_controller_spec.rb index f209e87a81..9d05a8c440 100644 --- a/spec/controllers/spree/admin/shipping_methods_controller_spec.rb +++ b/spec/controllers/spree/admin/shipping_methods_controller_spec.rb @@ -29,13 +29,22 @@ describe Spree::Admin::ShippingMethodsController, type: :controller do expect(shipping_method.reload.calculator.preferred_currency).to eq "EUR" end - it "updates preferred_per_kg of a Weight calculator" do + it "updates preferred_per_unit of a Weight calculator" do shipping_method.calculator = create(:weight_calculator, calculable: shipping_method) - params[:shipping_method][:calculator_attributes][:preferred_per_kg] = 10 + params[:shipping_method][:calculator_attributes][:preferred_per_unit] = 10 spree_post :update, params - expect(shipping_method.reload.calculator.preferred_per_kg).to eq 10 + expect(shipping_method.reload.calculator.preferred_per_unit).to eq 10 + end + + it "updates preferred_unit of a Weight calculator" do + shipping_method.calculator = create(:weight_calculator, calculable: shipping_method) + params[:shipping_method][:calculator_attributes][:preferred_unit] = "kg" + + spree_post :update, params + + expect(shipping_method.reload.calculator.preferred_unit).to eq "kg" end it "updates preferred_flat_percent of a FlatPercentPerItem calculator" do diff --git a/spec/factories/calculator_factory.rb b/spec/factories/calculator_factory.rb index 1268a8ccb7..196fefa935 100644 --- a/spec/factories/calculator_factory.rb +++ b/spec/factories/calculator_factory.rb @@ -13,7 +13,14 @@ FactoryBot.define do end factory :weight_calculator, class: Calculator::Weight do - after(:build) { |c| c.set_preference(:per_kg, 0.5) } - after(:create) { |c| c.set_preference(:per_kg, 0.5); c.save! } + after(:build) { |c| + c.set_preference(:per_unit, 0.5) + c.set_preference(:unit, "kg") + } + after(:create) { |c| + c.set_preference(:per_unit, 0.5) + c.set_preference(:unit, "kg") + c.save! + } end end diff --git a/spec/features/consumer/shopping/cart_spec.rb b/spec/features/consumer/shopping/cart_spec.rb index 5339aa99f7..9597e8a35e 100644 --- a/spec/features/consumer/shopping/cart_spec.rb +++ b/spec/features/consumer/shopping/cart_spec.rb @@ -118,7 +118,7 @@ feature "full-page cart", js: true do describe "admin weight calculated fees" do context "order with 2 line items" do let(:admin_fee) { - create(:enterprise_fee, calculator: Calculator::Weight.new(preferred_per_kg: 1), + create(:enterprise_fee, calculator: Calculator::Weight.new(preferred_per_unit: 1, preferred_unit: "kg"), enterprise: order_cycle.coordinator, fee_type: 'admin') } diff --git a/spec/models/calculator/weight_spec.rb b/spec/models/calculator/weight_spec.rb index 1ca1759b40..6c5a8e51e2 100644 --- a/spec/models/calculator/weight_spec.rb +++ b/spec/models/calculator/weight_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Calculator::Weight do - it_behaves_like "a model using the LocalizedNumber module", [:preferred_per_kg] + it_behaves_like "a model using the LocalizedNumber module", [:preferred_per_unit] it "computes shipping cost for an order by total weight" do variant1 = build(:variant, unit_value: 10_000) @@ -14,7 +14,8 @@ describe Calculator::Weight do order = double(:order, line_items: [line_item1, line_item2, line_item3]) - subject.set_preference(:per_kg, 5) + subject.set_preference(:per_unit, 5) + subject.set_preference(:unit, "kg") expect(subject.compute(order)).to eq(350) # (10 * 1 + 20 * 3) * 5 end @@ -22,7 +23,10 @@ describe Calculator::Weight do let(:variant) { create(:variant, unit_value: 10_000) } let(:line_item) { create(:line_item, variant: variant, quantity: 2) } - before { subject.set_preference(:per_kg, 5) } + before { + subject.set_preference(:per_unit, 5) + subject.set_preference(:unit, "kg") + } it "computes shipping cost for a line item" do expect(subject.compute(line_item)).to eq(100) # 10 * 2 * 5 @@ -55,7 +59,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, 5) + subject.set_preference(:per_unit, 5) + subject.set_preference(:unit, "kg") expect(subject.compute(object_with_order)).to eq(250) # (10 * 1 + 20 * 2) * 5 end @@ -63,7 +68,7 @@ describe Calculator::Weight do let!(:product) { create(:product, product_attributes) } let!(:variant) { create(:variant, variant_attributes.merge(product: product)) } - let(:calculator) { described_class.new(preferred_per_kg: 6) } + let(:calculator) { described_class.new(preferred_per_unit: 6, preferred_unit: "kg") } let(:line_item) do create(:line_item, variant: variant, quantity: 2).tap do |object| object.send(:calculate_final_weight_volume) @@ -158,7 +163,10 @@ describe Calculator::Weight do } let(:line_item) { create(:line_item, variant: variant, quantity: 1) } - before { subject.set_preference(:per_kg, 5) } + before { + subject.set_preference(:per_unit, 5) + subject.set_preference(:unit, "kg") + } context "when unit_value is zero variant.weight is present" do let(:variant) { create(:variant, product: product, unit_value: 0, weight: 10.0) }