<?php

namespace app\common\model\school\classes\hourorder;

use app\admin\model\Admin;
use app\admin\model\school\classes\Blacklist;
use app\common\model\manystore\Shop;
use app\common\model\school\classes\ClassesLib;
use app\common\model\school\classes\ClassesSpec;
use app\common\model\User;
use app\manystore\model\Manystore;
use bw\Common;
use fast\Random;
use think\Cache;
use think\Model;
use traits\model\SoftDelete;
use app\common\model\BaseModel;
class Order extends BaseModel
{

    use SoftDelete;

    

    // 表名
    protected $name = 'school_classes_hour_order';
    
    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'integer';

    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $deleteTime = 'deletetime';

    // 追加属性
    protected $append = [
        'start_time_text',
        'end_time_text',
        'status_text',
        'reservation_time_text',
        'finish_time_text',
        'cancel_time_text'
    ];


    protected $order_user_id;
    

    
    public function getStatusList()
    {
        return ['-3' => __('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']){
            if($with && in_array('detail',$with)){
                $model = $model->where("{$alisa}order_no|{$alisa}id|{$alisa}name|detail.title", 'like',  "%" .$whereData['keywords'] . "%");
            }else{
                $model = $model->where("{$alisa}order_no|{$alisa}id|{$alisa}name", 'like',  "%" .$whereData['keywords'] . "%");
            }

        }
        if (isset($whereData['createtime'])&&$whereData['createtime']){

            $model = $model->time(["{$alisa}createtime",$whereData['createtime']]);
        }

        if (isset($whereData['start_time'])&&$whereData['start_time']){

            $model = $model->time(["{$alisa}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']);


       if (isset($whereData['time'])&&$whereData['time']){

                    if(strstr($whereData['time'], '---') !== false){
                        [$startTime, $endTime] = explode('---', $whereData['time']);
                    }elseif (strstr($whereData['time'], '-') !== false){
                        [$startTime, $endTime] = explode('-', $whereData['time']);
                    }
                    $start_time = trim($startTime);
                    $end_time = trim($endTime);
                    $start_time = strtotime($startTime);
                    $end_time = strtotime($endTime);


                    //sudo：此方法必须是时间戳
           $model = $model->where(function ($query) use ($alisa,$start_time,$end_time) {
//                    if($alisa)$alisa = "`order`.";
                    //兩個時間區間重合 存在任意交集 都不行
                    $query->where("{$alisa}start_time BETWEEN {$start_time} AND {$end_time}");
                    $query->whereOr("{$alisa}end_time BETWEEN {$start_time} AND {$end_time}");
                    $query->whereOr("{$alisa}start_time <= {$start_time} AND {$alisa}end_time >= {$end_time}");
                    $query->whereOr("{$alisa}start_time >= {$start_time} AND {$alisa}end_time <= {$end_time}");
                   });
        }

        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,$time = 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,"time"=>$time];
//        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,$time=null,$shop_id=0){
        if(!$classes_lib_ids) $classes_lib_ids = [-5];

//        var_dump($classes_lib_ids);die;

        $with_field = [
            'user'=>['nickname','mobile','avatar','realname'],
            'base'=>['*'],
            'classesorder'=>['*'],
            'detail'=>['*'],
        ];
        $CANCEL = '-3';
        $NOAUDIT = '-1';
        $HAVE = '0';
//         var_dump($classes_lib_ids);die;
        $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,"time"=>$time,"shop_id"=>$shop_id];


        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,$shop_id=0){
        if(!$classes_lib_ids) $classes_lib_ids = [-5];
        return self::baseCount(['classes_lib_id'=>$classes_lib_id,'classes_order_id'=>$classes_order_id,"classes_lib_ids"=>$classes_lib_ids,"shop_id"=>$shop_id]);
    }






    /**
     * 设置订单缓存
     * @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 $classes_order_id
     * @return void
     */
    public static function serverCheck($classes_order_id){
       $order = \app\common\model\school\classes\order\Order::where("id",$classes_order_id)->find();
       if(!$order)throw new \Exception("课程单不存在！");
       if($order["status"]!="3")throw new \Exception("当前课程单属于锁定状态，可能在售后或其他状态");
    }




    /** 订单确认(订单计算)
     * @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)throw new \Exception("缺少必要参数");


        //代下单检测是否有代下单权限
        if(isset($param["help_user_id"]) && $param["help_user_id"] && $classes_order_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"]);

        }
//        $user_id = $classesOrder["user_id"];


        //默认校验订单是否已创建
        if($check){
            if(!$classes_order_id)throw new \Exception("缺少订单参数");
            //判断订单是否已创建
            $order_info = self::where(['order_no'=>$order_no])->find();
            if($order_info) throw new \Exception("订单已生成，如需重新下单请退出页面重新进入！");
            if(!$classes_lib_spec_id)throw new \Exception("请选择您要预约的课时信息！");
        }

        if($classes_order_id){
         //校验订单参数
        //更新最近次数后进行验证
        \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($check && $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"] ?? $param["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' => self::where("id",$res1['id'])->find()];
        \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(config("site.free_classes_cancel_check")){
                   if($order->detail["feel"]=='1'){
                       //免费课才判断
                       //课时到开始时间无法取消
                       if($order["start_time"] <= time()){
                           throw new \Exception("免费课程课时到开始时间无法取消！");
                       }
                   }
            }
            //同课时已取消超n次无法再取消 n取配置值
            $cancel_num = config("site.same_hour_cancel_number");
            if($cancel_num >= 0){
                $cancel_count = Order::where("classes_lib_spec_id",$order["classes_lib_spec_id"])
                    ->where("status","in",["-3"])
                    ->count();
                if($cancel_count >= $cancel_num){
                    throw new \Exception("同课时已取消超".$cancel_num."次，无法再取消！");
                }

            }
            self::serverCheck($order['classes_order_id']);
        }

        //判断逻辑
        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' =>  self::where("id",$order['id'])->find(),"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","3"])
            ->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","3"])->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("该课时已满，请选择其他课时！");
                }

            }
        }
               //将空格转义去掉（要考虑unicode解码）
        


            //判断是否是免费课
            $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 checkOnlyone($user_id,$classes_lib_info,$check=false){
            $as = (new self)->getWithAlisaName();
                  //配置
             $onlyone_check = config("site.free_classes_onlyone_check");
             if(!$onlyone_check)return true;

             //同个免费课只能只能买一次
             $order_count = \app\common\model\school\classes\order\Order::with("detail")->where("{$as}.status",'not in',["-3"])
                  ->where("detail.feel",'1')
                  ->where("{$as}.user_id",$user_id)
                  ->where("{$as}.classes_lib_id" ,'=',$classes_lib_info["id"])
                  ->count();
             //已达到进入黑名单条件
             if($check && $order_count){
                 throw new \Exception("您已有正在进行的同类型免费课程，无需重复报名！");

             }


                   //免费课开始和结束时间有交叠无法下预约
             if(!config("site.free_time_overlap_check")){
              //如果是免费课
                $specs = $classes_lib_info->specs;
                foreach ($specs as $classes_lib_spec_info){
                    //判断时间是否有交叠
                $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']}，无法再下单其他免费课程");

                }


            }


    }


    //执行免费课黑名单判断
    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,$only_user=false,$only_shop=false,$only_admin=false){

        //课程是否存在并上架
        $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($only_admin)throw new \Exception("您无权操作该订单！");

                //自己或操作员
                if($oper_id != $classesOrder["user_id"]){
                    if($only_user) throw new \Exception("您无权操作该订单！");

                    $Shop  = Shop::where("user_id",$oper_id)->find();
                    if($Shop){
                        if($Shop["id"] == $classesOrder["shop_id"]){
                            break;
                        }

                    }

                    //说明是操作员
                    $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("该课程不在您的授权范围内，无法代操作！");
                }else{
                     $classes_lib_ids = (new ClassesLib)->getClassesAuthIds($oper_id);
                     //不是员工并且想操作只有机构能操作的单
                    if(!in_array($classesOrder["classes_lib_id"],$classes_lib_ids) && $only_shop)throw new \Exception("您无权操作该订单！");
                }
                break;
            case 'admin':
                $admin_info = Admin::where('id',$oper_id)->find();
                if(!$admin_info) throw new \Exception("代下单管理员不存在！");
                break;
            case 'shop':
                if($only_admin)throw new \Exception("您无权操作该订单！");

                   if($only_user) throw new \Exception("您无权操作该订单！");

                $admin_info = Manystore::where('id',$oper_id)->find();
                if(!$admin_info) throw new \Exception("代下单管理员不存在！");
                $classes_lib_ids = ClassesLib::where("manystore_id",$oper_id)->column("id");
                 //判断当前订单课程是否在此课程授权范围内
                if(!in_array($classesOrder["classes_lib_id"],$classes_lib_ids)) 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);

            self::serverCheck($order['classes_order_id']);

        }
        //审核状态字段检测
        $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' => self::where("id",$order['id'])->find(),"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' => self::where("id",$order['id'])->find(),"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);

            self::serverCheck($order['classes_order_id']);

        }

        //判断逻辑
        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' => self::where("id",$order['id'])->find(),"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);

            self::serverCheck($order['classes_order_id']);
        }


        //判断逻辑
        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' => self::where("id",$order['id'])->find(),"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;
    }




        public static function getMonthByTime($time,$user_id=null,$status="-1,0"){
          $statistics_data_time = $time;
          if(!$statistics_data_time)throw new \Exception("请输入时间！");
          //如果不是时间戳先格式
            if(!is_numeric($statistics_data_time)){
                $statistics_data_time = strtotime($statistics_data_time);
            }

          if($statistics_data_time){
            //得到开始和结束时间
            $start_time  = strtotime(date( 'Y-m-1 00:00:00', $statistics_data_time ));
            $end_time  = strtotime('+1 month', $start_time) -1;
          }

        //得到$start_time 到 $end_time 时间戳的所有天
        $days = [];
        for($i = $start_time; $i <= $end_time; $i += 86400){
            $day = [];
            //得到$date当前是周几
            //需处理周日为7
            $day["week"] = date('w',$i)==0? '7' :date('w',$i);
            $day["day"] = date('d',$i);
            $day["month"] = date('m',$i);
            $day["year"] = date('Y',$i);
            //得到$date的开始和结束时间
            $day["start_time"] = strtotime(date('Y-m-d 00:00:00',$i));
            $day["end_time"] = strtotime(date('Y-m-d 23:59:59',$i));
            $day["field"]   =  "day".$day["day"];
            $week_field = $day['week'];
            $day["title"]   =  $day["day"]."号"."-周{$week_field}";
            $day["check"] = false;
            if($statistics_data_time >= $day["start_time"] && $statistics_data_time <= $day["end_time"]){
                $day["check"] = true;
            }
            $days[] = $day;
        }
           $as = "";
           foreach ($days as $i=>&$day){
                $start_time =$day["start_time"];
                $end_time = $day["end_time"];
                //查询用户在开始和结束事件内的预约
                $model = new self;
                if($user_id)$model = $model->where($as.'user_id',$user_id);
                $model = $model->where($as.'status',"in",$status);
                $day["hour_order_ids"] = $model->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}");
                   })->column("{$as}id");
                $day["number"] = count($day["hour_order_ids"]);
            }
          return $days;
        }




}
