Przeglądaj źródła

修改礼品卡功能

llp 2 tygodni temu
rodzic
commit
e455cc1350

+ 1 - 0
composer.json

@@ -20,6 +20,7 @@
         "api-platform/graphql": "v4.2.3",
         "api-platform/graphql": "v4.2.3",
         "api-platform/laravel": "v4.1.25",
         "api-platform/laravel": "v4.1.25",
         "astrotomic/laravel-translatable": "^11.0.0",
         "astrotomic/laravel-translatable": "^11.0.0",
+        "bagisto/bagisto-package-generator": "^2.1",
         "bagisto/image-cache": "dev-master",
         "bagisto/image-cache": "dev-master",
         "barryvdh/laravel-dompdf": "^2.0.0",
         "barryvdh/laravel-dompdf": "^2.0.0",
         "diglactic/laravel-breadcrumbs": "^9.0",
         "diglactic/laravel-breadcrumbs": "^9.0",

+ 53 - 2
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
         "This file is @generated automatically"
     ],
     ],
-    "content-hash": "5b4ecb6b96b299dce930ca9b3090436b",
+    "content-hash": "0d6a2d88fb8413fb7204b29f3496d0f1",
     "packages": [
     "packages": [
         {
         {
             "name": "api-platform/documentation",
             "name": "api-platform/documentation",
@@ -1160,6 +1160,57 @@
             ],
             ],
             "time": "2024-08-28T09:20:26+00:00"
             "time": "2024-08-28T09:20:26+00:00"
         },
         },
+        {
+            "name": "bagisto/bagisto-package-generator",
+            "version": "v2.1.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/bagisto/bagisto-package-generator.git",
+                "reference": "e6e9639c366f31f615160ff9c91bc78528aa8061"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/bagisto/bagisto-package-generator/zipball/e6e9639c366f31f615160ff9c91bc78528aa8061",
+                "reference": "e6e9639c366f31f615160ff9c91bc78528aa8061",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "type": "library",
+            "extra": {
+                "laravel": {
+                    "aliases": [],
+                    "providers": [
+                        "Webkul\\PackageGenerator\\Providers\\PackageGeneratorServiceProvider"
+                    ]
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Webkul\\PackageGenerator\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jitendra Singh",
+                    "email": "jitendra@webkul.com"
+                }
+            ],
+            "description": "Bagisto Package Generator",
+            "support": {
+                "issues": "https://github.com/bagisto/bagisto-package-generator/issues",
+                "source": "https://github.com/bagisto/bagisto-package-generator/tree/v2.1.2"
+            },
+            "time": "2025-09-02T16:15:30+00:00"
+        },
         {
         {
             "name": "bagisto/image-cache",
             "name": "bagisto/image-cache",
             "version": "dev-master",
             "version": "dev-master",
@@ -15963,5 +16014,5 @@
         "ext-tokenizer": "*"
         "ext-tokenizer": "*"
     },
     },
     "platform-dev": [],
     "platform-dev": [],
-    "plugin-api-version": "2.3.0"
+    "plugin-api-version": "2.6.0"
 }
 }

+ 7 - 0
packages/Longyi/Gift/src/Contracts/GiftCardUsageLog.php

@@ -0,0 +1,7 @@
+<?php
+
+namespace Longyi\Gift\Contracts;
+
+interface GiftCardUsageLog
+{
+}

+ 0 - 1
packages/Longyi/Gift/src/Database/Migrations/2026_04_01_230815_add_giftcard_fields_to_cart_table.php

@@ -14,7 +14,6 @@ return new class extends Migration
         Schema::table('cart', function (Blueprint $table) {
         Schema::table('cart', function (Blueprint $table) {
             $table->string('giftcard_number', 191)->nullable()->after('applied_cart_rule_ids');
             $table->string('giftcard_number', 191)->nullable()->after('applied_cart_rule_ids');
             $table->decimal('giftcard_amount', 10, 2)->nullable()->after('giftcard_number');
             $table->decimal('giftcard_amount', 10, 2)->nullable()->after('giftcard_number');
-            $table->decimal('remaining_giftcard_amount', 10, 2)->default(0.00)->after('giftcard_amount');
         });
         });
     }
     }
 
 

