Promotion rules

The Spree::PromotionRule model sets a rule that determines whether a promotion is eligible to be applied. Promotions may have no rules or many different rules.

An example of a typical promotion rule would be a minimum order total of $75 USD or that a specific product is in the cart at checkout.

Many conventional types of promotion rules are included by default. Multiple promotion rules can exist on each promotion, although no rules are required.

Available promotion rule types

The following classes are subclasses of the Spree::Promotion::Rules model :

  • FirstOrder: Eligible for a customer's first order only.
  • FirstRepeatPurchaseSince: Eligible for a customer's first repeat purchase since a specified date.
  • NthOrder: Eligible for a customer's nth order only.
  • ItemTotal: Eligible if the order total (before any adjustments) is less than or greater than a specified amount.
  • OneUsePerUser: Eligible for use one time for each user.
  • Product: Eligible for specified products only.
  • OptionValue: Eligible for specified variants (product option values) only.
  • Taxon: Eligible for products with specified taxons.
  • User: Eligible for specified users.
  • UserRole: Eligible for users with the specified user role.
  • UserLoggedIn: Eligible for users who are logged in.

Eligibility

Note that whenever an order, line item, or shipment with a promotion adjustment on it is updated, the eligibility of the promotion is re-checked, and the adjustment is recalculated if necessary.

Rules match policy

By default, Spree::Promotions have a match_policy value of all, meaning that all of the promotion rules on a promotion must be met before the promotion is eligible. However, this can be changed to any.

Administrators can change the match policy when adding or editing a promotion. By default, promotions use the "Match all of these rules" setting, but they can be changed to use "Match any of these rules".

Register a custom promotion rule

You can create a custom promotion rule by creating a new class that inherits from Spree::PromotionRule:

app/models/spree/promotion/rules/my_promotion_rule.rb
Ruby
    
      module Spree
  class Promotion
    module Rules
      class MyPromotionRule < Spree::PromotionRule
        def applicable?(promotable)
          promotable.is_a?(Spree::Order)
        end

        def eligible?(order, options = {})
          ...
        end

        def actionable?(line_item)
          ...
        end
      ...

    
  

Note that the applicable? and eligible? are required:

  • eligible? should return true or false to indicate if the promotion is eligible for an order.
  • If your promotion supports discounts for some line items but not others, define actionable? to return true when the specified line item meets the criteria for the promotion. It should return true or false to indicate if this line item can have a line item adjustment carried out on it.

For example, if you are giving a promotion on specific products only, eligible? should return true if the order contains one of the products eligible for promotion, and actionable? should return true when the line item specified is one of the specific products for this promotion.

Note that you can retrieve the associated Spree::Promotion information by calling the promotion method.

You must then register the custom rule in an initializer in your config/initializers/ directory:

Ruby
    
      Rails.application.config.spree.promotions.rules << Spree::Promotion::Rules::MyPromotionRule

    
  

Feedback

Solidus is an open source platform supported by the community. We encourage everyone using Solius to contribute back to the documentation and the code.

If you’re interested in contributing to the docs, get started with the contributing guidelines. If you see something that needs fixing and can’t do it yourself, please send us an email.