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.