+ 55 - 0
packages/Longyi/Gift/src/Database/Migrations/2026_04_10_012025_create_gift_card_usage_logs_table.php

@@ -0,0 +1,55 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::create('gift_card_usage_logs', function (Blueprint $table) {
+            $table->id();
+
+            // 礼品卡信息
+            $table->string('giftcard_number', 191)->index()->comment('礼品卡号');
+            $table->foreignId('customer_id')->nullable()->index()->comment('用户ID');
+
+            // 关联订单
+            $table->foreignId('order_id')->nullable()->index()->comment('订单ID');
+            $table->string('order_increment_id', 50)->nullable()->index()->comment('订单编号');
+
+            // 金额信息
+            $table->decimal('used_amount', 10, 2)->default(0)->comment('本次使用金额');
+            $table->decimal('balance_before', 10, 2)->default(0)->comment('使用前余额');
+            $table->decimal('balance_after', 10, 2)->default(0)->comment('使用后余额');
+
+            // 操作类型
+            $table->tinyInteger('action_type')->default(1)->comment('操作类型:1-使用 2-退款 3-手动调整');
+
+            // 状态
+            $table->string('status', 20)->default('completed')->comment('状态:completed, pending, cancelled, refunded');
+
+            // 备注
+            $table->text('notes')->nullable()->comment('备注说明');
+
+            // 时间戳
+            $table->timestamps();
+
+            // 索引
+            $table->index(['giftcard_number', 'created_at']);
+            $table->index(['order_id', 'created_at']);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('gift_card_usage_logs');
+    }
+};

+ 69 - 0
packages/Longyi/Gift/src/Listeners/OrderCancelHandler.php

@@ -0,0 +1,69 @@
+<?php
+
+namespace Longyi\Gift\Listeners;
+
+use Longyi\Gift\Models\GiftCards;
+use Illuminate\Support\Facades\Log;
+use Longyi\Gift\Models\GiftCardUsageLog;
+
+class OrderCancelHandler
+{
+    /**
+     * Handle order cancel event.
+     *
+     * @param  \Webkul\Sales\Contracts\Order  $order
+     * @return void
+     */
+    public function afterCancelOrder($order)
+    {
+        if (!$order) {
+            return;
+        }
+
+        // 检查订单是否使用了礼品卡
+        if (!$order->giftcard_number || !$order->giftcard_amount || $order->giftcard_amount <= 0) {
+            return;
+        }
+
+        $giftCardNumber = $order->giftcard_number;
+        $refundAmount = $order->giftcard_amount;
+
+        // 查找礼品卡
+        $giftCard = GiftCards::where('giftcard_number', $giftCardNumber)->first();
+
+        if (!$giftCard) {
+            return;
+        }
+        // 记录退款前余额
+        $balanceBefore = $giftCard->remaining_giftcard_amount;
+        // 恢复礼品卡余额
+        $giftCard->used_giftcard_amount = max(0, $giftCard->used_giftcard_amount - $refundAmount);
+        $giftCard->remaining_giftcard_amount += $refundAmount;
+
+        // 恢复状态为未使用
+        if ($giftCard->remaining_giftcard_amount > 0) {
+            $giftCard->giftcard_status = 1; // 未使用
+        }
+
+        $giftCard->save();
+        // 记录退款日志
+        GiftCardUsageLog::create([
+            'giftcard_number' => $giftCardNumber,
+            'customer_id' => $giftCard->customer_id,
+            'order_id' => $order->id,
+            'order_increment_id' => $order->increment_id,
+            'used_amount' => $refundAmount,
+            'balance_before' => $balanceBefore,
+            'balance_after' => $giftCard->remaining_giftcard_amount,
+            'action_type' => GiftCardUsageLog::ACTION_REFUND,
+            'status' => 'completed',
+            'notes' => "订单 #{$order->increment_id} 取消,礼品卡余额已恢复",
+        ]);
+        Log::channel('giftcard')->info('订单已取消,礼品卡余额已恢复', [
+            'order_id' => $order->id,
+            'giftcard_number' => $giftCardNumber,
+            'refunded_amount' => $refundAmount,
+            'remaining_amount' => $giftCard->remaining_giftcard_amount,
+        ]);
+    }
+}

