Browse Source

Merge branch 'master' into custom_manager
判客调整合并代码

yb 6 months ago
parent
commit
17f8be2e40

+ 66 - 11
app/admin/controller/coupon/CouponController.php

@@ -2,6 +2,7 @@
 
 namespace app\admin\controller\coupon;
 
+use app\admin\service\coupon\CouponDetailService;
 use app\admin\validate\coupon\CouponValidate;
 use app\admin\validate\device\DeviceValidate;
 use app\controller\Curd;
@@ -157,6 +158,7 @@ class CouponController extends Curd
     {
         $coupons = Coupon::where('coupon_status', 'ACTIVED')
             ->select('coupon_id', 'coupon_name')
+            ->orderBy('coupon_addtimes', 'DESC')
             ->get()
             ->toArray();
 
@@ -187,9 +189,9 @@ class CouponController extends Curd
             return json_fail($this->validateClass->getError());
         }
         $goods = $request->post('goodsContentList', []);
-        if (empty($goods)) {
-            return json_fail("请选择关联的产品");
-        }
+//        if (empty($goods)) {
+//            return json_fail("请选择关联的产品");
+//        }
 
         Db::beginTransaction();
         try {
@@ -275,7 +277,7 @@ class CouponController extends Curd
             }
         } else if ($params['coupon_use_member'] == 'all') {
             $couponJson['member']['list'] = [];
-            $couponJson['member']['range'] = '全部员';
+            $couponJson['member']['range'] = '全部员';
             $couponJson['member']['where'] = '';
         }
 
@@ -291,6 +293,64 @@ class CouponController extends Curd
         return $data;
     }
 
