{"id":17024652,"url":"https://github.com/michael-rubel/laravel-couponables","last_synced_at":"2025-04-05T00:09:50.231Z","repository":{"id":37433355,"uuid":"458192339","full_name":"michael-rubel/laravel-couponables","owner":"michael-rubel","description":"Promocode functionality leveraging Eloquent polymorphic relationships.","archived":false,"fork":false,"pushed_at":"2024-03-15T21:14:50.000Z","size":398,"stargazers_count":181,"open_issues_count":0,"forks_count":8,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-10-15T07:26:23.281Z","etag":null,"topics":["coupon","coupon-code-generator","coupon-service","coupons","laravel","looking-for-contributors","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/michael-rubel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":["https://paypal.com/donate/?hosted_button_id=KHLEL8PFS4AXJ"]}},"created_at":"2022-02-11T13:13:15.000Z","updated_at":"2024-09-14T12:28:59.000Z","dependencies_parsed_at":"2024-10-25T19:11:08.994Z","dependency_job_id":"7425f286-d3b4-4fdf-97b2-6c167007c029","html_url":"https://github.com/michael-rubel/laravel-couponables","commit_stats":{"total_commits":236,"total_committers":3,"mean_commits":78.66666666666667,"dds":0.04661016949152541,"last_synced_commit":"df9a672e88f30dfd850951d2156d2c1ec09faae6"},"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-rubel%2Flaravel-couponables","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-rubel%2Flaravel-couponables/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-rubel%2Flaravel-couponables/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-rubel%2Flaravel-couponables/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michael-rubel","download_url":"https://codeload.github.com/michael-rubel/laravel-couponables/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247266565,"owners_count":20910836,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coupon","coupon-code-generator","coupon-service","coupons","laravel","looking-for-contributors","php"],"created_at":"2024-10-14T07:26:28.440Z","updated_at":"2025-04-05T00:09:50.215Z","avatar_url":"https://github.com/michael-rubel.png","language":"PHP","funding_links":["https://paypal.com/donate/?hosted_button_id=KHLEL8PFS4AXJ"],"categories":[],"sub_categories":[],"readme":"![Laravel Couponables](https://user-images.githubusercontent.com/37669560/224356302-5c021249-2290-4fb4-8bbe-99fbef4b5df5.png)\n\n# Laravel Couponables\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/michael-rubel/laravel-couponables.svg?style=flat-square\u0026logo=packagist)](https://packagist.org/packages/michael-rubel/laravel-couponables)\n[![Tests](https://img.shields.io/github/actions/workflow/status/michael-rubel/laravel-couponables/run-tests.yml?branch=main\u0026style=flat-square\u0026label=tests\u0026logo=github)](https://github.com/michael-rubel/laravel-couponables/actions)\n[![Code Quality](https://img.shields.io/scrutinizer/quality/g/michael-rubel/laravel-couponables.svg?style=flat-square\u0026logo=scrutinizer)](https://scrutinizer-ci.com/g/michael-rubel/laravel-couponables/?branch=main)\n[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/michael-rubel/laravel-couponables.svg?style=flat-square\u0026logo=scrutinizer)](https://scrutinizer-ci.com/g/michael-rubel/laravel-couponables/?branch=main)\n[![Infection](https://img.shields.io/github/actions/workflow/status/michael-rubel/laravel-couponables/infection.yml?branch=main\u0026style=flat-square\u0026label=infection\u0026logo=php)](https://github.com/michael-rubel/laravel-couponables/actions)\n[![Larastan](https://img.shields.io/github/actions/workflow/status/michael-rubel/laravel-couponables/phpstan.yml?branch=main\u0026style=flat-square\u0026label=larastan\u0026logo=laravel)](https://github.com/michael-rubel/laravel-couponables/actions)\n\nThis package provides coupons/promocodes functionality for your Laravel application leveraging Eloquent's polymorphic relationships.\n\nThe package requires `PHP 8.1` or higher and `Laravel 10` or higher.\n\n---\n\n## #StandWithUkraine\n[![SWUbanner](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)\n\n---\n\n## Installation\nInstall the package using composer:\n```bash\ncomposer require michael-rubel/laravel-couponables\n```\n\nPublish the migrations:\n```bash\nphp artisan vendor:publish --tag=\"couponables-migrations\"\n```\n\nPublish the config file:\n```bash\nphp artisan vendor:publish --tag=\"couponables-config\"\n```\n\n---\n\n## Usage\nAfter publishing migrations, apply a trait in the model you want to use as a `$redeemer`:\n```php\nuse HasCoupons;\n```\n\n---\n\n### Artisan command\nYou can add coupons to your database using Artisan command:\n```bash\nphp artisan make:coupon YourCouponCode\n```\n\nOptionally, you can pass the next arguments:\n```php\n'--value'         // The 'value' to perform calculations based on the coupon provided\n'--type'          // The 'type' to point out the calculation strategy\n'--limit'         // Limit how many times the coupon can be applied by the model\n'--quantity'      // Limit how many coupons are available overall (this value will decrement)\n'--expires_at'    // Set expiration time for the coupon\n'--redeemer_type' // Polymorphic model type. Can as well be morph-mapped value, i.e. 'users'\n'--redeemer_id'   // Redeemer model ID\n'--data'          // JSON column to store any metadata you want for this particular coupon\n```\n\n#### Adding coupons using model\nYou can as well add coupons simply using model:\n```php\nCoupon::create([\n    'code'  =\u003e '...',\n    'type'  =\u003e '...'\n    'value' =\u003e '...',\n    ...\n]);\n```\n\n- **Note:** `type` and `value` columns are used for cost calculations (this is optional).\\\nIf the `type` column is `null`, the `subtraction` strategy will be chosen.\n\n---\n\n### Basic operations\nVerify the coupon code:\n```php\n$redeemer-\u003everifyCoupon($code);\n```\n\nRedeem the coupon:\n```php\n$redeemer-\u003eredeemCoupon($code);\n```\n\nRedeem the coupon in context of another model:\n```php\n$redeemer\n  -\u003eredeemCoupon($code)\n  -\u003efor($course);\n```\n\nCombined `redeemCoupon` and `for` behavior (assuming the `$course` includes `HasCoupons` trait):\n```php\n$course-\u003eredeemBy($redeemer, $code);\n```\n\nIf something's going wrong, methods `verifyCoupon` and `redeemCoupon` will throw an exception:\n\n```php\nCouponDisabledException     // Coupon is disabled (`is_enabled` column).\nCouponExpiredException      // Coupon is expired (`expires_at` column).\nInvalidCouponException      // Coupon is not found in the database.\nInvalidCouponTypeException  // Wrong coupon type found in the database (`type` column).\nInvalidCouponValueException // Wrong coupon value passed from the database (`value` column).\nNotAllowedToRedeemException // Coupon is assigned to the specific model (`redeemer` morphs).\nOverLimitException          // Coupon is over the limit for the specific model (`limit` column).\nOverQuantityException       // Coupon is exhausted (`quantity` column).\nCouponException             // Generic exception for all cases.\n```\n\nIf you want to bypass the exception and do something else:\n```php\n$redeemer-\u003everifyCouponOr($code, function ($code, $exception) {\n    // Your action with $code or $exception!\n});\n```\n\n```php\n$redeemer-\u003eredeemCouponOr($code, function ($code, $exception) {\n    // Your action with $code or $exception!\n});\n```\n\n### [Redeemer](https://github.com/michael-rubel/laravel-couponables/blob/main/src/HasCoupons.php) checks\nCheck if this coupon is already used by the model:\n```php\n$redeemer-\u003eisCouponAlreadyUsed($code);\n```\n\nCheck if the coupon is over the limit for the model:\n```php\n$redeemer-\u003eisCouponOverLimit($code);\n```\n\n### [Coupon](https://github.com/michael-rubel/laravel-couponables/blob/main/src/Models/Coupon.php) checks\n```php\npublic function isExpired(): bool;\npublic function isNotExpired(): bool;\npublic function isDisposable(): bool;\npublic function isOverQuantity(): bool;\npublic function isRedeemedBy(Model $redeemer): bool;\npublic function isOverLimitFor(Model $redeemer): bool;\n```\n\nThis method references the model assigned to redeem the coupon:\n```php\npublic function redeemer(): ?Model;\n```\n\n### Calculations\n\n```php\n$coupon = Coupon::create([\n    'code'  =\u003e 'my-generated-coupon-code-to-use',\n    'type'  =\u003e CouponContract::TYPE_PERCENTAGE, // 'percentage'\n    'value' =\u003e '10', // \u003c-- %10\n]);\n\n$coupon-\u003ecalc(using: 300); // 270.00\n```\n\nThe package supports three types of item cost calculations:\n- `subtraction` - subtracts the given value from the value defined in the coupon model;\n- `percentage` - subtracts the given value by the percentage defined in the coupon model;\n- `fixed` - completely ignores the given value and takes the coupon model value instead.\n\nNote: you can find constants for coupon types in the [`CouponContract`](https://github.com/michael-rubel/laravel-couponables/blob/main/src/Models/Contracts/CouponContract.php)\n\n### Listeners\nIf you go event-driven, you can handle package events:\n- [CouponVerified](https://github.com/michael-rubel/laravel-couponables/blob/main/src/Events/CouponVerified.php)\n- [CouponRedeemed](https://github.com/michael-rubel/laravel-couponables/blob/main/src/Events/CouponRedeemed.php)\n- [CouponExpired](https://github.com/michael-rubel/laravel-couponables/blob/main/src/Events/CouponExpired.php)\n- [CouponIsOverLimit](https://github.com/michael-rubel/laravel-couponables/blob/main/src/Events/CouponIsOverLimit.php)\n- [CouponIsOverQuantity](https://github.com/michael-rubel/laravel-couponables/blob/main/src/Events/CouponIsOverQuantity.php)\n- [NotAllowedToRedeem](https://github.com/michael-rubel/laravel-couponables/blob/main/src/Events/NotAllowedToRedeem.php)\n\n---\n\n### Extending package functionality\nTraits [DefinesColumns](https://github.com/michael-rubel/laravel-couponables/blob/main/src/Models/Traits/DefinesColumns.php) and [DefinesPivotColumns](https://github.com/michael-rubel/laravel-couponables/blob/main/src/Models/Traits/DefinesPivotColumns.php) contain the methods that define column names to use by the package, so you can use inheritance to override them.\n\nIf you need to override the entire classes, use the [config values](https://github.com/michael-rubel/laravel-couponables/blob/main/config/couponables.php) or [container bindings](https://github.com/michael-rubel/laravel-couponables/blob/main/src/CouponableServiceProvider.php). All the classes in the package have their own contract (interface), so you're free to modify it as you wish.\n\n`CouponService` has the `Macroable` trait, This way you can inject the methods to interact with the service without overriding anything.\n\n\n## Contributing\nIf you see any ways we can improve the package, PRs are welcome. But remember to write tests for your use cases.\n\n## Testing\n```bash\ncomposer test\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichael-rubel%2Flaravel-couponables","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichael-rubel%2Flaravel-couponables","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichael-rubel%2Flaravel-couponables/lists"}