<?php
namespace app\common\model;

use app\common\util\AppMsg;
use app\hander\HelpHander;
use think\Db;
use think\Exception;

class Todo extends Base
{

    public $table = 'todo';

    public function formatTodo($v){
        $v['order_type'] = '';
        $v['order_type_matter'] = '';
        $v['address_title'] = '';
        $v['repair_priority'] = '';
        if($v['work_type_mode']==1){
            $typeInfo =  (new \app\common\model\OrderType())
                ->getTypeByOrderId($v['order_id']);
            $v['order_type'] = isset($typeInfo['title'])?$typeInfo['title']:'';
            $v['order_type_matter'] = isset($typeInfo['child_title'])?$typeInfo['child_title']:'';
            $v['address_title'] = isset($typeInfo['address_title'])?$typeInfo['address_title']:'';
            $v['repair_priority'] = isset($typeInfo['repair_priority'])?$typeInfo['repair_priority']:'';
            $v['bx_sign'] = Db::name('todo')->where('id',$v['id'])->value('sign');
        }

        $v['work_type_mode_text'] = $this->getTableField('work_type_mode', ['id'=>$v['work_type_mode']], 'name');
        $v['real_name'] = $this->getTableField('user',['id'=>$v['create_user_id']],'real_name');

        $v['pause_cost'] = '';
        if(!empty($v['pause_time']) && !empty($v['pause_end']) && $v['todo_mode']==3){
             if(!empty($v['confirm_time'])){
                 $v['time_cost'] = $this->getM1($v['done_time'],$v['confirm_time'],$v['pause_end'],$v['pause_time']);
             }else{
                 $v['time_cost'] = '';
             }

            $v['pause_cost'] = $this->getM($v['pause_time'],$v['pause_end']);
        }else{
            $v['time_cost'] = $v['todo_mode']==3 && !empty($v['confirm_time'])?$this->getM($v['done_time'],$v['confirm_time']):'';

        }
        $pDep = '';
        $depInfo = Db::name('dep')
            ->where('id',$v['dep_id'])
            ->find();
        if($depInfo){
            $pDep = Db::name('dep_cate')
                ->where('id',$depInfo['cate_id'])
                ->value('title');
        }
        $v['dep_cate_name'] = $pDep;
        $v['source_type_text'] =$v['from']>0? isset(model('Orders')->source_type[$v['from']])?model('Orders')->source_type[$v['from']]:'':$this->getTableField('work_type_mode', ['id' => $v['work_type_mode']], 'name');
        $v['dispatch_time'] = $this->getM($v['to_create_time'],$v['create_time']);
        $v['jiedan_time'] = !empty($v['confirm_time'])?$this->getM($v['confirm_time'],$v['to_create_time']):'';
        $orderInfo = Db::name('orders')
            ->where('id',$v['order_id'])
            ->find();
        $v['dep'] = $this->getTableField('dep', ['id'=>$orderInfo['dep_id']], 'title');
        $v['order_info'] = model('orders')->formatOrder($orderInfo,1);

        if($v['work_type_mode']==3){
            $oc = Db::name('order_convey')
                ->where('order_id',$v['order_id'])
                ->find();

            $oc['type_name']=$v['type_name'] = isset($oc['type'])?$this->getTableField('convey_cate',['id'=>$oc['type']],'title'):"";
            $oc['start_name']=$v['start_name'] = isset($oc['start'])?$this->getTableField('address',['id'=>$oc['start']],'title'):"";
            $oc['end_name'] =$v['end_name'] =isset($oc['end'])?$this->getTableField('address',['id'=>$oc['end']],'title'):'';
            $oc['device_name']= $v['device_name'] = isset($oc['device_id'])?$this->getTableField('convey_device',['id'=>$oc['device_id']],'title'):'';
            $v['xq_time'] = isset($oc['xq_time'])?$oc['xq_time']:'';
            $v['ywc_time'] = isset($oc['ywc_time'])?$oc['ywc_time']:"";
            $v['oc'] = $oc;
            $v['ocp'] = [];
            $cate =  isset($oc['type'])?$this->getTableField('convey_cate',['id'=>$oc['type']],'cate'):'';
            if($cate==1){
                $ocp = Db::name('order_convey_patient')
                    ->where('order_id',$v['order_id'])
                    ->find();
                $v['ocp'] = $ocp;
            }
        }
        $pauseList = [];
        if($v['todo_mode']==2 && $v['pause']==1){
            $ll = Db::name('todo_puase')
                ->where('todo_id',$v['id'])
                ->select();
            foreach ($ll as $pp=>$dd) {
                $pauseList[$pp]['content'] = $dd['reason'];
                $pauseList[$pp]['timestamp'] = $dd['create_time'];
                $pauseList[$pp]['color'] ='#0bbd87';
            }
        }
        $v['pauseList'] = $pauseList;
        return $v;
    }


