Browse Source

完善功能

gorden 10 months ago
parent
commit
17c1705640

+ 10 - 0
app/admin/controller/goods/ServiceGoodsController.php

@@ -82,6 +82,16 @@ class ServiceGoodsController
         return GoodsService::update($request->post());
     }
 
+    public function changeStatus(Request $request): Response
+    {
+        $validate = new GoodsValidate();
+        if (!$validate->scene('changeStatus')->check($request->post())) {
+            return json_fail($validate->getError());
+        }
+
+        return GoodsService::changeStatus($request->post());
+    }
+
     /**
      * @Desc 删除商品
      * @Author Gorden

+ 5 - 1
app/admin/controller/order/AppointmentController.php

@@ -23,7 +23,6 @@ class AppointmentController
         return AppointmentService::select($request);
     }
 
-
     public function confirm($id): Response
     {
         return AppointmentService::confirm($id);
@@ -38,4 +37,9 @@ class AppointmentController
     {
         return AppointmentService::update($request);
     }
+
+    public function getTimes(Request $request)
+    {
+        return AppointmentService::getTimes($request);
+    }
 }

+ 34 - 3
app/admin/controller/order/WholeController.php

@@ -7,6 +7,7 @@ use app\admin\validate\device\DeviceValidate;
 use app\admin\validate\order\OrderExpressValidate;
 use app\admin\validate\order\OrderValidate;
 use app\controller\Curd;
+use app\model\Appointment;
 use app\model\Coupon;
 use app\model\Device;
 use app\model\Goods;
@@ -250,8 +251,8 @@ class WholeController extends Curd
             'goods' => function ($query) {
                 $query->select('goods_id', 'goods_name', 'goods_cover');
             },
-            'order' => function($query){
-                $query->select('order_id','order_status_system','order_status_payment','order_status_storage');
+            'order' => function ($query) {
+                $query->select('order_id', 'order_status_system', 'order_status_payment', 'order_status_storage');
             }
         ])->where('join_sheet_member_id', $memberId)
             ->orderBy('order_sheet_addtimes', 'desc')
@@ -262,7 +263,37 @@ class WholeController extends Curd
                 $item->goods->goods_cover = getenv('STORAGE_DOMAIN') . $item->goods->goods_cover;
             }
         }
-        return json_success('', $sheet);
+
+        // 预约单
+        $appointments = Db::table('appointment')
+//            ->leftJoin('member', 'member.member_id', '=', 'appointment.join_appointment_member_id')
+//            ->leftJoin('member_cert', 'member_cert.join_cert_member_id', '=', 'appointment.join_appointment_member_id')
+//            ->leftJoin('member_info', 'member_info.join_info_member_id', '=', 'appointment.join_appointment_member_id')
+            ->leftJoin('goods', 'goods.goods_id', '=', 'appointment.join_appointment_goods_id')
+//            ->leftJoin('order', 'order.order_id', '=', 'appointment.join_appointment_order_id')
+            ->leftJoin('member_benefit', 'member_benefit.member_benefit_id', '=', 'appointment.join_appointment_member_benefit_id')
+//            ->leftJoin('goods_sku', 'goods_sku.goods_sku_id', '=', 'appointment.join_appointment_goods_sku_id')
+            ->where('join_appointment_member_id', $memberId)
+            ->select('appointment.*',
+//            'member.member_mobile',
+//            'member_cert.member_cert_name',
+//            'member_info.member_info_nickname',
+                'goods.goods_name', 'goods.goods_sales_price',
+//            'order.order_name', 'goods_sku.goods_sku_specs_json', 'order.order_amount_total', 'order.order_amount_pay',
+//            'order.order_category', 'order.order_status_system', 'order.order_status_payment', 'order.order_status_storage',
+//            'order.order_addtimes',
+                'member_benefit.member_benefit_name'
+            )
+            ->orderBy('appointment.appointment_addtimes', 'desc')
+            ->get();
+        foreach ($appointments as &$row) {
+            if ($row->appointment_category == 'NOFEE') {
+                $row->member_benefit_name = "后付费预约";
+            }
+            $row->appointment_addtimes = date('Y-m-d H:i:s', $row->appointment_addtimes);
+        }
+
+        return json_success('', ['order' => $sheet, 'appointment' => $appointments]);
     }
 
     // TODO 确认收货(完成订单)

+ 39 - 1
app/admin/controller/sys_manage/RoleController.php

@@ -4,10 +4,19 @@ namespace app\admin\controller\sys_manage;
 
 use app\admin\service\sys_manage\RoleService;
 use app\admin\validate\sys_manage\RoleValidate;
+use app\common\Tree;
+use app\controller\Curd;
+use app\model\SysRole;
 use support\Request;
+use support\Response;
 
-class RoleController
+class RoleController extends Curd
 {
+    public function __construct()
+    {
+        $this->model = new SysRole();
+    }
+
     /**
      * @Desc 角色列表
      * @Author Gorden
@@ -21,6 +30,35 @@ class RoleController
         return RoleService::roleList($request);
     }
 
+    public function select(Request $request): Response
+    {
+        [$where, $format, $limit, $field, $order] = $this->selectInput($request);
+        $format = 'tree';
+        $order = $request->get('order', 'desc');
+        $field = $field ?? 'role_addtimes';
+        $query = $this->doSelect($where, $field, $order);
+        return $this->doFormat($query, $format, 1000);
+    }
+
+    protected function formatTree($items): Response
+    {
+        $format_items = [];
+        foreach ($items as $item) {
+            $format_items[] = [
+                'name' => $item->role_name,
+                'value' => (string)$item->role_id,
+                'id' => $item->id ?? $item->role_id,
+                'pid' => $item->pid ?? $item->role_superior_id,
+                'role_status' => $item->role_status,
+                'role_permission' => $item->role_permission,
+                'role_category' => $item->role_category,
+                'role_addtimes' => $item->role_addtimes,
+            ];
+        }
+        $tree = new Tree($format_items);
+        return json_success('success', $tree->getTree());
+    }
+
     /**
      * @Desc 角色详情
      * @Author Gorden

+ 34 - 5
app/admin/service/goods/GoodsService.php

@@ -259,6 +259,13 @@ class GoodsService
                 $data['goods_detail_slider_json'] = rtrim($slider, ',');
             }
 
+            if ($data['is_support_appointment'] == 'Y') {
+                $extendJson = json_decode($data['goods_extend_json'], true);
+                if (isset($extendJson['times'])){
+                    $data['appointment_times'] = $extendJson['times'];
+                }
+            }
+
             $data['goods_on_addtimes'] = date('Y-m-d\TH:i:s.u\Z', $data['goods_on_addtimes'] - 60 * 60 * 8);
 
             return json_success('', $data);
@@ -392,7 +399,7 @@ class GoodsService
                 $redis->sAdd(Goods::LISTING_KEY_PREFIX . $key, $params['goods_id']);
             }
             // 自动下架
-            if ($params['goods_running_off_type'] == 'T' && !empty($params['goods_off_addtimes'])) {
+            if (!empty($params['goods_running_off_type']) && $params['goods_running_off_type'] == 'T' && !empty($params['goods_off_addtimes'])) {
                 $redis = Redis::connection();
                 $key = Goods::LISTING_OFF_KEY_PREFIX . date('YmdHi', strtotime($params['goods_off_addtimes']));
                 $redis->sAdd($key, $params['goods_id']);
@@ -489,6 +496,17 @@ class GoodsService
         return json_success('success');
     }
 
+    public static function changeStatus($params)
+    {
+        try {
+            Goods::where('goods_id', $params['goods_id'])->update(['goods_status' => $params['goods_status']]);
+
+            return json_success('修改成功');
+        } catch (\Exception $e) {
+            return json_fail('修改状态失败');
+        }
+    }
+
 
     public static function updatePackage($params)
     {
@@ -604,6 +622,12 @@ class GoodsService
             $model->goods_remark = $params['goods_remark'] ?? '';
             $model->goods_extend_json = $params['goods_extend_json'] ?? '{}';
             $model->goods_addtimes = time();
+
+            if (!empty($params['is_support_appointment']) && $params['is_support_appointment'] == 'Y' &&  !empty($params['appointment_times'])) {
+                $model->goods_extend_json = [
+                    'times' => $params['appointment_times']
+                ];
+            }
             if ($model->save()) {
                 return $model->goods_id;
             }
@@ -722,8 +746,8 @@ class GoodsService
             $model->join_running_goods_id = $params['goods_id'];
             $model->goods_running_storage = $params['goods_running_storage'] ?? '';
             $model->goods_running_sale = $params['goods_running_sale'] ?? '';
-            $model->goods_running_off_type = $params['goods_running_off_type'] ?? '';
-            $model->goods_running_off_json = $params['goods_running_off_type'] == 'T' && !empty($params['goods_off_addtimes']) ? json_encode(['time' => strtotime($params['goods_off_addtimes'])]) : '[]';
+            $model->goods_running_off_type = !empty($params['goods_running_off_type']) ? $params['goods_running_off_type'] : '';
+            $model->goods_running_off_json = !empty($params['goods_running_off_type']) && $params['goods_running_off_type'] == 'T' && !empty($params['goods_off_addtimes']) ? json_encode(['time' => strtotime($params['goods_off_addtimes'])]) : '[]';
             if (!$model->save()) {
                 throw new BusinessException('数据写入失败');
             }
@@ -792,6 +816,11 @@ class GoodsService
                 $newKey = Goods::LISTING_KEY_PREFIX . date('YmdHi', $data['goods_on_addtimes']);
                 $redis->sadd($newKey, $data['goods_id']);
             }
+            if (!empty($params['is_support_appointment']) && $params['is_support_appointment'] == 'Y' &&  !empty($params['appointment_times'])) {
+                $data['goods_extend_json'] = [
+                    'times' => $params['appointment_times']
+                ];
+            }
             foreach ($data as $key => $val) {
                 $row->{$key} = $val;
             }
@@ -874,7 +903,7 @@ class GoodsService
             $data = self::inputFilter($params, new GoodsRunning());
             // 根据goods_id 查详情ID
             $detail = GoodsRunning::where('join_running_goods_id', $params['goods_id'])->first();
-            if ($params['goods_running_off_type'] == 'T') {
+            if (!empty($params['goods_running_off_type']) && $params['goods_running_off_type'] == 'T') {
                 $redis = Redis::connection();
                 if (!empty($detail->goods_running_off_json)) {
                     $goodsRunningOffJson = json_decode($detail->goods_running_off_json, true);
@@ -895,7 +924,7 @@ class GoodsService
                 $newKey = Goods::LISTING_OFF_KEY_PREFIX . date('YmdHi', strtotime($params['goods_off_addtimes']));
                 $redis->sAdd($newKey, $params['goods_id']);
 
-            } else if ($params['goods_running_off_type'] == 'H' && $detail->goods_running_off_type == 'T') {
+            } else if (!empty($params['goods_running_off_type']) && !empty($detail->goods_running_off_type) && $params['goods_running_off_type'] == 'H' && $detail->goods_running_off_type == 'T') {
                 $goodsRunningOffJson = json_decode($detail->goods_running_off_json, true);
                 if (isset($goodsRunningOffJson['time'])) {
                     $oldKey = Goods::LISTING_OFF_KEY_PREFIX . date('YmdHi', $goodsRunningOffJson['time']);

+ 345 - 7
app/admin/service/order/AppointmentService.php

@@ -4,7 +4,14 @@ namespace app\admin\service\order;
 
 use app\model\Appointment;
 use app\model\Goods;
+use app\model\Member;
+use app\model\MemberAccount;
 use app\model\MemberBenefit;
+use app\model\MemberCert;
+use app\model\MemberInfo;
+use app\model\Order;
+use app\model\OrderSheet;
+use app\model\PayDetail;
 use app\model\SysSerial;
 use support\Db;
 use support\Request;
@@ -20,7 +27,6 @@ class AppointmentService
         $mobile = $request->get('mobile', '');
         $status = $request->get('status', '');
 
-
         $rows = Db::table('appointment')
             ->leftJoin('member', 'member.member_id', '=', 'appointment.join_appointment_member_id')
             ->leftJoin('member_cert', 'member_cert.join_cert_member_id', '=', 'appointment.join_appointment_member_id')
@@ -57,12 +63,16 @@ class AppointmentService
             $row->goods_sku_specs_json = !empty($row->goods_sku_specs_json) ? json_decode($row->goods_sku_specs_json, true) : [];
             $row->order_addtimes = date('Y-m-d H:i:s', $row->order_addtimes);
             $row->appointment_addtimes = date('Y-m-d H:i:s', $row->appointment_addtimes);
-            $row->appointment_apply_json = !empty($row->appointment_apply_json) ? json_decode($row->appointment_apply_json) : [];
+//            $row->appointment_apply_json = !empty($row->appointment_apply_json) ? json_decode($row->appointment_apply_json) : [];
             if ($row->appointment_category == 'NOFEE') {
                 $row->member_benefit_name = "后付费预约";
             }
+            if (!empty($row->appointment_apply_json)) {
+                $applyJson = json_decode($row->appointment_apply_json, true);
+                $row->person = $applyJson['person'] ?? '';
+                $row->appointment_times = $applyJson['times'] ?? '';
+            }
         }
-
         return json_success('', compact('rows', 'page', 'pageSize', 'total'));
     }
 
@@ -89,12 +99,81 @@ class AppointmentService
         $params = $request->post();
         Db::beginTransaction();
         try {
+            // 先检查选择的时段是否可预约
+            $goods = Goods::where('goods_id', $params['join_appointment_goods_id'])->first();
+            $appointments = Appointment::where('appointment_datetime', $params['appointment_datetime'])->get()->toArray();
+            if ($goods->is_support_appointment == 'Y' && !empty($goods->goods_extend_json)) {
+                // {"times": [{"person": 2, "appointmentTimeEnd": "07:00", "appointmentTimeStart": "06:30"}, {"person": 3, "appointmentTimeEnd": "07:30", "appointmentTimeStart": "07:00"}]}
+                $extendJson = json_decode($goods->goods_extend_json, true);
+                foreach ($extendJson['times'] as $key => $time) {
+                    $timesStr = $time['appointmentTimeStart'] . '~' . $time['appointmentTimeEnd'];
+                    if ($timesStr == $params['appointment_times']) {
+                        foreach ($appointments as $appointment) {
+                            $applyJson = json_decode($appointment['appointment_apply_json'], true);
+                            $applyJsonTimes = $applyJson['times'] ?? '';
+
+                            if ($timesStr == $applyJsonTimes) {
+                                $extendJson['times'][$key]['person'] -= $applyJson['person'];
+                                if ($extendJson['times'][$key]['person'] < $params['person']) {
+                                    return json_fail('当前时段已满员,请选择其他时段');
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            // 如果没有,新建
+            if (empty($params['join_appointment_member_id']) && !empty($params['username']) && !empty($params['mobile'])) {
+                $memberId = "ME" . str_pad(SysSerial::getSerial(), 16, "0", STR_PAD_LEFT) . random_string(6, 'up');
+                $params['join_appointment_member_id'] = $memberId;
+
+                // 主表
+                $memberData = [
+                    'member_id' => $memberId,
+                    'member_is_owner' => 'N',
+                    'member_classify' => 'MEMBER',
+                    'member_status' => 'ACTIVED',
+                    'member_mobile' => $params['mobile'],
+                    'member_from' => 'backstage',
+                    'member_addtimes' => time()
+                ];
+                Member::insert($memberData);
+                // 账户表
+                $accountData = [
+                    'join_account_member_id' => $memberId,
+                    'member_account_classify' => 'POINTS',
+                    'member_account_status' => 'ACTIVED',
+                    'member_account_category' => 'NORMAL',
+                    'member_account_nbr' => $memberId . '-POINTS',
+                    'member_account_name' => '积分账户',
+                    'member_account_addtimes' => time()
+                ];
+                // 积分账户
+                MemberAccount::insert($accountData);
+                $accountData['member_account_classify'] = 'CASH';
+                $accountData['member_account_nbr'] = $memberId . '-CASH';
+                $accountData['member_account_name'] = '余额账户';
+                // 现金/余额账户
+                MemberAccount::insert($accountData);
+                // cert
+                $certData = [
+                    'join_cert_member_id' => $memberId,
+                    'member_cert_name' => $params['username']
+                ];
+                MemberCert::insert($certData);
+                // info
+                $infoData = [
+                    'join_info_member_id' => $memberId,
+                    'member_info_nickname' => $params['username']
+                ];
+                MemberInfo::insert($infoData);
+            }
             $data = [
                 'appointment_id' => "AP" . str_pad(SysSerial::getSerial(), 16, '0') . random_string(6, 'up'),
                 'join_appointment_member_id' => $params['join_appointment_member_id'] ?? '',
                 'join_appointment_goods_id' => $params['join_appointment_goods_id'] ?? '',
                 'appointment_status' => $params['appointment_status'] ?? '',
-                'appointment_datetime' => isset($params['appointment_datetime']) ? date('Y-m-d H:i:s', strtotime($params['appointment_datetime'])) : '',
+                'appointment_datetime' => isset($params['appointment_datetime']) ? date('Y-m-d', strtotime($params['appointment_datetime'])) : '',
                 'appointment_apply_datetime' => isset($params['appointment_apply_datetime']) ? date('Y-m-d H:i:s', strtotime($params['appointment_apply_datetime'])) : '',
                 'appointment_doing_datetime' => isset($params['appointment_doing_datetime']) ? date('Y-m-d H:i:s', strtotime($params['appointment_doing_datetime'])) : '',
                 'appointment_done_datetime' => isset($params['appointment_done_datetime']) ? date('Y-m-d H:i:s', strtotime($params['appointment_done_datetime'])) : '',
@@ -102,10 +181,103 @@ class AppointmentService
                 'appointment_remark' => $params['appointment_remark'] ?? '',
                 'appointment_category' => 'NOFEE',
                 'appointment_addtimes' => time(),
+                'appointment_mode' => $params['appointment_mode'] ?? '',
+                'settlement_mode' => $params['settlement_mode'] ?? '',
             ];
 
+            if (!empty($params['join_appointment_member_id'])) {
+                $member = Member::with([
+                    'cert' => function ($query) {
+                        $query->select('join_cert_member_id', 'member_cert_name');
+                    }
+                ])->where('member_id', $params['join_appointment_member_id'])
+                    ->first()
+                    ->toArray();
+                $data['appointment_apply_json'] = json_encode([
+                    'name' => !empty($member['cert']['member_cert_name']) ? $member['cert']['member_cert_name'] : $member['member_mobile'],
+                    'mobile' => $member['member_mobile'],
+                    'person' => $params['person'],
+                    'remark' => $data['appointment_remark'],
+                    'premises' => $params['premises'],
+                    'times' => $params['appointment_times']
+                ]);
+            }
+
             Appointment::insert($data);
 
+            // 如果预约成功,生成订单
+            if ($params['appointment_status'] == 'PENDING') {
+                $orderId = 'OD' . date('YmdHis') . random_string(6, 'up');
+                $order = [
+                    'order_id' => $orderId,
+                    'join_order_member_id' => $params['join_appointment_member_id'],
+                    'order_name' => "预约-" . $goods->goods_name,
+                    'order_amount_total' => $goods->goods_sales_price * $params['person'],
+                    'order_amount_pay' => $goods->goods_sales_price * $params['person'],
+                    'order_is_complete' => 'N',
+                    'order_category' => 'OTHER',
+                    'order_status_system' => 'PAYING',
+                    'order_status_payment' => 'PENDING',
+                    'order_status_storage' => 'PENDING',
+                    'order_addtimes' => time()
+                ];
+                Order::insert($order);
+                // 订单详情
+                $sheet = [
+                    'join_sheet_member_id' => $params['join_appointment_member_id'],
+                    'join_sheet_order_id' => $orderId,
+                    'join_sheet_goods_id' => $params['join_appointment_goods_id'],
+                    'order_sheet_status' => 'PAYING',
+                    'order_sheet_category' => 'APPOINTMENT',
+                    'order_sheet_unit' => '套',
+                    'order_sheet_num' => $params['person'],
+                    'order_sheet_price' => $goods->goods_sales_price,
+                    'order_sheet_amount' => $goods->goods_sales_price * $params['person'],
+                    'order_sheet_pay' => $goods->goods_sales_price * $params['person'],
+                    'order_sheet_task_status' => 'NONE',
+                    'order_sheet_addtimes' => time()
+                ];
+                OrderSheet::insert($sheet);
+                // 订单号更新到预约
+                Appointment::where('appointment_id', $data['appointment_id'])->update(['join_appointment_order_id' => $orderId]);
+                // 支付数据
+                $pay = [
+                    'join_pay_member_id' => $params['join_appointment_member_id'],
+                    'join_pay_order_id' => $orderId,
+                    'pay_amount' => $sheet['order_sheet_pay'],
+                    'pay_remark' => '预约单',
+                    'pay_addtimes' => time()
+                ];
+                // 现金余额结算
+                if ($params['settlement_mode'] == 'CASH') {
+                    $account = MemberAccount::where('join_account_member_id', $params['join_appointment_member_id'])
+                        ->where('member_account_classify', 'CASH')
+                        ->where('member_account_status', 'ACTIVED')
+                        ->first();
+                    if (!$account) {
+                        Db::rollBack();
+                        return json_fail('当前账户不存在或已过期');
+                    }
+
+                    if ($account->member_account_surplus < $sheet['order_sheet_pay']) {
+                        $pay['pay_status'] = 'PENDING';
+                    } else {
+                        MemberAccount::where('member_account_id', $account->member_account_id)->update([
+                            'member_account_expend' => $account->member_account_expend + $sheet['order_sheet_pay'],
+                            'member_account_surplus' => $account->member_account_surplus - $sheet['order_sheet_pay']
+                        ]);
+                        $pay['pay_status'] = 'SUCCESS';
+                        $pay['join_pay_object_json'] = json_encode(['payment' => ['member_account_id' => $account->member_account_id]]);
+                    }
+                    $pay['pay_category'] = 'CASH';
+                    PayDetail::insert($pay);
+                }elseif ($params['settlement_mode'] == 'QRCODE'){
+                    $pay['pay_category'] = 'QRCODE';
+                    $pay['pay_status'] = 'SUCCESS';
+                    PayDetail::insert($pay);
+                }
+            }
+
             Db::commit();
             return json_success("添加预约成功");
         } catch (\Exception $e) {
@@ -126,21 +298,144 @@ class AppointmentService
         $params = $request->post();
         Db::beginTransaction();
         try {
+            // 先检查选择的时段是否可预约
+            $goods = Goods::where('goods_id', $params['join_appointment_goods_id'])->first();
+            $appointments = Appointment::where('appointment_datetime', $params['appointment_datetime'])
+                ->where('appointment_id', '<>', $params['appointment_id'])
+                ->get()
+                ->toArray();
+            if ($goods->is_support_appointment == 'Y' && !empty($goods->goods_extend_json)) {
+                // {"times": [{"person": 2, "appointmentTimeEnd": "07:00", "appointmentTimeStart": "06:30"}, {"person": 3, "appointmentTimeEnd": "07:30", "appointmentTimeStart": "07:00"}]}
+                $extendJson = json_decode($goods->goods_extend_json, true);
+                foreach ($extendJson['times'] as $key => $time) {
+                    $timesStr = $time['appointmentTimeStart'] . '~' . $time['appointmentTimeEnd'];
+                    if ($timesStr == $params['appointment_times']) {
+                        foreach ($appointments as $appointment) {
+                            $applyJson = json_decode($appointment['appointment_apply_json'], true);
+                            $applyJsonTimes = $applyJson['times'] ?? '';
+//                            dump($timesStr.'=='.$applyJsonTimes);
+                            if ($timesStr == $applyJsonTimes) {
+                                $extendJson['times'][$key]['person'] -= $applyJson['person'];
+                            }
+                        }
+
+                        if ($extendJson['times'][$key]['person'] < $params['person']) {
+                            return json_fail('当前时段已满员,请选择其他时段');
+                        }
+                    }
+                }
+            }
             $data = [
                 'appointment_status' => $params['appointment_status'],
-                'appointment_datetime' => $params['appointment_datetime'] ? date('Y-m-d H:i:s', strtotime($params['appointment_datetime'])) : null,
+                'appointment_datetime' => $params['appointment_datetime'] ? date('Y-m-d', strtotime($params['appointment_datetime'])) : null,
                 'appointment_apply_datetime' => $params['appointment_apply_datetime'] ? date('Y-m-d H:i:s', strtotime($params['appointment_apply_datetime'])) : null,
                 'appointment_doing_datetime' => $params['appointment_doing_datetime'] ? date('Y-m-d H:i:s', strtotime($params['appointment_doing_datetime'])) : null,
                 'appointment_done_datetime' => $params['appointment_done_datetime'] ? date('Y-m-d H:i:s', strtotime($params['appointment_done_datetime'])) : null,
                 'appointment_cancel_datetime' => $params['appointment_cancel_datetime'] ? date('Y-m-d H:i:s', strtotime($params['appointment_cancel_datetime'])) : null,
                 'appointment_remark' => $params['appointment_remark'] ?? '',
+                'appointment_mode' => $params['appointment_mode'] ?? '',
+                'settlement_mode' => $params['settlement_mode'] ?? '',
             ];
-
-            Appointment::where('appointment_id', $appointmentId)->update($data);
             // 如果是完成状态
             if ($params['appointment_status'] == 'DONE' && $appointment->appointment_status != 'DONE') {
+                if (empty($params['appointment_done_datetime'])) {
+                    $data['appointment_done_datetime'] = date('Y-m-d H:i:s');
+                }
                 MemberBenefit::where('member_benefit_id', $appointment->join_appointment_member_benefit_id)->increment('member_benefit_used_count');
             }
+            if (!empty($params['join_appointment_member_id'])) {
+                $member = Member::with([
+                    'cert' => function ($query) {
+                        $query->select('join_cert_member_id', 'member_cert_name');
+                    }
+                ])->where('member_id', $params['join_appointment_member_id'])
+                    ->first()
+                    ->toArray();
+                $data['appointment_apply_json'] = json_encode([
+                    'name' => !empty($member['cert']['member_cert_name']) ? $member['cert']['member_cert_name'] : $member['member_mobile'],
+                    'mobile' => $member['member_mobile'],
+                    'person' => $params['person'],
+                    'remark' => $data['appointment_remark'],
+                    'premises' => $params['premises'],
+                    'times' => $params['appointment_times']
+                ]);
+            }
+
+            Appointment::where('appointment_id', $appointmentId)->update($data);
+
+            // 如果预约成功,没有生成过订单,生成订单
+            if ($params['appointment_status'] == 'PENDING' && empty($appointment->join_appointment_order_id)) {
+                $orderId = 'OD' . date('YmdHis') . random_string(6, 'up');
+                $order = [
+                    'order_id' => $orderId,
+                    'join_order_member_id' => $params['join_appointment_member_id'],
+                    'order_name' => "预约-" . $goods->goods_name,
+                    'order_amount_total' => $goods->goods_sales_price * $params['person'],
+                    'order_amount_pay' => $goods->goods_sales_price * $params['person'],
+                    'order_is_complete' => 'N',
+                    'order_category' => 'OTHER',
+                    'order_status_system' => 'PAYING',
+                    'order_status_payment' => 'PENDING',
+                    'order_status_storage' => 'PENDING',
+                    'order_addtimes' => time()
+                ];
+                Order::insert($order);
+                // 订单详情
+                $sheet = [
+                    'join_sheet_member_id' => $params['join_appointment_member_id'],
+                    'join_sheet_order_id' => $orderId,
+                    'join_sheet_goods_id' => $params['join_appointment_goods_id'],
+                    'order_sheet_status' => 'PAYING',
+                    'order_sheet_category' => 'APPOINTMENT',
+                    'order_sheet_unit' => '套',
+                    'order_sheet_num' => $params['person'],
+                    'order_sheet_price' => $goods->goods_sales_price,
+                    'order_sheet_amount' => $goods->goods_sales_price * $params['person'],
+                    'order_sheet_pay' => $goods->goods_sales_price * $params['person'],
+                    'order_sheet_task_status' => 'NONE',
+                    'order_sheet_addtimes' => time()
+                ];
+                OrderSheet::insert($sheet);
+                // 订单号更新到预约
+                Appointment::where('appointment_id', $data['appointment_id'])->update(['join_appointment_order_id' => $orderId]);
+
+                // 支付数据
+                $pay = [
+                    'join_pay_member_id' => $params['join_appointment_member_id'],
+                    'join_pay_order_id' => $orderId,
+                    'pay_amount' => $sheet['order_sheet_pay'],
+                    'pay_remark' => '预约单',
+                    'pay_addtimes' => time()
+                ];
+                // 现金余额结算
+                if ($params['settlement_mode'] == 'CASH') {
+                    $account = MemberAccount::where('join_account_member_id', $params['join_appointment_member_id'])
+                        ->where('member_account_classify', 'CASH')
+                        ->where('member_account_status', 'ACTIVED')
+                        ->first();
+                    if (!$account) {
+                        Db::rollBack();
+                        return json_fail('当前账户不存在或已过期');
+                    }
+
+                    if ($account->member_account_surplus < $sheet['order_sheet_pay']) {
+                        $pay['pay_status'] = 'PENDING';
+                    } else {
+                        MemberAccount::where('member_account_id', $account->member_account_id)->update([
+                            'member_account_expend' => $account->member_account_expend + $sheet['order_sheet_pay'],
+                            'member_account_surplus' => $account->member_account_surplus - $sheet['order_sheet_pay']
+                        ]);
+                        $pay['pay_status'] = 'SUCCESS';
+                        $pay['join_pay_object_json'] = json_encode(['payment' => ['member_account_id' => $account->member_account_id]]);
+                    }
+                    $pay['pay_category'] = 'CASH';
+                    PayDetail::insert($pay);
+                }elseif ($params['settlement_mode'] == 'QRCODE'){
+                    $pay['pay_category'] = 'QRCODE';
+                    $pay['pay_status'] = 'SUCCESS';
+                    PayDetail::insert($pay);
+                }
+            }
 
             Db::commit();
             return json_success("数据更新成功");
@@ -150,4 +445,47 @@ class AppointmentService
             return json_fail("数据更新失败");
         }
     }
+
+    public static function getTimes(Request $request)
+    {
+        $goodsId = $request->get('goods_id', '');
+        $date = $request->get('date', '');
+        $memberId = $request->get('member_id', '');
+        if (!$goodsId || !$date) {
+            return json_fail("查询时间段失败!");
+        }
+
+        $goods = Goods::where('goods_id', $goodsId)->first();
+        if (!$goods) {
+            return json_fail('数据不存在');
+        }
+
+        // 当前服务已预约出去的
+        $appointments = Appointment::where('join_appointment_goods_id', $goodsId)
+            ->where('appointment_datetime', $date)
+            ->where('join_appointment_member_id', '<>', $memberId)
+            ->get()
+            ->toArray();
+        if ($goods->is_support_appointment == 'Y' && !empty($goods->goods_extend_json)) {
+            $extendJson = json_decode($goods->goods_extend_json, true);
+            $times = $extendJson['times'];
+            foreach ($times as $key => $time) {
+                $timesStr = $time['appointmentTimeStart'] . '~' . $time['appointmentTimeEnd'];
+                $times[$key]['timesStr'] = $timesStr;
+                foreach ($appointments as $appointment) {
+                    if (!empty($appointment['appointment_apply_json'])) {
+                        $applyJson = json_decode($appointment['appointment_apply_json'], true);
+                        $applyJsonTimes = $applyJson['times'] ?? '';
+                        if ($timesStr == $applyJsonTimes) {
+                            $times[$key]['person'] -= $applyJson['person'];
+                            if ($times[$key]['person'] < 1) {
+                                unset($times[$key]);
+                            }
+                        }
+                    }
+                }
+            }
+            return json_success('', $times);
+        }
+    }
 }

+ 1 - 0
app/admin/validate/goods/GoodsValidate.php

@@ -63,6 +63,7 @@ class GoodsValidate extends Validate
             'goods_sku_specs_json', 'goods_sku_title', 'goods_sku_images_json', 'goods_sku_market_price', 'goods_sku_sales_price',
             'goods_sku_storage_json', 'goods_sku_service_json', 'goods_sku_extend_json'],
         'info' => ['goods_id'],
+        'changeStatus' => ['goods_id','goods_status']
     ];
 
     /**

+ 16 - 0
app/model/PayDetail.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace app\model;
+
+use support\Model;
+
+class PayDetail extends Model
+{
+    protected $table = 'pay_detail';
+
+    protected $dateFormat = 'U';
+
+    const CREATED_AT = 'pay_addtimes';
+
+    const UPDATED_AT = null;
+}

+ 4 - 1
route/admin.php

@@ -37,6 +37,7 @@ Route::group('/admin', function () {
             Route::get('/info', [\app\admin\controller\goods\ServiceGoodsController::class, 'info']);
             Route::post('/add', [\app\admin\controller\goods\ServiceGoodsController::class, 'insert']);
             Route::post('/update', [\app\admin\controller\goods\ServiceGoodsController::class, 'update']);
+            Route::post('/changeStatus', [\app\admin\controller\goods\ServiceGoodsController::class, 'changeStatus']);
             Route::delete('/delete', [\app\admin\controller\goods\ServiceGoodsController::class, 'delete']);
         })->middleware([
             \app\middleware\AdminAuthCheck::class
@@ -76,6 +77,7 @@ Route::group('/admin', function () {
         ]);
         /* 角色管理 */
         Route::group('/role', function () {
+            Route::get('/select', [\app\admin\controller\sys_manage\RoleController::class, 'select']);
             Route::get('/list', [\app\admin\controller\sys_manage\RoleController::class, 'roleList']);
             Route::get('/info/{id:\d+}', [\app\admin\controller\sys_manage\RoleController::class, 'roleInfo']);
             Route::post('/add', [\app\admin\controller\sys_manage\RoleController::class, 'addRole']);
@@ -482,7 +484,7 @@ Route::group('/admin', function () {
         Route::post('/add', [\app\admin\controller\customer\IndexController::class, 'insert']);
         Route::post('/update', [\app\admin\controller\customer\IndexController::class, 'update']);
         Route::delete('/delete', [\app\admin\controller\customer\IndexController::class, 'delete']);
-        Route::post('/conversion',[\app\admin\controller\customer\IndexController::class,'conversion']);
+        Route::post('/conversion', [\app\admin\controller\customer\IndexController::class, 'conversion']);
     });
     /* 用户管理 */
     Route::group('/member', function () {
@@ -665,6 +667,7 @@ Route::group('/admin', function () {
             Route::get('/add', [\app\admin\controller\order\AppointmentController::class, 'add']);
             Route::get('/update', [\app\admin\controller\order\AppointmentController::class, 'update']);
             Route::post('/confirm/{id:[0-9a-zA-Z]+}', [\app\admin\controller\order\AppointmentController::class, 'confirm']);
+            Route::get('/getTimes', [\app\admin\controller\order\AppointmentController::class, 'getTimes']);
         })->middleware([
             \app\middleware\AdminAuthCheck::class
         ]);