gorden 7 сар өмнө
parent
commit
78bce66978

+ 4 - 3
app/admin/controller/coupon/CouponDetailController.php

@@ -211,13 +211,13 @@ class CouponDetailController extends Curd
 
         $details = CouponDetail::with([
             'coupon' => function ($query) {
-                $query->select('coupon_id', 'coupon_name', 'coupon_classify', 'coupon_value', 'coupon_minimum_limit');
+                $query->select('coupon_id', 'coupon_name', 'coupon_classify', 'coupon_value', 'coupon_category', 'coupon_minimum_limit');
             }
         ])
             ->whereIn('join_detail_coupon_id', $couponIds)
             ->where('join_coupon_detail_member_id', $memberId)
             ->where('coupon_detail_status', 'ACTIVED')
-            ->select('join_detail_coupon_id', 'join_coupon_detail_member_id')
+            ->selectRaw('join_detail_coupon_id,join_coupon_detail_member_id,COUNT(*) as count')
             ->groupBy('join_detail_coupon_id', 'join_coupon_detail_member_id')
             ->get()
             ->toArray();
@@ -226,11 +226,12 @@ class CouponDetailController extends Curd
             if (empty($detail['coupon'])) {
                 continue;
             }
-            $classify = CouponService::couponClassifyInfo($detail['coupon']['coupon_classify'], $detail['coupon']['coupon_value'], $detail['coupon']['coupon_minimum_limit']);
+            $classify = CouponService::couponClassifyInfo($detail['coupon']['coupon_classify'], $detail['coupon']['coupon_category'], $detail['coupon']['coupon_value'], $detail['coupon']['coupon_minimum_limit']);
             $data[] = [
                 'coupon_id' => $detail['coupon']['coupon_id'],
                 'coupon_name' => $detail['coupon']['coupon_name'],
                 'classify' => $classify,
+                'count' => $detail['count'],
                 'coupon_classify' => $detail['coupon']['coupon_classify'],
                 'coupon_value' => $detail['coupon']['coupon_value'] ?? '',
                 'coupon_minimum_limit' => $detail['coupon']['coupon_minimum_limit'] ?? '',

+ 83 - 16
app/admin/controller/order/WholeController.php

@@ -2,6 +2,7 @@
 
 namespace app\admin\controller\order;
 
+use app\admin\service\coupon\CouponService;
 use app\admin\service\member\MemberService;
 use app\admin\service\order\OrderService;
 use app\admin\validate\coupon\CouponValidate;
@@ -502,10 +503,17 @@ class WholeController extends Curd
             $orderDiscountJson = json_decode($order->order_discount_json, true);
             foreach ($orderDiscountJson as $discountItem) {
                 if (!empty($discountItem['coupon_id'])) {
-                    $discount['coupon_name'] .= Coupon::where('coupon_id', $discountItem['coupon_id'])->value('coupon_name') . ', ';
+                    $coupon = Coupon::where('coupon_id', $discountItem['coupon_id'])
+                        ->select('coupon_name','coupon_classify','coupon_category','coupon_value','coupon_minimum_limit')
+                        ->first();
+                    if (!$coupon){
+                        continue;
+                    }
+                    $classify = CouponService::couponClassifyInfo($coupon->coupon_classify,$coupon->coupon_category,$coupon->coupon_value,$coupon->coupon_minimum_limit);
+                    $discount['coupon_name'] .=  $coupon->coupon_classify.':'.$coupon->coupon_name.'(优惠¥'.$discountItem['coupon_value']. '), ';
                 }
                 if (empty($discountItem['coupon_id']) && !empty($discountItem['coupon_classify'])) {
-                    $discount['classify'] .= $discountItem['coupon_classify'] . '(' . round($discountItem['coupon_value'], 2) . '), ';
+                    $discount['classify'] .= $discountItem['coupon_classify'] . '(' . round($discountItem['coupon_value'], 2) . '), ';
                 }
                 if (!empty($discountItem['coupon_value'])) {
                     $discount['value'] += $discountItem['coupon_value'];
@@ -773,9 +781,24 @@ class WholeController extends Curd
         }
         Db::beginTransaction();
         try {
+            // 使用优惠券
+            $couponUseJson = [];
+            if (!empty($params['join_order_member_id']) && !empty($params['preferential'])) {
+                $couponResult = OrderService::payUseCoupon($params['join_order_member_id'], $params['goodsContentList'], $params['preferential'], $params['order_amount_total']);
+                if ($couponResult['pay_amount'] != $params['order_amount_pay']) {
+                    throw new BusinessException("计算优惠后,实付金额错误!");
+                }
+                // 组装优惠券使用数据,存主表优惠里
+                $couponUseJson = $couponResult['use_coupon_json'];
+                if (!empty($order->order_discount_json)) {
+                    $orderDiscountJson = json_decode($order->order_discount_json, true);
+                    if (!empty($orderDiscountJson)) {
+                        $couponUseJson = json_encode(array_merge($orderDiscountJson, json_decode($couponUseJson, true)));
+                    }
+                }
+            }
             // 存储优惠信息
-            $order->order_discount_json = json_encode($this->discountRecord($order->order_discount_json, $params));
-
+            $order->order_discount_json = json_encode($this->discountRecord($couponUseJson, $params));
             // 组合支付时,付款码应收金额
             $qrcodePayAmount = 0;
             if ($params['pay_category'] == 'OFFLINE' || $params['pay_category'] == 'MONEY') {
@@ -1209,18 +1232,18 @@ class WholeController extends Curd
             $json = json_decode($orderDiscountJson, true);
         }
         try {
-            if (!empty($params['preferential']) && $params['preferential'] == 'wipe') {
+            if (!empty($params['preferential']) && in_array('wipe', $params['preferential'])) {
                 if (intval($params['order_amount_total'] / 10) * 10 != $params['order_amount_pay']) {
                     throw new BusinessException("抹零后实际支付金额错误");
                 }
                 $params['order_discount_amount'] = $params['order_amount_total'] - $params['order_amount_pay'];
                 $couponClassifyDesc = $couponClassify = '抹零';
-            } else if (!empty($params['preferential']) && $params['preferential'] == 'custom') {
+            } elseif (!empty($params['preferential']) && in_array('custom', $params['preferential'])) {
                 if (sprintf("%.2f", $params['order_amount_total'] - $params['order_discount_amount']) != sprintf("%.2f", $params['order_amount_pay'])) {
                     throw new BusinessException("餐厅前台优惠后实际支付金额错误");
                 }
                 $couponClassifyDesc = $couponClassify = '餐厅前台优惠';
-            } else if (!empty($params['preferential']) && intval($params['preferential']) < 100 && intval($params['preferential']) >= 50) {
+            } else if (!empty($params['preferential']) && intval($params['preferential'][0]) < 100 && intval($params['preferential'][0]) >= 50) {
                 if (($params['order_amount_total'] * intval($params['preferential'])) / 100 !== $params['order_amount_pay']) {
                     throw new BusinessException("折扣后实际支付金额错误");
                 }
@@ -1313,9 +1336,24 @@ class WholeController extends Curd
         }
         $payDetail = PayDetail::where('join_pay_order_id', $order->order_groupby)->first();
         Db::beginTransaction();
-        try {
+        try {// 使用优惠券
+            $couponUseJson = [];
+            if (!empty($params['join_order_member_id']) && !empty($params['preferential'])) {
+                $couponResult = OrderService::payUseCoupon($params['join_order_member_id'], $params['goodsContentList'], $params['preferential'], $params['order_amount_total']);
+                if ($couponResult['pay_amount'] != $params['order_amount_pay']) {
+                    throw new BusinessException("计算优惠后,实付金额错误!");
+                }
+                // 组装优惠券使用数据,存主表优惠里
+                $couponUseJson = $couponResult['use_coupon_json'];
+                if (!empty($order->order_discount_json)) {
+                    $orderDiscountJson = json_decode($order->order_discount_json, true);
+                    if (!empty($orderDiscountJson)) {
+                        $couponUseJson = json_encode(array_merge($orderDiscountJson, json_decode($couponUseJson, true)));
+                    }
+                }
+            }
             // 存储优惠信息
-            $order->order_discount_json = json_encode($this->discountRecord($order->order_discount_json, $params));
+            $order->order_discount_json = json_encode($this->discountRecord($couponUseJson, $params));
             $orderAmountPay = $params['order_amount_pay'];
             $constituteList = array_column($params['pay_category_constitute_list'], 'amount', 'category');// 验证金额
             $constituteAmount = 0;
@@ -1709,8 +1747,18 @@ class WholeController extends Curd
         $params['goods_classify'] = $goodsClassifys[0];
         Db::beginTransaction();
         try {
+            // 使用优惠券
+            $couponUseJson = [];
+            if (!empty($params['join_order_member_id']) && !empty($params['preferential'])) {
+                $couponResult = OrderService::payUseCoupon($params['join_order_member_id'], $params['goodsContentList'], $params['preferential'], $params['order_amount_total']);
+                if ($couponResult['pay_amount'] != $params['order_amount_pay']) {
+                    throw new BusinessException("计算优惠后,实付金额错误!");
+                }
+                // 组装优惠券使用数据,存主表优惠里
+                $couponUseJson = $couponResult['use_coupon_json'];
+            }
             // 存储优惠信息
-            $params['order_discount_json'] = json_encode($this->discountRecord([], $params));
+            $params['order_discount_json'] = json_encode($this->discountRecord($couponUseJson, $params));
             // 验证库存
             foreach ($params['goodsContentList'] as $goods) {
                 // 减库存,规格和总库存
@@ -2279,8 +2327,18 @@ class WholeController extends Curd
 
         Db::beginTransaction();
         try {
+            // 使用优惠券
+            $couponUseJson = [];
+            if (!empty($params['join_order_member_id']) && !empty($params['preferential'])) {
+                $couponResult = OrderService::payUseCoupon($params['join_order_member_id'], $params['goodsContentList'], $params['preferential'], $params['order_amount_total']);
+                if ($couponResult['pay_amount'] != $params['order_amount_pay']) {
+                    throw new BusinessException("计算优惠后,实付金额错误!");
+                }
+                // 组装优惠券使用数据,存主表优惠里
+                $couponUseJson = $couponResult['use_coupon_json'];
+            }
             // 存储优惠信息
-            $params['order_discount_json'] = json_encode($this->discountRecord([], $params));
+            $params['order_discount_json'] = json_encode($this->discountRecord($couponUseJson, $params));
             $orderAmountPay = $params['order_amount_pay'];
             $constituteList = array_column($params['pay_category_constitute_list'], 'amount', 'category');
             // 验证金额
@@ -4273,7 +4331,7 @@ class WholeController extends Curd
         $goods = $request->post('goods', []);
         $coupon = $request->post('coupon', []);
         $payAmount = $request->post('pay_amount', 0);
-        $totalAmount = $request->post('total_amount', 0);
+//        $totalAmount = $request->post('total_amount', 0);
         $memberId = $request->post('member_id', '');
         if (empty($goods) || empty($coupon) || empty($memberId)) {
             return json_fail("参数异常");
@@ -4283,15 +4341,24 @@ class WholeController extends Curd
                 return json_fail("参数异常");
             }
         }
-        $goodsCount = count($goods);
-        $goodsIds = array_column($goods, 'goods_id');
+        $amountBalance = [
+            'pay_amount' => $payAmount,
+            'welfare_balance' => 0,
+            'cut_balance' => 0,
+        ];
         foreach ($goods as $good) {
-            $payAmount = OrderService::useCoupon($memberId, $goodsIds, $good, $goodsCount, $coupon, $payAmount, $totalAmount);
+            $result = OrderService::chooseCoupon($memberId, $goods, $good, $coupon, $amountBalance);
+            $amountBalance = [
+                'pay_amount' => $result['pay_amount'],
+                'welfare_balance' => $result['welfare_balance'],
+                'cut_balance' => $result['cut_balance'],
+            ];
         }
 
+        dump("使用过的抵扣券:", Redis::sMembers("ORDER:USE:COUPON:" . $memberId));
         Redis::del("ORDER:USE:COUPON:" . $memberId);
 
-        return json_success("success", ['pay_amount' => $payAmount]);
+        return json_success("success", ['pay_amount' => $amountBalance['pay_amount']]);
     }
 
     public static $goodsClassify = [

+ 13 - 14
app/admin/service/coupon/CouponService.php

@@ -26,35 +26,33 @@ class CouponService
         }
     }
 
-    public static function couponClassifyInfo($classify, $value, $limit)
+    public static function couponClassifyInfo($classify, $category, $value, $limit)
     {
         try {
-            switch ($classify){
+            switch ($classify) {
                 case "满减券":
-                    return "满".$limit.'减'.$value;
+                    return "满" . $limit . '减' . $value;
                     break;
                 case "立减券":
-                    return "立减".$value;
+                    return "立减" . $value;
                     break;
                 case "抵用券":
                     return "抵用券";
                     break;
                 case "折扣券":
-                    if (!empty($limit)){
-                        return "满".$limit.'打'.($value/10).'折';
-                    }else{
-                        return $value.'折';
+                    if (!empty($limit) && $category == 'NORMAL') {
+                        return "满" . $limit . '打' . ($value / 10) . '折';
+                    }else if (!empty($limit) && !empty($value) && $category == 'PIECE') {
+                        return "满" . intval($limit) . '件打' . ($value / 10) . '折';
+                    } else {
+                        return $value/10 . '折';
                     }
                     break;
                 case "赠品券":
                     return "赠品券";
                     break;
                 case "福利券":
-                    if (!empty($limit)){
-                        return "满".$limit.'抵扣'.$value;
-                    }else{
-                        return '抵扣'.$value;
-                    }
+                    return '抵扣' . $value;
                     break;
                 case "年卡":
                     return "年卡";
@@ -66,7 +64,8 @@ class CouponService
                     return "月卡";
                     break;
             }
-        }catch (\Exception $e){}
+        } catch (\Exception $e) {
+        }
 
     }
 }

+ 366 - 21
app/admin/service/order/OrderService.php

@@ -3,6 +3,7 @@
 namespace app\admin\service\order;
 
 use app\model\CouponDetail;
+use app\model\CouponGoods;
 use app\model\GoodsRunning;
 use app\model\GoodsSku;
 use app\model\Member;
@@ -296,7 +297,6 @@ class OrderService
                 SupportLog::channel('pay')->error("FIND_WXPAY", ['msg' => '订单查询失败', 'order_id' => $orderId]);
                 return ['msg' => '订单查询失败'];
             }
-            dump('nbr-' . $nbr);
             sleep(5);
             SupportLog::channel('pay')->error("FIND_WXPAY", ['nbr' => $nbr, 'order_id' => $orderId]);
             return self::findWxpay($orderId, $nbr + 1);
@@ -428,59 +428,404 @@ class OrderService
         return $payWay;
     }
 
-    public static function useCoupon($memberId, $goodsIds, $goods, $goodsCount, $coupon, $payAmount, $totalAmount)
+    /**
+     * @Desc 支付使用优惠券
+     * @Author Gorden
+     * @Date 2024/8/28 14:59
+     *
+     * @param $memberId
+     * @param $goods
+     * @param $coupon
+     * @param $payAmount
+     * @return array|mixed
+     */
+    public static function payUseCoupon($memberId, $goods, $coupon, $payAmount)
+    {
+        foreach ($coupon as $item) {
+            if (!in_array(substr($item, 0, 2), ['CU', 'CO'])) {
+                return $payAmount;
+            }
+        }
+        $amountBalance = [
+            'pay_amount' => $payAmount,
+            'welfare_balance' => 0,
+            'cut_balance' => 0,
+        ];
+        foreach ($goods as $good) {
+            $result = OrderService::useCoupon($memberId, $goods, $good, $coupon, $amountBalance);
+            $amountBalance = [
+                'pay_amount' => $result['pay_amount'],
+                'welfare_balance' => $result['welfare_balance'],
+                'cut_balance' => $result['cut_balance'],
+            ];
+        }
+
+        $couponDetailsIds = Redis::sMembers("ORDER:USE:COUPON:" . $memberId);
+        Redis::del("ORDER:USE:COUPON:" . $memberId);
+        $useCouponJson = Redis::get("ORDER:USE:COUPON:DISCOUNT:" . $memberId);
+        Redis::del("ORDER:USE:COUPON:DISCOUNT:" . $memberId);
+
+        return [
+            'pay_amount' => $amountBalance['pay_amount'],
+            'detail_ids' => $couponDetailsIds,
+            'use_coupon_json' => $useCouponJson ?? []
+        ];
+    }
+
+    public static function useCoupon($memberId, $goods, $good, $coupon, $amountBalance)
     {
         try {
-            $goodsId = $goods['goods_id'];
-            $money = $goods['goods_sales_price'] * $goods['nbr'];
+            $cacheKey = "ORDER:USE:COUPON:" . $memberId;
+            $cacheDiscountKey = "ORDER:USE:COUPON:DISCOUNT:" . $memberId;
+            $payAmount = $amountBalance['pay_amount'];
+            $welfareBalance = $amountBalance['welfare_balance'];
+            $cutBalance = $amountBalance['cut_balance'];
+            $goodsId = $good['goods_id'];
+            $money = $good['goods_sales_price'] * $good['nbr'];
+
+            $discountData = Redis::get($cacheDiscountKey);
+            if (empty($discountData)) {
+                $discountData = [];
+            } else {
+                $discountData = json_decode($discountData, true);
+            }
             foreach ($coupon as $couponId) {
                 $couponDetail = CouponDetail::leftJoin('coupon_goods', 'coupon_goods.join_goods_coupon_id', '=', 'coupon_detail.join_detail_coupon_id')
                     ->leftJoin('coupon', 'coupon.coupon_id', '=', 'coupon_detail.join_detail_coupon_id')
                     ->select('coupon_detail.coupon_detail_id', 'coupon_goods.coupon_goods_id', 'coupon_id', 'coupon_classify', 'coupon_value', 'coupon_minimum_limit', 'coupon_category')
                     ->where('coupon_goods.join_coupon_goods_id', $goodsId)
-                    ->where('coupon_goods.join_coupon_goods_sku_id', $goods['sku_id'])
+                    ->where('coupon_goods.join_coupon_goods_sku_id', $good['sku_id'])
                     ->where('join_goods_coupon_id', $couponId)
                     ->where('coupon_detail.join_coupon_detail_member_id', $memberId)
                     ->first();
+                if (!$couponDetail) {
+                    continue;
+                }
+                // 计算优惠券包含的优惠商品的件数和总价
+                $countAndAmount = self::countAndAmount($goods, $couponId);
+                // 如果是计件
+                if ($couponDetail->coupon_category == 'PIECE' && $countAndAmount['count'] < $couponDetail->coupon_minimum_limit) {
+                    continue;
+                }
                 if (in_array($couponDetail->coupon_classify, ['立减券', '满减券'])) {
-                    if (($couponDetail->coupon_category == 'PIECE' && $goodsCount >= $couponDetail->coupon_minimum_limit) || ($couponDetail->coupon_category == 'NORMAL' && $totalAmount >= $couponDetail->coupon_minimum_limit)) {
-                        if ($money - $couponDetail->coupon_value >= 0) {
-                            $money = $money - $couponDetail->coupon_value;
-                            $payAmount = $payAmount - $couponDetail->coupon_value;
-                        } elseif ($money - $couponDetail->coupon_value < 0) {
+                    if ($couponDetail->coupon_category == 'PIECE' || ($couponDetail->coupon_category == 'NORMAL' && $countAndAmount['amount'] >= $couponDetail->coupon_minimum_limit)) {
+                        if (!Redis::sIsMember($cacheKey, $couponId)) {
+                            Redis::sAdd($cacheKey, $couponId);
+                            $cutBalance = $couponDetail->coupon_value;
+                        }
+                        if ($cutBalance - $money >= 0) {
                             $payAmount = $payAmount - $money;
-                            $money = 0;
+                            $cutBalance = $cutBalance - $money;
+                        } elseif ($cutBalance != 0 && $cutBalance - $money < 0) {
+                            $payAmount = $payAmount - $cutBalance;
+                            $cutBalance = 0;
                         }
+                        // json记录
+                        $discountData[$couponId] = [
+                            'coupon_id' => $couponId,
+                            'coupon_value' => $cutBalance == 0 ? $couponDetail->coupon_value : $money,
+                            'coupon_classify' => $couponDetail->coupon_classify,
+                            'coupon_detail_id' => [$couponDetail->coupon_detail_id]
+                        ];
+                        Redis::set($cacheDiscountKey, json_encode($discountData,JSON_UNESCAPED_UNICODE));
+
+                        CouponDetail::where('coupon_detail_id', $couponDetail->coupon_detail_id)->update(['coupon_detail_status' => 'USED']);
                     }
                 } elseif ($couponDetail->coupon_classify == '折扣券') {
-                    if (($couponDetail->coupon_category == 'PIECE' && $goodsCount >= $couponDetail->coupon_minimum_limit) || ($couponDetail->coupon_category == 'NORMAL' && $totalAmount >= $couponDetail->coupon_minimum_limit)) {
+                    if ($couponDetail->coupon_category == 'PIECE' || ($couponDetail->coupon_category == 'NORMAL' && $countAndAmount['amount'] >= $couponDetail->coupon_minimum_limit)) {
                         $payAmount = $payAmount - ($money * $couponDetail->coupon_value / 100);
+                        if (!empty($discountData[$couponId]['coupon_value'])) {
+                            $zhekouAmount = $discountData[$couponId]['coupon_value'] + ($money * $couponDetail->coupon_value / 100);
+                        } else {
+                            $zhekouAmount = $money * $couponDetail->coupon_value / 100;
+                        }
+                        // json记录
+                        $discountData[$couponId] = [
+                            'coupon_id' => $couponId,
+                            'coupon_value' => $zhekouAmount,
+                            'coupon_classify' => $couponDetail->coupon_classify,
+                            'coupon_detail_id' => [$couponDetail->coupon_detail_id]
+                        ];
+                        Redis::set($cacheDiscountKey, json_encode($discountData,JSON_UNESCAPED_UNICODE));
+                        CouponDetail::where('coupon_detail_id', $couponDetail->coupon_detail_id)->update(['coupon_detail_status' => 'USED']);
                     }
-                } elseif ($couponDetail->coupon_classify == '抵用券') {
-                    if (($couponDetail->coupon_category == 'PIECE' && $goodsCount >= $couponDetail->coupon_value) || ($couponDetail->coupon_category == 'NORMAL' && $totalAmount >= $couponDetail->coupon_minimum_limit)) {
+                } elseif (in_array($couponDetail->coupon_classify, ['抵用券', '赠品券'])) {
+                    if ($couponDetail->coupon_category == 'PIECE' || ($couponDetail->coupon_category == 'NORMAL' && $countAndAmount['amount'] >= $couponDetail->coupon_minimum_limit)) {
                         $diyongCouponDetailIds = CouponDetail::leftJoin('coupon_goods', 'coupon_goods.join_goods_coupon_id', '=', 'coupon_detail.join_detail_coupon_id')
                             ->where('join_detail_coupon_id', $couponId)
                             ->where('coupon_goods.join_coupon_goods_id', $goodsId)
-                            ->where('coupon_goods.join_coupon_goods_sku_id', $goods['sku_id'])
+                            ->where('coupon_goods.join_coupon_goods_sku_id', $good['sku_id'])
                             ->where('coupon_detail_status', 'ACTIVED')
                             ->where('coupon_detail.join_coupon_detail_member_id', $memberId)
                             ->pluck('coupon_detail_id')
                             ->toArray();
+                        $couponDetailsIds = Redis::sMembers($cacheKey);
+                        foreach ($diyongCouponDetailIds as $key => $detailId) {
+                            if (in_array($detailId, $couponDetailsIds)) {
+                                unset($diyongCouponDetailIds[$key]);
+                            }
+                        }
+                        if (count($diyongCouponDetailIds) > $good['nbr']) {
+                            $diyongCouponDetailIds = array_slice($diyongCouponDetailIds, 0, ceil($good['nbr']));
+                        }
+                        $useDetailIds = [];
+                        if (!empty($discountData[$couponId]['coupon_detail_id'])) {
+                            $useDetailIds = $discountData[$couponId]['coupon_detail_id'];
+                        }
+                        $diyongAmount = 0;
+                        if (!empty($discountData[$couponId]['coupon_value'])) {
+                            $diyongAmount = $discountData[$couponId]['coupon_value'];
+                        }
                         foreach ($diyongCouponDetailIds as $detailId) {
-                            $key = "ORDER:USE:COUPON:" . $memberId;
-                            if (!Redis::sIsMember($key, $detailId)) {
-                                Redis::sAdd($key, $detailId);
-                                $payAmount = $payAmount - $money;
+                            // 是否计算过了
+                            if (!Redis::sIsMember($cacheKey, $detailId)) {
+                                $useDetailIds[] = $detailId;
+                                Redis::sAdd($cacheKey, $detailId);
+                                CouponDetail::where('coupon_detail_id', $detailId)->update(['coupon_detail_status' => 'USED']);
+                                if ($good['nbr'] > 1) {
+                                    $payAmount = $payAmount - $good['goods_sales_price'];
+                                    $diyongAmount += $good['goods_sales_price'];
+                                    $good['nbr'] = $good['nbr'] - 1;
+                                } elseif (ceil($good['nbr']) == 1) {
+                                    $payAmount = $payAmount - ($good['goods_sales_price'] * $good['nbr']);
+                                    $diyongAmount = $diyongAmount + ($good['goods_sales_price'] * $good['nbr']);
+                                    $good['nbr'] = 0;
+                                }
                             }
                         }
+                        // json记录
+                        $discountData[$couponId] = [
+                            'coupon_id' => $couponId,
+                            'coupon_value' => $diyongAmount,
+                            'coupon_classify' => $couponDetail->coupon_classify,
+                            'coupon_detail_id' => array_unique($useDetailIds)
+                        ];
+                        Redis::set($cacheDiscountKey, json_encode($discountData,JSON_UNESCAPED_UNICODE));
+                    }
+                } elseif ($couponDetail->coupon_classify == '福利券') {
+                    if (!Redis::sIsMember($cacheKey, $couponId)) {
+                        Redis::sAdd($cacheKey, $couponId);
+                        CouponDetail::where('coupon_detail_id', $couponDetail->coupon_detail_id)->update(['coupon_detail_status' => 'USED']);
+                        $welfareBalance = $couponDetail->coupon_value;
+                    }
+                    $fuliAmount = 0;
+                    if (!empty($discountData[$couponId]['coupon_value'])) {
+                        $fuliAmount = $discountData[$couponId]['coupon_value'];
+                    }
+                    if ($welfareBalance >= $money) {
+                        $payAmount = $payAmount - $money;
+                        $welfareBalance = $welfareBalance - $money;
+                        $fuliAmount += $money;
+                    } else {
+                        $fuliAmount += $welfareBalance;
+                        $payAmount = $payAmount - $welfareBalance;
+                        $welfareBalance = 0;
+                    }
+                    // json记录
+                    $discountData[$couponId] = [
+                        'coupon_id' => $couponId,
+                        'coupon_value' => $fuliAmount,
+                        'coupon_classify' => $couponDetail->coupon_classify,
+                        'coupon_detail_id' => [$couponDetail->coupon_detail_id]
+                    ];
+                    Redis::set($cacheDiscountKey, json_encode($discountData,JSON_UNESCAPED_UNICODE));
+                } elseif (in_array($couponDetail->coupon_classify, ['年卡', '季卡', '月卡'])) {
+                    if (Redis::sIsMember($cacheKey, $couponId) && Redis::sIsMember($cacheKey, $goodsId)) {
+                        continue;
+                    }
+                    Redis::sAdd($cacheKey, $couponId);
+                    Redis::sAdd($cacheKey, $goodsId);
+                    $kaAmount = 0;
+                    if (!empty($discountData[$couponId]['coupon_value'])) {
+                        $kaAmount = $discountData[$couponId]['coupon_value'];
+                    }
+                    if ($good['nbr'] > 1) {
+                        $payAmount = $payAmount - $good['goods_sales_price'];
+                        $kaAmount = $good['goods_sales_price'];
+                    } else {
+                        $payAmount = $payAmount - $good['goods_sales_price'] * $good['nbr'];
+                        $kaAmount = $good['goods_sales_price'] * $good['nbr'];
                     }
 
+                    // json记录
+                    $discountData[$couponId] = [
+                        'coupon_id' => $couponId,
+                        'coupon_value' => $kaAmount,
+                        'coupon_classify' => $couponDetail->coupon_classify,
+                        'coupon_detail_id' => [$couponDetail->coupon_detail_id]
+                    ];
+                    Redis::set($cacheDiscountKey, json_encode($discountData,JSON_UNESCAPED_UNICODE));
                 }
             }
 
-            return $payAmount;
+            if ($payAmount < 0) {
+                $payAmount = 0;
+            }
+            $amountBalance = [
+                'pay_amount' => round($payAmount, 2),
+                'welfare_balance' => $welfareBalance,
+                'cut_balance' => $cutBalance
+            ];
+            return $amountBalance;
         } catch (\Exception $e) {
-            dump($e->getMessage());
+            dump($e->getTrace());
+        }
+    }
+
+    /**
+     * @Desc 选择优惠券,计算
+     * @Author Gorden
+     * @Date 2024/8/28 14:18
+     *
+     * @param $memberId
+     * @param $goods
+     * @param $good
+     * @param $coupon
+     * @param $amountBalance
+     * @return array|void
+     */
+    public static function chooseCoupon($memberId, $goods, $good, $coupon, $amountBalance)
+    {
+        try {
+            $cacheKey = "ORDER:USE:COUPON:" . $memberId;
+            $payAmount = $amountBalance['pay_amount'];
+            $welfareBalance = $amountBalance['welfare_balance'];
+            $cutBalance = $amountBalance['cut_balance'];
+            $goodsId = $good['goods_id'];
+            $money = $good['goods_sales_price'] * $good['nbr'];
+            foreach ($coupon as $couponId) {
+                $couponDetail = CouponDetail::leftJoin('coupon_goods', 'coupon_goods.join_goods_coupon_id', '=', 'coupon_detail.join_detail_coupon_id')
+                    ->leftJoin('coupon', 'coupon.coupon_id', '=', 'coupon_detail.join_detail_coupon_id')
+                    ->select('coupon_detail.coupon_detail_id', 'coupon_goods.coupon_goods_id', 'coupon_id', 'coupon_classify', 'coupon_value', 'coupon_minimum_limit', 'coupon_category')
+                    ->where('coupon_goods.join_coupon_goods_id', $goodsId)
+                    ->where('coupon_goods.join_coupon_goods_sku_id', $good['sku_id'])
+                    ->where('join_goods_coupon_id', $couponId)
+                    ->where('coupon_detail.join_coupon_detail_member_id', $memberId)
+                    ->first();
+                if (!$couponDetail) {
+                    continue;
+                }
+                // 计算优惠券包含的优惠商品的件数和总价
+                $countAndAmount = self::countAndAmount($goods, $couponId);
+                // 如果是计件
+                if ($couponDetail->coupon_category == 'PIECE' && $countAndAmount['count'] < $couponDetail->coupon_minimum_limit) {
+                    continue;
+                }
+                if (in_array($couponDetail->coupon_classify, ['立减券', '满减券'])) {
+                    if ($couponDetail->coupon_category == 'PIECE' || ($couponDetail->coupon_category == 'NORMAL' && $countAndAmount['amount'] >= $couponDetail->coupon_minimum_limit)) {
+                        if (!Redis::sIsMember($cacheKey, $couponId)) {
+                            Redis::sAdd($cacheKey, $couponId);
+                            $cutBalance = $couponDetail->coupon_value;
+                        }
+                        if ($cutBalance - $money >= 0) {
+                            $payAmount = $payAmount - $money;
+                            $cutBalance = $cutBalance - $money;
+                        } elseif ($cutBalance != 0 && $cutBalance - $money < 0) {
+                            $payAmount = $payAmount - $cutBalance;
+                            $cutBalance = 0;
+                        }
+                    }
+                } elseif ($couponDetail->coupon_classify == '折扣券') {
+                    if ($couponDetail->coupon_category == 'PIECE' || ($couponDetail->coupon_category == 'NORMAL' && $countAndAmount['amount'] >= $couponDetail->coupon_minimum_limit)) {
+                        $payAmount = $payAmount - ($money * $couponDetail->coupon_value / 100);
+                    }
+                } elseif (in_array($couponDetail->coupon_classify, ['抵用券', '赠品券'])) {
+                    if ($couponDetail->coupon_category == 'PIECE' || ($couponDetail->coupon_category == 'NORMAL' && $countAndAmount['amount'] >= $couponDetail->coupon_minimum_limit)) {
+                        $diyongCouponDetailIds = CouponDetail::leftJoin('coupon_goods', 'coupon_goods.join_goods_coupon_id', '=', 'coupon_detail.join_detail_coupon_id')
+                            ->where('join_detail_coupon_id', $couponId)
+                            ->where('coupon_goods.join_coupon_goods_id', $goodsId)
+                            ->where('coupon_goods.join_coupon_goods_sku_id', $good['sku_id'])
+                            ->where('coupon_detail_status', 'ACTIVED')
+                            ->where('coupon_detail.join_coupon_detail_member_id', $memberId)
+                            ->pluck('coupon_detail_id')
+                            ->toArray();
+                        $couponDetailsIds = Redis::sMembers($cacheKey);
+                        foreach ($diyongCouponDetailIds as $key => $detailId) {
+                            if (in_array($detailId, $couponDetailsIds)) {
+                                unset($diyongCouponDetailIds[$key]);
+                            }
+                        }
+                        if (count($diyongCouponDetailIds) > $good['nbr']) {
+                            $diyongCouponDetailIds = array_slice($diyongCouponDetailIds, 0, ceil($good['nbr']));
+                        }
+                        foreach ($diyongCouponDetailIds as $detailId) {
+                            // 是否计算过了
+                            if (!Redis::sIsMember($cacheKey, $detailId)) {
+                                Redis::sAdd($cacheKey, $detailId);
+                                if ($good['nbr'] > 1) {
+                                    $payAmount = $payAmount - $good['goods_sales_price'];
+                                    $good['nbr'] = $good['nbr'] - 1;
+                                } elseif (ceil($good['nbr']) == 1) {
+                                    $payAmount = $payAmount - ($good['goods_sales_price'] * $good['nbr']);
+                                    $good['nbr'] = 0;
+                                }
+                            }
+                        }
+                    }
+                } elseif ($couponDetail->coupon_classify == '福利券') {
+                    if (!Redis::sIsMember($cacheKey, $couponId)) {
+                        Redis::sAdd($cacheKey, $couponId);
+                        $welfareBalance = $couponDetail->coupon_value;
+                    }
+                    if ($welfareBalance >= $money) {
+                        $payAmount = $payAmount - $money;
+                        $welfareBalance = $welfareBalance - $money;
+                    } else {
+                        $payAmount = $payAmount - $welfareBalance;
+                        $welfareBalance = 0;
+                    }
+                } elseif (in_array($couponDetail->coupon_classify, ['年卡', '季卡', '月卡'])) {
+                    if (Redis::sIsMember($cacheKey, $couponId) && Redis::sIsMember($cacheKey, $goodsId)) {
+                        continue;
+                    }
+                    Redis::sAdd($cacheKey, $couponId);
+                    Redis::sAdd($cacheKey, $goodsId);
+                    if ($good['nbr'] > 1) {
+                        $payAmount = $payAmount - $good['goods_sales_price'];
+                    } else {
+                        $payAmount = $payAmount - $good['goods_sales_price'] * $good['nbr'];
+                    }
+
+                }
+            }
+
+            if ($payAmount < 0) {
+                $payAmount = 0;
+            }
+            $amountBalance = [
+                'pay_amount' => round($payAmount, 2),
+                'welfare_balance' => $welfareBalance,
+                'cut_balance' => $cutBalance
+            ];
+            return $amountBalance;
+        } catch (\Exception $e) {
+            dump($e->getTrace());
+        }
+    }
+
+    public static function countAndAmount($goods, $couponId)
+    {
+        try {
+            $goodsIds = array_column($goods, 'goods_id');
+            $couponGoods = CouponGoods::whereIn('join_coupon_goods_id', $goodsIds)
+                ->where('join_goods_coupon_id', $couponId)
+                ->select('join_coupon_goods_id', 'join_coupon_goods_sku_id')
+                ->get()
+                ->toArray();
+            $count = 0;
+            $amount = 0;
+            foreach ($couponGoods as $couponGood) {
+                foreach ($goods as $good) {
+                    if ($good['goods_id'] == $couponGood['join_coupon_goods_id'] && $good['sku_id'] == $couponGood['join_coupon_goods_sku_id']) {
+                        $count += $good['nbr'];
+                        $amount += $good['goods_sales_price'] * $good['nbr'];
+                    }
+                }
+            }
+
+            return compact('count', 'amount');
+        } catch (\Exception $e) {
+            dump($e->getTrace());
         }
     }