mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-25 20:46:48 +00:00
95 lines
2.4 KiB
Ruby
95 lines
2.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "active_support/concern"
|
|
|
|
module CalculatedAdjustments
|
|
extend ActiveSupport::Concern
|
|
|
|
CALCULATORS = %w{
|
|
Calculator::DefaultTax
|
|
Calculator::FlatPercentItemTotal
|
|
Calculator::FlatPercentPerItem
|
|
Calculator::FlatRate
|
|
Calculator::FlexiRate
|
|
Calculator::None
|
|
Calculator::PerItem
|
|
Calculator::PriceSack
|
|
Calculator::Weight
|
|
}.freeze
|
|
|
|
included do
|
|
has_one :calculator, as: :calculable, class_name: "Spree::Calculator", dependent: :destroy
|
|
accepts_nested_attributes_for :calculator
|
|
validates :calculator, presence: true
|
|
end
|
|
|
|
class_methods do
|
|
def calculators
|
|
spree_calculators.__send__(model_name_without_spree_namespace)
|
|
end
|
|
|
|
private
|
|
|
|
def model_name_without_spree_namespace
|
|
to_s.tableize.gsub('/', '_').sub('spree_', '')
|
|
end
|
|
|
|
def spree_calculators
|
|
Rails.application.config.spree.calculators
|
|
end
|
|
end
|
|
|
|
def calculator_type
|
|
calculator.class.to_s if calculator
|
|
end
|
|
|
|
def calculator_type=(calculator_type)
|
|
return unless calculator_type
|
|
|
|
return unless CALCULATORS.include?(calculator_type)
|
|
|
|
klass = calculator_type.constantize
|
|
self.calculator = klass.new if klass && !calculator.is_a?(klass)
|
|
end
|
|
|
|
# Creates a new adjustment for the target object
|
|
# (which is any class that has_many :adjustments) and sets amount based on the
|
|
# calculator as applied to the given calculable (Order, LineItems[], Shipment, etc.)
|
|
# By default the adjustment will not be considered mandatory
|
|
def create_adjustment(label, adjustable, mandatory = false, state = "closed", tax_category = nil)
|
|
amount = compute_amount(adjustable)
|
|
return if amount.zero? && !mandatory
|
|
|
|
adjustment_attributes = {
|
|
amount:,
|
|
originator: self,
|
|
order: order_object_for(adjustable),
|
|
label:,
|
|
mandatory:,
|
|
state:,
|
|
tax_category:
|
|
}
|
|
|
|
if adjustable.respond_to?(:adjustments)
|
|
adjustable.adjustments.create(adjustment_attributes)
|
|
else
|
|
adjustable.create_adjustment(adjustment_attributes)
|
|
end
|
|
end
|
|
|
|
# Calculate the amount to be used when creating an adjustment
|
|
# NOTE: May be overriden by classes where this module is included into.
|
|
def compute_amount(calculable)
|
|
calculator.compute(calculable)
|
|
end
|
|
|
|
def order_object_for(target)
|
|
# Temporary method for adjustments transition.
|
|
if target.is_a? Spree::Order
|
|
target
|
|
elsif target.respond_to?(:order)
|
|
target.order
|
|
end
|
|
end
|
|
end
|