fluentcart-coupons-discounts
Implements and audits FluentCart coupon creation, fixed/percentage calculation, eligibility conditions, stacking/priority, usage limits, recurring discounts, order snapshots, and virtual coupon resolution. Use when working with CouponResource, DiscountService, fct_coupons, fct_ap
Install
npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/fluentcart/fluentcart-coupons-discounts
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart
git clone https://github.com/Lonsdale201/wp-agent-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole lonsdale201/wp-agent-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
FluentCart coupons and discounts
Extend the calculation pipeline instead of altering displayed totals. Revalidate every coupon against current server-owned cart data.
Read coupon-pipeline.md before implementing a virtual coupon, new rule, custom type, or recurring discount.
Use the canonical model
Coupon stores code, type, amount, priority, status, stackable, show_on_checkout, dates, use_count, and JSON conditions. AppliedCoupon stores the order-time snapshot. Never reconstruct historical discounts from the currently editable Coupon.
Use CouponResource for admin CRUD because it validates and converts fixed amounts/limits. In 1.6.0:
- fixed amount uses integer minor units after formatting;
- percentage amount is a percentage value from 0 through 100;
- lower numeric priority applies first;
- multiple coupons survive together only under the stackability rules.
Extend eligibility
- fluent_cart/coupon/can_use_coupon: reject the whole coupon with false or WP_Error.
- fluent_cart/coupon/will_skip_item: exclude one item.
- fluent_cart/discount/pre_apply: transform candidate cart items before application; preserve complete shape and avoid price trust.
- fluent_cart/coupon/per_customer_usage_query: add legitimate usage scoping.
- fluent_cart/coupon/validating_coupon: normalize/admin-order validation code.
Keep eligibility callbacks pure. Coupon recalculation runs after cart/address/ shipping/tax changes and may run repeatedly.
Implement virtual coupons carefully
fluent_cart/coupon/resolve_coupons receives the database-found collection, requested codes, and cart context. Append an unsaved Coupon model for an addon-owned code only after server-side lookup and authorization.
add_filter(
'fluent_cart/coupon/resolve_coupons',
static function ($coupons, array $codes, array $context) {
// Resolve only this addon's opaque code from server-owned state.
// Append a fully populated unsaved Coupon model.
return $coupons;
},
10,
3
);
Give the virtual coupon a stable normalized code, supported type, integer amount where applicable, status, priority, stackable flag, and full conditions. It is not persisted in fct_coupons, so build separate atomic redemption accounting if it represents a finite balance or single-use right.
Do not assume every accepted type is calculated
CouponRequest 1.6.0 accepts fixed, percentage, free_shipping, and buy_x_get_y. The active DiscountService calculation path is source-confirmed for fixed and percentage; it does not contain equivalent type branches for free_shipping or buy_x_get_y. Do not ship those types, or a new custom type, based only on the request enum. Implement and test all validation, allocation, recurring, order snapshot, refund, reporting, and UI behavior or keep the type unavailable.
Preserve calculation invariants
- Recalculate from item subtotal/server price; never discount a browser total.
- Apply included/excluded product variation IDs and product-category term IDs in their correct namespaces.
- Treat email wildcards and per-customer limits as authorization-sensitive.
- Respect min_amount_basis: new coupons default to subtotal, while legacy missing values preserve total behavior.
- Cap line discount at the eligible line amount.
- Correct fixed-discount rounding deterministically across eligible items.
- Record per-coupon allocation so removal, tax, refund, and order snapshots remain explainable.
- Treat recurring discount separately from initial/trial/signup amounts.
Test matrix
Test case-normalized duplicate code, schedule boundaries in GMT, fixed and percentage rounding, 0/100 percent, min/max spend basis, category/product include/exclude, locked line, anonymous/email restriction, per-customer/global limits under concurrency, stacking order, remove/reapply, tax-inclusive cart, shipping/fee change, trial/setup/renewal, virtual redemption replay, refund, and manual order editing.
Cross-references
- Use fluentcart-cart-checkout for cart revalidation.
- Use fluentcart-orders-transactions for immutable order snapshots/refunds.
- Use fluentcart-subscriptions-renewals for recurring discounts.
References
- Official product/coupon hooks: https://dev.fluentcart.com/hooks/actions/products-coupons/
- Verified Free source paths:
- fluent-cart/app/Models/Coupon.php
- fluent-cart/app/Models/AppliedCoupon.php
- fluent-cart/api/Resource/CouponResource.php
- fluent-cart/app/Http/Requests/CouponRequest.php
- fluent-cart/app/Services/Coupon/DiscountService.php
- fluent-cart/app/Services/Coupon/Concerns/
- fluent-cart/app/Models/Cart.php
Files (wp-agent-skills)
-
agents
-
openai.yaml 311 B
interface: display_name: "FluentCart coupons and discounts" short_description: "Extend discount rules, allocation, and virtual coupons" default_prompt: "Use $fluentcart-coupons-discounts to implement or audit this promotion against the verified coupon pipeline, amount units, usage rules, and snapshots."
-
-
references
-
coupon-pipeline.md 2 KB
# FluentCart 1.6.0 coupon pipeline ## Storefront application ~~~text requested codes plus existing cart codes -> query fct_coupons -> fluent_cart/coupon/resolve_coupons -> format in requested order -> status/date/spend/usage validation -> can_use_coupon -> stackability and priority sort -> reset prior coupon allocations -> pre_apply -> will_skip_item and native conditions -> fixed/percentage allocation and rounding correction -> recurring allocation where eligible -> save cart items, codes, per-coupon amounts ~~~ The pipeline can invalidate some codes while applying others. Inspect coupon_results rather than assuming a non-error response applied every request. ## Native conditions - min_purchase_amount - min_amount_basis: subtotal or total - max_purchase_amount - max_discount_amount - max_uses - max_per_customer - included_products / excluded_products - included_categories / excluded_categories - email_restrictions - is_recurring - apply_to_whole_cart / apply_to_quantity and related type data Confirm whether the active calculator consumes a condition before relying on it. The admin/request schema can contain planned or path-specific values. ## Amount conventions - Coupon amount: fixed is minor units; percentage is percentage points. - min_purchase_amount and max_discount_amount are converted by CouponResource. - Cart totals and line allocations are integer minor units. - Display/edit clients may send decimal currency values to Resource formatting code; direct model creation must not skip conversion. ## Virtual redemption design For wallet/store credit or a single-use generated code: 1. keep the external entitlement in an addon-owned table; 2. resolve it into an in-memory Coupon for calculation; 3. atomically reserve/claim at order creation or payment according to policy; 4. finalize at verified payment; 5. release safely on failed/expired order; 6. store an addon-owned order allocation/idempotency record; 7. reconcile refunds explicitly. The resolve filter alone does not provide redemption accounting.
-
-
SKILL.md 5.4 KB
--- name: fluentcart-coupons-discounts description: >- Implements and audits FluentCart coupon creation, fixed/percentage calculation, eligibility conditions, stacking/priority, usage limits, recurring discounts, order snapshots, and virtual coupon resolution. Use when working with CouponResource, DiscountService, fct_coupons, fct_applied_coupons, fluent_cart/coupon/resolve_coupons, can_use_coupon, will_skip_item, discount/pre_apply, custom promotion codes, or investigating rounding, double application, and per-customer usage errors. metadata: wp-skills-author: "Soczó Kristóf" wp-skills-contact: "mailto:lonsdale201@hotmail.com" wp-skills-plugin: "fluent-cart" wp-skills-plugin-version-tested: "1.6.0" wp-skills-wp-version-tested: "7.0.2" wp-skills-php-min: "7.4" wp-skills-last-updated: "2026-08-06" --- # FluentCart coupons and discounts Extend the calculation pipeline instead of altering displayed totals. Revalidate every coupon against current server-owned cart data. Read [coupon-pipeline.md](references/coupon-pipeline.md) before implementing a virtual coupon, new rule, custom type, or recurring discount. ## Use the canonical model Coupon stores code, type, amount, priority, status, stackable, show_on_checkout, dates, use_count, and JSON conditions. AppliedCoupon stores the order-time snapshot. Never reconstruct historical discounts from the currently editable Coupon. Use CouponResource for admin CRUD because it validates and converts fixed amounts/limits. In 1.6.0: - fixed amount uses integer minor units after formatting; - percentage amount is a percentage value from 0 through 100; - lower numeric priority applies first; - multiple coupons survive together only under the stackability rules. ## Extend eligibility - fluent_cart/coupon/can_use_coupon: reject the whole coupon with false or WP_Error. - fluent_cart/coupon/will_skip_item: exclude one item. - fluent_cart/discount/pre_apply: transform candidate cart items before application; preserve complete shape and avoid price trust. - fluent_cart/coupon/per_customer_usage_query: add legitimate usage scoping. - fluent_cart/coupon/validating_coupon: normalize/admin-order validation code. Keep eligibility callbacks pure. Coupon recalculation runs after cart/address/ shipping/tax changes and may run repeatedly. ## Implement virtual coupons carefully fluent_cart/coupon/resolve_coupons receives the database-found collection, requested codes, and cart context. Append an unsaved Coupon model for an addon-owned code only after server-side lookup and authorization. ~~~php add_filter( 'fluent_cart/coupon/resolve_coupons', static function ($coupons, array $codes, array $context) { // Resolve only this addon's opaque code from server-owned state. // Append a fully populated unsaved Coupon model. return $coupons; }, 10, 3 ); ~~~ Give the virtual coupon a stable normalized code, supported type, integer amount where applicable, status, priority, stackable flag, and full conditions. It is not persisted in fct_coupons, so build separate atomic redemption accounting if it represents a finite balance or single-use right. ## Do not assume every accepted type is calculated CouponRequest 1.6.0 accepts fixed, percentage, free_shipping, and buy_x_get_y. The active DiscountService calculation path is source-confirmed for fixed and percentage; it does not contain equivalent type branches for free_shipping or buy_x_get_y. Do not ship those types, or a new custom type, based only on the request enum. Implement and test all validation, allocation, recurring, order snapshot, refund, reporting, and UI behavior or keep the type unavailable. ## Preserve calculation invariants - Recalculate from item subtotal/server price; never discount a browser total. - Apply included/excluded product variation IDs and product-category term IDs in their correct namespaces. - Treat email wildcards and per-customer limits as authorization-sensitive. - Respect min_amount_basis: new coupons default to subtotal, while legacy missing values preserve total behavior. - Cap line discount at the eligible line amount. - Correct fixed-discount rounding deterministically across eligible items. - Record per-coupon allocation so removal, tax, refund, and order snapshots remain explainable. - Treat recurring discount separately from initial/trial/signup amounts. ## Test matrix Test case-normalized duplicate code, schedule boundaries in GMT, fixed and percentage rounding, 0/100 percent, min/max spend basis, category/product include/exclude, locked line, anonymous/email restriction, per-customer/global limits under concurrency, stacking order, remove/reapply, tax-inclusive cart, shipping/fee change, trial/setup/renewal, virtual redemption replay, refund, and manual order editing. ## Cross-references - Use fluentcart-cart-checkout for cart revalidation. - Use fluentcart-orders-transactions for immutable order snapshots/refunds. - Use fluentcart-subscriptions-renewals for recurring discounts. ## References - Official product/coupon hooks: <https://dev.fluentcart.com/hooks/actions/products-coupons/> - Verified Free source paths: - fluent-cart/app/Models/Coupon.php - fluent-cart/app/Models/AppliedCoupon.php - fluent-cart/api/Resource/CouponResource.php - fluent-cart/app/Http/Requests/CouponRequest.php - fluent-cart/app/Services/Coupon/DiscountService.php - fluent-cart/app/Services/Coupon/Concerns/ - fluent-cart/app/Models/Cart.php
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.