+    public function customSend(Request $request)
+    {
+        $chooseCoupons = $request->post('chooseCoupons', []);
+        $couponUseMember = $request->post('coupon_use_member', '');
+        $memberList = $request->post('member_list', []);
+        $condition = $request->post('condition', '');
+        if ($couponUseMember == 'condition') {
+            if ($condition == 'is_employ') {
+                $memberList = Member::where('member_classify', 'EMPLOY')->pluck('member_id')->toArray();
+            } elseif ($condition == 'is_member') {
+                $memberList = Member::where('member_classify', 'MEMBER')->pluck('member_id')->toArray();
+            } elseif ($condition == 'is_vip') {
+                $memberList = Member::where('member_is_vip', 'Y')->pluck('member_id')->toArray();
+            }
+        }
+
+        Db::beginTransaction();
+        try {
+            $couponIds = array_column($chooseCoupons, 'id');
+            $coupons = Coupon::whereIn('coupon_id', $couponIds)->get()->toArray();
+            foreach ($coupons as $coupon) {
+                foreach ($chooseCoupons as $chooseCoupon) {
+                    if ($chooseCoupon['id'] == $coupon['coupon_id']) {
+                        if (empty($chooseCoupon['gain_datetime'])) {
+                            $chooseCoupon['gain_datetime'] = date('Y-m-d H:i:s');
+                        }
+                        $params['coupon_id'] = $coupon['coupon_id'];
+                        $params['coupon_detail_gain_datetime'] = date('Y-m-d H:i:s', strtotime($chooseCoupon['gain_datetime']));
+                        if (($coupon['coupon_validdate_day'] == 0 || $coupon['coupon_validdate_day'] == '') && !empty($coupon['coupon_validdate_end'])) {
+                            $params['coupon_detail_deadline_datetime'] = $coupon['coupon_validdate_end'];
+                        } elseif ($coupon['coupon_validdate_day'] > 0) {
+                            $endUnix = strtotime($chooseCoupon['gain_datetime']);
+                            $params['coupon_detail_deadline_datetime'] = date('Y-m-d H:i:s', $endUnix + ($coupon['coupon_validdate_day'] * 24 * 3600) -1);
+                        }
+                        foreach ($memberList as $item) {
+                            $params['member_id'] = $item;
+                            if ($chooseCoupon['nbr'] > 0) {
+                                for ($i = 0; $i < $chooseCoupon['nbr']; $i++) {
+                                    CouponDetailService::customSendCoupon($params);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            Db::commit();
+            return json_success("发放成功");
+        } catch (BusinessException $e) {
+            return json_fail($e->getMessage());
+        } catch (\Exception $e) {
+            Db::rollBack();
+            return json_fail('优惠券发放失败');
+
+        }
+
+    }
+
     /**
      * @Desc 修改优惠券
      * @Author Gorden
@@ -489,7 +549,7 @@ class CouponController extends Curd
 //            }
         } else if ($params['coupon_use_member'] == 'all') {
             $couponJson['member']['list'] = [];
-            $couponJson['member']['range'] = '全部员';
+            $couponJson['member']['range'] = '全部员';
             $couponJson['member']['where'] = '';
 
             if (isset($couponJson['member']['list'])) {
@@ -661,12 +721,7 @@ class CouponController extends Curd
                 }
                 CouponGoods::where('join_goods_coupon_id', $id)->delete();
 
-//                CouponDetail::where('join_detail_coupon_id', $id)
-//                    ->whereIn('coupon_detail_status',['INIT','PENDING','ACTIVED'])
-//                    ->delete();
-//                CouponDetail::where('join_detail_coupon_id', $id)
-//                    ->where('coupon_detail_status','WAITING')
-//                    ->update(['coupon_detail_status'=>'DISABLED']);
+                CouponDetail::where('join_detail_coupon_id', $id)->delete();
             }
             $this->doDelete($ids);
             Db::commit();

+ 66 - 9
app/admin/controller/coupon/CouponDetailController.php

@@ -2,10 +2,12 @@
 
 namespace app\admin\controller\coupon;
 
+use app\admin\service\coupon\CouponService;
 use app\admin\service\member\MemberService;
 use app\controller\Curd;
 use app\model\Coupon;
 use app\model\CouponDetail;
+use app\model\CouponGoods;
 use support\Request;
 use support\Response;
 
@@ -120,7 +122,7 @@ class CouponDetailController extends Curd
             }
             if (!empty($item['coupon_detail_extend_json'])) {
                 $couponDetailExtendJson = json_decode($item['coupon_detail_extend_json'], true);
-                if (isset($couponDetailExtendJson['gettype'])){
+                if (isset($couponDetailExtendJson['gettype'])) {
                     $item['gettype'] = $couponDetailExtendJson['gettype'];
                 }
             }
@@ -170,21 +172,76 @@ class CouponDetailController extends Curd
      */
     public function info(Request $request): Response
     {
-        $detailId = $request->get('detail_id','');
-        if (empty($detailId)){
+        $detailId = $request->get('detail_id', '');
+        if (empty($detailId)) {
             return json_fail('参数异常');
         }
 
-        $detail = CouponDetail::where('coupon_detail_id',$detailId)
-            ->select('coupon_detail_id','coupon_detail_extend_json')
+        $detail = CouponDetail::where('coupon_detail_id', $detailId)
+            ->select('coupon_detail_id', 'coupon_detail_extend_json')
             ->first();
-        if (!empty($detail->coupon_detail_extend_json)){
-            $couponDetailExtendJson = json_decode($detail->coupon_detail_extend_json,true);
-            if (isset($couponDetailExtendJson['from'])){
+        if (!empty($detail->coupon_detail_extend_json)) {
+            $couponDetailExtendJson = json_decode($detail->coupon_detail_extend_json, true);
+            if (isset($couponDetailExtendJson['from'])) {
                 $detail['from'] = MemberService::getMemberNameByMemberId($couponDetailExtendJson['from']);
             }
         }
 
-        return json_success('',$detail);
+        return json_success('', $detail);
+    }
+
+    public function myCouponGrouping(Request $request)
+    {
+        $memberId = $request->get('member_id', '');
+        $goods = $request->get('goods', []);
+        $settlementNow = $request->get('settlement_now', 'N');
+        if ($memberId == '') {
+            return json_fail("参数异常");
+        }
+
+        $goodsIds = array_column($goods, 'goods_id');
+        $couponGoods = CouponGoods::whereIn('join_coupon_goods_id', $goodsIds)->get()->toArray();
+        $couponIds = [];
+        foreach ($couponGoods as $couponGood) {
+            foreach ($goods as $good) {
+                if ($good['sku_id'] = $couponGood['join_coupon_goods_sku_id']) {
+                    $couponIds[] = $couponGood['join_goods_coupon_id'];
+                }
+            }
+        }
+
+        $details = CouponDetail::with([
+            'coupon' => function ($query) {
+                $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);
+            if ($settlementNow == 'Y') {
+                $details = $details->whereIn('coupon_detail.coupon_detail_status', ['ACTIVED', 'WAITING']);
+            } else {
+                $details = $details->where('coupon_detail.coupon_detail_status', 'ACTIVED');
+            }
+            $details = $details->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();
+        $data = [];
+        foreach ($details as $detail) {
+            if (empty($detail['coupon'])) {
+                continue;
+            }
+            $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'] ?? '',
+            ];
+        }
+
+        return json_success('', $data);
     }
 }

+ 1 - 0
app/admin/controller/member/AccountController.php

@@ -45,6 +45,7 @@ class AccountController extends Curd
 
         foreach ($account as &$item){
             $item['member_account_duedate'] = !empty($item['member_account_duedate']) ? date('Y-m-d H:i:s',$item['member_account_duedate']) : '长期有效';
+            $item['member_account_surplus'] = round($item['member_account_surplus'] + $item['member_account_added'],2);
         }
 
         return json_success('', $account);

+ 91 - 7
app/admin/controller/member/MemberController.php

@@ -457,17 +457,101 @@ class MemberController
         return MemberService::deleteDevice($request);
     }
 
-    public function coupon(Request $request)
+    /**
+     * @Desc 卡券数量
+     * @Author Gorden
+     * @Date 2024/8/22 18:51
+     *
+     * @param Request $request
+     * @return \support\Response
+     */
+    public function couponCount(Request $request)
     {
-        $memberId = $request->get('member_id','');
-        $active = $request->get('active','');
+        $memberId = $request->get('member_id', '');
+        $coupons = CouponDetail::leftJoin('coupon', 'coupon.coupon_id', '=', 'coupon_detail.join_detail_coupon_id')
+            ->where('join_coupon_detail_member_id', $memberId)
+            ->select('coupon.coupon_name', 'coupon.coupon_classify')
+            ->get()
+            ->toArray();
+        $data = ['manjian'=>0,'diyong'=>0,'zhekou'=>0,'lijian'=>0,'zengpin'=>0,'fuli'=>0,'nianka'=>0,'jika'=>0,'yueka'=>0];
+        foreach ($coupons as $item) {
+            if ($item['coupon_classify'] == '满减券'){
+                $data['manjian'] += 1;
+            }elseif ($item['coupon_classify'] == '抵用券'){
+                $data['diyong'] += 1;
+            }elseif ($item['coupon_classify'] == '折扣券'){
+                $data['zhekou'] += 1;
+            }elseif ($item['coupon_classify'] == '立减券'){
+                $data['lijian'] += 1;
+            }elseif ($item['coupon_classify'] == '赠品券'){
+                $data['zengpin'] += 1;
+            }elseif ($item['coupon_classify'] == '福利券'){
+                $data['fuli'] += 1;
+            }elseif ($item['coupon_classify'] == '年卡'){
+                $data['nianka'] += 1;
+            }elseif ($item['coupon_classify'] == '季卡'){
+                $data['jika'] += 1;
+            }elseif ($item['coupon_classify'] == '月卡'){
+                $data['yueka'] += 1;
+            }
+        }
+        $data['total'] = $data['manjian']+$data['diyong']+$data['zhekou']+$data['lijian']+$data['zengpin']+$data['fuli']+$data['nianka']+$data['jika']+$data['yueka'];
 
-        $coupons = CouponDetail::where('join_coupon_detail_member_id',$memberId)
-            ->leftJoin('coupon','coupon.coupon_id','=','coupon_detail.join_detail_coupon_id')
-            ->groupBy('join_detail_coupon_id')
+        return json_success('',$data);
+    }
+
+    /**
+     * @Desc 我的卡券
+     * @Author Gorden
+     * @Date 2024/8/22 18:45
+     *
+     * @param Request $request
+     * @return \support\Response
+     */
+    public function coupon(Request $request)
+    {
+        $memberId = $request->get('member_id', '');
+        $classify = $request->get('classify', '');
+        $page = $request->get('page', 1);
+        $pageSize = $request->get('pageSize', 20);
+
+        $coupons = CouponDetail::with([
+            'member' => function ($query) {
+                $query->select('member_id', 'member_mobile');
+            },
+            'cert' => function ($query) {
+                $query->select('join_cert_member_id', 'member_cert_name');
+            },
+            'info' => function ($query) {
+                $query->select('join_info_member_id', 'member_info_nickname');
+            }
+        ])
+            ->leftJoin('coupon', 'coupon.coupon_id', '=', 'coupon_detail.join_detail_coupon_id')
+            ->where('join_coupon_detail_member_id', $memberId)
+            ->where('coupon.coupon_classify', $classify);
+        $total = $coupons->count();
+        $rows = $coupons->select('coupon_detail.*', 'coupon.coupon_name', 'coupon.coupon_classify','coupon_value')
+            ->forPage($page, $pageSize)
             ->get()
             ->toArray();
 
-        dump($coupons);
+        foreach ($rows as &$item) {
+            $mobile = $certName = $nickname = '';
+            if (!empty($item['member']) && !empty($item['member']['member_mobile'])) {
+                $mobile = $item['member']['member_mobile'];
+            }
+            if (!empty($item['cert']) && !empty($item['cert']['member_cert_name'])) {
+                $certName = $item['cert']['member_cert_name'];
+            }
+            if (!empty($item['info']) && !empty($item['info']['member_info_nickname'])) {
+                $nickname = $item['info']['member_info_nickname'];
+            }
+            $item['member_name'] = MemberService::getMemberName($mobile, $certName, $nickname);
+            unset($item['member'], $item['cert'], $item['info']);
+
+            $data[$item['coupon_classify']][] = $item;
+        }
+
+        return json_success('', compact('rows', 'page', 'pageSize', 'total'));
     }
 }

+ 35 - 31
app/admin/controller/order/DishesController.php

@@ -10,7 +10,8 @@ use app\model\OrderSheet;
 use support\Request;
 use support\Response;
 
-class DishesController extends Curd{
+class DishesController extends Curd
+{
     public function __construct()
     {
         $this->model = new Order();
@@ -30,6 +31,7 @@ class DishesController extends Curd{
     public function select(Request $request): Response
     {
         [$where, $format, $limit, $field, $order] = $this->selectInput($request);
+
         if (!empty($where['order_addtimes'])) {
             $where['order_addtimes'][0] = strtotime($where['order_addtimes'][0]);
             $where['order_addtimes'][1] = strtotime($where['order_addtimes'][1]);
@@ -40,7 +42,7 @@ class DishesController extends Curd{
         // $where['order_category'] = 'DISHES';
         if (!empty($where['order_status_system']) && in_array($where['order_status_system'], ['PENDING', 'WAITING', 'SENDING', 'RECVING', 'SIGNED', 'CONFIRM'])) {
             $where['order_is_complete'] = 'N';
-            $where['order_category'] = ['<>','RETURN'];
+            $where['order_category'] = ['<>', 'RETURN'];
         }
 
         // if (!empty($where['order_status_system']) && $where['order_status_system'] == 'RETURN') {
@@ -52,32 +54,34 @@ class DishesController extends Curd{
         //     $where['order_return.order_return_status'] = $request->get('return');
         // }
         // if ($request->get('goods_classify') || $request->get('goods_name')){
-            $where['order_id'] = '';
+//            $where['order_id'] = '';
+        if (empty($where['order_id'])){
             $goodsClassify = 'MEALS';
-            $goodsName = $request->get('goods_name','');
-            if (!empty($goodsName) && empty($goodsClassify)){
-                $goodsIds = Goods::where('goods_name','like','%'.$request->get('goods_name').'%')->pluck('goods_id')->toArray();
-            }else if(!empty($goodsClassify)){
-                if($goodsClassify == 'SERVICE'){
-                    $goodsModel = Goods::whereIn('goods_classify',['SERVICE','CHNMED','CHNNCD']);
-                }else{
-                    $goodsModel = Goods::where('goods_classify',$goodsClassify);
-                }
-
-                if(!empty($goodsName)){
-                    $goodsModel->where('goods_name','like','%'.$goodsName.'%');
-                }
+        }
+//        $goodsClassify = $request->get('goods_classify', '');
+        $goodsName = $request->get('goods_name', '');
+        if (!empty($goodsName) && empty($goodsClassify)) {
+            $goodsIds = Goods::where('goods_name', 'like', '%' . $request->get('goods_name') . '%')->pluck('goods_id')->toArray();
+        } else if (!empty($goodsClassify)) {
+            if ($goodsClassify == 'SERVICE') {
+                $goodsModel = Goods::whereIn('goods_classify', ['SERVICE', 'CHNMED', 'CHNNCD']);
+            } else {
+                $goodsModel = Goods::where('goods_classify', $goodsClassify);
+            }
 
-                $goodsIds = $goodsModel->pluck('goods_id')->toArray();
+            if (!empty($goodsName)) {
+                $goodsModel->where('goods_name', 'like', '%' . $goodsName . '%');
             }
-            if($goodsIds){
-                $orderIds = OrderSheet::whereIn('join_sheet_goods_id',$goodsIds)->pluck('join_sheet_order_id')->toArray();
-                if($orderIds){
-                    $where['order_id'] = ['in',implode(',',$orderIds)];
-                }
+
+            $goodsIds = $goodsModel->pluck('goods_id')->toArray();
+        }
+        if (!empty($goodsIds)) {
+            $orderIds = OrderSheet::whereIn('join_sheet_goods_id', $goodsIds)->pluck('join_sheet_order_id')->toArray();
+            if ($orderIds) {
+                $where['order_id'] = ['in', implode(',', $orderIds)];
             }
+        }
         // }
-
         $query = $this->doSelect($where, $field, $order);
         return $this->doFormat($query, $format, $limit);
     }
@@ -86,7 +90,7 @@ class DishesController extends Curd{
     {
         $model = $this->model->with([
             'sheets' => function ($query) {
-                $query->select('join_sheet_order_id', 'order_sheet_id', 'join_sheet_goods_id', 'order_sheet_num','order_sheet_price');
+                $query->select('join_sheet_order_id', 'order_sheet_id', 'join_sheet_goods_id', 'order_sheet_num', 'order_sheet_price');
             },
             'member' => function ($query) {
                 $query->select('member_id', 'member_mobile');
@@ -104,7 +108,7 @@ class DishesController extends Curd{
             'express' => function ($query) {
                 $query->select('join_express_order_id', 'order_express_type');
             }
-        ])->leftJoin('order_return','order_return.join_return_order_id','=','order.order_id');
+        ])->leftJoin('order_return', 'order_return.join_return_order_id', '=', 'order.order_id');
         // ->leftJoin('order_sheet','join_sheet_order_id','=','order.order_id');
         foreach ($where as $column => $value) {
             if (is_array($value)) {
@@ -138,7 +142,7 @@ class DishesController extends Curd{
         if ($field) {
             $model = $model->orderBy($field, $order);
         }
-        $model = $model->select('order.*','order_return.orders_return_id', 'order_return.join_return_order_id', 'order_return.order_return_status','order_return.order_return_apply_json','order_return.order_return_remark');
+        $model = $model->select('order.*', 'order_return.orders_return_id', 'order_return.join_return_order_id', 'order_return.order_return_status', 'order_return.order_return_apply_json', 'order_return.order_return_remark');
         return $model;
     }
 
@@ -149,21 +153,21 @@ class DishesController extends Curd{
             $item['sheet'] = $item['sheets'][0] ?? [];
             if (!empty($item['sheet'])) {
                 $goods = Goods::where('goods_id', $item['sheet']['join_sheet_goods_id'])->first();
-                if(count($item['sheets']) > 1 && $goods->goods_classify == 'MEALS'){
+                if (count($item['sheets']) > 1 && $goods && $goods->goods_classify == 'MEALS') {
                     $sheetDeng = ' 等餐品';
                 }
-                $item['sheet']['goods_name'] = ($goods && $goods->goods_name) ? $goods->goods_name.$sheetDeng : '';
+                $item['sheet']['goods_name'] = ($goods && $goods->goods_name) ? $goods->goods_name . $sheetDeng : '';
                 $item['sheet']['goods_classify'] = $goods->goods_classify ?? '';
                 $item['sheet']['order_sheet_num'] = intval($item['sheet']['order_sheet_num']);
             }
             unset($item['sheets']);
-            if (isset($item['orders_return_id'])){
+            if (isset($item['orders_return_id'])) {
                 $item['return'] = [
-                    'orders_return_id'=>$item['orders_return_id'],
+                    'orders_return_id' => $item['orders_return_id'],
                     'join_return_order_id' => $item['join_return_order_id'],
                     'order_return_status' => $item['order_return_status'],
                     'order_return_apply_json' => $item['order_return_apply_json'],
-                    'order_return_remark'=>$item['order_return_remark']
+                    'order_return_remark' => $item['order_return_remark']
                 ];
             }
         }

+ 68 - 5
app/admin/controller/order/PayDetailController.php

@@ -34,6 +34,20 @@ class PayDetailController extends Curd
             $where['pay_status'] = 'SUCCESS';
             $where['pay_category'] = ['<>', 'RECHARGE'];
         }
+        if (!empty($where['pay_addtimes'])) {
+            $where['pay_addtimes'][0] = !empty($where['pay_addtimes'][0]) ? strtotime($where['pay_addtimes'][0]) : '';
+            $where['pay_addtimes'][1] = !empty($where['pay_addtimes'][1]) ? strtotime($where['pay_addtimes'][1]) : '';
+        }
+        if (!empty($request->get('premises_id'))) {
+            $payIds = PayDetail::whereJsonContains('pay_extend_json->remark->premises_id', intval($request->get('premises_id')))
+                ->pluck('pay_id')
+                ->toArray();
+            $where['pay_id'] = '';
+            if (!empty($payIds)) {
+                $where['pay_id'] = ['in', $payIds];
+            }
+        }
+
         // else if ($where['pay_category'] == 'RECHARGE') {
         //     $where['pay_status'] = 'SUCCESS';
         //     $where['pay_category'] = 'RECHARGE';
@@ -76,8 +90,8 @@ class PayDetailController extends Curd
             }
         }
         $model = $model->where(function ($query) {
-            $query->whereIn('pay_prepayid',['ALIPAY','WXPAY'])
-                ->orWhere('pay_prepayid','like','%CASH%');
+            $query->whereIn('pay_prepayid', ['ALIPAY', 'WXPAY'])
+                ->orWhere('pay_prepayid', 'like', '%CASH%');
         });
 
         if ($field) {
@@ -85,6 +99,7 @@ class PayDetailController extends Curd
         }
         return $model;
     }
+
     public function selectWelfare(Request $request): Response
     {
         [$where, $format, $limit, $field, $order] = $this->selectInput($request);
@@ -137,7 +152,7 @@ class PayDetailController extends Curd
             }
         }
         $model = $model->where(function ($query) {
-            $query->Where('pay_prepayid','like','%WELFARE%');
+            $query->Where('pay_prepayid', 'like', '%WELFARE%');
         });
 
         if ($field) {
@@ -154,13 +169,22 @@ class PayDetailController extends Curd
                 $item->pay_prepayid = $prepayId[1];
             }
             $memberAccount = [];
-            if(!empty($item->memberAccount)){
-                foreach($item->memberAccount as $account){
+            if (!empty($item->memberAccount)) {
+                foreach ($item->memberAccount as $account) {
                     $memberAccount[strtolower($account->member_account_classify)] = $account;
                 }
 
                 $item->memberAccount = $memberAccount;
             }
+            if (!empty($item->pay_extend_json)) {
+                $payExtendJson = json_decode($item->pay_extend_json, true);
+                if (isset($payExtendJson['remark'])) {
+                    $item->service = $payExtendJson['remark']['service'] ?? '';
+                    $item->business = $payExtendJson['remark']['business'] ?? '';
+                    $item->premises_id = $payExtendJson['remark']['premises_id'] ?? '';
+                    $item->premises_name = $payExtendJson['remark']['premises_name'] ?? '';
+                }
+            }
         }
 
         return $items;
@@ -362,4 +386,43 @@ class PayDetailController extends Curd
         $data['pay_prepayid'] = 0;
         return $data;
     }
+
+    /**
+     * @Desc 加备注-门店、服务人员、业务人员
+     * @Author Gorden
+     * @Date 2024/8/29 16:14
+     *
+     * @param Request $request
+     * @return Response
+     */
+    public function remark(Request $request)
+    {
+        $payId = $request->post('pay_id', '');
+        if (!$payId) {
+            return json_fail('参数异常');
+        }
+        $payDetail = PayDetail::where('pay_id', $payId)->first();
+        if (!$payDetail) {
+            return json_fail("数据异常");
+        }
+        try {
+            $data = [
+                'premises_id' => $request->post('premises_id', ''),
+                'premises_name' => $request->post('premises_name', ''),
+                'business' => $request->post('business', ''),
+                'service' => $request->post('service', '')
+            ];
+            $payExtendJson = [];
+            if (!empty($payDetail->pay_extend_json)) {
+                $payExtendJson = json_decode($payDetail->pay_extend_json, true);
+            }
+            $payExtendJson['remark'] = $data;
+            $payDetail->pay_extend_json = json_encode($payExtendJson, JSON_UNESCAPED_UNICODE);
+            $payDetail->save();
+
+            return json_success('success');
+        } catch (\Exception $e) {
+            return json_fail('备注保存失败');
+        }
+    }
 }

+ 20 - 4
app/admin/controller/order/RefundController.php

@@ -238,7 +238,20 @@ class RefundController extends Curd
             // 主订单,退款作为优惠入库
             $this->updateMainOrderByRefund($order, $amount, $remark);
             // return 表记录
-            $returnId = $this->createReturnRecord($order, $amount,$remark);
+            if (!OrderReturn::where('join_return_order_id', $orderId)->exists()) {
+                $returnId = $this->createReturnRecord($order, $amount, $remark);
+            }else{
+                //['amount' => $amount, 'user_id' => JwtToken::getCurrentId(), 'datetime' => date('Y-m-d H:i:s'), 'remark' => $remark ?? '']
+                OrderReturn::where('join_return_order_id', $orderId)->update([
+                    'order_return_status' => 'DONE',
+                    'order_return_refund_json'=>json_encode([
+                        'amount' => $amount,
+                        'user_id' => JwtToken::getCurrentId(),
+                        'datetime' => date('Y-m-d H:i:s'),
+                        'remark' => $remark ?? ''
+                    ])
+                ]);
+            }
 
             // 组合支付,退到余额账户
             $prepayid = '';
@@ -255,6 +268,9 @@ class RefundController extends Curd
                 } elseif ($payWay[0] == 'ALIPAY') {
                     $prepayid = 'WXPAY';
                     $response = $this->refundToAlipay($payDetail0, $amount);
+                } elseif ($payWay[0] == 'MONEY') {
+                    $prepayid = 'MONEY';
+                    $response = $this->refundToCash($payDetail0, $amount);
                 } elseif (isset($payWay[1]) && $payWay[1] == 'CASH') {
                     $prepayid = $order->join_order_member_id . '-CASH';
                     $this->refundToCash($order->join_order_member_id, $amount);
@@ -413,7 +429,7 @@ class RefundController extends Curd
                 'coupon_id' => null,
                 'coupon_value' => $amount,
                 'coupon_classify' => '退款',
-                'coupon_detail_id' => $remark
+                'coupon_detail_id' => [$remark]
             ];
 
             $order->order_discount_json = json_encode($orderDiscountJson, JSON_UNESCAPED_UNICODE);
@@ -434,7 +450,7 @@ class RefundController extends Curd
      * @return int
      * @throws BusinessException
      */
-    private function createReturnRecord($order, $amount,$remark)
+    private function createReturnRecord($order, $amount, $remark)
     {
         try {
             return OrderReturn::insertGetId([
@@ -446,7 +462,7 @@ class RefundController extends Curd
                 'order_return_apply_datetime' => date('Y-m-d H:i:s'),
                 'order_return_apply_json' => json_encode(['reason' => '后台自定义退款']),
                 'order_return_accept_datetime' => date('Y-m-d H:i:s'),
-                'order_return_refund_json' => json_encode(['amount' => $amount, 'user_id' => JwtToken::getCurrentId(), 'datetime' => date('Y-m-d H:i:s'),'remark'=>$remark ?? '']),
+                'order_return_refund_json' => json_encode(['amount' => $amount, 'user_id' => JwtToken::getCurrentId(), 'datetime' => date('Y-m-d H:i:s'), 'remark' => $remark ?? '']),
                 'order_return_addtimes' => time()
             ]);
         } catch (\Exception $e) {

File diff suppressed because it is too large
+ 383 - 326
app/admin/controller/order/WholeController.php


+ 37 - 0
app/admin/service/coupon/CouponDetailService.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace app\admin\service\coupon;
+
+use app\model\CouponDetail;
+use app\model\SysSerial;
+use support\exception\BusinessException;
+
+class CouponDetailService
+{
+    /**
+     * @Desc 手动发券
+     * @Author Gorden
+     * @Date 2024/8/27 9:57
+     *
+     * @param $params
+     * @return void
+     * @throws BusinessException
+     */
+    public static function customSendCoupon($params)
+    {
+        try {
+            CouponDetail::insert([
+                'coupon_detail_id' => 'CUDT' . str_pad(SysSerial::getSerial(), 6, '0') . random_string(6, 'up'),
+                'join_detail_coupon_id' => $params['coupon_id'],
+                'join_coupon_detail_member_id' => $params['member_id'],
+                'coupon_detail_status' => 'ACTIVED',
+                'coupon_detail_gain_datetime' => $params['coupon_detail_gain_datetime'],
+                'coupon_detail_deadline_datetime' => $params['coupon_detail_deadline_datetime'],
+                'coupon_detail_extend_json'=>json_encode(['gettype'=>'SEND']),
+                'coupon_detail_addtimes' => time(),
+            ]);
+        } catch (\Exception $e) {
+            throw new BusinessException('写入优惠券失败');
+        }
+    }
+}

+ 75 - 0
app/admin/service/coupon/CouponService.php

@@ -0,0 +1,75 @@
+<?php
+
+namespace app\admin\service\coupon;
+
+use app\model\CouponDetail;
+use support\Db;
+
+class CouponService
+{
+    /**
+     * @Desc 优惠券自动过期
+     * @Author Gorden
+     * @Date 2024/8/26 17:58
+     *
+     * @return void
+     */
+    public static function checkCouponExpired()
+    {
+        $couponDetails = Db::select("select * from app_coupon_detail where (coupon_detail_status = 'INIT' OR coupon_detail_status = 'PENDING' OR coupon_detail_status = 'ACTIVED' OR coupon_detail_status = 'WAITING') AND coupon_detail_deadline_datetime != '' AND CAST(UNIX_TIMESTAMP(coupon_detail_deadline_datetime) as SIGNED) < " . time());
+        foreach ($couponDetails as $detail) {
+            $endTimeUnix = strtotime($detail->coupon_detail_deadline_datetime);
+            if ($endTimeUnix < time()) {
+                CouponDetail::where('coupon_detail_id', $detail->coupon_detail_id)->update(['coupon_detail_status' => 'EXPIRED']);
+                echo $detail->coupon_detail_id . "已过期\n";
+            }
+        }
+    }
+
+    public static function couponClassifyInfo($classify, $category, $value, $limit)
+    {
+        try {
+            switch ($classify) {
+                case "满减券":
+                    if (!empty($limit) && $category == 'NORMAL') {
+                        return "满" . $limit . '减' . $value;
+                    }elseif (!empty($limit) && !empty($value) && $category == 'PIECE'){
+                        return "满" . intval($limit) . '件减' . $value;
+                    }
+                    break;
+                case "立减券":
+                    return "立减" . $value;
+                    break;
+                case "抵用券":
+                    return "抵用券";
+                    break;
+                case "折扣券":
+                    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 "福利券":
+                    return '抵扣' . $value;
+                    break;
+                case "年卡":
+                    return "年卡";
+                    break;
+                case "季卡":
+                    return "季卡";
+                    break;
+                case "月卡":
+                    return "月卡";
+                    break;
+            }
+        } catch (\Exception $e) {
+        }
+
+    }
+}

+ 2 - 0
app/admin/service/goods/GoodsService.php

@@ -1325,6 +1325,8 @@ class GoodsService
             self::labelUpdate($params);
             // 产品运行控制信息表
             self::goodsRunningUpdate($params);
+            // sku表
+            self::goodsSkuSet($params, 'update');
 
             Db::commit();
         } catch (BusinessException $e) {

+ 3 - 1
app/admin/service/member/MemberService.php

@@ -55,7 +55,9 @@ class MemberService
             })->when($level != '', function ($query) use ($level) {
                 if ($level == 'other') {
                     $query->where('member.join_member_role_id', NULL)->orWhere('member.join_member_role_id', '');
-                } else {
+                } else if($level == 'VIP'){
+                    $query->where('member.member_is_vip', 'Y');
+                }else {
                     $query->where('member_role.member_role_id', $level);
                 }
             })->when($isAuth != '', function ($query) use ($isAuth) {

+ 32 - 0
app/admin/service/order/OrderProcessService.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace app\admin\service\order;
+
+use app\model\OrderProcess;
+use support\Log;
+
+class OrderProcessService
+{
+    public static function insert($params)
+    {
+        try {
+            OrderProcess::insert([
+                'join_order_process_member_id' => $params['member_id'],
+                'join_order_process_user_id' => $params['user_id'] ?? '',
+                'join_order_process_dept_id' => $params['dept_id'] ?? 0,
+                'join_process_order_id' => $params['order_id'],
+                'order_process_key' => $params['process_key'],
+                'order_process_name' => $params['process_name'],
+                'order_process_json' => !empty($params['process_json']) ? json_encode($params['process_json']) : '[]',
+                'order_process_datetimes' => date('Y-m-d H:i:s'),
+                'order_process_remark' => $params['process_remark'] ?? '',
+                'order_process_extend_json' => !empty($params['process_extend_json']) ? json_encode($params['process_extend_json']) : '[]',
+                'order_process_addtimes' => time()
+            ]);
+        } catch (\Exception $e) {
+            dump($e->getMessage());
+            $params['msg'] = $e->getMessage();
+            Log::error("WRITE_ORDER_PROCESS_ERROR", $params);
+        }
+    }
+}

+ 428 - 24
app/admin/service/order/OrderService.php

@@ -2,6 +2,8 @@
 
 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;
@@ -225,16 +227,17 @@ class OrderService
                 $config['notify_url'] = getenv('NOTIFY_DOMAIN_ADMIN') . '/notify/orderPay/wxpay';
                 Pay::wechat($config)->pos($payData);
                 $result = self::findWxpay($params['orderGroupId'], 0);
-            }catch (GatewayException $g){
+            } catch (GatewayException $g) {
                 $result = self::findWxpay($params['orderGroupId'], 0);
             } catch (\Exception $e) {
                 $log->error("WXPAY", ['msg' => $e->getMessage()]);
                 $result = self::findWxpay($params['orderGroupId'], 0);
 //                throw new BusinessException("支付失败");
             }
-            try{
+            try {
                 $log->info("WXPAY_RETURN", json_decode(json_encode($result), true));
-            }catch (\Exception $e){}
+            } catch (\Exception $e) {
+            }
 
 
         } else if (in_array($prefix, [25, 26, 27, 28, 29, 30])) {
@@ -246,19 +249,20 @@ class OrderService
             ];
             try {
                 $config = config('payment.alipay');
-                $config['notify_url'] = getenv('NOTIFY_DOMAIN_ADMIN').'/notify/orderPay/alipay';
+                $config['notify_url'] = getenv('NOTIFY_DOMAIN_ADMIN') . '/notify/orderPay/alipay';
                 Pay::alipay($config)->pos($payData);
                 $result = self::findAlipay($params['orderGroupId'], 0);
-            } catch (GatewayException $g){
+            } catch (GatewayException $g) {
                 $result = self::findAlipay($params['orderGroupId'], 0);
             } catch (\Exception $e) {
                 $log->error("ALIPAY", ['msg' => $e->getMessage()]);
                 throw new BusinessException("支付失败");
             }
 
-            try{
+            try {
                 $log->info("ALIPAY_RETURN", json_decode(json_encode($result), true));
-            }catch (\Exception $e){}
+            } catch (\Exception $e) {
+            }
         } else {
             throw new BusinessException("付款码无效");
         }
@@ -286,16 +290,15 @@ class OrderService
         }
 
         if (!empty($result['return_code']) && $result['return_code'] == 'SUCCESS' && !empty($result['result_code']) && $result['result_code'] == 'SUCCESS' && !empty($result['trade_state']) && $result['trade_state'] == 'SUCCESS') {
-            SupportLog::channel('pay')->info("FIND_WXPAY_SUCCESS", ['nbr' => $nbr,'order_id'=>$orderId]);
+            SupportLog::channel('pay')->info("FIND_WXPAY_SUCCESS", ['nbr' => $nbr, 'order_id' => $orderId]);
             return $result;
         } else {
-            if ($nbr > 2) {
-                SupportLog::channel('pay')->error("FIND_WXPAY", ['msg' => '订单查询失败','order_id'=>$orderId]);
-                return ['msg'=>'订单查询失败'];
+            if ($nbr > 1) {
+                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]);
+            sleep(3);
+            SupportLog::channel('pay')->error("FIND_WXPAY", ['nbr' => $nbr, 'order_id' => $orderId]);
             return self::findWxpay($orderId, $nbr + 1);
         }
     }
@@ -320,15 +323,15 @@ class OrderService
         }
 
         if (!empty($result['code']) && $result['code'] == '10000' && !empty($result['trade_status']) && $result['trade_status'] == 'TRADE_SUCCESS') {
-            SupportLog::channel('pay')->info("FIND_ALIPAY_SUCCESS", ['nbr' => $nbr,'order_id'=>$orderId]);
+            SupportLog::channel('pay')->info("FIND_ALIPAY_SUCCESS", ['nbr' => $nbr, 'order_id' => $orderId]);
             return $result;
         } else {
-            if ($nbr > 2) {
-                SupportLog::channel('pay')->error("FIND_ALIPAY", ['msg' => '订单查询失败','order_id'=>$orderId]);
-                return ['msg'=>'订单查询失败'];
+            if ($nbr > 1) {
+                SupportLog::channel('pay')->error("FIND_ALIPAY", ['msg' => '订单查询失败', 'order_id' => $orderId]);
+                return ['msg' => '订单查询失败'];
             }
-            sleep(5);
-            SupportLog::channel('pay')->error("FIND_ALIPAY", ['nbr' => $nbr,'order_id'=>$orderId]);
+            sleep(3);
+            SupportLog::channel('pay')->error("FIND_ALIPAY", ['nbr' => $nbr, 'order_id' => $orderId]);
             return self::findAlipay($orderId, $nbr + 1);
         }
     }
@@ -340,7 +343,7 @@ class OrderService
     {
         foreach ($params['goodsContentList'] as $goods) {
             // 减库存,规格和总库存
-            if (!isset($params['submit_goods_classify']) || $params['submit_goods_classify'] != 'MEALS') {
+            if (!isset($params['submit_goods_classify']) || !in_array($params['submit_goods_classify'], ['MEALS', 'PACKAGE'])) {
                 $goodsSku = GoodsSku::where('goods_sku_id', $goods['sku_id'])->first();
                 $skuStorageJson = json_decode($goodsSku->goods_sku_storage_json, true);
                 if (isset($skuStorageJson['storage']) && !empty($skuStorageJson['storage'])) {
@@ -412,9 +415,410 @@ class OrderService
         $payDetail->save();
     }
 
+    public static function getPayWayByPrepayId($prepayId)
+    {
+        $payWay = '';
+        $categoryArray = explode('-', $prepayId);
+        if (isset($categoryArray[1])) {
+            $payWay = $categoryArray[1];
+        } else if (in_array($categoryArray[0], ['WXPAY', 'ALIPAY', 'OFFLINE', 'OFFLINE_ALIPAY', 'OFFLINE_WXPAY', 'MONEY'])) {
+            $payWay = $categoryArray[0];
+        }
+
+        return $payWay;
+    }
+
+    /**
+     * @Desc 支付使用优惠券
+     * @Author Gorden
+     * @Date 2024/8/28 14:59
+     *
+     * @param $memberId
+     * @param $goods
+     * @param $coupon
+     * @param $payAmount
+     * @return array|mixed
+     */
+    public static function payUseCoupon($type, $settlementNow, $memberId, $goods, $coupon, $payAmount)
+    {
+        try {
+            foreach ($coupon as $item) {
+                if (!in_array(substr($item, 0, 2), ['CU', 'CO'])) {
+                    return [];
+                }
+            }
+            $amountBalance = [
+                'pay_amount' => $payAmount,
+                'welfare_balance' => 0,
+                'cut_balance' => 0,
+            ];
+            foreach ($goods as $good) {
+                $result = OrderService::useCoupon($type, $settlementNow, $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 ?? []
+            ];
+        } catch (\Exception $e) {
+            dump($e->getTrace());
+        }
+    }
+
+    public static function useCoupon($type, $settlementNow, $memberId, $goods, $good, $coupon, $amountBalance)
+    {
+        try {
+            $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', $good['sku_id'])
+                    ->where('join_goods_coupon_id', $couponId)
+                    ->where('coupon_detail.join_coupon_detail_member_id', $memberId);
+                if ($settlementNow == 'Y' && $type == 'pay') {
+                    $couponDetail = $couponDetail->whereIn('coupon_detail.coupon_detail_status', ['ACTIVED', 'WAITING']);
+                } else {
+                    $couponDetail = $couponDetail->where('coupon_detail.coupon_detail_status', 'ACTIVED');
+                }
+                $couponDetail = $couponDetail->orderBy('coupon_detail_id', 'DESC')
+                    ->first();
+                if (!$couponDetail) {
+                    continue;
+                }
+                if ($settlementNow == 'Y') {
+                    $updateData = [
+                        'coupon_detail_status' => 'USED',
+                        'coupon_detail_used_datetime' => date('Y-m-d H:i:s')
+                    ];
+                } else {
+                    $updateData = [
+                        'coupon_detail_status' => 'WAITING',
+                    ];
+                }
+                // 计算优惠券包含的优惠商品的件数和总价
+                $countAndAmount = self::countAndAmount($goods, $couponId);
+                // 如果是计件
+                if ($couponDetail->coupon_category == 'PIECE' && $countAndAmount['count'] < $couponDetail->coupon_minimum_limit) {
+                    continue;
+                }
+                if (in_array($couponDetail->coupon_classify, ['立减券', '满减券'])) {
+                    if (Redis::sIsMember($cacheKey, $couponId)) {
+                        continue;
+                    }
+                    Redis::sAdd($cacheKey, $couponId);
+                    if ($couponDetail->coupon_category == 'PIECE' || ($couponDetail->coupon_category == 'NORMAL' && $countAndAmount['amount'] >= $couponDetail->coupon_minimum_limit)) {
+                        $payAmount = $payAmount - $couponDetail->coupon_value;
+                        // json记录
+                        $discountData[$couponId] = [
+                            'coupon_id' => $couponId,
+                            'coupon_value' => $couponDetail->coupon_value,
+                            '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($updateData);
+                    }
+                } elseif ($couponDetail->coupon_classify == '折扣券') {
+                    if (Redis::sIsMember($cacheKey, $couponId)) {
+                        continue;
+                    }
+                    Redis::sAdd($cacheKey, $couponId);
+                    if ($couponDetail->coupon_category == 'PIECE' || ($couponDetail->coupon_category == 'NORMAL' && $countAndAmount['amount'] >= $couponDetail->coupon_minimum_limit)) {
+                        $zhekouAmount = round($countAndAmount['amount'] * (100 - $couponDetail->coupon_value) / 100, 2);
+                        $payAmount = $payAmount - $zhekouAmount;
+                        // 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($updateData);
+                    }
+                } elseif (in_array($couponDetail->coupon_classify, ['抵用券', '赠品券'])) {
+                    if (Redis::sIsMember($cacheKey, $couponId)) {
+                        continue;
+                    }
+                    Redis::sAdd($cacheKey, $couponId);
+                    CouponDetail::where('coupon_detail_id', $couponDetail->coupon_detail_id)->update($updateData);
+                    if ($good['nbr'] > 1) {
+                        $diyongAmount = $good['goods_sales_price'];
+                        $payAmount = $payAmount - $diyongAmount;
+                    } elseif (ceil($good['nbr']) == 1) {
+                        $diyongAmount = round($good['goods_sales_price'] * $good['nbr'], 2);
+                        $payAmount = $payAmount - $diyongAmount;
+                    }
+                    // json记录
+                    $discountData[$couponId] = [
+                        'coupon_id' => $couponId,
+                        'coupon_value' => $diyongAmount,
+                        'coupon_classify' => $couponDetail->coupon_classify,
+                        'coupon_detail_id' => [$couponDetail->coupon_detail_id]
+                    ];
+                    Redis::set($cacheDiscountKey, json_encode($discountData, JSON_UNESCAPED_UNICODE));
+                } elseif ($couponDetail->coupon_classify == '福利券') {
+                    if (Redis::sIsMember($cacheKey, $couponId)) {
+                        continue;
+                    }
+                    Redis::sAdd($cacheKey, $couponId);
+                    CouponDetail::where('coupon_detail_id', $couponDetail->coupon_detail_id)->update($updateData);
+                    $fuliAmount = 0;
+                    if (!empty($couponDetail->coupon_value)) {
+                        $fuliAmount = $couponDetail->coupon_value;
+                    }
+
+                    if ($fuliAmount >= $countAndAmount['amount']) {
+                        $preferentialAmount = $countAndAmount['amount'];
+                    } else {
+                        $preferentialAmount = $fuliAmount;
+                    }
+                    $payAmount = $payAmount - $preferentialAmount;
+
+                    // json记录
+                    $discountData[$couponId] = [
+                        'coupon_id' => $couponId,
+                        'coupon_value' => $preferentialAmount,
+                        '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));
+                }
+            }
+
+            if ($payAmount < 0) {
+                $payAmount = 0;
+            }
+            $amountBalance = [
+                'pay_amount' => round($payAmount, 2),
+                'welfare_balance' => 0,
+                'cut_balance' => 0
+            ];
+            return $amountBalance;
+        } catch (\Exception $e) {
+            Redis::del("ORDER:USE:COUPON:" . $memberId);
+            Redis::del("ORDER:USE:COUPON:DISCOUNT:" . $memberId);
+            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($settlementNow, $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);
+                if ($settlementNow == 'Y') {
+                    $couponDetail = $couponDetail->whereIn('coupon_detail.coupon_detail_status', ['ACTIVED', 'WAITING']);
+                } else {
+                    $couponDetail = $couponDetail->where('coupon_detail.coupon_detail_status', 'ACTIVED');
+                }
+                $couponDetail = $couponDetail->orderBy('coupon_detail_id', 'DESC')
+                    ->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 (Redis::sIsMember($cacheKey, $couponId)) {
+                        continue;
+                    }
+                    Redis::sAdd($cacheKey, $couponId);
+                    if ($couponDetail->coupon_category == 'PIECE' || ($couponDetail->coupon_category == 'NORMAL' && $countAndAmount['amount'] >= $couponDetail->coupon_minimum_limit)) {
+                        $payAmount = $payAmount - $couponDetail->coupon_value;
+                    }
+                } elseif ($couponDetail->coupon_classify == '折扣券') {
+                    if (Redis::sIsMember($cacheKey, $couponId)) {
+                        continue;
+                    }
+                    Redis::sAdd($cacheKey, $couponId);
+                    if ($couponDetail->coupon_category == 'PIECE' || ($couponDetail->coupon_category == 'NORMAL' && $countAndAmount['amount'] >= $couponDetail->coupon_minimum_limit)) {
+                        $zhekouAmount = round($countAndAmount['amount'] * (100 - $couponDetail->coupon_value) / 100, 2);
+                        $payAmount = $payAmount - $zhekouAmount;
+                    }
+                } elseif (in_array($couponDetail->coupon_classify, ['抵用券', '赠品券'])) {
+                    if (Redis::sIsMember($cacheKey, $couponId)) {
+                        continue;
+                    }
+                    Redis::sAdd($cacheKey, $couponId);
+                    if ($good['nbr'] > 1) {
+                        $diyongAmount = $good['goods_sales_price'];
+                        $payAmount = $payAmount - $diyongAmount;
+                    } elseif (ceil($good['nbr']) == 1) {
+                        $diyongAmount = round($good['goods_sales_price'] * $good['nbr'], 2);
+                        $payAmount = $payAmount - $diyongAmount;
+                    }
+                } elseif ($couponDetail->coupon_classify == '福利券') {
+                    if (Redis::sIsMember($cacheKey, $couponId)) {
+                        continue;
+                    }
+                    Redis::sAdd($cacheKey, $couponId);
+                    $fuliAmount = 0;
+                    if (!empty($couponDetail->coupon_value)) {
+                        $fuliAmount = $couponDetail->coupon_value;
+                    }
+                    if ($fuliAmount >= $countAndAmount['amount']) {
+                        $preferentialAmount = $countAndAmount['amount'];
+                    } else {
+                        $preferentialAmount = $fuliAmount;
+                    }
+                    $payAmount = $payAmount - $preferentialAmount;
+                } 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) {
+            Redis::del("ORDER:USE:COUPON:" . $memberId);
+            Redis::del("ORDER:USE:COUPON:DISCOUNT:" . $memberId);
+            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());
+        }
+    }
+
+
+    public static $couponClassify = [
+        'wipe' => '抹零',
+        'custom' => '自定义优惠金额'
+    ];
 
-    public static $couponClassify=[
-        'wipe'=>'抹零',
-        'custom'=>'自定义优惠金额'
+    public static $payWay = [
+        'WXPAY' => '微信支付',
+        'ALIPAY' => '支付宝',
+        'CASH' => '账户余额',
+        'CARD' => '储值卡',
+        'WELFARE' => '福利账户',
+        'MONEY' => '现金',
+        'OFFLINE' => '线下支付',
+        'OFFLINE_WXPAY' => '线下支付-微信',
+        'OFFLINE_ALIPAY' => '线下支付-支付宝',
+        'QRCODE' => '付款码',
+        'NONE' => '付零',
+        'VIP' => 'VIP账户'
     ];
 }

+ 11 - 7
app/admin/service/statistics/MemberService.php

@@ -12,7 +12,7 @@ class MemberService
         $data = [];
 
         // 会员数量
-        $data['memberCount'] = Member::where('member_is_owner', 'N')->count();
+        $data['memberCount'] = Member::where('member_is_owner', 'N')->where('member_mobile', '<>', '0000')->count();
         // 业主数量
         $data['ownerCount'] = Member::where('member_is_owner', 'Y')->count();
         // 用户总数
@@ -22,7 +22,11 @@ class MemberService
         $data['todayCount'] = Member::where('member_addtimes', '>', $todayTime)->where('member_is_owner', 'N')->count();
         // 本月新增用户数
         $monthTime = strtotime(date('Y-m-01 00:00:00'));
-        $data['monthCount'] = Member::where('member_addtimes', '>', $monthTime)->where('member_is_owner', 'N')->count();
+        $monthEndTime = strtotime(date('y-m-t 23:59:59'));
+        $data['monthCount'] = Member::whereBetween('member_addtimes', [$monthTime, $monthEndTime])
+            ->where('member_is_owner', 'N')
+            ->where('member_mobile', '<>', '0000')
+            ->count();
 
         // 折线图-会员
         $newAddition = Db::select("
@@ -30,18 +34,18 @@ class MemberService
                 DATE_FORMAT(FROM_UNIXTIME(member_addtimes), '%Y/%m') AS `month`,
                 count(*) as `num` 
             FROM app_member 
-            where member_is_owner='N' and member_addtimes >= UNIX_TIMESTAMP(DATE_SUB(CURDATE(), INTERVAL 12 MONTH)) and member_addtimes <= UNIX_TIMESTAMP()
+            where member_is_owner='N' and member_mobile != '0000' and member_addtimes >= UNIX_TIMESTAMP(DATE_SUB(CURDATE(), INTERVAL 12 MONTH)) and member_addtimes <= UNIX_TIMESTAMP()
             group by month 
             order by month asc ");
         $newAddition12Month = [];
         $months = month_12();
-        foreach ($months as $key => $month){
-            foreach ($newAddition as $item){
-                if ($month == $item->month){
+        foreach ($months as $key => $month) {
+            foreach ($newAddition as $item) {
+                if ($month == $item->month) {
                     $newAddition12Month[$key] = $item;
                 }
             }
-            if (!isset($newAddition12Month[$key])){
+            if (!isset($newAddition12Month[$key])) {
                 $std = new \stdClass();
                 $std->month = $month;
                 $std->num = 0;

+ 23 - 4
app/event/order/KangyangCityEvent.php

@@ -8,13 +8,26 @@ use app\model\Goods;
 use app\model\Member;
 use app\model\MemberAccount;
 use app\model\SysSerial;
+use support\Log;
 
 class KangyangCityEvent
 {
     public function grant($params)
     {
         // 会员VIP 标识
-        Member::where('member_id', $params['member_id'])->update(['member_is_vip' => 'Y']);
+        $member = Member::where('member_id', $params['member_id'])->select('member_mobile', 'member_is_vip', 'member_extend_json')->first();
+        $memberUpdateData = [
+            'member_is_vip' => 'Y'
+        ];
+        if (!empty($params['referee'])) {
+            $memberExtendJson = [];
+            if (!empty($member->member_extend_json)) {
+                $memberExtendJson = json_decode($member->member_extend_json, true);
+            }
+            $memberExtendJson['referee'][date('Y-m-d H:i:s')] = $params['referee'];
+            $memberUpdateData['member_extend_json'] = json_encode($memberExtendJson, JSON_UNESCAPED_UNICODE);
+        }
+        Member::where('member_id', $params['member_id'])->update($memberUpdateData);
         // 康养城VIP账户
         $memberAccount = MemberAccount::where('join_account_member_id', $params['member_id'])->where('member_account_classify', 'VIP')->first();
         if (!$memberAccount) {
@@ -48,14 +61,14 @@ class KangyangCityEvent
                         continue;
                     }
                     // 券是否过期
-                    if (!empty($couponModel->coupon_validdate_end) && strtotime($couponModel->coupon_validdate_end) < time()){
+                    if (!empty($couponModel->coupon_validdate_end) && strtotime($couponModel->coupon_validdate_end) < time()) {
                         continue;
                     }
                     $endDate = '';
                     if (!empty($couponModel->coupon_validdate_end)) {
                         $endDate = $couponModel->coupon_validdate_end;
                     } elseif ($couponModel->coupon_validdate_day > 0) {
-                        $endDate = date('Y-m-d H:i:s', time() + ($couponModel->coupon_validdate_day * 24 * 3600));
+                        $endDate = date('Y-m-d H:i:s', time() + ($couponModel->coupon_validdate_day * 24 * 3600) - 1);
                     }
 
                     $num = $coupon['num'];
@@ -68,12 +81,18 @@ class KangyangCityEvent
                             'coupon_detail_gain_datetime' => date('Y-m-d H:i:s'),
                             'coupon_detail_deadline_datetime' => $endDate,
                             'coupon_detail_json' => '[]',
-                            'coupon_detail_extend_json' => json_encode(['gettype'=>'VIP']),
+                            'coupon_detail_extend_json' => json_encode(['gettype' => 'VIP']),
                             'coupon_detail_addtimes' => time()
                         ]);
                     }
                 }
             }
         }
+        // 通知判客
+        if (!empty($member->member_mobile)) {
+            $url = getenv("MARKET_NOTICE_DOMAIN") . '/custom/market_custom/update';
+            $result = http_post($url, ['mobile' => $member->member_mobile]);
+            Log::info("MARKET_NOTICE_" . $member->member_mobile, json_decode($result, true));
+        }
     }
 }

+ 42 - 0
app/event/order/OrderProcessEvent.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace app\event\order;
+
+use app\admin\service\order\OrderProcessService;
+use app\model\OrderProcess;
+use support\Log;
+use Tinywan\Jwt\JwtToken;
+
+class OrderProcessEvent
+{
+    public function orderComplete($params)
+    {
+        try {
+            $userId = JwtToken::getCurrentId();
+        } catch (\Exception $e) {
+        }
+
+        try {
+            $data = [
+                'process_key' => 'DONE',
+                'process_name' => '订单完成',
+                'user_id' => $userId ?? '',
+                'process_json' => $params
+            ];
+            if (!empty($params['join_order_member_id'])) {
+                $data['member_id'] = $params['join_order_member_id'];
+            }
+            if (!empty($params['orderId'])) {
+                $data['order_id'] = $params['orderId'];
+            }
+            if (!empty($params['submit_premises_id'])) {
+                $data['dept_id'] = $params['submit_premises_id'];
+            }
+            OrderProcessService::insert($data);
+        } catch (\Exception $e) {
+            dump($e->getMessage());
+            $params['msg'] = $e->getMessage();
+            Log::error("WRITE_ORDER_PROCESS_ERROR", $params);
+        }
+    }
+}

+ 2 - 1
app/model/CouponGoods.php

@@ -27,7 +27,8 @@ class CouponGoods extends Model
     }
 
     public function skus(){
-        return $this->hasMany(GoodsSku::class,'join_sku_goods_id','join_coupon_goods_id');
+        return $this->hasMany(GoodsSku::class,'join_sku_goods_id','join_coupon_goods_id')
+            ->where('goods_sku_status','ON');
     }
 
     public function sku(){

+ 2 - 1
app/model/Goods.php

@@ -70,7 +70,8 @@ class Goods extends Model
     public function sku()
     {
         return $this->hasMany(GoodsSku::class,'join_sku_goods_id','goods_id')
-            ->select('goods_sku_id','join_sku_goods_id','goods_sku_specs_json','goods_sku_sales_price');
+//            ->where('goods_sku_status','ON')
+            ->select('goods_sku_id','join_sku_goods_id','goods_sku_specs_json','goods_sku_sales_price','goods_sku_status');
     }
 
     public function user(){

+ 23 - 0
app/model/OrderProcess.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace app\model;
+
+use support\Model;
+
+class OrderProcess extends Model
+{
+    protected $table = 'order_process';
+
+    protected $primaryKey = 'orders_process_id';
+
+    protected $dateFormat = 'U';
+
+    const CREATED_AT = 'order_process_addtimes';
+
+    const UPDATED_AT = null;
+
+    public function serializeDate(\DateTimeInterface $date)
+    {
+        return $date->format('Y-m-d H:i:s');
+    }
+}

+ 3 - 0
config/event.php

@@ -15,5 +15,8 @@ return [
     ],
     'order_pay.member_level.up' => [
         [\app\event\MemberLevelEvent::class,'payOrderLevelUp']
+    ],
+    'order.complete' => [
+        [\app\event\order\OrderProcessEvent::class,'orderComplete']
     ]
 ];

+ 4 - 0
process/Task.php

@@ -4,6 +4,7 @@ namespace process;
 
 use app\admin\controller\notify\RechargeController;
 use app\admin\service\client\MessageService;
+use app\admin\service\coupon\CouponService;
 use app\admin\service\goods\GoodsService;
 use app\admin\service\order\OrderService;
 use app\admin\service\order\PayDetailService;
@@ -28,6 +29,9 @@ class Task
 
             // 会员消息 30分钟未读,发送站内信
             MessageService::unreadChatMessage();
+
+            // 优惠券自动过期
+            CouponService::checkCouponExpired();
         });
 
         // 每天的2点执行,注意这里省略了秒位

+ 3 - 0
route/admin.php

@@ -683,6 +683,7 @@ Route::group('/admin', function () {
             Route::get('/welfareInfo', [\app\admin\controller\member\MemberController::class, 'welfareInfo']);
             Route::get('/vipInfo', [\app\admin\controller\member\MemberController::class, 'vipInfo']);
             Route::get('/coupon', [\app\admin\controller\member\MemberController::class, 'coupon']);
+            Route::get('/couponCount', [\app\admin\controller\member\MemberController::class, 'couponCount']);
             Route::get('/balanceInfo', [\app\admin\controller\member\MemberController::class, 'balanceInfo']);
             Route::get('/pointInfo', [\app\admin\controller\member\MemberController::class, 'pointInfo']);
             Route::get('/list', [\app\admin\controller\member\MemberController::class, 'list']);
@@ -869,6 +870,7 @@ Route::group('/admin', function () {
             Route::get('/selectList', [\app\admin\controller\coupon\CouponController::class, 'selectList']);
             Route::get('/info', [\app\admin\controller\coupon\CouponController::class, 'info']);
             Route::post('/add', [\app\admin\controller\coupon\CouponController::class, 'insert']);
+            Route::post('/customSend', [\app\admin\controller\coupon\CouponController::class, 'customSend']);
             Route::post('/update', [\app\admin\controller\coupon\CouponController::class, 'update']);
             Route::delete('/delete', [\app\admin\controller\coupon\CouponController::class, 'delete']);
         })->middleware([
@@ -878,6 +880,7 @@ Route::group('/admin', function () {
             Route::get('/list', [\app\admin\controller\coupon\CouponDetailController::class, 'select']);
             Route::get('/info', [\app\admin\controller\coupon\CouponDetailController::class, 'info']);
             Route::post('/updateStatus', [\app\admin\controller\coupon\CouponDetailController::class, 'updateStatus']);
+            Route::get('/myCouponGrouping',[\app\admin\controller\coupon\CouponDetailController::class,'myCouponGrouping']);
         })->middleware([
             \app\middleware\AdminAuthCheck::class
         ]);

Some files were not shown because too many files changed in this diff