Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move all Calculators from spree to OFN and out of the Spree namespace #5613

Merged
merged 21 commits into from
Jul 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c2898ba
Bring calculators from spree_core
luisramos0 Jun 15, 2020
6b04df0
Fix indentation and extract Calculator as a separate module declaration
luisramos0 Jun 15, 2020
f2a46d2
Merge decorators into original classes brought from spree_core
luisramos0 Jun 15, 2020
a544102
Fix some rubocop issues
luisramos0 Jun 15, 2020
9c3eb37
Remove dead code related to promotions, we dont have promotions in OFN
luisramos0 Jun 15, 2020
5e8438c
Move all calculators outside the spree namespace
luisramos0 Jun 15, 2020
9c7cb23
Move calculator specs out of the spree namespace
luisramos0 Jun 15, 2020
6a94168
Remove Spree namespace from DefaultTax
luisramos0 Jun 15, 2020
f625462
Define DefaultTax calculator outside of spree namespace the tax_rate …
luisramos0 Jun 16, 2020
e225c5c
Migrate calculators to outside spree namespace
luisramos0 Jun 16, 2020
eedf31e
Make migration a bit easier to read
luisramos0 Jun 16, 2020
4b12a5f
Extract line_items_total from compute_order
luisramos0 Jun 16, 2020
21120dd
Extract per_item_fees_total out of compute_order
luisramos0 Jun 16, 2020
b096717
Extract per_order_fees_total out of compute_order
luisramos0 Jun 16, 2020
fbe0a32
Extract applicable_rate? and thus resolve rubocop complexity issue
luisramos0 Jun 16, 2020
70432e3
Early exit if max is zero to make method shorted
luisramos0 Jun 16, 2020
68359d4
Remove unnecessary variable (this sum and += come from the original
luisramos0 Jun 16, 2020
d92f977
Extract compute_for and thus resolve the rubocop complexity issue
luisramos0 Jun 16, 2020
0b79e7c
Fix rubucop issue in enterprise_fee model
luisramos0 Jun 16, 2020
99e12b6
Convert calculators in new spec
luisramos0 Jun 17, 2020
5e6739c
Fix long lines in new spec
luisramos0 Jun 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .rubocop_manual_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ Layout/LineLength:
- app/models/concerns/variant_stock.rb
- app/models/content_configuration.rb
- app/models/customer.rb
- app/models/enterprise_fee.rb
- app/models/enterprise_group.rb
- app/models/enterprise_role.rb
- app/models/inventory_item.rb
Expand Down
93 changes: 93 additions & 0 deletions app/models/calculator/default_tax.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# frozen_string_literal: false

require_dependency 'spree/calculator'
require 'open_food_network/enterprise_fee_calculator'

module Calculator
class DefaultTax < Spree::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
calculable
end

# Enable calculation of tax for enterprise fees with tax rates where included_in_price = false
def compute_order(order)
calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(order.distributor,
order.order_cycle)

[
line_items_total(order),
per_item_fees_total(order, calculator),
per_order_fees_total(order, calculator)
].sum do |total|
round_to_two_places(total * rate.amount)
end
end

def line_items_total(order)
matched_line_items = order.line_items.select do |line_item|
line_item.product.tax_category == rate.tax_category
end

matched_line_items.sum(&:total)
end

# Finds relevant fees for each line_item,
# calculates the tax on them, and returns the total tax
def per_item_fees_total(order, calculator)
order.line_items.sum do |line_item|
calculator.per_item_enterprise_fee_applicators_for(line_item.variant)
.select { |applicator| applicable_rate?(applicator, line_item) }
.sum { |applicator| applicator.enterprise_fee.compute_amount(line_item) }
end
end

def applicable_rate?(applicator, line_item)
fee = applicator.enterprise_fee
(!fee.inherits_tax_category && fee.tax_category == rate.tax_category) ||
(fee.inherits_tax_category && line_item.product.tax_category == rate.tax_category)
end

# Finds relevant fees for whole order,
# calculates the tax on them, and returns the total tax
def per_order_fees_total(order, calculator)
calculator.per_order_enterprise_fee_applicators_for(order)
.select { |applicator| applicator.enterprise_fee.tax_category == rate.tax_category }
.sum { |applicator| applicator.enterprise_fee.compute_amount(order) }
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(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
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
# frozen_string_literal: false

require_dependency 'spree/calculator'
require 'spree/localized_number'

module Spree
Calculator::FlatPercentItemTotal.class_eval do
module Calculator
class FlatPercentItemTotal < Spree::Calculator
extend Spree::LocalizedNumber

preference :flat_percent, :decimal, default: 0

localize_number :preferred_flat_percent

def self.description
Spree.t(:flat_percent)
end

def compute(object)
item_total = line_items_for(object).map(&:amount).sum
value = item_total * BigDecimal(preferred_flat_percent.to_s) / 100.0
Expand Down
23 changes: 23 additions & 0 deletions app/models/calculator/flat_rate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: false

require_dependency 'spree/calculator'
require 'spree/localized_number'

module Calculator
class FlatRate < Spree::Calculator
extend Spree::LocalizedNumber

preference :amount, :decimal, default: 0
preference :currency, :string, default: Spree::Config[:currency]

localize_number :preferred_amount

def self.description
I18n.t(:flat_rate_per_order)
end

def compute(_object = nil)
preferred_amount
end
end
end
46 changes: 46 additions & 0 deletions app/models/calculator/flexi_rate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: false

require_dependency 'spree/calculator'
require 'spree/localized_number'

module Calculator
class FlexiRate < Spree::Calculator
extend Spree::LocalizedNumber

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]

localize_number :preferred_first_item,
:preferred_additional_item

def self.description
I18n.t(:flexible_rate)
end

def self.available?(_object)
true
end

def compute(object)
max = preferred_max_items.to_i
items_count = line_items_for(object).map(&:quantity).sum

# check max value to avoid divide by 0 errors
return 0 if max.zero?

if items_count > max
compute_for(max - 1)
elsif items_count <= max
compute_for(items_count - 1)
end
end

private

def compute_for(count)
count * preferred_additional_item.to_f + preferred_first_item.to_f
end
end
end
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# frozen_string_literal: false

require_dependency 'spree/calculator'
require 'spree/localized_number'

module Spree
Calculator::PerItem.class_eval do
module Calculator
class PerItem < Spree::Calculator
extend Spree::LocalizedNumber

preference :amount, :decimal, default: 0
preference :currency, :string, default: Spree::Config[:currency]

localize_number :preferred_amount

def self.description
Expand All @@ -14,11 +20,7 @@ def compute(object = nil)
return 0 if object.nil?

number_of_line_items = line_items_for(object).reduce(0) do |sum, line_item|
value_to_add = if matching_products.blank? || matching_products.include?(line_item.product)
line_item.quantity
else
0
end
value_to_add = line_item.quantity
sum + value_to_add
end
preferred_amount * number_of_line_items
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
# frozen_string_literal: false

require_dependency 'spree/calculator'
# For #to_d method on Ruby 1.8
require 'bigdecimal/util'
require 'spree/localized_number'

module Spree
Calculator::PriceSack.class_eval do
module Calculator
class PriceSack < Spree::Calculator
extend Spree::LocalizedNumber

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]