+ 41 - 8
packages/Longyi/Gift/src/Listeners/OrderPlacedHandler.php

@@ -3,6 +3,8 @@
 namespace Longyi\Gift\Listeners;
 namespace Longyi\Gift\Listeners;
 
 
 use Longyi\Gift\Models\GiftCards;
 use Longyi\Gift\Models\GiftCards;
+use Longyi\Gift\Models\GiftCardUsageLog;
+use Illuminate\Support\Facades\Log;
 
 
 class OrderPlacedHandler
 class OrderPlacedHandler
 {
 {
@@ -17,20 +19,51 @@ class OrderPlacedHandler
         if (!$order || !$order->cart) {
         if (!$order || !$order->cart) {
             return;
             return;
         }
         }
-
         $cart = $order->cart;
         $cart = $order->cart;
-
-        if (!$cart->giftcard_number) {
+        // 检查订单是否使用了礼品卡
+        if (!$cart->giftcard_number || !$cart->giftcard_amount || $cart->giftcard_amount <= 0) {
             return;
             return;
         }
         }
-
         $giftCardNumber = $cart->giftcard_number;
         $giftCardNumber = $cart->giftcard_number;
+        $usedAmount = $cart->giftcard_amount;
 
 
+        // 查找礼品卡
         $giftCard = GiftCards::where('giftcard_number', $giftCardNumber)->first();
         $giftCard = GiftCards::where('giftcard_number', $giftCardNumber)->first();
-
-        if ($giftCard) {
-            $giftCard->giftcard_status = 2;
-            $giftCard->save();
+        if (!$giftCard) {
+            return;
+        }
+        // 检查余额是否足够
+        if ($giftCard->remaining_giftcard_amount < $usedAmount) {
+            return;
+        }
+        // 记录使用前余额
+        $balanceBefore = $giftCard->remaining_giftcard_amount;
+        // 扣除礼品卡余额
+        $giftCard->used_giftcard_amount += $usedAmount;
+        $giftCard->remaining_giftcard_amount -= $usedAmount;
+        // 如果余额为0,标记为已使用
+        if ($giftCard->remaining_giftcard_amount <= 0) {
+            $giftCard->giftcard_status = 2; // 已使用
         }
         }
+        $giftCard->save();
+        // 记录使用日志
+        GiftCardUsageLog::create([
+            'giftcard_number' => $giftCardNumber,
+            'customer_id' => $giftCard->customer_id,
+            'order_id' => $order->id,
+            'order_increment_id' => $order->increment_id,
+            'used_amount' => $usedAmount,
+            'balance_before' => $balanceBefore,
+            'balance_after' => $giftCard->remaining_giftcard_amount,
+            'action_type' => GiftCardUsageLog::ACTION_USE,
+            'status' => 'completed',
+            'notes' => "订单 #{$order->increment_id} 使用礼品卡",
+        ]);
+        \Log::channel('giftcard')->info('订单创建成功,礼品卡余额已扣除', [
+            'order_id' => $order->id,
+            'giftcard_number' => $giftCardNumber,
+            'used_amount' => $usedAmount,
+            'remaining_amount' => $giftCard->remaining_giftcard_amount,
+        ]);
     }
     }
 }
 }

+ 92 - 0
packages/Longyi/Gift/src/Models/GiftCardUsageLog.php

