I have a function-controlled auto discount, handling both order and product based discount. Recently it failed to combine with discount codes, due to the auto discount being treated as order discount class even when no order discount is being issued.
Therefore want to confirm if the discount class of a function-controlled auto discount, is controlled by “whether orderDiscountsAdd object is presented”, or “whether an actual candidate is included in candidates”?
Case
Discount code
order discount
set to allow combineWith product discounts
Auto discount
set to allow combineWith product and order discounts
orderDiscountsAdd: empty candidates, selectionStrategy = Maximum
productDiscountsAdd: have value for candidates
Based on Discount API doc, this auto discount should be treated as product discount class, thus allowing the combination.
In actual use case, this auto discount is also treated a order discount class, which is not expected. This is confirmed by allowing order combineWith in discount code, the two discount successfully combine.
The combination was working until last week, so may I know if the logic regarding discount classes was updated since then?
Hello all, may I know if theres any update on this issue? I just checked the admin combination section, it shows that the two discounts can be combined. I am a bit confused because it used to work. Thanks in advance.
Does this mean that the discount class is fixed when I create the discount, accounting to the defined discountClasses.
Sound contradict to
So in high level, if a discount is set to cannot combined with order discount. My auto discount (defined discountClasses [order, product]) can never be combined with this discount, even with empty OrderDiscountCandidateTarget?
Discount class compatibility at cart/checkout is based on the discountClasses declared at creation, not what the function returns at runtime. A discount registered with discountClasses: [ORDER, PRODUCT] is treated as both an order and product discount for combination purposes, even when the function only returns a productDiscountsAdd operation at cart/checkout. This is intended behavior.
I recommend setting discountClasses to match only the type you intend to apply. If you need a function to conditionally apply different discount types, you’ll need separate discounts with the appropriate class for each scenario.
Hope that clarifies things. Let me know if you have any questions!
The discount class for combineWith matching is declared at create/update time via the discountClasses field on the discount node, not derived from what the function returns at runtime.
The doc passage you quoted —
“Discount classes are assigned based on their associated Discount Function targets: OrderDiscountCandidateTarget, ProductDiscountCandidateTarget, DeliveryDiscountCandidateTarget.”
— refers to which candidate targets the function is capable of emitting, declared upfront. It doesn’t get re-evaluated per-run. So a discount declared with [ORDER, PRODUCT] is treated as both classes for combineWith logic, regardless of whether orderDiscountsAdd.candidates is empty on a given run.
Your own test (allowing orderDiscounts: true on the code made it combine) confirms it — Shopify is using your declared classes.