localize_number :preferred_minimal_amount,
:preferred_normal_amount,
:preferred_discount_amount
Expand Down
4 changes: 3 additions & 1 deletion app/models/enterprise_fee.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ class EnterpriseFee < ActiveRecord::Base
has_many :exchanges, through: :exchange_fees

FEE_TYPES = %w(packing transport admin sales fundraising).freeze
PER_ORDER_CALCULATORS = ['Spree::Calculator::FlatRate', 'Spree::Calculator::FlexiRate', 'Spree::Calculator::PriceSack'].freeze
PER_ORDER_CALCULATORS = ['Calculator::FlatRate',
'Calculator::FlexiRate',
'Calculator::PriceSack'].freeze

validates :fee_type, inclusion: { in: FEE_TYPES }
validates :name, presence: true
Expand Down
40 changes: 0 additions & 40 deletions app/models/spree/calculator/default_tax_decorator.rb

This file was deleted.

13 changes: 0 additions & 13 deletions app/models/spree/calculator/flat_rate_decorator.rb

This file was deleted.

30 changes: 0 additions & 30 deletions app/models/spree/calculator/flexi_rate_decorator.rb

This file was deleted.

2 changes: 1 addition & 1 deletion app/models/spree/payment_method_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def init
self.class.include Spree::Core::CalculatedAdjustments
end

self.calculator ||= Spree::Calculator::FlatRate.new(preferred_amount: 0)
self.calculator ||= Calculator::FlatRate.new(preferred_amount: 0)
end

def has_distributor?(distributor)
Expand Down
Loading