mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Add a per-pound calculator and a spec for it
This commit is contained in:
@@ -88,7 +88,8 @@ 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_per_kg,
|
||||
:preferred_per_lb, :preferred_flat_percent,
|
||||
:preferred_first_item, :preferred_additional_item, :preferred_max_items,
|
||||
:preferred_minimal_amount, :preferred_normal_amount, :preferred_discount_amount
|
||||
]
|
||||
|
||||
75
app/models/calculator/weight_lb.rb
Normal file
75
app/models/calculator/weight_lb.rb
Normal file
@@ -0,0 +1,75 @@
|
||||
require 'spree/localized_number'
|
||||
|
||||
module Calculator
|
||||
class WeightLb < Spree::Calculator
|
||||
extend Spree::LocalizedNumber
|
||||
preference :per_lb, :decimal, default: 0.0
|
||||
localize_number :preferred_per_lb
|
||||
|
||||
def self.description
|
||||
I18n.t('spree.weight_lb')
|
||||
end
|
||||
|
||||
def compute(object)
|
||||
line_items = line_items_for object
|
||||
(total_weight(line_items) * preferred_per_lb).round(2)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def total_weight(line_items)
|
||||
line_items.sum do |line_item|
|
||||
line_item_weight(line_item)
|
||||
end
|
||||
end
|
||||
|
||||
def line_item_weight(line_item)
|
||||
if final_weight_volume_present?(line_item)
|
||||
weight_per_final_weight_volume(line_item)
|
||||
else
|
||||
weight_per_variant(line_item) * line_item.quantity
|
||||
end
|
||||
end
|
||||
|
||||
def weight_per_variant(line_item)
|
||||
if variant_unit(line_item) == 'weight'
|
||||
# The calculator price is per_lb so we need to convert unit_value to lb
|
||||
convert_g_to_lb(line_item.variant.andand.unit_value)
|
||||
else
|
||||
line_item.variant.andand.weight || 0
|
||||
end
|
||||
end
|
||||
|
||||
def weight_per_final_weight_volume(line_item)
|
||||
if variant_unit(line_item) == 'weight'
|
||||
# The calculator price is per_lb so we need to convert final_weight_volume to lb
|
||||
convert_g_to_lb(line_item.final_weight_volume)
|
||||
else
|
||||
weight_per_variant(line_item) * quantity_implied_in_final_weight_volume(line_item)
|
||||
end
|
||||
end
|
||||
|
||||
# Example: 2 (line_item.quantity) wine glasses of 125mL (line_item.variant.unit_value)
|
||||
# Customer ends up getting 350mL (line_item.final_weight_volume) of wine
|
||||
# that represent 2.8 (quantity_implied_in_final_weight_volume) glasses of wine
|
||||
def quantity_implied_in_final_weight_volume(line_item)
|
||||
return line_item.quantity if line_item.variant.unit_value.to_f.zero?
|
||||
|
||||
(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_lb(value)
|
||||
return 0 unless value
|
||||
|
||||
value / 453.6
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -54,7 +54,8 @@ module Openfoodnetwork
|
||||
Calculator::FlexiRate,
|
||||
Calculator::PerItem,
|
||||
Calculator::PriceSack,
|
||||
Calculator::Weight
|
||||
Calculator::Weight,
|
||||
Calculator::WeightLb
|
||||
]
|
||||
|
||||
app.config.spree.calculators.add_class('enterprise_fees')
|
||||
@@ -64,7 +65,8 @@ module Openfoodnetwork
|
||||
Calculator::FlexiRate,
|
||||
Calculator::PerItem,
|
||||
Calculator::PriceSack,
|
||||
Calculator::Weight
|
||||
Calculator::Weight,
|
||||
Calculator::WeightLb
|
||||
]
|
||||
|
||||
app.config.spree.calculators.add_class('payment_methods')
|
||||
|
||||
@@ -3127,6 +3127,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
|
||||
inventory: Inventory
|
||||
zipcode: Postcode
|
||||
weight: Weight (per kg)
|
||||
weight_lb: Weight (per 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."
|
||||
|
||||
@@ -38,6 +38,15 @@ describe Spree::Admin::ShippingMethodsController, type: :controller do
|
||||
expect(shipping_method.reload.calculator.preferred_per_kg).to eq 10
|
||||
end
|
||||
|
||||
it "updates preferred_per_lb of a Weight (Lb) calculator" do
|
||||
shipping_method.calculator = create(:weight_lb_calculator, calculable: shipping_method)
|
||||
params[:shipping_method][:calculator_attributes][:preferred_per_lb] = 10
|
||||
|
||||
spree_post :update, params
|
||||
|
||||
expect(shipping_method.reload.calculator.preferred_per_lb).to eq 10
|
||||
end
|
||||
|
||||
it "updates preferred_flat_percent of a FlatPercentPerItem calculator" do
|
||||
shipping_method.calculator = Calculator::FlatPercentPerItem.new(preferred_flat_percent: 20,
|
||||
|
||||
|
||||
@@ -16,4 +16,9 @@ FactoryBot.define do
|
||||
after(:build) { |c| c.set_preference(:per_kg, 0.5) }
|
||||
after(:create) { |c| c.set_preference(:per_kg, 0.5); c.save! }
|
||||
end
|
||||
|
||||
factory :weight_lb_calculator, class: Calculator::WeightLb do
|
||||
after(:build) { |c| c.set_preference(:per_lb, 0.5) }
|
||||
after(:create) { |c| c.set_preference(:per_lb, 0.5); c.save! }
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user