llp 3 godzin temu
rodzic
commit
d9b07e3d3a

+ 23 - 8
packages/Longyi/FreeGift/src/Services/GiftProcessor.php

@@ -302,8 +302,10 @@ class GiftProcessor
 
             $cartItem = $this->writeGiftCartItem($cart, $product, $gift, $qty, $gift->getCartItemId());
 
+            // reserved 必须以行上的真实总量为准:writeGiftCartItem 传进去的是差额,
+            // 加完之后行数量才是「已经占用」的量
             $gift->setCartItemId((int) $cartItem->id)
-                ->setReservedQty($qty);
+                ->setReservedQty((float) $cartItem->quantity);
         }
     }
 
@@ -373,7 +375,7 @@ class GiftProcessor
 
         $this->giftItemRepository->update([
             'cart_item_id'    => $cartItem->id,
-            'reserved_qty'    => $qty,
+            'reserved_qty'    => (float) $cartItem->quantity,
             'is_item_deleted' => 0,
         ], $row->id);
 
@@ -395,6 +397,24 @@ class GiftProcessor
      */
     protected function writeGiftCartItem($cart, $product, GiftItem $gift, float $qty, $cartItemId = null)
     {
+        /*
+         * $qty 的语义是「本次新增的数量」,不是「这一行应有的总数量」。
+         *
+         * 已存在赠品行时必须在行上累加:购物车金额增长会让名额从 1 变 2,
+         * 自动加购传进来的就是差额 1,若直接覆盖 quantity,行永远是 1,
+         * 第二个赠品永远补不上(free_gift_items 会一直停在 allowed=2/reserved=1)。
+         */
+        if ($cartItemId) {
+            $existing = $this->cartItemRepository->find($cartItemId);
+
+            // 指针悬空(赠品行被删过 / 购物车被重建)→ 退回新建
+            if ($existing && (int) $existing->cart_id === (int) $cart->id) {
+                $qty = (float) $existing->quantity + $qty;
+            } else {
+                $cartItemId = null;
+            }
+        }
+
         $originalPrice = $this->getOriginalPrice($product, $qty);
 
         // 赠品实付单价:原价 - 折扣,并以 minimal_items_price 兜底
@@ -430,12 +450,7 @@ class GiftProcessor
         ];
 
         if ($cartItemId) {
-            $updated = $this->cartItemRepository->update($payload, $cartItemId);
-
-            // 指针可能悬空(赠品行被删过 / 购物车被重建),退回新建
-            if ($updated && (int) $updated->cart_id === (int) $cart->id) {
-                return $updated;
-            }
+            return $this->cartItemRepository->update($payload, $cartItemId);
         }
 
         return $this->cartItemRepository->create(array_merge($payload, [