    public function newFormatTodo($v){
        $v['order_type'] = '';
        $v['order_type_matter'] = '';
        $v['address_title'] = '';
        $v['repair_priority'] = '';
        if($v['work_type_mode']==1){
            $typeInfo =  (new \app\common\model\OrderType())
                ->getTypeByOrderId($v['order_id']);
            $v['order_type'] = isset($typeInfo['title'])?$typeInfo['title']:'';
            $v['order_type_matter'] = isset($typeInfo['child_title'])?$typeInfo['child_title']:'';
            $v['address_title'] = isset($typeInfo['address_title'])?$typeInfo['address_title']:'';
            $v['repair_priority'] = isset($typeInfo['repair_priority'])?$typeInfo['repair_priority']:'';
            $v['bx_sign'] = Db::name('todo')->where('id',$v['id'])->value('sign');
        }

        $v['work_type_mode_text'] = $this->getTableField('work_type_mode', ['id'=>$v['work_type_mode']], 'name');
        $v['real_name'] = $this->getTableField('user',['id'=>$v['create_user_id']],'real_name');

        $v['pause_cost'] = '';
        if(!empty($v['pause_time']) && !empty($v['pause_end']) && $v['todo_mode']==3){
            if(!empty($v['confirm_time'])){
                $v['time_cost'] = $this->getM1($v['done_time'],$v['confirm_time'],$v['pause_end'],$v['pause_time']);
            }else{
                $v['time_cost'] = '';
            }

            $v['pause_cost'] = $this->getM($v['pause_time'],$v['pause_end']);
        }else{
            $v['time_cost'] = $v['todo_mode']==3 && !empty($v['confirm_time'])?$this->getM($v['done_time'],$v['confirm_time']):'';

        }
        $pDep = '';
        $depInfo = Db::name('dep')
            ->where('id',$v['dep_id'])
            ->find();
        if($depInfo){
            $pDep = Db::name('dep_cate')
                ->where('id',$depInfo['cate_id'])
                ->value('title');
        }
        $v['dep_cate_name'] = $pDep;
        $v['source_type_text'] =$v['from']>0? isset(model('Orders')->source_type[$v['from']])?model('Orders')->source_type[$v['from']]:'':$this->getTableField('work_type_mode', ['id' => $v['work_type_mode']], 'name');
        $v['dispatch_time'] = $this->getM($v['to_create_time'],$v['create_time']);
        $v['jiedan_time'] = !empty($v['confirm_time'])?$this->getM($v['confirm_time'],$v['to_create_time']):'';
        $orderInfo = Db::name('orders')
            ->where('id',$v['order_id'])
            ->find();
        $v['dep'] = $this->getTableField('dep', ['id'=>$orderInfo['dep_id']], 'title');

        if($v['work_type_mode']==3){
            $oc = Db::name('order_convey')
                ->where('order_id',$v['order_id'])
                ->find();

            $oc['type_name']=$v['type_name'] = isset($oc['type'])?$this->getTableField('convey_cate',['id'=>$oc['type']],'title'):"";
            $oc['start_name']=$v['start_name'] = isset($oc['start'])?$this->getTableField('address',['id'=>$oc['start']],'title'):"";
            $oc['end_name'] =$v['end_name'] =isset($oc['end'])?$this->getTableField('address',['id'=>$oc['end']],'title'):'';
            $oc['device_name']= $v['device_name'] = isset($oc['device_id'])?$this->getTableField('convey_device',['id'=>$oc['device_id']],'title'):'';
            $v['xq_time'] = isset($oc['xq_time'])?$oc['xq_time']:'';
            $v['ywc_time'] = isset($oc['ywc_time'])?$oc['ywc_time']:"";
            $v['oc'] = $oc;
            $v['ocp'] = [];
            $cate =  isset($oc['type'])?$this->getTableField('convey_cate',['id'=>$oc['type']],'cate'):'';
            if($cate==1){
                $ocp = Db::name('order_convey_patient')
                    ->where('order_id',$v['order_id'])
                    ->find();
                $v['ocp'] = $ocp;
            }
        }
//        $pauseList = [];
//        if($v['todo_mode']==2 && $v['pause']==1){
//            $ll = Db::name('todo_puase')
//                ->where('todo_id',$v['id'])
//                ->select();
//            foreach ($ll as $pp=>$dd) {
//                $pauseList[$pp]['content'] = $dd['reason'];
//                $pauseList[$pp]['timestamp'] = $dd['create_time'];
//                $pauseList[$pp]['color'] ='#0bbd87';
//            }
//        }
//        $v['pauseList'] = $pauseList;
        return $v;
    }
    public function apiFormatTodo($v){

        $v['work_type_mode_text'] = $this->getTableField('work_type_mode', ['id'=>$v['work_type_mode']], 'name');
        $v['todo_mode_text'] = $this->getTableField('todo_mode', ['id'=>$v['todo_mode']], 'out_content');
        $v['real_name'] = $this->getTableField('user',['id'=>$v['to_user_id']],'real_name');
        $v['time_cost'] = $v['todo_mode']==3 && !empty($v['confirm_time'])?$this->getM($v['done_time'],$v['confirm_time']):'';
        $v['confirm_time'] = $v['confirm_time']?$v['confirm_time']:"";
        $v['done_time'] = $v['done_time']?$v['done_time']:"";
        $orderInfo = Db::name('orders')
            ->where('id',$v['order_id'])
            ->find();
        $v['dep'] = $this->getTableField('dep', ['id'=>$orderInfo['dep_id']], 'title');
        return $v;
    }
    public function getM($do,$cof){
        $diff = strtotime($do) - strtotime($cof);
        $days = floor(($diff )/ (60*60*24));
        $hours = floor(($diff - $days*60*60*24)  / (60*60));
        $minutes = floor(($diff - $days*60*60*24  - $hours*60*60)/ 60);
        $seconds = floor(($diff - $days*60*60*24  - $hours*60*60 - $minutes*60));
        if ($diff < 60) {
            $time_cost = $seconds."秒";
        } else if ($diff >= 60 && $diff < 60*60) {
            $time_cost = $minutes."分钟".$seconds."秒";
        } else if ($diff >= 60*60 && $diff < 60*60*24) {
            $time_cost = $hours."小时".$minutes."分钟".$seconds."秒";
        } else {
            $time_cost = $days."天".$hours."小时".$minutes."分钟".$seconds."秒";
        }
        return $time_cost;
    }
    public function getM1($do,$cof,$e,$a){
        $diff = strtotime($do) - strtotime($cof);
        $aa = strtotime($e) - strtotime($a);
        $diff = $diff-$aa;
        $days = floor(($diff )/ (60*60*24));
        $hours = floor(($diff - $days*60*60*24)  / (60*60));
        $minutes = floor(($diff - $days*60*60*24  - $hours*60*60)/ 60);
        $seconds = floor(($diff - $days*60*60*24  - $hours*60*60 - $minutes*60));
        if ($diff < 60) {
            $time_cost = $seconds."秒";
        } else if ($diff >= 60 && $diff < 60*60) {
            $time_cost = $minutes."分钟".$seconds."秒";
        } else if ($diff >= 60*60 && $diff < 60*60*24) {
            $time_cost = $hours."小时".$minutes."分钟".$seconds."秒";
        } else {
            $time_cost = $days."天".$hours."小时".$minutes."分钟".$seconds."秒";
        }
        return $time_cost;
    }
    // 检查工单状态变化后续的操作
    public function checkToDo($orderId,$todoId,$todoMode){
        $list = Db::name('todo')
            ->where('todo_mode','in',array(1,2,4))
            ->where('order_id',$orderId)
            ->where('id','<>',$todoId)
            ->where('del',0)
            ->field('todo_mode')
            ->select();
        $todoInfo = Db::name('todo')
            ->where('id',$todoId)
            ->find();
        Db::name('task')
            ->where('bus_id', $todoId)
            ->where('user_id', $todoInfo['to_user_id'])
            ->where('type', 1)
            ->delete();
        if($list){
            return true; //不需要修改
        }
        if($todoMode == 3){ // 完成
            $res = Db::name('orders')
                ->where('id',$orderId)->update([
                'order_mode' => 5,
                'finish_time' => date('Y-m-d H:i:s')
            ]);
            if(!$res){
                return false;
            }
            $this->finishTodoPush($orderId,$todoId);
            return true;
        }else if ($todoMode==5){//无法完成
            $check = Db::name('todo')
                ->where('todo_mode',3)
                ->where('order_id',$orderId)
                ->where('id','<>',$todoId)
                ->field('todo_mode')
                ->find();
            if($check){
                $res = Db::name('orders')
                    ->where('id',$orderId)->update([
                        'order_mode' => 5,
                        'finish_time' => date('Y-m-d H:i:s')
                    ]);
                if($res){
                    $this->finishTodoPush($orderId,$todoId);
                    return true;
                }
                return false;
            }else{
                $res = Db::name('orders')
                    ->where('id',$orderId)
                    ->update(['order_mode'=>7,'update_time'=>getTime()]);
                if($res){
                    return true;
                }
                return false;
            }

        } else { //取消
            $res = Db::name('orders')
                ->where('id',$orderId)->update([
                'order_mode' =>3,
            ]);
            return $res?true:false;
        }
    }
    public function finishTodoPush($orderId,$todoId){
        $todoInfo = Db::name('todo')
            ->where('id',$todoId)
            ->find();
        // 投诉完成推送
        model('Complain')->pushCreateUser($orderId,0);

        // 是病人运送订单且需要收费时需要生成,缴费单
        // 检查运送收费开发是否开启
        $ysoff = model('Config')->getConfig('org_ys_switch',$todoInfo['org_id']);
        $money1 = model('Config')->getConfig('org_ys_init_money',$todoInfo['org_id']);
        $money2 = model('Config')->getConfig('org_ys_lj_money',$todoInfo['org_id']);
        $money1 = $money1?$money1:0;
        $money2 = $money2?$money2:0;
        if($ysoff){
            // 检查订单是不是病人运送
            $convey = Db::name('order_convey')
                ->alias('a')
                ->join('convey_cate b','a.type = b.id')
                ->where('a.order_id',$orderId)
                ->where('b.cate',1)
                ->field('a.*')
                ->find();
            if($convey){
                $count = Db::name('order_convey_end')->where('order_convey_id',$convey['id'])->count();
                $money = round($money1 + $count*$money2,2);
                if($money > 0){
                    $ret = Db::name('order_convey_pay')->insert([
                        'sn' => get_unique_id('YS'),
                        'org_id' => $todoInfo['org_id'],
                        'order_id' => $convey['order_id'],
                        'order_convey_id' => $convey['id'],
                        'money' => $money,
                        'status' => 0,
                        'create_time' => date('Y-m-d H:i:s'),
                        'type' => 0
                    ]);
                    if(!$ret){
                        return false;
                    }
                }
            }
        }
    }
    public function cancel($id,$reason){
        $info = $this->where('id',$id)->find();
        if (!$info) {
            $this->error='工单不存在';
            return false;
        }
        if (!in_array($info['todo_mode'], array(1, 2, 4))) {
            $this->error='此状态不能取消工单';
            return false;
        }
        $this->startTrans();
        try {
            if ($info['todo_mode'] == 1 || $info['todo_mode'] == 2) {
                $mode = 6;
            } else {
                $mode = 7;
            }
            $ret = $this->where('id', $id)->update(['todo_mode'=>$mode,'cancel_reason'=>$reason]);
            if (!$ret) {
                exception('工单状态修改失败');
            }
            $ret = $this->checktodo($info['order_id'],$id,6);
            if(!$ret){
                exception('订单修改失败');
            }

            $this->commit();
            return true;
        } catch (Exception $e) {
            $this->rollback();
            $this->error=$e->getMessage();
            return false;
        }
    }
    public function finish($id){
        $info = $this->where('id',$id)->find();
        if (!$info) {
            $this->error='工单不存在';
            return false;
        }
        if (!in_array($info['todo_mode'], array(1, 2))) {
            $this->error='此状态不能完成工单';
            return false;
        }
        $this->startTrans();
        try {
            $curTime = date('Y-m-d H:i:s');
            $cfTime = $info['confirm_time'];
            $sData = array(
                'todo_mode' => 3,
                'done_time' => $curTime,
            );
            if($info['todo_mode'] == 1){
                $cfTime = $sData['confirm_time'] = $info['create_time'];
            }
            $wc_time = time() - strtotime($cfTime);
            $sData['wc_time'] = $cfTime?$wc_time:0;
            $ret = $this->where('id',$id)->update($sData);
            if(!$ret){
                 exception('操作失败');
            }

            $ret = $this->checktodo($info['order_id'],$info['id'],3);
            if(!$ret){
                exception('订单修改失败');
            }
            $this->commit();
            return true;
        } catch (Exception $e) {
            $this->rollback();
            $this->error=$e->getMessage();
            return false;
        }
    }
    //后台重新分配
    public function send($id,$userId,$data){
        $info = Db::name('todo_view')->where('id',$id)->find();
        if(!$info||$info['org_id']!=$data['org_id']){
            $this->error='订单不存在';
            return false;
        }
        if(!in_array($info['todo_mode'],array(4))){
            $this->error='此状态不能重新下发任务';
            return false;
        }
        if($info['order_mode'] != 4){
            $this->error='订单已完成不能重新下发任务';
            return false;
        }
        if(!isset($data['to_user_id'])||empty($data['to_user_id'])){
            $this->error='请选择执行人';
            return false;
        }

        $send_user_num = (new Orders())->sendUserNum($info['work_type_mode'],$data['org_id']);
        $users = explode(',', $data['to_user_id']);
        if($send_user_num==1 && count($users) >1){
            $this->error = '执行人只能选择单人';
            return false;
        }
        $to_user_id = array_unique($users);
        $todo = array();
        $this->startTrans();
        try{
            //todo::订单状态暂时不做修改

            //取消驳回的订单
            $res = $this
                ->where('id',$id)->update(['todo_mode'=>7]);
            if(!$res){
                 exception('订单状态更改失败');
            }

            $todoData = [
                'order_id' => $info['order_id'],
                'todo_content' => $data['todo_content'],
                'create_user_id' => $userId,
                'org_id' => $data['org_id'],
                'create_time' => getTime(),
                'todo_mode' => 1,
                'work_type_mode' => $info['work_type_mode'],
                'create_yyyy' => date('Y'),
                'create_yyyymm' => date('Ym'),
                'create_yyyymmdd' => date('Ymd'),
            ];
            $taskData=[
                'org_id'=>$data['org_id'],
                'type'=>1,
                'start_time'=>getTime(),
                'create_time'=>getTime(),
            ];
            $pusharr =[];
            $sns = [];
            foreach ($to_user_id as $k => $v) {
                if(empty($v)){
                    continue;
                }
                $todoData['to_user_id'] = $v;
                $todoData['sn'] = get_unique_sn(get_config('sn_prefix'));
                while (true){
                    if(in_array($todoData['sn'],$sns)){
                        $todoData['sn'] = get_unique_sn(get_config('sn_prefix'));
                    }else{
                        $sns[] = $todoData['sn'];
                        break;
                    }
                }
                $res = Db::name('todo')
                    ->insertGetId($todoData);
                if (!$res){
                    \exception('执行人:'.$v.'派单失败');
                }

                $taskData['user_id'] = $v;
                $taskData['bus_id'] = $res;
                $res = Db::name('task')
                    ->insert($taskData);
                if (!$res){
                    \exception('执行人:'.$v.'任务保存失败');
                }
                $pusharr[] = [
                    'user_id'=>$v,
                    'todo_id'=>$res
                ];
            }
            $res = Db::name('orders')->where('id',$info['order_id'])
                ->update(['order_mode'=>4,'send_time'=>getTime()]);
            if (!$res){
                \exception('订单更新失败');
            }
            if($info['work_type_mode']==1){//报修订单
                $rData = [];
                if(isset($data['type_id']) && !empty($data['type_id'])){
                    $rData['type_id'] = $data['type_id'];
                }
                if(isset($data['address_id']) && !empty($data['address_id'])){
                    $rData['address_id'] = $data['address_id'];
                }
                if(!empty($rData)){
                    $rData['order_id'] = $info['order_id'];
                    Db::name('order_repair')
                        ->where('order_id',$info['order_id'])->delete();
                    $res = Db::name('order_repair')
                        ->insert($rData);
                    if(!$res){
                        \exception('保存维修扩展失败');
                    }
                }
            }
            $this->commit();
            if($pusharr){
                foreach ($pusharr as $k=>$v){
                    // 极光推送
                    send_jpush([$v['user_id']],AppMsg::PUSH_WORKER_ORDER_SEND,'',['id'=>$v['todo_id']]);
                }
            }
            return true;
        }catch (Exception $e){
            $this->rollback();
            $this->error=$e->getMessage();
            return false;
        }
    }
    //api 工单列表
    public function lists($page,$size,$userId,$orgId,$type){
        $offset = ($page-1)*$size;
        if($type==1){//已完成
            $map[] = ['org_id','=',$orgId];
            $map[] = ['del','=',0];
            $map[] = ['to_user_id','=',$userId];
            $map[] = ['todo_mode','=',3];
            $list = $this->where($map)
                ->limit($offset,$size)
                ->order('id','desc')
                ->select();
            $list = $list?$list->toArray():[];
        }else if ($type==2){//已评价
            $list = Db::name('todo')
                ->alias('a')
                ->join('orders b','b.id=a.order_id','left')
                ->where('a.to_user_id',$userId)
                ->where('a.del',0)
                ->where('b.del',0)
                ->where('a.org_id',$orgId)
                ->where('b.order_mode',6)
                ->field('a.*')
                ->order('a.id','desc')
                ->limit($offset,$size)
                ->select();
        }else if ($type==0){//所有
            $list = Db::name('todo')
                ->alias('a')
                ->join('orders b','b.id=a.order_id','left')
                ->where('a.to_user_id',$userId)
                ->where('a.del',0)
                ->where('b.del',0)
                ->where('a.org_id',$orgId)
                ->where(function ($query){
                    $query->where('a.todo_mode', 3)->whereor('b.order_mode', 6);
                })
                ->field('a.*')
                ->order('a.id','desc')
                ->limit($offset,$size)
                ->select();
        }

        $n = [];
        foreach ($list as $k=>$v){
            $a= $this->apiFormatTodo($v);
            $n[] = formatArray(
                [
                    'id',
                    'confirm_time',
                    'done_time',
                    'work_type_mode',
                    'sn'
                ]
                , $a);
        }
        return $n;
    }
    //api工单详情
    public function apiDetail($todoId){
        $info = Db::name('todo_view')->where('id',$todoId)
            ->find();
        if(empty($info)){
            HelpHander::error('工单信息不存在');
        }
        $order = Db::name('orders')
            ->where('id',$info['order_id'])
            ->find();

        $orderInfo = (new Orders())->apiFormatOrder($order,1,$todoId);

        if($order['work_type_mode'] == 3){
            // 地点路径
            $conveyends = Db::name('order_convey_end')
                ->alias('a')
                ->join('address b','b.id = a.addr')
                ->where('a.order_id',$order['id'])
                ->order('a.id asc')
                ->field('a.id,a.addr,b.title,a.scan,a.create_time,a.update_time')
                ->select();
            $orderInfo['ends'] = $conveyends?$conveyends:[];

            $payinfo = [
                'is_pay' => 0,
                'id' => 0,
                'url' => '',
                'money' => 0,
                'remark' => '',
                'type' => 1,
                'pay_time' => '',
            ];

            // 是否需要支付
            $pay = Db::name('order_convey_pay')->where('order_id',$order['id'])->find();
            if($pay){
                $payinfo['is_pay'] = $pay['status'] == 0?0:1;
                $payinfo['url'] = url('h5/Index/pay',['id'=>$pay['id']],false,true);
                $payinfo['money'] = round($pay['money'],2);
                $payinfo['remark'] = $pay['remark'];
                $payinfo['pay_time'] = $pay['pay_time']?$pay['pay_time']:'';
                $payinfo['id'] = $pay['id'];
            }
            $orderInfo['pay'] = $payinfo;
        }

        return $orderInfo;
    }

