add preferred_unit to weight shipping calculator

This commit is contained in:
Andy Brett
2020-09-07 08:41:48 -07:00
parent 5793f0103d
commit adb29a9c8f
7 changed files with 55 additions and 24 deletions

View File

@@ -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
]

View File

@@ -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

View File

@@ -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."

View File

@@ -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

View File

@@ -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

View File

@@ -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')
}

View File

@@ -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) }