getOrderDispatchModel() ->with(['orderInfo' => function ($query) { $query->with( [ 'area' => function ($query) { $query->field('id,area_code,merge_name'); }, 'coupon' => function ($query) { $query->field('id,threshold,discount_value'); } ] )->field('id,order_no,item_id,item_title,receive_type,address,lng,lat,plan_time,online_amount,discount_amount,area_id,status,coupon_id'); }]) ->where('status', OrderDispatch::STATUS_TOGET) ->where('type', '<>', 1) ->where('worker_id', $workerId) ->field(['id', 'order_id', 'status', 'remark', 'create_time']) ->order('id desc') ->paginate($pageSize); } /** * 工作台列表 * @param int $workerId 师傅id * @param string $type 类型:pending=待沟通,need_visit=待上门,ongoing=服务中,finished=已完成 * @param string $needVisitType 待上门类型:today=今日,tomorrow=明日,all=全部 * @param int $pageSize */ public function workbenchOrderList(int $workerId, string $type, int $pageSize, string $needVisitType) { $model = $this->getWorkbenchOrderModel($workerId, $type, $needVisitType); $result = $model ->field(['id', 'order_id', 'status', 'remark', 'create_time', 'plan_time']) ->order('id desc') ->paginate($pageSize); return $result; } /** * 统计工作台订单 * @param int $workerId * @return array */ public function countWorkbenchOrder(int $workerId) { $needVisit = $this->getWorkbenchOrderModel($workerId, 'need_visit')->count(); return [ 'pending' => $this->getWorkbenchOrderModel($workerId, 'pending')->count(), 'need_visit' => $needVisit, 'ongoing' => $this->getWorkbenchOrderModel($workerId, 'ongoing')->count(), 'finished' => $this->getWorkbenchOrderModel($workerId, 'finished')->count(), 'today' => $this->getWorkbenchOrderModel($workerId, 'need_visit', 'today')->count(), 'tomorrow' => $this->getWorkbenchOrderModel($workerId, 'need_visit', 'tomorrow')->count(), 'all' => $needVisit, ]; } /** * 获取工作台订单模型 * @param int $workerId * @param string $type * @param string $needVisitType */ private function getWorkbenchOrderModel(int $workerId, string $type, string $needVisitType = '') { $model = $this->getOrderDispatchModel() ->with(['orderInfo' => function ($query) { $query->with([ 'area' => function ($query) { $query->field('id,area_code,merge_name'); }, 'coupon' => function ($query) { $query->field('id,threshold,discount_value'); } ])->field('id,order_no,item_id,item_title,receive_type,address,lng,lat,plan_time,online_amount,discount_amount,area_id,customer,tel,status,coupon_id'); }]) ->where('type', '<>', 1) ->where('worker_id', $workerId); switch ($type) { case 'pending': //待沟通 $model->where('status', OrderDispatch::STATUS_GOTIT); break; case 'need_visit': //待上门 $model->where('status', OrderDispatch::STATUS_PLANIT); switch ($needVisitType) { case 'today': $model->where('plan_time', '>=', date('Y-m-d 00:00:00')); $model->where('plan_time', '<=', date('Y-m-d 23:59:59')); break; case 'tomorrow': $model->where('plan_time', '>=', date('Y-m-d 00:00:00', strtotime('+1 day'))); $model->where('plan_time', '<=', date('Y-m-d 23:59:59', strtotime('+1 day'))); break; } break; case 'ongoing': //服务中 $model->where('status', OrderDispatch::STATUS_CLOCK); break; case 'finished': //已完成 $model->where('status', OrderDispatch::STATUS_FINISH); break; } return $model; } /** * 师傅接单/拒接 * @param int $workerId 师傅id * @param array $params 请求参数 * @return true */ public function orderConfirm(int $workerId, array $params) { $orderDispatchId = $params['order_dispatch_id']; $type = $params['type']; $orderDispatch = $this->getOrderDispatchModel() ->where('worker_id', $workerId) ->where('id', $orderDispatchId) ->find(); if (!$orderDispatch) { $this->apiError('订单不存在'); } if ($orderDispatch->status !== OrderDispatch::STATUS_TOGET) { $this->apiError('该订单已被接单'); } //接单或拒接 $orderDispatchStatus = $type == 'accept' ? OrderDispatch::STATUS_GOTIT : OrderDispatch::STATUS_REFUSED; Db::startTrans(); try { //接单 $orderDispatch->status = $orderDispatchStatus; //拒接原因 if ($type == 'reject') { if (empty($params['reject_reason'])) { $this->apiError('请输入拒接原因'); } $orderDispatch->reject_reason = $params['reject_reason']; $orderDispatch->remark = $params['reject_reason']; } $orderDispatch->save(); $orderDispatch->admin_user = '师傅:'. $orderDispatch->worker_name; $orderDispatchChangeParams = [ 'dispatch' => $orderDispatch, 'remark' => $type == 'accept' ? '师傅接单' : '师傅拒接', ]; Hook::listen('order_dispatch_change', $orderDispatchChangeParams); //拒接,更新订单状态 if ($type == 'reject') { $order = $this->getOrderModel()->find($orderDispatch->order_id); $order->status = Order::STATUS_DISPATCHING; $order->save(); $orderChangeParams['order'] = $order; $orderChangeParams['role'] = 2; $orderChangeParams['auth'] = $this->getWorkerModel()->find($orderDispatch->worker_id); $orderChangeParams['remark'] = "任务被师傅拒接[OrderDispatchId:{$orderDispatch->id},原因为:{$params['reject_reason']},订单状态回退"; Hook::listen('order_change', $orderChangeParams); } Db::commit(); } catch (ApiException $e) { Db::rollback(); $this->apiError($e->getMessage()); } catch (\Exception $e) { Db::rollback(); $this->apiError('操作失败', $e, [ 'msg' => '师傅接单或拒接操作失败', 'workerId' => $workerId, 'orderDispatchId' => $orderDispatchId, 'type' => $type, ]); } return true; } /** * 派单详情 * @param int $workerId 师傅id * @param int $orderDispatchId 派单id */ public function dispatchInfo(int $workerId, int $orderDispatchId) { $orderFields = [ 'id', 'order_no', 'item_id', 'item_title', 'receive_type', 'address', 'lng', 'lat', 'plan_time', 'online_amount', 'discount_amount', 'area_id', 'customer', 'tel', 'remark', 'detail', 'images', 'status', 'coupon_id', 'is_material_used', 'material_cost', 'material_images', ]; $orderDispatchFields = [ 'id', 'order_id', 'status', 'remark', 'worker_remark', 'create_time', 'total', 'online_total', 'is_receipt', 'plan_time', 'reject_reason', 'arrive_images', 'arrive_time', 'images', 'image', 'finish_time', 'offline_total_type', 'is_finish_today', 'estimated_finish_time', 'work_progress', ]; $res = $this->getOrderDispatchModel() ->with(['orderInfo' => function ($query) use ($orderFields) { $query->with([ 'area' => function ($query) { $query->field('id,area_code,merge_name'); }, 'coupon' => function ($query) { $query->field('id,threshold,discount_value'); } ])->field($orderFields); }]) ->where('id', $orderDispatchId) ->where('worker_id', $workerId) ->field($orderDispatchFields) ->find(); if (!$res) { $this->apiError('订单不存在'); } return $res; } /** * 提交预约上门时间 * @param int $workerId 师傅id * @param int $orderDispatchId 派单id * @param string $planTime 预约时间 * @return true */ public function appointmentTime(int $workerId, int $orderDispatchId, string $planTime) { $orderDispatch = $this->getOrderDispatchInfo($workerId, $orderDispatchId); $orderDispatch->status = OrderDispatch::STATUS_PLANIT; $orderDispatch->plan_time = $planTime; $orderDispatch->save(); $orderDispatch->admin_user = '师傅:'. $orderDispatch->worker_name; $orderDispatchChangeParams = [ 'dispatch' => $orderDispatch, 'remark' => '师傅已和客户预约,预约时间:' . $planTime, ]; Hook::listen('order_dispatch_change', $orderDispatchChangeParams); return true; } public function updatePlanTime(int $workerId, int $orderDispatchId, string $planTime) { $orderDispatch = $this->getOrderDispatchInfo($workerId, $orderDispatchId); if ($orderDispatch->status !== OrderDispatch::STATUS_PLANIT) { $this->apiError('该单不支持修改上门时间'); } $orderDispatch->plan_time = $planTime; $orderDispatch->save(); $orderDispatch->admin_user = '师傅:'. $orderDispatch->worker_name; $orderDispatchChangeParams = [ 'dispatch' => $orderDispatch, 'remark' => "师傅修改上门时间,旧的时间:{$orderDispatch->plan_time},新的时间:$planTime" ]; Hook::listen('order_dispatch_change', $orderDispatchChangeParams); return true; } /** * 完成上门 * @param int $workerId 师傅id * @param int $orderDispatchId 派单id * @param string $images 上门图片 * @return true */ public function arrivedOnSite(int $workerId, int $orderDispatchId, string $images) { $time = datetime(time()); $orderDispatch = $this->getOrderDispatchInfo($workerId, $orderDispatchId); $orderDispatch->status = OrderDispatch::STATUS_CLOCK; $orderDispatch->arrive_images = $this->removeStrCdnUrl($images); $orderDispatch->arrive_time = $time; $orderDispatch->save(); $orderDispatch->admin_user = '师傅:'. $orderDispatch->worker_name; //派单状态变更 $orderDispatchChangeParams = [ 'dispatch' => $orderDispatch, 'remark' => '师傅已上门,上门时间:' . $time, ]; Hook::listen('order_dispatch_change', $orderDispatchChangeParams); return true; } /** * 移除字符串中的 cdnUrl * @param string $str * @return string */ private function removeStrCdnUrl(string $str): string { $cdnUrl = cdnurl('', true); return str_replace($cdnUrl, '', $str); } /** * 获取订单信息 * @param int $workerId 师傅id * @param int $orderDispatchId 派单id */ private function getOrderDispatchInfo(int $workerId, int $orderDispatchId) { $res = $this->getOrderDispatchModel() ->where('id', $orderDispatchId) ->where('worker_id', $workerId) ->find(); if (!$res) { $this->apiError('工单不存在'); } return $res; } /** * @param int $workerId 师傅id * @param array $params 请求参数 * @return bool */ public function completeService(int $workerId, array $params) { Db::startTrans(); try { $time = datetime(time()); $orderDispatch = $this->getOrderDispatchInfo($workerId, $params['order_dispatch_id']); $orderDispatch->status = OrderDispatch::STATUS_FINISH; $orderDispatch->images = $this->removeStrCdnUrl($params['complete_images']); $orderDispatch->finish_time = $time; // 材料相关 $order = $this->getOrderModel()->where('id', $orderDispatch->order_id)->find(); // 是否使用材料 $order->is_material_used = $params['is_material_used']; if ($order->is_material_used == 1) { // 材料成本 $order->material_cost = $params['material_cost']; // 材料凭证图片组 $order->material_images = $this->removeStrCdnUrl($params['material_images']); $order->save(); } if ($params['receive_type'] == 1) { $orderDispatch->image = $this->removeStrCdnUrl($params['payment_image']); $orderDispatch->offline_total_type = $params['offline_total_type']; //线下尾款 if ($params['final_payment_method'] == 1) { $orderDispatch->total = $params['amount']; } //线上尾款 if ($params['final_payment_method'] == 2) { $orderDispatch->online_total = $params['amount']; } } $orderDispatch->save(); $orderDispatch->admin_user = '师傅:'. $orderDispatch->worker_name; //派单状态变更 $orderDispatchChangeParams = [ 'dispatch' => $orderDispatch, 'remark' => '师傅已完成服务,完成时间:' . $time, ]; Hook::listen('order_dispatch_change', $orderDispatchChangeParams); //修改订单状态 $orderDispatchInfo = OrderDispatch::get($params['order_dispatch_id']); $roleInfo = ['role' => 2, 'auth' => $this->getWorkerModel()->find($workerId), 'remark' => '师傅完成服务']; $this->getOrderLogic()->dispachFinishAfter($orderDispatchInfo, $roleInfo); Db::commit(); } catch (\Exception $e) { Db::rollback(); $this->apiError('操作失败', $e); } return true; } /** * 保存师傅备注 * @param int $workerId 师傅id * @param int $orderDispatchId 订单派单id * @param string $workerRemark 备注信息 * @return true */ public function saveWorkerRemark(int $workerId, int $orderDispatchId, string $workerRemark) { $orderDispatch = $this->getOrderDispatchInfo($workerId, $orderDispatchId); $orderDispatch->worker_remark = $workerRemark; $orderDispatch->save(); return true; } public function updateProgress(int $workerId, array $params) { $orderDispatch = $this->getOrderDispatchInfo($workerId, $params['order_dispatch_id']); $orderDispatch->is_finish_today = $params['is_finish_today']; $orderDispatch->estimated_finish_time = $params['estimated_finish_time']; if ($params['is_finish_today'] == 0) { $orderDispatch->work_progress = $params['work_progress']; } $orderDispatch->save(); return true; } }