safeMood/discountify

Laravel 动态折扣包,支持自定义条件。

1.5.0 2024-04-07 09:44 UTC

This package is auto-updated.

Last update: 2024-09-29 05:36:40 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Discountify 是一个为管理具有自定义条件的动态折扣而设计的 Laravel 包。它允许您创建灵活且强大的折扣策略,轻松定义条件并将基于百分比的折扣应用于电子商务应用程序以增强功能。

安装

您可以通过 composer 安装此包

composer require safemood/discountify

您可以使用以下命令发布配置文件

php artisan vendor:publish --tag="discountify-config"

这是已发布的配置文件的内容

// config/discountify.php
return [
    'condition_namespace' => 'App\\Conditions',
    'condition_path' => app_path('Conditions'),
    'fields' => [
        'price' => 'price',
        'quantity' => 'quantity',
    ],
    'global_discount' => 0,
    'global_tax_rate' => 0,
    'fire_events' => env('DISCOUNTIFY_FIRE_EVENTS', true)
];

用法

定义条件

use Illuminate\Support\ServiceProvider;
use Safemood\Discountify\Facades\Condition;
use Carbon\Carbon;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        // If items are more than 2, apply a 10% discount.
        Condition::define('more_than_2_products_10', fn (array $items) => count($items) > 2, 10)
            // If the date is within a 7-day interval starting March 1, 2024, apply a 15% discount.
            ->add([
                [
                    'slug' => 'promo_early_spring_sale_2024',
                    'condition' => fn ($items) => now()->between(
                        Carbon::createFromDate(2024, 3, 1),
                        Carbon::createFromDate(2024, 3, 15)->addDays(7)
                    ),
                    'discount' => 15,
                ],
                // If 'special' items are in the cart, apply a 10% discount.
                [
                    'slug' => 'special_type_product_10',
                    'condition' => fn ($items) => in_array('special', array_column($items, 'type')),
                    'discount' => 10,
                ],
            ])
            // If the user has a renewal, apply a 10% discount.
            ->defineIf('client_has_renewal_10', auth()->user()->hasRenewal(), 10);
    }
}

设置商品、全局折扣和税率

$items = [
        ['id' => '1', 'quantity' => 2, 'price' => 50],
        ['id' => '2', 'quantity' => 1, 'price' => 100, 'type' => 'special'],
    ];

// Set the items in the cart
Discountify::setItems($items)

// Set a global discount for all items in the cart
    ->setGlobalDiscount(15)

// Set a global tax rate for all items in the cart
    ->setGlobalTaxRate(19);

计算总额

// Calculate the total amount considering the set conditions and discounts

$total = Discountify::total();

// Calculate total amount with detailed breakdown
// (array contains total, subtotal, tax amount, total after discount, savings, tax rate, discount rate)
$total = Discountify::totalDetailed();

// Calculate the total amount with the applied global discount

$totalWithDiscount = Discountify::totalWithDiscount();

// Calculate the total amount with taxes applied based on the set global tax rate

$totalWithTaxes = Discountify::tax();

// Calculate the total tax amount based on the given tax rate (19 in this case) (before discounts)

$taxAmount = Discountify::taxAmount(19);

// Calculate tax amount with tax applied after discounts

$taxAmount = Discountify::calculateTaxAmount(19, true);


// Calculate the amount saved
$savings = Discountify::savings();

动态字段名称

// Set custom field names through configuration
return [
    'condition_namespace' => 'App\\Conditions',
    'condition_path' => app_path('Conditions'),
    'fields' => [
        'price' => 'price',
        'quantity' => 'quantity',
    ],
    'global_discount' => 0,
    'global_tax_rate' => 0,
    'fire_events' => env('DISCOUNTIFY_FIRE_EVENTS', true)
];

// Alternatively, set dynamic field names on the fly
$items = [
    ['id' => 'item1', 'qty' => 2, 'amount' => 20],
    ['id' => 'item2', 'qty' => 1, 'amount' => 20],
];

$discountify->setFields([
    'price' => 'amount',
    'quantity' => 'qty',
])->setItems($items);

$totalWithDiscount = $discountify->totalWithDiscount(50);

基于类的折扣

App\Conditions 中的类将由 Discountify 自动发现以实现无缝集成——无需配置。

  • 创建基于类的条件

要使用 discountify:condition artisan 命令创建基于类的条件,您可以运行以下命令

