allocatr/application/services/OrderDispatchService.php
2025-05-07 22:04:33 +08:00

401 lines
13 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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');
}])->field('id,order_no,item_id,item_title,receive_type,address,lng,lat,plan_time,online_amount,discount_amount,area_id');
}])
->where('status', OrderDispatch::STATUS_TOGET)
->where('worker_id', $workerId)
->field(['id', 'order_id', 'status', 'remark', 'create_time'])
->order('id desc')
->paginate($pageSize);
}
/**
* @param int $workerId 师傅id
* @param string $type 类型ongoing=进行中,today=当日,tomorrow=昨日,all=全部订单
* @param int $pageSize
*/
public function workbenchOrderList(int $workerId, string $type, int $pageSize)
{
$model = $this->getWorkbenchOrderModel($workerId, $type);
$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)
{
return [
'ongoing' => $this->getWorkbenchOrderModel($workerId, 'ongoing')->count(),
'today' => $this->getWorkbenchOrderModel($workerId, 'today')->count(),
'tomorrow' => $this->getWorkbenchOrderModel($workerId, 'tomorrow')->count(),
'all' => $this->getWorkbenchOrderModel($workerId, 'all')->count(),
];
}
/**
* 获取工作台订单模型
* @param int $workerId
* @param string $type
*/
private function getWorkbenchOrderModel(int $workerId, string $type)
{
$model = $this->getOrderDispatchModel()
->with(['orderInfo' => function ($query) {
$query->with(['area' => function ($query) {
$query->field('id,area_code,merge_name');
}])->field('id,order_no,item_id,item_title,receive_type,address,lng,lat,plan_time,online_amount,discount_amount,area_id,customer,tel');
}])
->where('worker_id', $workerId);
$status = [
OrderDispatch::STATUS_GOTIT,
OrderDispatch::STATUS_PLANIT,
OrderDispatch::STATUS_CLOCK,
];
switch ($type) {
case 'ongoing':
//所有已接单未完成的订单
$model->whereIn('status', $status);
break;
case 'today':
$model->whereIn('status', $status);
$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->whereIn('status', $status);
$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;
case 'all':
$status[] = OrderDispatch::STATUS_REFUSED;
$status[] = OrderDispatch::STATUS_FINISH;
$model->whereIn('status', $status);
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->save();
$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',
];
$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',
];
$res = $this->getOrderDispatchModel()
->with(['orderInfo' => function ($query) use ($orderFields) {
$query->with(['area' => function ($query) {
$query->field('id,area_code,merge_name');
}])->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();
$orderDispatchChangeParams = [
'dispatch' => $orderDispatch,
'remark' => '师傅已和客户预约,预约时间:' . $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();
//派单状态变更
$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;
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();
//派单状态变更
$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;
}
}