@@ -0,0 +1,92 @@
+<?php
+
+namespace Longyi\Gift\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+
+class GiftCardUsageLog extends Model
+{
+    use HasFactory;
+
+    protected $table = 'gift_card_usage_logs';
+
+    protected $fillable = [
+        'giftcard_number',
+        'customer_id',
+        'order_id',
+        'order_increment_id',
+        'used_amount',
+        'balance_before',
+        'balance_after',
+        'action_type',
+        'status',
+        'notes',
+    ];
+
+    protected $casts = [
+        'used_amount' => 'decimal:2',
+        'balance_before' => 'decimal:2',
+        'balance_after' => 'decimal:2',
+        'customer_id' => 'integer',
+        'order_id' => 'integer',
+        'action_type' => 'integer',
+    ];
+
+    // 操作类型常量
+    const ACTION_USE = 1;      // 使用
+    const ACTION_REFUND = 2;   // 退款
+    const ACTION_ADJUST = 3;   // 手动调整
+
+    /**
+     * 获取关联的礼品卡
+     */
+    public function giftCard(): BelongsTo
+    {
+        return $this->belongsTo(GiftCards::class, 'giftcard_number', 'giftcard_number');
+    }
+
+    /**
+     * 获取关联的订单
+     */
+    public function order(): BelongsTo
+    {
+        return $this->belongsTo(\Webkul\Sales\Models\Order::class, 'order_id');
+    }
+
+    /**
+     * 获取关联的客户
+     */
+    public function customer(): BelongsTo
+    {
+        return $this->belongsTo(\Webkul\Customer\Models\Customer::class, 'customer_id');
+    }
+
+    /**
+     * 获取操作类型文本
+     */
+    public function getActionTypeTextAttribute(): string
+    {
+        return match($this->action_type) {
+            self::ACTION_USE => '使用',
+            self::ACTION_REFUND => '退款',
+            self::ACTION_ADJUST => '手动调整',
+            default => '未知',
+        };
+    }
+
+    /**
+     * 获取状态文本
+     */
+    public function getStatusTextAttribute(): string
+    {
+        return match($this->status) {
+            'completed' => '已完成',
+            'pending' => '待处理',
+            'cancelled' => '已取消',
+            'refunded' => '已退款',
+            default => $this->status,
+        };
+    }
+}

+ 9 - 0
packages/Longyi/Gift/src/Models/GiftCardUsageLogProxy.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace Longyi\Gift\Models;
+
+use Konekt\Concord\Proxies\ModelProxy;
+
+class GiftCardUsageLogProxy extends ModelProxy
+{
+}

+ 16 - 59
packages/Longyi/Gift/src/Models/GiftCards.php

@@ -31,86 +31,43 @@ class GiftCards extends Model implements GiftCardsContract
         'customer_id' => 'integer',
         'customer_id' => 'integer',
         'expirationdate' => 'date',
         'expirationdate' => 'date',
     ];
     ];
