Copied to Clipboard
6. New discount compatibility system
9.0.x
The compatibility system relies on the ps_cart_rule_combination table and the cart_rule_restriction field. Each forbidden combination is stored as a pair in the table, causing exponential data explosion with many rules.
9.1.x
The new system introduces compatibility by discount type:
- Discounts are no longer ordered by promo code vs. automatic
-
Fixed application order:
- Catalog (product) → Cart (cart) → Free Shipping → Free Gift
-
Within the same type: sorted by priority (lower = applied first), then by creation date
-
Dynamic re-evaluation on each cart modification
7. Impact on CartRuleCalculator.php
While this file is separate from CartRule.php, the changes are intrinsically linked. The CartRuleCalculator (in src/Core/Cart/) integrates the same feature flag checks:
<span class="k">if</span> <span class="p">(</span><span class="nv">$cartRule</span><span class="o">-></span><span class="nb">getType</span><span class="p">()</span> <span class="o">===</span> <span class="nc">DiscountType</span><span class="o">::</span><span class="no">ORDER_LEVEL</span>
<span class="o">&&</span> <span class="p">(</span><span class="n">float</span><span class="p">)</span> <span class="nv">$cartRule</span><span class="o">-></span><span class="n">reduction_percent</span> <span class="o">></span> <span class="mi">0</span>
<span class="o">&&</span> <span class="nv">$cartRule</span><span class="o">-></span><span class="n">reduction_product</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-></span><span class="nf">isDiscountFeatureFlagEnabled</span><span class="p">())</span> <span class="p">{</span>
<span class="c1">// New calculation: products + shipping</span>
<span class="nv">$initialShippingFees</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-></span><span class="n">calculator</span><span class="o">-></span><span class="nf">getFees</span><span class="p">()</span><span class="o">-></span><span class="nf">getInitialShippingFees</span><span class="p">();</span>
<span class="nv">$productsTotal</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-></span><span class="n">calculator</span><span class="o">-></span><span class="nf">getRowTotal</span><span class="p">();</span>
<span class="nv">$orderTotal</span> <span class="o">=</span> <span class="nv">$productsTotal</span><span class="o">-></span><span class="nf">add</span><span class="p">(</span><span class="nv">$initialShippingFees</span><span class="p">);</span>
<span class="c1">// ...</span>
<span class="p">}</span>
<span class="p">}</span>
8. Associated database changes
The 9.1.x introduces schema modifications to support the new discount system (visible in install-dev/upgrade/sql/9.1.0.sql). These changes are linked to the feature flag and don’t alter existing tables as long as the flag remains disabled.
9. Changes summary table
Aspect 9.0.x 9.1.x Imports No Discount dependency DiscountType, DiscountSettings, FeatureFlagSettings Feature Flag Absent isDiscountFeatureFlagEnabled() present Discount typing Implicit (individual fields) Explicit via getType() → DiscountType % on ORDER_LEVEL Products only Products + shipping Fixed amount cap Product total Product total + shipping (ORDER_LEVEL) XSS security messages $cart_rule->name htmlspecialchars($cart_rule->name) Discount compatibility cart_rule_combination table By type with fixed application order Backward compatibility — ✅ Flag disabled = 9.0.x behavior ---
10. Recommendations for module developers
-
Don’t override
CartRule.php if you plan to support 9.1.x — the file is actively evolving.
-
Check the feature flag in your modules if you interact with discounts:
<span class="nv">$featureFlagManager</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-></span><span class="nf">get</span><span class="p">(</span><span class="nc">FeatureFlagStateCheckerInterface</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$featureFlagManager</span><span class="o">-></span><span class="nf">isEnabled</span><span class="p">(</span><span class="nc">FeatureFlagSettings</span><span class="o">::</span><span class="no">FEATURE_FLAG_DISCOUNT</span><span class="p">))</span> <span class="p">{</span>
<span class="c1">// New system logic</span>
<span class="p">}</span>
Test both modes (flag enabled and disabled) as merchants can switch between both.
Use getType() instead of manually checking reduction_product, free_shipping, gift_product etc.
Be careful with shipping calculation: if your module calculates discount totals, behavior changes based on discount type in 9.1.x.
🔑#### Key Takeaways — CartRule.php in PrestaShop 9.1.x
What every PrestaShop module developer must remember about the CartRule evolution from 9.0.x to 9.1.x:
-
The feature flag protects backward compatibility. The new Discount system is disabled by default — 9.1.x behaves exactly like 9.0.x as long as the flag remains off. No forced migration pressure.
-
ORDER_LEVEL calculation changes fundamentally. With the flag enabled, percentage and fixed-amount discounts now apply to products + shipping, not products alone. Your cart calculation tests must cover both modes.
-
Use
getType() instead of individual fields. The new method cleanly encapsulates the discount type (Catalog, Cart, Free Shipping, Free Gift) — no more manually checking reduction_product, free_shipping, gift_product.
-
Don’t override CartRule.php. This file is actively evolving. Use hooks and Symfony services instead to interact with the discount system.
-
Test both flag states in your CI: flag disabled (9.0.x behavior) and flag enabled (new system). It’s the only way to guarantee compatibility across your clients’ stores.
Sources and references