Solidus's promotions system allows you to give discounts to customers. Discounts can be applied to different amounts that make up the order:
The promotions system provides a set of handlers, rules, and actions that work together to provide flexible discounts in any scenario.
To account for all of the ways a discount may be applied, the promotions system has many complex moving parts.
We recommend that you start up a Solidus store on your local machine and see the
built-in promotions functionality yourself, as store administrators have a
flexible promotions system available by default
(
http://localhost:3000/admin/promotions
). Here,
administrators can add promotions and create complex strings of promotion rules
and actions if necessary.
The following sections summarize the main parts of Solidus's promotions system.
The Spree::Promotion
model defines essential information about a promotion.
This includes the promotion's name, description, and whether the promotion
should be active or not.
Take note of the following promotion attributes:
name
: The name for the promotion. This is displayed to customers as an
adjustment label when it is applied.description
: An administrative description for the promotion.usage_limit
: How many times the promotion can be used before becoming
inactive.starts_at
and expires_at
: Optional date values for the start and end of
the promotion.match_policy
: When set to all
, all promotion rules must be met in order
for the promotion to be eligible. When set to any
, just one of the
promotion rules
must be met.
Using "any" is deprecated and will be removed in future Solidus versions.
You can create separate promotions for each rule you have in mind instead.path
: If the promotion is activated when the customer visits a URL, this
value is the path for the URL.per_code_usage_limit
: Specifies how many times each code can be used before
it becomes inactive.apply_automatically
: If true
, the promotion is activated and applied
automatically once all of the
eligibility checks
have passed.Note that you can access promotion information using the promotion
method on
its associated Spree::PromotionRule
and Spree::PromotionAction
objects:
Spree::PromotionAction.find(1).promotion
Subclasses of the Spree::PromotionHandler
model activate a promotion if the
promotion is
eligible
to be applied. There are Cart
, Coupon
,
Page
, and Shipping
subclasses, each one used for a different promotion
activation method. For more information, see the
Promotion
handlers
article.
Once a promotion handler activates a promotion, and all of the eligibility
checks pass, the Spree::PromotionAction
can be applied to the applicable
shipment, order, or line item.
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.
By default, Spree::Promotion
s 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
.
Using "any" is deprecated and will be removed in future Solidus versions. You can create separate promotions for each rule you have in mind instead.
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. In this case, create one promotion with the order total rule, and a separate one with the product rule.
For a list of available rule types and more information, see the Promotion rules article.
The Spree::PromotionAction
model defines an action that should occur if the
promotion is activated and eligible to be applied. There can be multiple
promotion actions on a promotion.
Typically, a promotion action could be free shipping or a fixed percentage discount.
A promotion action calculates the discount amount and creates a
Spree::Adjustment
for the promotion. The adjustment then adjusts the price of
an order, line item, or shipment.
Finally, the Spree::Adjustment
model defines the discount amount that is
applied. Each adjustment is created by a Spree::PromotionAction
.
Every time that the promotion adjustment needs to be recalculated, the
Spree::PromotionRule
s are re-checked to ensure the promotion is still
eligible.
Note that shipments and taxes can also create adjustments. See the adjustments documentation for more information.
Spree::Promotion
's performs a number of checks to determine whether a
promotion is eligible to be applied:
Spree::PromotionRule
s.If all of these checks pass, then the promotion is eligible.
See the eligible?
method defined in the
Spree::Promotion
model
:
def eligible?(promotable, promotion_code: nil)
return false if inactive?
return false if usage_limit_exceeded?
return false if promotion_code && promotion_code.usage_limit_exceeded?
return false if blacklisted?(promotable)
!!eligible_rules(promotable, {})
end
Note that promotions without rules are eligible by default.
Once the promotion is confirmed eligible, the promotion can be activated through
the relevant Spree::PromotionHandler
.
This section provides a high-level view of the promotion system in action. For the sake of this example, the store administrator is creating a free shipping promotion for orders over $100 USD.
Spree::Promotion
from the Solidus backend.
Spree::PromotionRule
s for the promotion.
Spree::Promotion::Rules::ItemTotal
) and set the rule so that the
order must be greater than $100 USD.Spree::PromotionAction
s for the promotion.
Spree::Promotion::Actions::Shipping
model. In this case, the only
available action is "Makes all shipments for the order free".Spree::PromotionHandler::Shipping
will be used when it is time to activate
the promotion.Different types of promotions would change the customer's experience of promotion activation. For example, the customer might be required to enter a promotion code to activate some promotions, while another promotion could be applied automatically.
In this case, because the administrator used the "Apply to all orders" activation method, the promotion is applied automatically:
Spree::Order
total is greater
than $100 USD.Spree::PromotionHandler::Shipping
handler checks that the
Spree::PromotionRule
s are met. Because the order total is
greater than $100 USD, the promotion is eligible.Spree::PromotionHandler::Shipping
activates the promotion.Spree::PromotionAction
associated with the promotion is computed and
applied as a Spree::Adjustment
that negates the order's shipping charges.
The customer's shipping is now free.Solidus is an open source platform supported by the community. We encourage everyone using Solidus 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.