PHPackages                             narpat-bishnoi/laravel-user-discounts - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. narpat-bishnoi/laravel-user-discounts

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

narpat-bishnoi/laravel-user-discounts
=====================================

Deterministic, idempotent user-level discounts for Laravel.

v1.0.0(7mo ago)00MITPHPPHP ^8.1

Since Oct 1Pushed 7mo agoCompare

[ Source](https://github.com/narpat-bishnoi/laravel-user-discounts)[ Packagist](https://packagist.org/packages/narpat-bishnoi/laravel-user-discounts)[ Docs](https://github.com/narpat-bishnoi/laravel-user-discounts)[ RSS](/packages/narpat-bishnoi-laravel-user-discounts/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (6)Versions (2)Used By (0)

How to install and use
======================

[](#how-to-install-and-use)

1. Publish (optional) and migrate:
----------------------------------

[](#1-publish-optional-and-migrate)

```
composer require acme/laravel-user-discounts
php artisan vendor:publish --tag=config --provider="NarpatBishnoi\UserDiscounts\DiscountsServiceProvider"
php artisan migrate

```

2. Create discounts (seed or admin UI):
---------------------------------------

[](#2-create-discounts-seed-or-admin-ui)

```
use NarpatBishnoi\UserDiscounts\Models\Discount;

$summer = Discount::create([
  'code' => 'SUMMER20',
  'name' => '20% off summer',
  'type' => 'percentage',
  'percent' => '20.00',
  'priority' => 10,
  'active' => true,
  'starts_at' => now(),
  'ends_at' => now()->addMonth(),
]);
```

3. Assign to user:
------------------

[](#3-assign-to-user)

```
use NarpatBishnoi\UserDiscounts\Facades\UserDiscounts;

UserDiscounts::assign($user, $summer, usageLimit: 2);
```

4. Check eligibility:
---------------------

[](#4-check-eligibility)

```
$eligible = app('acme.user-discounts')->eligibleFor($user);
// -> Collection of Discount models
```

5. Apply to an order subtotal (in cents!) with an idempotency context key:
--------------------------------------------------------------------------

[](#5-apply-to-an-order-subtotal-in-cents-with-an-idempotency-context-key)

```
$result = app('acme.user-discounts')->apply($user, 4599 /* $45.99 */, 'order:98765');

/*
$result = [
  'application_uid' => '01J..ULID..',
  'context_key' => 'order:98765',
  'subtotal_before_cents' => 4599,
  'subtotal_after_cents' => 3899,
  'total_discount_cents' => 700,
  'lines' => [
      ['discount_id' => 1, 'amount_cents' => 200],
      ['discount_id' => 2, 'amount_cents' => 500],
  ],
]
*/
```

6. Revoke (soft by default):
----------------------------

[](#6-revoke-soft-by-default)

```
UserDiscounts::revoke($user, $summer);          // sets revoked_at
UserDiscounts::revoke($user, $summer, true);     // hard delete pivot
```

How this meets your Acceptance Criteria
=======================================

[](#how-this-meets-your-acceptance-criteria)

Assign → eligible → apply works with audits assign() creates/updates pivot; eligibleFor() filters active window + usage caps; apply() writes a row per discount into discount\_audits with an application\_uid to group lines; event DiscountApplied fires.

Expired/inactive excluded Discount::scopeActiveWindow() and active flag enforced; eligibleFor() and apply() both respect this.

Usage caps enforced user\_discounts.used\_count &lt; usage\_limit checked and rows locked via lockForUpdate() so concurrent apply can’t double-increment.

Stacking and rounding correct Configured type order + priority + ID tie-break; percentage lines rounded per discounts.rounding.mode; optional aggregate cap (e.g., max 80% off) with deterministic proportional scaling.

Revoked discounts not applied user\_discounts.revoked\_at excluded in queries.

Concurrency safe Transaction + lockForUpdate() on pivots + unique index on (user\_id, discount\_id, context\_key) yields idempotent writes; duplicate concurrent inserts are handled and usage increments occur at most once.

Unit Test included tests/Feature/DiscountApplicationTest.php validates discount math, idempotency, and cap logic.

Notes / Options
===============

[](#notes--options)

Money representation: Inputs/outputs are integer cents to avoid float drift. If you use a Money library, adapt apply() signatures accordingly.

Stacking policies: Update config/discounts.php to switch order (e.g., apply fixed before percentage), or add further strategies (e.g., “best of”).

Global usage limits / product scopes: Extend the schema and eligibleFor() as needed.

Audits shape: Each discount line is individually auditable and replayable via (user\_id, context\_key) query.

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance63

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity44

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

223d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/11cd9480e207cc4ad09d1e30af96d32a97aeae5023bac9fe5fe381283cc06a36?d=identicon)[narpat-bishnoi](/maintainers/narpat-bishnoi)

---

Top Contributors

[![narpat-bishnoi](https://avatars.githubusercontent.com/u/5460640?v=4)](https://github.com/narpat-bishnoi "narpat-bishnoi (3 commits)")

---

Tags

laravelpackageecommercediscountscouponspricing

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/narpat-bishnoi-laravel-user-discounts/health.svg)

```
[![Health](https://phpackages.com/badges/narpat-bishnoi-laravel-user-discounts/health.svg)](https://phpackages.com/packages/narpat-bishnoi-laravel-user-discounts)
```

###  Alternatives

[barryvdh/laravel-ide-helper

Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.

14.9k123.0M687](/packages/barryvdh-laravel-ide-helper)[psalm/plugin-laravel

Psalm plugin for Laravel

3274.9M308](/packages/psalm-plugin-laravel)[efureev/laravel-trees

Multi-Tree structures for Laravel

14253.3k4](/packages/efureev-laravel-trees)[tehwave/laravel-achievements

Simple, elegant Achievements the Laravel way

7012.8k](/packages/tehwave-laravel-achievements)[bensampo/laravel-embed

Painless responsive embeds for videos, slideshows and more.

142146.8k](/packages/bensampo-laravel-embed)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