    //处理驳回订单
    public function createNtbo($todoId,$toUserIdArray,$todoContent,$userId,$typeId,$addressId){
        $todo=$this
            ->where('id',$todoId)->find();
        if(!$todo || $todo['del'] == 1){
            $this->error = '工单不存在';
            return false;
        }

        if($todo['todo_mode'] != 4){
            $this->error = '无权限分配订单';
            return false;
        }
        if(!isset($toUserIdArray)||empty($toUserIdArray)){
            $this->error='请选择执行人';
            return false;
        }

        $send_user_num = (new Orders())->sendUserNum($todo['work_type_mode'],$todo['org_id']);
        $users = explode(',', $toUserIdArray);
        if($send_user_num==1 && count($users) >1){
            $this->error = '执行人只能选择单人';
            return false;
        }
        $to_user_id = array_unique($users);
        $this->startTrans();
        try{
            $res = $this
                ->where('id',$todoId)->update(['todo_mode'=>7]);
            if(!$res){
                \exception('订单状态更改失败');
            }
            if($todo['work_type_mode']==1){//报修订单
                $rData = [];
                if(!empty($typeId) && $typeId>0 ){
                    $rData['type_id'] =$typeId;
                }
                if(!empty($addressId) && $addressId>0){
                    $rData['address_id'] = $addressId;
                }
                if(!empty($rData)){
                    $rData['order_id'] = $todo['order_id'];
                    Db::name('order_repair')
                        ->where('order_id',$todo['order_id'])->delete();
                    $res = Db::name('order_repair')
                        ->insert($rData);
                    if(!$res){
                        \exception('保存维修扩展失败');
                    }
                }
            }
            $todoData = [
                'order_id' => $todo['order_id'],
                'todo_content' => $todoContent,
                'create_user_id' => $userId,
                'org_id' => $todo['org_id'],
                'create_time' => getTime(),
                'todo_mode' => 1,
                'work_type_mode' => $todo['work_type_mode'],
                'create_yyyy' => date('Y'),
                'create_yyyymm' => date('Ym'),
                'create_yyyymmdd' => date('Ymd'),
            ];
            $taskData=[
                'org_id'=>$todo['org_id'],
                'type'=>1,
                'start_time'=>getTime(),
                'create_time'=>getTime(),
            ];
            $sns = [];
            foreach ($to_user_id as $k => $v) {
                if(empty($v)){
                    continue;
                }
                $todoData['to_user_id'] = $v;
                $todoData['sn'] = get_unique_sn(get_config('sn_prefix'));
                while (true){
                    if(in_array($todoData['sn'],$sns)){
                        $todoData['sn'] = get_unique_sn(get_config('sn_prefix'));
                    }else{
                        $sns[] = $todoData['sn'];
                        break;
                    }
                }
                $res = Db::name('todo')
                    ->insertGetId($todoData);
                if (!$res){
                    \exception('执行人:'.$v.'派单失败');
                }

                $taskData['user_id'] = $v;
                $taskData['bus_id'] = $res;
                $res = Db::name('task')
                    ->insert($taskData);
                if (!$res){
                    \exception('执行人:'.$v.'任务保存失败');
                }
                // 极光推送
                send_jpush([$v],AppMsg::PUSH_WORKER_ORDER_SEND,'',['id'=>$res]);
            }

            $this->commit();
            return true;
        }catch (Exception $e){
            $this->rollback();
            return false;
        }

    }
    //修改工单状态 4 驳回 5客观原因
    public function updateState($todoId,$todoMode,$nodoReason,$userId,$rejectVoice){
        $todo = $this
            ->where('id',$todoId)
            ->where('del',0)
            ->find();
        if(!$todo){
            $this->error = '工单不存在';
            return false;
        }

        if($todoMode == 4){ // 驳回
            if($todo['todo_mode']!==1){
                $this->error = '当前状态不能驳回';
                return false;
            }
            $this->startTrans();
            try{
                $ret = $this
                    ->where('id',$todoId)
                    ->update(['todo_mode'=>$todoMode,
                        'nodo_reason'=>$nodoReason,
                        'reject_voice'=>$rejectVoice,
                        'reject_time' => date('Y-m-d H:i:s')]);
                if(!$ret){
                    \exception('操作失败');
                }
                Db::name('task')
                    ->where('org_id',$todo['org_id'])
                    ->where('user_id',$userId)
                    ->where('type',1)
                    ->where('bus_id',$todoId)
                    ->delete();

                $this->commit();
            }catch (Exception $e){
                $this->rollback();
                $this->error = $e->getMessage();
                return false;
            }

        }else if($todoMode == 2){
            if($todo['todo_mode']!==1){
                $this->error = '当前状态不能领取';
                return false;
            }
            $XY_TIME = time() - strtotime($todo['create_time']);
            $ret = $this->where('id',$todoId)->update([
                'todo_mode'=>$todoMode,
                'confirm_time' => date('Y-m-d H:i:s'),
                'xy_time' => $XY_TIME
            ]);
//            $todoIds = Db::name('todo')
//                ->where('id','<>',$todoId)
//                ->where('order_id','=',$todo['order_id'])
//                ->column('id');
//            if(!empty($todoIds)){
//                $r = Db::name('todo')
//                    ->where('id','in',$todoIds)
//                    ->delete();
//                Db::name('task')
//                    ->where('bus_id', 'in', $todoIds)
//                    ->where('type', 1)
//                    ->delete();
//                if(!$r){
//                    $this->error = '操作失败';
//                    return false;
//                }
//            }

            if(!$ret){
                $this->error = '操作失败';
                return false;
            }
        }else if($todoMode == 6){ // 取消驳回工单

            $this->startTrans();
            try{
                $ret = $this
                    ->where('id',$todoId)
                    ->update(['todo_mode'=>$todoMode,
                        'cancel_reason' => $nodoReason]);
                if(!$ret){
                  \exception('订单错误失败');
                }

                $ret = $this->checkToDo($todo['order_id'],$todoId,$todoMode);
                if(!$ret){
                     \exception('订单修改失败');
                }
                Db::name('task')
                    ->where('org_id',$todo['org_id'])
                    ->where('user_id',$userId)
                    ->where('type',1)
                    ->where('bus_id',$todoId)
                    ->delete();
                $this->commit();
            }catch (Exception $e){
                $this->rollback();
                $this->error = $e->getMessage();
                return false;
            }
        }

        return true;
    }