-    protected static function booted()
-    {
-        // 监听保存后事件
-        static::saved(function ($giftCard) {
-            // 在这里添加你的逻辑
-            // 例如:记录日志、发送通知等
-            $original = $giftCard->getOriginal();
-            $amountStr = '';
-            $amount = 0;
-            if (isset($original['remaining_giftcard_amount'])) {
-                $amount = $original['remaining_giftcard_amount'] - $giftCard->remaining_giftcard_amount;
-            }
-            if ($amount > 0) {
-                $amountStr .= '-' . abs($amount);
-            } else {
-                $amountStr .= '+' . abs($amount);
-            }
-            \Log::channel('giftcard')->info('礼品卡已更新', [
-                'giftcard_number' => $giftCard->giftcard_number,
-                'used_amount' => $amountStr,
-                'remaining_amount' => $giftCard->remaining_giftcard_amount,
-            ]);
-        });
-    }
 
 
     public static function setGiftCardCode($giftcard)
     public static function setGiftCardCode($giftcard)
     {
     {
-        $customerId = auth()->user()->id;
         if (!$giftcard) {
         if (!$giftcard) {
             return false;
             return false;
         }
         }
         $cart = cart()->getCart();
         $cart = cart()->getCart();
         $cart->giftcard_number = $giftcard->giftcard_number;
         $cart->giftcard_number = $giftcard->giftcard_number;
-        $cart->giftcard_amount = $giftcard->remaining_giftcard_amount;
-
-        $giftCards = static::where('giftcard_number', $giftcard->giftcard_number)->where('customer_id', $customerId)->first();
-
-        if ($giftCards) {
-            if ($cart->grand_total <= $giftcard->remaining_giftcard_amount) {
-                $cart->giftcard_amount = $cart->grand_total;
-                $giftCards->used_giftcard_amount += $cart->grand_total;
-                $giftCards->remaining_giftcard_amount -= $cart->grand_total;
-                $cart->remaining_giftcard_amount = $giftCards->remaining_giftcard_amount;
-                $cart->grand_total = 0;
-            } else {
-                $giftCards->used_giftcard_amount += $giftcard->remaining_giftcard_amount;
-                $giftCards->remaining_giftcard_amount = 0;
-                $cart->remaining_giftcard_amount = 0;
-                $cart->grand_total -= $giftcard->remaining_giftcard_amount;
-            }
-
-            $giftCards->save();
+        // 计算可以使用的礼品卡金额
+        if ($cart->grand_total <= $giftcard->remaining_giftcard_amount) {
+            // 礼品卡余额充足,使用全部订单金额
+            $cart->giftcard_amount = $cart->grand_total;
+        } else {
+            // 礼品卡余额不足,使用全部余额
+            $cart->giftcard_amount = $giftcard->remaining_giftcard_amount;
         }
         }
-
+        // 更新购物车总额
+        $cart->grand_total = max(0, $cart->grand_total - $cart->giftcard_amount);
+        $cart->base_grand_total = max(0, $cart->base_grand_total - $cart->giftcard_amount);
         $cart->save();
         $cart->save();
-
         return true;
         return true;
     }
     }
 
 
     public static function removeGiftCardCode()
     public static function removeGiftCardCode()
     {
     {
         $cart = cart()->getCart();
         $cart = cart()->getCart();
-        $giftCardNumber = $cart->giftcard_number;
-        $giftcardAmount = $cart->giftcard_amount;
+        $giftcardAmount = $cart->giftcard_amount ?? 0;
 
 
+        // 清除购物车中的礼品卡标记
         $cart->giftcard_number = null;
         $cart->giftcard_number = null;
         $cart->giftcard_amount = null;
         $cart->giftcard_amount = null;
-        $cart->remaining_giftcard_amount = null;
-
-        $cart->save();
 
 
-        if ($giftCardNumber) {
-            $giftCards = static::where('giftcard_number', $giftCardNumber)->first();
+        // 恢复购物车总额
+        $cart->grand_total += $giftcardAmount;
+        $cart->base_grand_total += $giftcardAmount;
 
 
-            if ($giftCards) {
-                $giftCards->used_giftcard_amount -= $giftcardAmount;
-                $giftCards->remaining_giftcard_amount += $giftcardAmount;
-                $giftCards->save();
-            }
-        }
+        $cart->save();
 
 
         return true;
         return true;
     }
     }

+ 1 - 0
packages/Longyi/Gift/src/Providers/EventServiceProvider.php

@@ -23,5 +23,6 @@ class EventServiceProvider extends ServiceProvider
         Event::listen('bagisto.shop.customers.account.orders.view.information.discount.after', 'Longyi\Gift\Listeners\OrderViewHandler@renderGiftCardInfo');
         Event::listen('bagisto.shop.customers.account.orders.view.information.discount.after', 'Longyi\Gift\Listeners\OrderViewHandler@renderGiftCardInfo');
         Event::listen('bagisto.admin.sales.order.view.discount.after', 'Longyi\Gift\Listeners\OrderViewHandler@renderGiftCardInfo');
         Event::listen('bagisto.admin.sales.order.view.discount.after', 'Longyi\Gift\Listeners\OrderViewHandler@renderGiftCardInfo');
         Event::listen('sales.invoice.save.after', 'Longyi\Gift\Listeners\InvoiceHandler@saveAfter');
         Event::listen('sales.invoice.save.after', 'Longyi\Gift\Listeners\InvoiceHandler@saveAfter');
+        Event::listen('sales.order.cancel.after', 'Longyi\Gift\Listeners\OrderCancelHandler@afterCancelOrder');
     }
     }
 }
 }