mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-17 04:34:24 +00:00
Bring calculators from spree_core
This commit is contained in:
59
app/models/spree/calculator/default_tax.rb
Normal file
59
app/models/spree/calculator/default_tax.rb
Normal file
@@ -0,0 +1,59 @@
|
||||
require_dependency 'spree/calculator'
|
||||
|
||||
module Spree
|
||||
class Calculator::DefaultTax < Calculator
|
||||
def self.description
|
||||
Spree.t(:default_tax)
|
||||
end
|
||||
|
||||
def compute(computable)
|
||||
case computable
|
||||
when Spree::Order
|
||||
compute_order(computable)
|
||||
when Spree::LineItem
|
||||
compute_line_item(computable)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def rate
|
||||
self.calculable
|
||||
end
|
||||
|
||||
def compute_order(order)
|
||||
matched_line_items = order.line_items.select do |line_item|
|
||||
line_item.tax_category == rate.tax_category
|
||||
end
|
||||
|
||||
line_items_total = matched_line_items.sum(&:total)
|
||||
if rate.included_in_price
|
||||
deduced_total_by_rate(line_items_total, rate)
|
||||
else
|
||||
round_to_two_places(line_items_total * rate.amount)
|
||||
end
|
||||
end
|
||||
|
||||
def compute_line_item(line_item)
|
||||
if line_item.tax_category == rate.tax_category
|
||||
if rate.included_in_price
|
||||
deduced_total_by_rate(line_item.total, rate)
|
||||
else
|
||||
round_to_two_places(line_item.total * rate.amount)
|
||||
end
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
def round_to_two_places(amount)
|
||||
BigDecimal.new(amount.to_s).round(2, BigDecimal::ROUND_HALF_UP)
|
||||
end
|
||||
|
||||
def deduced_total_by_rate(total, rate)
|
||||
round_to_two_places(total - ( total / (1 + rate.amount) ) )
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
18
app/models/spree/calculator/flat_percent_item_total.rb
Normal file
18
app/models/spree/calculator/flat_percent_item_total.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
require_dependency 'spree/calculator'
|
||||
|
||||
module Spree
|
||||
class Calculator::FlatPercentItemTotal < Calculator
|
||||
preference :flat_percent, :decimal, default: 0
|
||||
|
||||
def self.description
|
||||
Spree.t(:flat_percent)
|
||||
end
|
||||
|
||||
def compute(object)
|
||||
return unless object.present? and object.respond_to?(:item_total)
|
||||
item_total = object.item_total
|
||||
value = item_total * BigDecimal(self.preferred_flat_percent.to_s) / 100.0
|
||||
(value * 100).round.to_f / 100
|
||||
end
|
||||
end
|
||||
end
|
||||
16
app/models/spree/calculator/flat_rate.rb
Normal file
16
app/models/spree/calculator/flat_rate.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
require_dependency 'spree/calculator'
|
||||
|
||||
module Spree
|
||||
class Calculator::FlatRate < Calculator
|
||||
preference :amount, :decimal, default: 0
|
||||
preference :currency, :string, default: Spree::Config[:currency]
|
||||
|
||||
def self.description
|
||||
Spree.t(:flat_rate_per_order)
|
||||
end
|
||||
|
||||
def compute(object=nil)
|
||||
self.preferred_amount
|
||||
end
|
||||
end
|
||||
end
|
||||
33
app/models/spree/calculator/flexi_rate.rb
Normal file
33
app/models/spree/calculator/flexi_rate.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
require_dependency 'spree/calculator'
|
||||
|
||||
module Spree
|
||||
class Calculator::FlexiRate < Calculator
|
||||
preference :first_item, :decimal, default: 0.0
|
||||
preference :additional_item, :decimal, default: 0.0
|
||||
preference :max_items, :integer, default: 0
|
||||
preference :currency, :string, default: Spree::Config[:currency]
|
||||
|
||||
def self.description
|
||||
Spree.t(:flexible_rate)
|
||||
end
|
||||
|
||||
def self.available?(object)
|
||||
true
|
||||
end
|
||||
|
||||
def compute(object)
|
||||
sum = 0
|
||||
max = self.preferred_max_items.to_i
|
||||
items_count = object.line_items.map(&:quantity).sum
|
||||
items_count.times do |i|
|
||||
if i == 0
|
||||
sum += self.preferred_first_item.to_f
|
||||
elsif ((max > 0) && (i <= (max - 1))) || (max == 0)
|
||||
sum += self.preferred_additional_item.to_f
|
||||
end
|
||||
end
|
||||
|
||||
sum
|
||||
end
|
||||
end
|
||||
end
|
||||
41
app/models/spree/calculator/per_item.rb
Normal file
41
app/models/spree/calculator/per_item.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
require_dependency 'spree/calculator'
|
||||
|
||||
module Spree
|
||||
class Calculator::PerItem < Calculator
|
||||
preference :amount, :decimal, default: 0
|
||||
preference :currency, :string, default: Spree::Config[:currency]
|
||||
|
||||
def self.description
|
||||
Spree.t(:flat_rate_per_item)
|
||||
end
|
||||
|
||||
def compute(object=nil)
|
||||
return 0 if object.nil?
|
||||
self.preferred_amount * object.line_items.reduce(0) do |sum, value|
|
||||
if matching_products.blank? || matching_products.include?(value.product)
|
||||
value_to_add = value.quantity
|
||||
else
|
||||
value_to_add = 0
|
||||
end
|
||||
sum + value_to_add
|
||||
end
|
||||
end
|
||||
|
||||
# Returns all products that match this calculator, but only if the calculator
|
||||
# is attached to a promotion. If attached to a ShippingMethod, nil is returned.
|
||||
def matching_products
|
||||
# Regression check for #1596
|
||||
# Calculator::PerItem can be used in two cases.
|
||||
# The first is in a typical promotion, providing a discount per item of a particular item
|
||||
# The second is a ShippingMethod, where it applies to an entire order
|
||||
#
|
||||
# Shipping methods do not have promotions attached, but promotions do
|
||||
# Therefore we must check for promotions
|
||||
if self.calculable.respond_to?(:promotion)
|
||||
self.calculable.promotion.rules.map do |rule|
|
||||
rule.respond_to?(:products) ? rule.products : []
|
||||
end.flatten
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
31
app/models/spree/calculator/price_sack.rb
Normal file
31
app/models/spree/calculator/price_sack.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
require_dependency 'spree/calculator'
|
||||
# For #to_d method on Ruby 1.8
|
||||
require 'bigdecimal/util'
|
||||
|
||||
module Spree
|
||||
class Calculator::PriceSack < Calculator
|
||||
preference :minimal_amount, :decimal, default: 0
|
||||
preference :normal_amount, :decimal, default: 0
|
||||
preference :discount_amount, :decimal, default: 0
|
||||
preference :currency, :string, default: Spree::Config[:currency]
|
||||
|
||||
def self.description
|
||||
Spree.t(:price_sack)
|
||||
end
|
||||
|
||||
# as object we always get line items, as calculable we have Coupon, ShippingMethod
|
||||
def compute(object)
|
||||
if object.is_a?(Array)
|
||||
base = object.map { |o| o.respond_to?(:amount) ? o.amount : BigDecimal(o.to_s) }.sum
|
||||
else
|
||||
base = object.respond_to?(:amount) ? object.amount : BigDecimal(object.to_s)
|
||||
end
|
||||
|
||||
if base < self.preferred_minimal_amount
|
||||
self.preferred_normal_amount
|
||||
else
|
||||
self.preferred_discount_amount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user