NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Coupons for Laravel

Validation rule

Rules\Redeemable validates a coupon-code form field and reports a precise, translatable message for the first failing reason — no need to catch six exceptions:

use RoundlyConsulting\Coupons\Rules\Redeemable;

$request->validate([
    'code' => ['required', 'string', new Redeemable(cartTotal: $cartTotal, redeemer: $request->user())],
]);
  • Both arguments are optional: omit cartTotal to skip the currency and minimum-spend checks, omit redeemer to skip the per-redeemer cap.
  • Empty, blank or non-string input and unknown codes fail with the not_found message. Codes match case-insensitively, so summer passes for SUMMER.
  • The rule never mutates anything — usage is only incremented by a redemption.
  • It asks Coupons::check() — the same checks, in the same order, as redemption and isRedeemableBy() — so they never disagree.

Messages

Messages live under the coupons::messages namespace; :code is replaced with the coupon code. The package ships English:

Key (coupons::messages.)Default (en)
not_foundThe coupon ":code" does not exist.
currency_mismatchThis coupon cannot be used in the selected currency.
minimum_spend_not_metYour total does not meet this coupon’s minimum spend.
expiredThis coupon is no longer available.
at_max_usageThis coupon has reached its usage limit.
already_redeemedYou have already used this coupon.
type.fixed.label / .descriptionFixed amount / Subtracts a fixed amount from the price.
type.percentage.label / .descriptionPercentage / Subtracts a percentage of the price.
type.free_shipping.label / .descriptionFree shipping / Marks the order for free shipping.

Translating

Publish the strings with the coupons-translations tag to reword them, or add a file for another locale under lang/vendor/coupons. For example, Slovak:

// lang/vendor/coupons/sk/messages.php
return [
    'not_found' => 'Kupón „:code“ neexistuje.',
    'currency_mismatch' => 'Tento kupón nie je možné použiť vo zvolenej mene.',
    'minimum_spend_not_met' => 'Hodnota objednávky nedosahuje minimálnu sumu pre tento kupón.',
    'expired' => 'Tento kupón už nie je platný.',
    'at_max_usage' => 'Tento kupón dosiahol limit použití.',
    'already_redeemed' => 'Tento kupón ste už použili.',
];

The rule follows the application locale, so the same form shows the Slovak message once the locale is sk.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.