    // 工人完成提交任务/无法完成
    public function finishTodo($todoId,$todoMode,$content,$userId,$images,$consItems,$sign){
        $todo = $this
            ->where('id',$todoId)
            ->where('del',0)->find();
        if(!$todo){
            $this->error = '工单不存在';
            return false;
        }
        if($todo['to_user_id'] != $userId || $todo['todo_mode'] != 2){
            $this->error = '无权限操作';
            return false;
        }

        if($todo['work_type_mode']== 1 && $todo['todo_mode'] == 2 && $todo['pause'] == 1){
            $this->error = '工单正在挂起,无法完成';
            return false;
        }

        if($todo['work_type_mode']==1 && $todoMode==3){
           $off =(new Config())->getConfig('org_sign',$todo['org_id']);
           if($off==1 && empty($sign)){
               $this->error = '请上传签名';
               return false;
           }
        }


        $this->startTrans();
        try{
            if($todo['pause'] == 2){
                $ct = strtotime($todo['confirm_time']);
                $pst = strtotime($todo['pause_time']);
                $pet = strtotime($todo['pause_end']);
                $WC_TIME = ($pst - $ct) + time()-$pet;
            }else{
                $WC_TIME = time() - strtotime($todo['confirm_time']);
            }

            $curTime = date('Y-m-d H:i:s');

            $ret = $this
                ->where('id',$todoId)->update([
                'nodo_reason' => $content,
                'images' => $images,
                'todo_mode' => $todoMode,
                'done_time' => $curTime,
                'wc_time' => $WC_TIME,
                'sign' => $sign
            ]);
            if(!$ret){
               \exception('工单修改失败');
            }

            if($todoMode == 3 && $consItems){ // 工单完成且有耗材
               $consItems = json_decode($consItems,true);
               $mate = [
                   'todo_id'=>$todoId,
                   'order_id'=>$todo['order_id'],
                   'org_id'=>$todo['org_id'],
                   'user_id'=>$userId,
                   'create_time'=>getTime()
               ];
               $todo_mate_id = Db::name('todo_mate')
                   ->insertGetId($mate);
               if(!$todo_mate_id){
                   \exception('订单使用物品记录失败');
               }
               $items = [];
               foreach ($consItems as $k=>$v){
                   $itemInfo = Db::name('mate_goods')
                       ->where('id',$v['itemsId'])
                       ->find();
                   if($itemInfo['nums'] < $v['total']){
                       \exception($itemInfo['title'].' 库存不足');
                   }
                   $items[] = [
                       'todo_mate_id'=>$todo_mate_id,
                       'items_id'=>$v['itemsId'],
                       'total'=>$v['total'],
                       'create_time'=>getTime(),
                       'user_id'=>$userId,
                       'money'=>$itemInfo['price'],
                       'total_money'=>$itemInfo['price']*$v['total'],

                   ];
                   $res = Db::name('mate_goods')
                       ->where('id',$v['itemsId'])
                       ->setDec('nums',$v['total']);
                   if(!$res){
                       \exception($itemInfo['title'].' 数量修改失败');

                   }
               }
               $res = Db::name('todo_mate_item')
                   ->insertAll($items);
                if(!$res){
                    \exception('物品使用记录失败');
                }
            }
            $ret = $this->checkToDo($todo['order_id'],$todoId,$todoMode);
            Db::name('task')
                ->where('bus_id', '=', $todoId)
                ->where('type', 1)
                ->delete();
            if(!$ret){
             \exception('订单修改失败');
            }
            $this->commit();
        }catch (Exception $e){
            $this->error = $e->getMessage();
            $this->rollback();
            return false;
        }

        return true;
    }
    //获取物品列表
    public function getMateGoods($orgId,$userId,$title,$page,$size){
        $map[] = ['org_id','=',$orgId];
        $map[] = ['enable','=',1];
        $map[] = ['del','=',0];
        if($title){
            $map[] = ['title','like','%'.$title.'%'];
        }
        $offset = ($page-1)*$size;
        $list = (new MateGoods())->getList($offset,$size,$map,'id desc');
        $a = [];
        foreach ($list as $k=>$v){
            $user_cons = Db::name('user_cons')
                ->where('user_id',$userId)
                ->where('goods_id',$v['id'])
                ->find();
            $v['is_fav'] = $user_cons?1:0;
            $a[] = formatArray([
                'id','price','nums','title','spec','is_fav'
            ],$v);
        }
        return $a;
    }
    //收藏/取消收藏
    public function favGoods($userId,$type,$goodsId){
        if($type==0){
            $res = Db::name('user_cons')
                ->where('goods_id',$goodsId)
                ->where('user_id',$userId)
                ->delete();
        }else{
            if(Db::name('user_cons')
                ->where('goods_id',$goodsId)
                ->where('user_id',$userId)->find()){
                HelpHander::error('该物品已收藏');
            }
            $res = Db::name('user_cons')
                ->insertGetId([
                    'goods_id'=>$goodsId,
                    'user_id'=>$userId,
                ]);
        }
        return $res;
    }
    //收藏物品列表
    public function favList($userId,$title){
        if($title){
            $map[] = ['b.title','like','%'.$title.'%'];
        }
        $map[] = ['a.user_id','=',$userId];
        $map[] = ['b.enable','=',1];
        $map[] = ['b.del','=',0];
        $list = Db::name('user_cons')
            ->alias('a')
            ->join('mate_goods b','a.goods_id = b.id')
            ->where($map)
            ->order('a.id desc')
            ->field('b.*')
            ->select();
        $a = [];
        foreach ($list as $k=>$v){
            $a[] = formatArray([
                'id','price','nums','title','spec',
            ],$v);
        }
        return $a;
    }
}