Product Type Compatibility with Price Rules and Discounts
Product Type Compatibility with Price Rules and Discounts
~6 Min. Lesezeit Zuletzt aktualisiert am August 9, 2026
A new product type has been fully sellable since chapter 76 and reliably books points. Before chapter 78 wraps up the series, this chapter settles a question that in practice regularly only surfaces after go-live: do catalog and cart price rules actually work correctly against a points package?
Catalog price rules and the indexer
Catalog price rules ("10% off all products in category X") run through the price indexer - and that's exactly what chapter 72 deliberately set to indexPriceModel="Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice", the same default class simple and virtual use. Catalog price rules therefore work for points packages without any special handling - provided the full reindex chapter 71 flagged after introducing the type was actually carried out. A partially updated price index would silently exclude points packages from every catalog price rule, with no visible error - the discount is simply missing.
Cart price rules work generically
Cart price rules (coupon codes, "free shipping over 50 EUR") check their conditions via Magento\SalesRule\Model\Rule\Condition\Product - a generic attribute condition engine that compares against arbitrary EAV attributes product-type-agnostically (price, category, loyalty_points_package_amount included). A coupon code "10% off orders over 50 EUR" therefore works for an order containing a points package without any adjustment for this series.
Where things can still snag
Not every extension sticks to this generic, attribute-based check. A fictional but realistic example - no real extension used in this project, just an illustration of the anti-pattern:
<?php
declare(strict_types=1);
namespace ThirdPartyPromo\FreeGift\Model\Rule\Condition;
use Magento\Catalog\Model\Product;
use Magento\Rule\Model\Condition\AbstractCondition;
/**
* Fictional third-party condition class, shown only for recognition - NOT
* part of app/code/Mironsoft/Loyalty. Illustrates the brittle pattern this
* chapter warns about: a hardcoded product type whitelist instead of an
* attribute- or capability-based check.
*/
class ProductTypeGate extends AbstractCondition
{
/**
* Rejects every product whose type is not in this hardcoded list -
* silently excludes loyalty_points_package (and any other custom type)
* from whatever promotion this condition gates, with no error or log
* entry anywhere.
*
* @param Product $product Product being evaluated against this condition
* @return bool
*/
public function isProductEligible(Product $product): bool
{
return in_array($product->getTypeId(), ['simple', 'virtual'], true);
}
}
Achtung: in_array($product->getTypeId(), ['simple', 'virtual'], true) is a shockingly common pattern in the wild - especially in older "gift with purchase" or "bundle discount" extensions that only knew about the core types that existed when they were written. The result is no error and no log line - the condition simply returns false, a points package gets silently excluded from the promotion, and nobody would notice without targeted testing. The only reliable way to uncover this: actually click through every price rule/campaign meant to apply to points packages with one in the cart.
Dedicated testing clearly recommended
- Create a catalog price rule on the points packages' category, wait for a full reindex, check the price on the product page and in the cart.
- Test a coupon code rule with a minimum order value only reachable with a points package in the cart.
- If present in the project: specifically test every "gift with purchase" or similar third-party campaign extension against a points package, not just against
simpleproducts.
Tipp: The same caution applies in the other direction: if it's desired for points packages to be explicitly excluded from certain discount campaigns (no "20% off everything" coupon on an already heavily discounted points package), that can be modeled with an entirely ordinary product condition in the cart price rule - type_id is available as a condition attribute in the admin price rule form by default, no custom code needed.
Price rules and discounts therefore largely work automatically for points packages - the only reliable proof remains a targeted end-to-end test instead of a silent assumption. Chapter 78 wraps up block 9.