__('Status -3'),'-1' => __('Status -1'), '0' => __('Status 0'), '3' => __('Status 3')]; } public function getStartTimeTextAttr($value, $data) { $value = $value ? $value : (isset($data['start_time']) ? $data['start_time'] : ''); return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; } public function getEndTimeTextAttr($value, $data) { $value = $value ? $value : (isset($data['end_time']) ? $data['end_time'] : ''); return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; } public function getStatusTextAttr($value, $data) { $value = $value ? $value : (isset($data['status']) ? $data['status'] : ''); $list = $this->getStatusList(); return isset($list[$value]) ? $list[$value] : ''; } public function getReservationTimeTextAttr($value, $data) { $value = $value ? $value : (isset($data['reservation_time']) ? $data['reservation_time'] : ''); return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; } public function getFinishTimeTextAttr($value, $data) { $value = $value ? $value : (isset($data['finish_time']) ? $data['finish_time'] : ''); return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; } public function getCancelTimeTextAttr($value, $data) { $value = $value ? $value : (isset($data['cancel_time']) ? $data['cancel_time'] : ''); return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; } protected function setStartTimeAttr($value) { return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value); } protected function setEndTimeAttr($value) { return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value); } protected function setReservationTimeAttr($value) { return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value); } protected function setFinishTimeAttr($value) { return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value); } protected function setCancelTimeAttr($value) { return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value); } public function classesorder() { return $this->belongsTo('app\common\model\school\classes\order\Order', 'classes_order_id', 'id', [], 'LEFT')->setEagerlyType(0); } public function spec() { return $this->belongsTo('app\common\model\school\classes\ClassesSpec', 'classes_lib_spec_id', 'id', [], 'LEFT')->setEagerlyType(0); } public function user() { return $this->belongsTo('app\common\model\User', 'user_id', 'id', [], 'LEFT')->setEagerlyType(0); } public function detail() { return $this->belongsTo('app\common\model\school\classes\order\OrderDetail', 'classes_order_detail_id', 'id', [], 'LEFT')->setEagerlyType(0); } public function lib() { return $this->belongsTo(ClassesLib::class, 'classes_lib_id', 'id', [], 'LEFT')->setEagerlyType(0); } /**得到基础条件 * @param $status * @param null $model * @param string $alisa */ public static function getBaseWhere($whereData = [], $model = null, $alisa = '',$with = false) { if (!$model) { $model = new static; if ($alisa&&!$with) $model = $model->alias($alisa); } if ($alisa) $alisa = $alisa . '.'; $tableFields = (new static)->getTableFields(); foreach ($tableFields as $fields) { if(in_array($fields, ['createtime','start_time','status','classes_lib_id']))continue; // if (isset($whereData[$fields]) && $whereData[$fields]) $model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]); if (isset($whereData[$fields]) && $whereData[$fields]){ if(is_array($whereData[$fields])){ $model = $model->where("{$alisa}{$fields}", $whereData[$fields][0], $whereData[$fields][1]); }else{ $model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]); } } } if (isset($whereData['status'])) $model = $model->where("{$alisa}status", 'in', $whereData['status']); if (isset($whereData['not_status'])) $model = $model->where("{$alisa}status", 'not in', $whereData['not_status']); if (isset($whereData['keywords'])&&$whereData['keywords']) $model = $model->where("{$alisa}order_no|{$alisa}id", '=', $whereData['keywords']); if (isset($whereData['createtime'])&&$whereData['createtime']){ $model = $model->time(["createtime",$whereData['createtime']]); } if (isset($whereData['start_time'])&&$whereData['start_time']){ $model = $model->time(["start_time",$whereData['start_time']]); } if (isset($whereData['user_id']) && $whereData['user_id']) $model = $model->where("{$alisa}user_id", '=', $whereData['user_id']); if (isset($whereData['classes_lib_ids']) && $whereData['classes_lib_ids']) $model = $model->where("{$alisa}classes_lib_id", 'in', $whereData['classes_lib_ids']); if (isset($whereData['classes_lib_id']) && $whereData['classes_lib_id']) $model = $model->where("{$alisa}classes_lib_id", 'in', $whereData['classes_lib_id']); return $model; } /**展示订单信息 * @param $order_no * @param $price_info * @return array */ public static function showInfo($order_no, $price_info = []){ $data = []; $data['order_no'] =$order_no; $data['order_info'] = self::getDetail($order_no); return array_merge($data,$price_info); } /**得到订单详情 * @param $order_no */ public static function getDetail($order_no,$classes_lib_id = [],$classes_lib_ids = []){ $model = self::where('order_no|id',$order_no); if($classes_lib_id)$model = $model->where("classes_lib_id","in",$classes_lib_id); if($classes_lib_ids)$model = $model->where("classes_lib_id","in",$classes_lib_ids); $data = $model->find(); if(!$data) return $data; //加载订单详情 $data->detail->teacher; //订单用户 $data->user->visible(['id','nickname','mobile','avatar','realname']); //订单机构 $data->classesorder; // //得到二维码 // $data->code_url = Common::getQrcode([ // 'text' => $data['code'], // 'size' => 200, // ]); // $data->one_code_url = Common::getBarcode([ // 'text' => $data['code'], // 'size' => 200, // ]); return $data; } public static function allList($user_id,$page, $limit,$keywords,$status,$classes_order_id=0,$classes_lib_id = [],$start_time = null,$createtime = null){ $with_field = [ 'user'=>['nickname','mobile','avatar','realname'], 'base'=>['*'], 'classesorder'=>['*'], 'detail'=>['*'], ]; $CANCEL = '-3'; $NOAUDIT = '-1'; $HAVE = '0'; $FINISH = '3'; $alisa = (new self)->getWithAlisaName(); $sort = "field({$alisa}.status,'{$NOAUDIT}','{$HAVE}','{$FINISH}','{$CANCEL}') asc,{$alisa}.id desc"; $serch_where = ['status'=>$status,'user_id'=>$user_id,'keywords'=>$keywords,'classes_order_id'=>$classes_order_id,'classes_lib_id'=>$classes_lib_id,"start_time"=>$start_time,"createtime"=>$createtime]; // if($type)$serch_where['type'] = $type; return (new self)->getBaseList($serch_where, $page, $limit,$sort,$with_field); } public static function baseCount($where = []){ $CANCEL = '-3'; $NOAUDIT = '-1'; $HAVE = '0'; $FINISH = '3'; $cancel_number = self::getBaseWhere(array_merge(['status'=>$CANCEL],$where))->count(); $noaudit_number = self::getBaseWhere(array_merge(['status'=>$NOAUDIT],$where))->count(); $have_number = self::getBaseWhere(array_merge(['status'=>$HAVE],$where))->count(); $finish_number = self::getBaseWhere(array_merge(['status'=>$FINISH],$where))->count(); return compact('cancel_number','noaudit_number','have_number','finish_number'); } /**订单数量统计 * @param int $user_id * @return array */ public static function orderCount($user_id = 0,$classes_order_id=0,$classes_lib_id=[]){ return self::baseCount(['user_id'=>$user_id,'classes_order_id'=>$classes_order_id,"classes_lib_id"=>$classes_lib_id]); } public static function workList($page, $limit,$keywords,$status,$classes_order_id=0,$user_id=0,$classes_lib_id = [],$classes_lib_ids = [],$start_time = null,$createtime = null){ $with_field = [ 'user'=>['nickname','mobile','avatar','realname'], 'base'=>['*'], 'classesorder'=>['*'], 'detail'=>['*'], ]; $CANCEL = '-3'; $NOAUDIT = '-1'; $HAVE = '0'; $FINISH = '3'; $alisa = (new self)->getWithAlisaName(); $sort = "field({$alisa}.status,'{$NOAUDIT}','{$HAVE}','{$FINISH}','{$CANCEL}') asc,{$alisa}.id desc"; $serch_where = ['status'=>$status,'user_id'=>$user_id,'keywords'=>$keywords,'classes_order_id'=>$classes_order_id,"classes_lib_id"=>$classes_lib_id,"classes_lib_ids"=>$classes_lib_ids,"start_time"=>$start_time,"createtime"=>$createtime]; // if($type)$serch_where['type'] = $type; return (new self)->getBaseList($serch_where, $page, $limit,$sort,$with_field); } /**订单数量统计 * @param int $user_id * @return array */ public static function workCount($classes_lib_id = [],$classes_lib_ids = [],$classes_order_id=0){ return self::baseCount(['classes_lib_id'=>$classes_lib_id,'classes_order_id'=>$classes_order_id,"classes_lib_ids"=>$classes_lib_ids]); } /** * 设置订单缓存 * @param $uid * @param $data * @return bool */ public static function setOrderCache($uid, $data) { //缓存名 = uid + order_no $cacheNmae = 'classes_hourorder_cache' . $uid . $data['order_no']; // 缓存在3600秒之后过期 return Cache::set($cacheNmae, $data, config("site.unpaid_order_expire_time")); } /** * 得到订单缓存 * @param $uid * @param $order_no * @return mixed */ public static function getOrderCache($uid, $order_no) { //缓存名 = uid + order_no $cacheNmae = 'classes_hourorder_cache' . $uid . $order_no; // 缓存在3600秒之后过期 return Cache::get($cacheNmae); } /** * 删除订单缓存 * @param $uid * @param $order_no * @return mixed */ public static function deleteOrderCache($uid, $order_no) { //缓存名 = uid + order_no $cacheNmae = 'classes_hourorder_cache' . $uid . $order_no; // 缓存在3600秒之后过期 return Cache::rm($cacheNmae); } /** 订单确认(订单计算) * @param $user_id 下单用户 * @param $order_no 订单号(缓存标识) * @param $classes_order_id 課程订单id * @param $classes_lib_spec_id 課程课时规格id * @param $param 額外参数(扩展用) * @param bool $is_compute 是否重新计算订单 * @return array */ public function confirm($user_id, $classes_order_id,$order_no,$classes_lib_spec_id=0,$param=[], $is_compute = false) { if ($order_no && !$is_compute) { //得到缓存 $data = self::getOrderCache($user_id, $order_no); if (!$data) throw new \Exception('請您完善預約信息!'); $price_info = $data['price_info']; } else { //订单信息计算 // if(!$param) throw new \Exception('缺少必要信息'); $this->orderVaild($user_id,$classes_order_id,$order_no,$classes_lib_spec_id, $param); //订单支付信息 $price_info = $this->getCost($user_id,$classes_order_id,$classes_lib_spec_id,$param); //生成订单号 if (!$order_no) $order_no = get_order_sn(); //生成缓存 $data = compact('user_id', 'classes_order_id','param', 'order_no', 'price_info','classes_lib_spec_id'); self::setOrderCache($user_id, $data); } \think\Hook::listen('classeshour_order_create_before', $data); //下单数据展示 return $this->showInfo($order_no, $price_info); } /**订单校验 * @param $user_id 用户id * @param $classes_order_id 课程订单id * @param $order_no 订单号 * @param $param 表单扩展参数 * @return bool */ public function orderVaild($user_id,$classes_order_id,$order_no,$classes_lib_spec_id, $param,$check=false){ if(!$user_id||!$classes_order_id)throw new \Exception("缺少必要参数"); //代下单检测是否有代下单权限 if(isset($param["help_user_id"]) && $param["help_user_id"]){ if(!isset($param["help_type"]) || !$param["help_type"])throw new \Exception("请选择代下单类型!"); //课程是否存在并上架 $classesOrder = \app\common\model\school\classes\order\Order::where("id",$classes_order_id)->find(); if(!$classesOrder)throw new \Exception("订单不存在!"); //代下单时将下单人修正成课程下单人,不影响后续判断 $user_id = $classesOrder["user_id"]; //用户操作权限检测 self::checkOptionAuth($classes_order_id,$param["help_user_id"],$param["help_type"]); } //默认校验订单是否已创建 if($check){ //判断订单是否已创建 $order_info = self::where(['order_no'=>$order_no])->find(); if($order_info) throw new \Exception("订单已生成,如需重新下单请退出页面重新进入!"); if(!$classes_lib_spec_id)throw new \Exception("请选择您要预约的课时信息!"); } //校验订单参数 //更新最近次数后进行验证 \app\common\model\school\classes\order\Order::statisticsAndUpdateClassesNumber($classes_order_id); //课程是否存在并上架 $classesOrder = \app\common\model\school\classes\order\Order::where("id",$classes_order_id) ->where("user_id",$user_id) ->find(); if(!$classesOrder){ throw new \Exception("课程不存在!"); } $detail = $classesOrder->detail; if(!$detail)throw new \Exception("课程不存在!"); //是否还有次数 if($detail['sub_num']<=0) throw new \Exception("该课程已无剩余课时!"); //不是可用状态 if($classesOrder['status']!="3") throw new \Exception("该课程单当前状态不可操作!"); //售后中 if($classesOrder['server_status']=="3") throw new \Exception("该课程单正在售后中,请勿操作!"); //判断课时信息 if($classes_lib_spec_id){ self::checkLibSpec($user_id,$detail["classes_lib_id"],$classes_lib_spec_id,true); } // $classes_lib_info = ClassesLib::where('id',$classesOrder["classes_lib_id"])->find(); // if(!$classes_lib_info || $classes_lib_info['status']!='1') throw new \Exception("该课程不存在或已下架!"); //用户存不存在 $user_info = User::where('id',$user_id)->find(); if(!$user_info) throw new \Exception("用户不存在!"); return true; } //计算订单所需返回数据接口 public static function getCost($user_id,$classes_order_id,$classes_lib_spec_id,$param=[],$other_params=[],$check = false){ if(isset($param["help_user_id"]) && $param["help_user_id"]){ //课程是否存在并上架 $classesOrder = \app\common\model\school\classes\order\Order::where("id",$classes_order_id)->find(); if(!$classesOrder)throw new \Exception("订单不存在!"); //代下单时将下单人修正成课程下单人,不影响后续判断 $user_id = $classesOrder["user_id"]; } //校验订单参数 //课程是否存在并上架 $classesOrder = \app\common\model\school\classes\order\Order::where("id",$classes_order_id) ->where("user_id",$user_id) ->find(); $detail = $classesOrder->detail; $classes_lib_info = $detail; $classes_lib_spec_info = null; //判断课时信息 if($classes_lib_spec_id){ $classes_lib_spec_info = ClassesSpec::where('id',$classes_lib_spec_id) ->where('classes_lib_id',$detail["classes_lib_id"]) ->find(); if($classes_lib_spec_info){ $classes_lib_spec_info = $classes_lib_spec_info->toArray(); } } //用户 $user_info = User::get($user_id); $user_data = [ "nickname"=>$user_info["nickname"], "realname"=>$user_info["realname"], "avatar"=>$user_info["avatar"], "mobile"=>$user_info["mobile"], "money" =>$user_info["money"], "score" =>$user_info["score"], ]; //组装订单下单数据 $order_data = []; $order_data["user_id"] = $user_id; $order_data["classes_order_id"] = $classes_order_id; $order_data["classes_lib_spec_id"] = $classes_lib_spec_id; $order_data["classes_order_detail_id"] = $detail["id"]; $order_data["classes_lib_id"] = $detail["classes_lib_id"]; $order_data["manystore_id"] = $detail["manystore_id"]; $order_data["shop_id"] = $detail["shop_id"]; $order_data["status"] = '-1'; $order_data["verification_user_id"] = 0; $order_data["reservation_time"] = time(); $order_data["type"] = $param["type"] ?? '1'; $order_data["help_user_id"] = $param["help_user_id"] ?? 0; $order_data["help_type"] = $param["help_type"] ?? null; $order_data["reason"] = ''; $order_data["auth_status"] = '0'; return compact('order_data','classes_lib_info','user_data','classes_lib_spec_info'); } /** * 根据缓存创建订单 */ public function cacheCreateOrder($order_no, $user_id,$remark="", $trans = false) { //得到缓存 $orderInfo = self::getOrderCache($user_id, $order_no); //得到下单信息 if (!$orderInfo) throw new \Exception('請您完善預約信息!'); if ($trans) { self::beginTrans(); } try { //1订单执行创建 $order = $this->createOrder($user_id,$orderInfo['classes_order_id'],$orderInfo['classes_lib_spec_id'],$order_no,$orderInfo['param'],$remark); //5删除缓存 self::deleteOrderCache($user_id, $order_no); // var_dump($order["type"]); //代下单直接执行审核成功的预约中状态 if($order["type"] == '2'){ //兼容代下单逻辑,修正下单人信息 // $user_id =$order['user_id']; // var_dump($order["status"]); //do something... if(config("site.admin_approved_swtich"))$this->examine($order_no,1,"",0,false,$order["help_type"],$order["help_user_id"],false); } if ($trans) { self::commitTrans(); } } catch (\Exception $e) { if ($trans) { self::rollbackTrans(); } throw new \Exception($e->getMessage()); } return self::showInfo($order_no); } /**得到可核销的订单 * @param $order_no * @return array|false|\PDOStatement|string|Model * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public static function getNoVerificationOrder($order_no){ $order = self::where('order_no|id',$order_no)->where("status","in",['0'])->find(); if(!$order)throw new \Exception("待核销订单不存在"); return $order; } /**得到可更新课时的订单 * @param $order_no * @return array|false|\PDOStatement|string|Model * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public static function getHaveUpdateOrder($order_no){ $order = self::where('order_no|id',$order_no)->where("status","in",['0','-1'])->find(); if(!$order)throw new \Exception("可更新课时订单不存在"); return $order; } /**得到可取消订单 * @param $order_no * @return array|false|\PDOStatement|string|Model * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public static function getHaveCancelOrder($order_no){ // $where = [self::STATUS_NOPAY,self::STATUS_PAYED]; $order = self::where('order_no|id',$order_no)->where("status","in",['0','-1'])->find(); if(!$order)throw new \Exception("只有待审核和已预约的订单可以取消!"); return $order; } //生成或更新课时 public static function buildLibSpec($order,$classes_lib_spec){ if(is_string($order)||is_numeric($order))$order = self::getHaveUpdateOrder($order); if(is_string($classes_lib_spec)||is_numeric($classes_lib_spec))$classes_lib_spec = ClassesSpec::where('id',$classes_lib_spec)->where('classes_lib_id',$order["classes_lib_id"])->find(); if(!$classes_lib_spec)throw new \Exception("课时信息不正确!"); $classes_lib_spec_data = $classes_lib_spec->toArray(); $classes_lib_spec_data['classes_lib_spec_id'] = $classes_lib_spec_data['id']; unset($classes_lib_spec_data['id']); unset($classes_lib_spec_data['status']); unset($classes_lib_spec_data['createtime']); unset($classes_lib_spec_data['updatetime']); unset($classes_lib_spec_data['deletetime']); $order_detail_data = $order->toArray(); $order_detail_data = array_merge($order_detail_data,$classes_lib_spec_data); $order->allowField(true)->save($order_detail_data); return $order; } public function createOrder($user_id,$classes_order_id,$classes_lib_spec_id,$order_no,$param,$remark='',$other_params=[]){ $this->orderVaild($user_id,$classes_order_id, $order_no, $classes_lib_spec_id, $param,true); //订单支付信息 $order_info = self::getCost($user_id,$classes_order_id,$classes_lib_spec_id,$param,$other_params,true); //组装订单数据 $order_data = $order_info['order_data']; $order_data["order_no"] = $order_no; //兼容代下单逻辑,修正下单人信息 $user_id =$order_data['user_id']; //课时数据 $classes_lib_spec_info = $order_info['classes_lib_spec_info']; $res1 = self::create($order_data); if (!$res1) throw new \Exception('创建订单失败'); //课时规格更新 $order = self::buildLibSpec($res1,$classes_lib_spec_id); //扣减课程数 \app\common\model\school\classes\order\Order::statisticsAndUpdateClassesNumber($classes_order_id); //记录订单日志 if($order["type"] == "1"){ OrderLog::log($order['id'],"课时预约下单成功,等待机构老师审核",'user',$user_id); }else{ OrderLog::log($order['id'],"课时预约机构老师代下单成功",'user',$order["help_user_id"]); } //7事件 $data = ['order' => $res1]; \think\Hook::listen('classeshour_order_create_after', $data); return $res1; } /**更新订单取消状态 * @param $order * @return array|false|\PDOStatement|string|Model * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public static function updateCancel($order){ if(is_string($order))$order = self::getHaveCancelOrder($order); $order->status = "-3";//refund_status $order->cancel_time = time(); $order->save(); return $order; } /**订单取消 * @param $order_no * @param int $user_id * @param bool $check * @param bool $trans * @return bool * @throws \Exception */ public function cancel($order_no,$user_id=0,$check=false,$oper_type='user',$oper_id=0,$trans=false){ //得到可取消订单 $order = self::getHaveCancelOrder($order_no); if($check){ //用户操作权限检测 self::checkOptionAuth($order['classes_order_id'],$user_id ?: $oper_id,$oper_type); } //判断逻辑 if($trans){ self::beginTrans(); } $res = true; try{ //事务逻辑 //更新订单取消状态 $order = Order::updateCancel($order); //插入订单取消日志 if(!$user_id ||$order["user_id"] !=$user_id ){ OrderLog::log($order['id'],"[员工代操作]课时预约单取消成功,课时已原路退回",$oper_type ?: 'user', $oper_id ?: $order['user_id']); }else{ OrderLog::log($order['id'],"课时预约单取消成功,课时已原路退回",$oper_type ?: 'user', $oper_id ?: $order['user_id']); } //调用订单取消事件 $data = ['order' => $order,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id]; \think\Hook::listen('classeshour_order_cancel_after', $data); //执行课时数更新 \app\common\model\school\classes\order\Order::statisticsAndUpdateClassesNumber($order['classes_order_id']); if($trans){ self::commitTrans(); } }catch (\Exception $e){ if($trans){ self::rollbackTrans(); } throw new \Exception($e->getMessage()); } return $res; } /** 课时信息选择合法检测 * @param $user_id 下单用户 * @param $classes_lib_id 课程id * @param $classes_lib_spec_id 课时规格id * @return void * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public static function checkLibSpec($user_id,$classes_lib_id,$classes_lib_spec_id,$add=false,$order=null){ if(!$classes_lib_spec_id || !$classes_lib_id)throw new \Exception("缺少必要信息!"); $classes_lib_spec_info = ClassesSpec::where('id',$classes_lib_spec_id) ->where('classes_lib_id',$classes_lib_id) ->find(); if(!$classes_lib_spec_info)throw new \Exception("课时信息不正确!"); //课时已下架 if($classes_lib_spec_info['status']!='1') throw new \Exception("该课时已下架,请选择其他课时!"); //存在同规格正在进行中的课时预约 $order_info = self::where('classes_lib_spec_id',$classes_lib_spec_id) ->where('status','in',['-1',"0"]) ->where('user_id',$user_id) ->find(); if($order_info) throw new \Exception("该课时已预约,请勿重复预约!"); //新增或更换课时时判断 //是否达成限制人数 //允许人数为0说明不限制 if($classes_lib_spec_info['limit_num'] > 0){ //得到当前课时已参与人数 $sign_num = self::where("classes_lib_spec_id",$classes_lib_spec_id)->where("status","in",["-1","0"])->count(); if($add){ //订单新增课时 //判断是否达到限制人数 if($sign_num >= $classes_lib_spec_info['limit_num']){ throw new \Exception("该课时已满,请选择其他课时!"); } }else{ //订单更换课时 //判断是否达到限制人数 if($sign_num >= $classes_lib_spec_info['limit_num']){ throw new \Exception("该课时已满,请选择其他课时!"); } } } //判断是否是免费课 $lib = $classes_lib_spec_info->lib; if(!$lib){ throw new \Exception("该课时课程信息缺失!"); } if($lib["price"] == 0){ //免费课开始和结束时间有交叠无法下预约 if(!config("site.free_time_overlap_check")){ //如果是免费课 //判断时间是否有交叠 $start_time = $classes_lib_spec_info['start_time']; $end_time = $classes_lib_spec_info['end_time']; $as = (new self)->getWithAlisaName(); //判断时间是否有交叠(只查所有的免费的预约记录) $order_info = self::with("detail")->where("detail.price",0) ->where("{$as}.status","in",["-1","0"]) ->where(function ($query) use ($as,$start_time,$end_time) { //兩個時間區間重合 存在任意交集 都不行 $query->where("{$as}.start_time BETWEEN {$start_time} AND {$end_time}"); $query->whereOr("{$as}.end_time BETWEEN {$start_time} AND {$end_time}"); $query->whereOr("{$as}.start_time <= {$start_time} AND {$as}.end_time >= {$end_time}"); $query->whereOr("{$as}.start_time >= {$start_time} AND {$as}.end_time <= {$end_time}"); }) ->where("{$as}.user_id",$user_id)->find(); if($order_info) throw new \Exception("当前时间区间内,您已预约免费课程{$order_info['detail']['title']},无法再预约其他免费课程"); } } if(!config("site.all_time_overlap_check")){ //判断时间是否有交叠 $start_time = $classes_lib_spec_info['start_time']; $end_time = $classes_lib_spec_info['end_time']; $as = (new self)->getWithAlisaName(); //判断时间是否有交叠(只查所有的免费的预约记录) $order_info = self::with("detail") ->where("{$as}.status","in",["-1","0"]) ->where(function ($query) use ($as,$start_time,$end_time) { //兩個時間區間重合 存在任意交集 都不行 $query->where("{$as}.start_time BETWEEN {$start_time} AND {$end_time}"); $query->whereOr("{$as}.end_time BETWEEN {$start_time} AND {$end_time}"); $query->whereOr("{$as}.start_time <= {$start_time} AND {$as}.end_time >= {$end_time}"); $query->whereOr("{$as}.start_time >= {$start_time} AND {$as}.end_time <= {$end_time}"); }) ->where("{$as}.user_id",$user_id)->find(); if($order_info) throw new \Exception("当前时间区间内,您已预约课程{$order_info['detail']['title']},无法再预约其他课程"); } //执行免费课黑名单判断 //免费课才进行判断 if($lib && $lib['feel']=='1'){ self::checkBlackList($user_id,true); } //过期课时无法下单(结束时间小于等于当前时间) if($classes_lib_spec_info["end_time"] <= time()){ throw new \Exception("该课时已过期结束,无法预约!"); } } //执行免费课黑名单判断 public static function checkBlackList($user_id,$check=false){ $as = (new self)->getWithAlisaName(); //黑名单配置 $black_limit = config("site.free_classes_not_verify_num"); //如果免费课程报名通过后到结束时间不去核销N次 ,则进入黑名单 $order_count = self::with("detail")->where("{$as}.status",'in',["0"]) ->where("detail.feel",'1') ->where("{$as}.user_id",$user_id) ->where("{$as}.end_time" ,'<=',time()) ->count(); //已达到进入黑名单条件 if($order_count >= $black_limit){ $where = [ "user_id"=>$user_id ]; $blacklist = Blacklist::where($where)->find(); if(!$blacklist){ $blacklist = new Blacklist(); } $blacklist->save($where); } if($check){ //判断用户是否在黑名单中 $where = [ "user_id"=>$user_id ]; $blacklist = Blacklist::where($where)->find(); if($blacklist)throw new \Exception("您已进入黑名单,无法进行其他免费课时报名!"); } } /** 课时订单操作权限检测 * @param $order 订单 * @param $oper_id 操作人id * @param $oper_type 操作人类型:user-用户或员工,admin-管理员 * @return void * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public static function checkOptionAuth($classes_order_id,$oper_id,$oper_type){ //课程是否存在并上架 $classesOrder = \app\common\model\school\classes\order\Order::where("id",$classes_order_id)->find(); if(!$classesOrder)throw new \Exception("订单不存在!"); switch ($oper_type) { case 'user': //自己或操作员 if($oper_id != $classesOrder["user_id"]){ //说明是操作员 $help_user_info = User::where('id',$oper_id)->find(); if(!$help_user_info) throw new \Exception("代下单员工不存在!"); $classes_lib_ids = (new ClassesLib)->getClassesAuthIds($oper_id); //判断当前订单课程是否在此课程授权范围内 if(!in_array($classesOrder["classes_lib_id"],$classes_lib_ids)) throw new \Exception("该课程不在您的授权范围内,无法代操作!"); } break; case 'admin': $admin_info = Admin::where('id',$oper_id)->find(); if(!$admin_info) throw new \Exception("代下单管理员不存在!"); break; case 'shop': $admin_info = Manystore::where('id',$oper_id)->find(); if(!$admin_info) throw new \Exception("代下单管理员不存在!"); break; default: throw new \Exception("请选择正确的代下单类型!"); } } /**得到可取消订单 * @param $order_no * @return array|false|\PDOStatement|string|Model * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public static function getHaveExamineOrder($order_no){ // $where = [self::STATUS_NOPAY,self::STATUS_PAYED]; $order = self::where('order_no|id',$order_no)->where("status","in",['-1'])->find(); if(!$order)throw new \Exception("不是待审核的订单!"); return $order; } /**更新订单取消状态 * @param $order * @return array|false|\PDOStatement|string|Model * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public static function updateExamineSuccess($order,$oper_id = 0,$oper_type='user'){ if(is_string($order))$order = self::getHaveExamineOrder($order); $order->status = "0";//refund_status $order->auth_status = "1";//refund_status $order->auth_time = time(); $order->auth_user_id = $oper_id; $order->auth_type = $oper_type; $order->save(); return $order; } /**更新订单取消状态 * @param $order * @return array|false|\PDOStatement|string|Model * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public static function updateExamineFail($order,$reason,$oper_id = 0,$oper_type='user'){ if(is_string($order))$order = self::getHaveExamineOrder($order); $order->auth_status = "2"; $order->auth_time = time(); $order->reason = $reason; $order->auth_user_id = $oper_id; $order->auth_type = $oper_type; $order->save(); return $order; } /**课时订单审核 * @param $order_no * @param int $user_id * @param bool $check * @param bool $trans * @return bool * @throws \Exception */ public function examine($order_no,$auth_status,$reason="",$user_id=0,$check=false,$oper_type='user',$oper_id=0,$trans=false){ //得到可取消订单 $order = self::getHaveExamineOrder($order_no); if($check){ //用户操作权限检测 self::checkOptionAuth($order['classes_order_id'],$user_id ?: $oper_id,$oper_type); } //审核状态字段检测 $auth_status_arr = [1,2];//0=待审核,1=审核通过,2=审核失败 if( !in_array($auth_status,$auth_status_arr)) throw new \Exception("审核状态不正确!"); //审核失败需要传理由 if($auth_status==2 && empty($reason)) throw new \Exception("审核失败需要填写理由!"); //判断逻辑 if($trans){ self::beginTrans(); } $res = true; try{ //事务逻辑 //插入订单取消日志 if(!$user_id ||$order["user_id"] !=$user_id ){ $pron = "[员工操作]"; }else{ $pron = ""; } //审核成功逻辑 if($auth_status == 1){ //更新订单状态 $order = Order::updateExamineSuccess($order,$user_id ?: $oper_id,$oper_type); OrderLog::log($order['id'],$pron."课时预约单审核成功,预约成功等待核销!",$oper_type ?: 'user', $oper_id ?: $order['user_id']); //调用订单事件 $data = ['order' => $order,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id]; \think\Hook::listen('classeshour_order_auth_success_after', $data); }else{ //更新订单状态 $order = Order::updateExamineFail($order,$reason,$user_id ?: $oper_id,$oper_type); //审核失败逻辑 OrderLog::log($order['id'],$pron."课时预约单审核不通过,原因;{$reason},该课时单将取消以便重新下单",$oper_type ?: 'user', $oper_id ?: $order['user_id']); //调用订单事件 $data = ['order' => $order,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id]; \think\Hook::listen('classeshour_order_auth_fail_after', $data); //执行订单取消逻辑 $this->cancel($order_no,$user_id,$check,$oper_type,$oper_id); } //执行课时数更新 // $res1 = \app\common\model\school\classes\order\Order::statisticsAndUpdateClassesNumber($order['classes_order_id']); if($trans){ self::commitTrans(); } }catch (\Exception $e){ if($trans){ self::rollbackTrans(); } throw new \Exception($e->getMessage()); } return $order; } /**更新订单核销状态 * @param $order * @return array|false|\PDOStatement|string|Model * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public static function updateVerification($order,$oper_id = 0,$oper_type='user'){ if(is_string($order))$order = self::getHaveVerificationOrder($order); $order->status = "3";//refund_status $order->verification_user_id = $oper_id; $order->verification_type = $oper_type; $order->finish_time = time(); $order->save(); return $order; } /**得到可核销订单 * @param $order_no * @return array|false|\PDOStatement|string|Model * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public static function getHaveVerificationOrder($order_no){ // $where = [self::STATUS_NOPAY,self::STATUS_PAYED]; $order = self::where('order_no|id',$order_no)->where("status","in",['-1',"0"])->find(); if(!$order)throw new \Exception("不是待核销的订单!"); return $order; } /**订单核销 * @param $order_no * @param int $user_id * @param bool $check * @param bool $trans * @return bool * @throws \Exception */ public function verification($order_no,$user_id=0,$check=false,$oper_type='user',$oper_id=0,$trans=false){ //得到可取消订单 $order = self::getHaveVerificationOrder($order_no); if($check){ //用户操作权限检测 self::checkOptionAuth($order['classes_order_id'],$user_id ?: $oper_id,$oper_type); } //判断逻辑 if($trans){ self::beginTrans(); } $res = true; try{ //事务逻辑 //更新订单状态 //如果没有审核,先审核成功再核销 if($order["status"] == '-1'){ $order = $this->examine($order_no,'1',"",$user_id,$check,$oper_type,$oper_id); } $order = Order::updateVerification($order,$user_id ?: $oper_id,$oper_type); //插入订单取消日志 if(!$user_id ||$order["user_id"] !=$user_id ){ OrderLog::log($order['id'],"[员工操作]课时预约单核销成功,当前课时已完成",$oper_type ?: 'user', $oper_id ?: $order['user_id']); }else{ OrderLog::log($order['id'],"课时预约单核销成功,当前课时已完成",$oper_type ?: 'user', $oper_id ?: $order['user_id']); } //调用订单取消事件 $data = ['order' => $order,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id]; \think\Hook::listen('classeshour_order_finish_after', $data); //执行课时数更新 \app\common\model\school\classes\order\Order::statisticsAndUpdateClassesNumber($order['classes_order_id']); if($trans){ self::commitTrans(); } }catch (\Exception $e){ if($trans){ self::rollbackTrans(); } throw new \Exception($e->getMessage()); } return $res; } /**订单修改课时 * @param $order_no * @param int $user_id * @param bool $check * @param bool $trans * @return bool * @throws \Exception */ public function updateClassesSpec($order_no,$classes_lib_spec_id,$user_id=0,$check=false,$oper_type='user',$oper_id=0,$trans=false){ //得到可取消订单 $order = self::getHaveUpdateOrder($order_no); if($check){ //用户操作权限检测 self::checkOptionAuth($order['classes_order_id'],$user_id ?: $oper_id,$oper_type); } //判断逻辑 if($trans){ self::beginTrans(); } $res = true; try{ //执行课时数更新 $res1 = \app\common\model\school\classes\order\Order::statisticsAndUpdateClassesNumber($order['classes_order_id']); if($classes_lib_spec_id == $order["classes_lib_spec_id"])throw new \Exception("请勿重复提交!"); self::checkLibSpec($order['user_id'],$order["classes_lib_id"],$classes_lib_spec_id,false,$res1); //事务逻辑 //更新订单状态 //课时规格更新 $order = self::buildLibSpec($order_no,$classes_lib_spec_id); //插入订单取消日志 if(!$user_id ||$order["user_id"] !=$user_id ){ OrderLog::log($order['id'],"[员工操作]预约课时订单规格已变更",$oper_type ?: 'user', $oper_id ?: $order['user_id']); }else{ OrderLog::log($order['id'],"预约课时订单规格已变更",$oper_type ?: 'user', $oper_id ?: $order['user_id']); } //调用订单事件 $data = ['order' => $order,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id]; \think\Hook::listen('classeshour_order_update_after', $data); //执行课时数更新 $res1 = \app\common\model\school\classes\order\Order::statisticsAndUpdateClassesNumber($order['classes_order_id']); if($trans){ self::commitTrans(); } }catch (\Exception $e){ if($trans){ self::rollbackTrans(); } throw new \Exception($e->getMessage()); } return $order; } }