php artisan discountify:condition OrderTotalDiscount 
php artisan discountify:condition OrderTotalDiscount --discount=10 --slug OrderTotal
<?php

namespace App\Conditions;

use Safemood\Discountify\Contracts\ConditionInterface;

class OrderTotalDiscount implements ConditionInterface
{
    public bool $skip = true; // Set to true to skip the condition

    public string $slug = 'order_total';

    public int $discount = 10;

    public function __invoke(array $items): bool
    {
         return count($items) > 5;
    }
}
  • 命令选项

--discount (-d): 指定条件的折扣值。默认值为 0。
--slug (-s): 指定条件的别名。如果未提供,则使用条件名称作为别名。
--force (-f): 即使条件类已存在,也会创建该类。

跳过折扣条件

这将允许您根据“跳过”字段排除特定的条件。

使用 Condition::define

Condition::define('condition2', fn ($items) => false, 20, true);  // Will be skipped
  • 使用 Condition::add
Condition::add([
    ['slug' => 'condition1', 'condition' => fn ($items) => true, 'discount' => 10, 'skip' => false],  // Won't be skipped
    ['slug' => 'condition2', 'condition' => fn ($items) => false, 'discount' => 20, 'skip' => true], // Will be skipped
    ['slug' => 'condition3', 'condition' => fn ($items) => true, 'discount' => 30], // Will not be skipped (default skip is false)
]);

事件跟踪

您可以使用 Laravel 的 Event 系统监听 DiscountAppliedEventCouponAppliedEvent

确保在 discountify.php 文件中配置以下内容

// config/discountify.php
'fire_events' => env('DISCOUNTIFY_FIRE_EVENTS', true) // Toggle event dispatching
// app/Providers/EventServiceProvider.php

use Illuminate\Support\Facades\Event;
use Safemood\Discountify\Events\DiscountAppliedEvent;

public function boot(): void
{
    Event::listen(function (DiscountAppliedEvent $event) {
        // Your event handling logic here
        // Ex : Mail to customer
        // dd($event);
    });

    Event::listen(function (CouponAppliedEvent $event) { // Added
        // Your event handling logic for CouponAppliedEvent here
        // Example: Log coupon usage
        // dd($event);
    });
}

有关更多详细信息,请参阅 Laravel 事件文档

基于优惠券的折扣

基于优惠券的折扣,轻松应用和计算给定优惠券代码的折扣(百分比)。

Discountify 优惠券允许您将各种类型的优惠券应用于购物车。

周期限制优惠券

use Safemood\Discountify\Facades\Coupon;

Coupon::add([
    'code' => 'PERIODLIMITED50',
    'discount' => 50,
    'startDate' => now(),
    'endDate' => now()->addWeek(),
]);

$discountedTotal = Discountify::setItems($items)
    ->applyCoupon('TIMELIMITED50')
    ->total();

单次使用优惠券

use Safemood\Discountify\Facades\Coupon;

Coupon::add([
    'code' => 'SINGLEUSE50',
    'discount' => 50,
    'singleUse' => true,
    'startDate' => now(),
    'endDate' => now()->addWeek(),
]);

$discountedTotal = Discountify::setItems($items)
    ->applyCoupon('SINGLEUSE50')
    ->total();

受限制的用户优惠券

use Safemood\Discountify\Facades\Coupon;

Coupon::add([
    'code' => 'RESTRICTED20',
    'discount' => 20,
    'userIds' => [123, 456], // Restricted to user IDs 123 and 456
    'startDate' => now(),
    'endDate' => now()->addWeek(),
]);

$discountedTotal = Discountify::setItems($items)
    ->applyCoupon('RESTRICTED20', 123) // Applying to user ID 123
    ->total();

有限使用次数优惠券

use Safemood\Discountify\Facades\Coupon;

Coupon::add([
    'code' => 'LIMITED25',
    'discount' => 25,
    'usageLimit' => 3, // Limited to 3 uses
    'startDate' => now(),
    'endDate' => now()->addWeek(),
]);

$discountedTotal = Discountify::setItems($items)
    ->applyCoupon('LIMITED25')
    ->total();

测试

composer test

变更日志

有关最近更改的更多信息,请参阅 CHANGELOG

贡献

有关详细信息,请参阅 CONTRIBUTING

安全漏洞

请参阅我们关于如何报告安全漏洞的 安全策略

鸣谢

许可证

MIT 许可证(MIT)。有关更多信息,请参阅 许可证文件