500 lines
17 KiB
PHP
500 lines
17 KiB
PHP
<?php
|
||
|
||
namespace app\services;
|
||
|
||
use app\admin\model\Order;
|
||
use app\admin\model\OrderDispatch;
|
||
use app\api\library\ApiException;
|
||
use think\Db;
|
||
use think\Hook;
|
||
|
||
class OrderDispatchService extends BaseService
|
||
{
|
||
public function dispatchList(int $workerId, int $pageSize)
|
||
{
|
||
return $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,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;
|
||
$orderDispatch->follow = 1;
|
||
$orderDispatch->got_time = date('Y-m-d H:i:s', time());
|
||
//拒接原因
|
||
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',
|
||
'off_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->follow = 1;
|
||
$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->follow = 1;
|
||
$orderDispatch->save();
|
||
|
||
$orderDispatch->admin_user = '工程师:'. $orderDispatch->worker_name;
|
||
//派单状态变更
|
||
$orderDispatchChangeParams = [
|
||
'dispatch' => $orderDispatch,
|
||
'remark' => '已上门',
|
||
];
|
||
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->follow = 2;
|
||
$orderDispatch->finish_time = $time;
|
||
|
||
$order = $this->getOrderModel()->where('id', $orderDispatch->order_id)->find();
|
||
|
||
// 定金核销凭证
|
||
if (!empty($params['off_images'])) {
|
||
$order->off_images = $this->removeStrCdnUrl($params['off_images']);
|
||
}
|
||
|
||
// 是否使用材料
|
||
$order->is_material_used = $params['is_material_used'];
|
||
if ($order->is_material_used == 1) {
|
||
// 材料成本
|
||
$orderDispatch->material_cost = $params['material_cost'];
|
||
$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' => '已完成服务',
|
||
];
|
||
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'];
|
||
$orderDispatch->follow = 1;
|
||
if ($params['is_finish_today'] == 0) {
|
||
$orderDispatch->work_progress = $params['work_progress'];
|
||
}
|
||
|
||
$orderDispatch->save();
|
||
|
||
return true;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|