tomatophp/tomato-coupons-module
A Laravel module that adds coupon and discount code management to TomatoPHP apps, letting you create, apply, and validate promo codes on orders with a ready-made admin interface and database migrations.
CouponService, store discount as a cart/order adjustment, record usage in the order-completion transaction) means the buy decision is reversible. You can start here and swap in a standalone promotions engine later without rewriting checkout, because your domain logic lives in your code, not the package's.Adopt when all of these hold:
Look elsewhere (or build) when:
Practical gate before committing: timebox a spike. Install in staging, publish config and migrations, create a fixed-amount coupon end-to-end (admin → checkout field → server-side validation → cart adjustment → usage row on paid order), and confirm money representation (integer minor units vs. decimal), rounding direction, and expiry timezone behavior. If that spike is clean in under a week, adopt. If it surfaces schema gaps, stop — the cost curve bends sharply after the first custom field.
For executives — the one-paragraph version: We have a gap: no way to run promotions. Building coupon management from scratch is roughly 2–4 engineer-weeks of undifferentiated work — admin screens, discount math, expiry logic, usage caps. An MIT-licensed Laravel module already does that, and it plugs directly into the admin panel we're already running. The trade is real but bounded: it's a small, young, single-maintainer project with no other adopters, so we treat it as a starting point we own rather than a vendor we depend on. We keep our checkout logic in our own service layer, which means if the package stalls or we outgrow it, we replace the storage layer and keep the business logic. Recommendation: adopt behind a spike, scope it to Tier-1 promos, and budget a small reserve for self-maintenance.
For engineering — what we're actually asking for: Integrate, don't extend-in-place. Own a CouponService that encapsulates all validation policy; never let checkout call the model directly. Apply discounts as order adjustments with the code and computed amount persisted at time of purchase — never mutate the total. Write usage rows inside the order-completion transaction with row locking or atomic increments so concurrent checkouts can't overspend a limited code. Extend the Filament resource from a service provider; never patch vendor/. Publish lang files to the app and override there. Add the vendor:publish step to the deploy script — migrations aren't auto-loaded, and skipping it fails at runtime, not at boot, which will burn an afternoon in triage.
For finance/support — what changes operationally: Deactivating a coupon must replace deleting it, so usage history and order references stay intact. We need one documented definition of expiry (recommend end-of-day in the customer's timezone, not a precise UTC instant) and one documented refund rule for orders that used a code. Support needs a runbook: how to check whether a code is live, how to tell a customer why their code was rejected, and who has authority to alter a live promotion.
Risks to name out loud, briefly: thin adoption and a stale release cadence (translation-only in March 2024) mean no community upgrade testing; Filament major-version coupling is the likely future blocker, not the coupon logic itself; and the money-representation and rounding questions are boring and expensive if we get them wrong. None of these are reasons to not start — they're reasons to start with the service boundary in place.
How can I help you explore Laravel packages today?