diff --git a/backend/app/views/spree/admin/promotions/rules/_item_total.html.erb b/backend/app/views/spree/admin/promotions/rules/_item_total.html.erb
index d0060ac4418..1b0767b2ea9 100644
--- a/backend/app/views/spree/admin/promotions/rules/_item_total.html.erb
+++ b/backend/app/views/spree/admin/promotions/rules/_item_total.html.erb
@@ -1,7 +1,7 @@
- <%= select_tag "#{param_prefix}[preferred_operator]", options_for_select(Spree::Promotion::Rules::ItemTotal::OPERATORS.map{|o| [t(o, scope: 'spree.item_total_rule.operators'),o]}, promotion_rule.preferred_operator), {class: 'custom-select select_item_total fullwidth'} %>
+ <%= select_tag "#{param_prefix}[preferred_operator]", options_for_select(promotion_rule.class.operator_options, promotion_rule.preferred_operator), {class: 'custom-select select_item_total fullwidth'} %>
diff --git a/core/app/models/spree/promotion/rules/item_total.rb b/core/app/models/spree/promotion/rules/item_total.rb
index 95e1b5c3b55..544c426a052 100644
--- a/core/app/models/spree/promotion/rules/item_total.rb
+++ b/core/app/models/spree/promotion/rules/item_total.rb
@@ -5,12 +5,38 @@ class Promotion < Spree::Base
module Rules
# A rule to apply to an order greater than (or greater than or equal to)
# a specific amount
+ #
+ # To add extra operators please override `self.operators_map` or any other helper method.
+ # To customize the error message you can also override `ineligible_message`.
class ItemTotal < PromotionRule
+ include ActiveSupport::Deprecation::DeprecatedConstantAccessor
+
preference :amount, :decimal, default: 100.00
preference :currency, :string, default: ->{ Spree::Config[:currency] }
- preference :operator, :string, default: '>'
+ preference :operator, :string, default: 'gt'
+
+ # The list of allowed operators names mapped to their symbols.
+ def self.operators_map
+ {
+ gte: :>=,
+ gt: :>,
+ }
+ end
+
+ def self.operator_options
+ operators_map.map do |name, _method|
+ [I18n.t(name, scope: 'spree.item_total_rule.operators'), name]
+ end
+ end
- OPERATORS = ['gt', 'gte']
+ # @deprecated
+ OPERATORS = operators_map.keys.map(&:to_s)
+ deprecate_constant(
+ :OPERATORS,
+ :operators_map,
+ message: "OPERATORS is deprecated! Use `operators_map.keys.map(&:to_s)` instead.",
+ deprecator: Spree::Deprecation,
+ )
def applicable?(promotable)
promotable.is_a?(Spree::Order)
@@ -18,8 +44,8 @@ def applicable?(promotable)
def eligible?(order, _options = {})
return false unless order.currency == preferred_currency
- item_total = order.item_total
- unless item_total.send(preferred_operator == 'gte' ? :>= : :>, BigDecimal(preferred_amount.to_s))
+
+ unless total_for_order(order).send(operator, threshold)
eligibility_errors.add(:base, ineligible_message, error_code: ineligible_error_code)
end
@@ -28,15 +54,33 @@ def eligible?(order, _options = {})
private
+ def operator
+ self.class.operators_map.fetch(
+ preferred_operator.to_sym,
+ preferred_operator_default,
+ )
+ end
+
+ def total_for_order(order)
+ order.item_total
+ end
+
+ def threshold
+ BigDecimal(preferred_amount.to_s)
+ end
+
def formatted_amount
Spree::Money.new(preferred_amount, currency: preferred_currency).to_s
end
def ineligible_message
- if preferred_operator == 'gte'
+ case preferred_operator.to_s
+ when 'gte'
eligibility_error_message(:item_total_less_than, amount: formatted_amount)
- else
+ when 'gt'
eligibility_error_message(:item_total_less_than_or_equal, amount: formatted_amount)
+ else
+ eligibility_error_message(:item_total_doesnt_match_with_operator, amount: formatted_amount, operator: preferred_operator)
end
end
diff --git a/core/config/locales/en.yml b/core/config/locales/en.yml
index 1ec5617e055..2d92b651652 100644
--- a/core/config/locales/en.yml
+++ b/core/config/locales/en.yml
@@ -1288,6 +1288,8 @@ en:
%{amount}.
item_total_less_than_or_equal: This coupon code can't be applied to orders
less than or equal to %{amount}.
+ item_total_doesnt_match_with_operator: This coupon code can't be applied to
+ orders %{operator} %{amount}.
limit_once_per_user: This coupon code can only be used once per user.
missing_product: This coupon code can't be applied because you don't have
all of the necessary products in your cart.