499 行
16 KiB
PHP
499 行
16 KiB
PHP
<?php
|
||
namespace Api\Controller;
|
||
|
||
use Api\Controller\BaseController;
|
||
use Common\Business\RiderOrderDispatch;
|
||
|
||
/**
|
||
* 骑手端订单API控制器
|
||
* Class RiderOrderController
|
||
* @package Api\Controller
|
||
*/
|
||
class RiderOrderController extends BaseController
|
||
{
|
||
/**
|
||
* 获取骑手订单列表
|
||
* @return void
|
||
*/
|
||
public function getOrderList()
|
||
{
|
||
$param = I('post.');
|
||
|
||
// 验证骑手身份
|
||
$riderInfo = $this->checkRiderAuth();
|
||
if ($riderInfo['status'] != 1) {
|
||
$this->ajaxReturn($riderInfo);
|
||
}
|
||
|
||
$riderId = $riderInfo['data']['id'];
|
||
|
||
// 设置默认参数
|
||
$page = isset($param['page']) ? intval($param['page']) : 1;
|
||
$pageSize = isset($param['page_size']) ? intval($param['page_size']) : 20;
|
||
$orderStatus = isset($param['order_status']) ? $param['order_status'] : '';
|
||
|
||
$riderOrderModel = D('RiderOrder');
|
||
|
||
// 构建查询条件
|
||
$where = ['rider_id' => $riderId];
|
||
if ($orderStatus !== '') {
|
||
$where['order_status'] = $orderStatus;
|
||
}
|
||
|
||
// 获取订单列表
|
||
$orders = $riderOrderModel->getOrderList($where, $page, $pageSize);
|
||
|
||
$this->ajaxReturn(callBack(statusCode()['success'], '获取订单列表成功', $orders));
|
||
}
|
||
|
||
/**
|
||
* 接受订单
|
||
* @return void
|
||
*/
|
||
public function acceptOrder()
|
||
{
|
||
$param = I('post.');
|
||
|
||
// 验证骑手身份
|
||
$riderInfo = $this->checkRiderAuth();
|
||
if ($riderInfo['status'] != 1) {
|
||
$this->ajaxReturn($riderInfo);
|
||
}
|
||
|
||
$riderId = $riderInfo['data']['id'];
|
||
|
||
if (empty($param['rider_order_id'])) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单ID不能为空'));
|
||
}
|
||
|
||
$riderOrderModel = D('RiderOrder');
|
||
|
||
// 获取订单信息
|
||
$orderInfo = $riderOrderModel->getFind(['id' => $param['rider_order_id'], 'rider_id' => $riderId]);
|
||
if (empty($orderInfo)) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单不存在'));
|
||
}
|
||
|
||
// 检查订单状态
|
||
if ($orderInfo['order_status'] != 0) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单状态不允许接受'));
|
||
}
|
||
|
||
// 检查骑手当前订单数量
|
||
import('@.Common.Business.OrderStatusUtil');
|
||
$inProgress = \Common\Business\OrderStatusUtil::getInProgressStatuses();
|
||
$currentOrders = $riderOrderModel->getCount([
|
||
'rider_id' => $riderId,
|
||
'order_status' => ['in', implode(',', $inProgress)]
|
||
]);
|
||
|
||
$riderInfoModel = D('RiderInfo');
|
||
$rider = $riderInfoModel->getFind(['id' => $riderId]);
|
||
|
||
if ($currentOrders >= $rider['max_orders_per_time']) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '当前订单数量已达上限'));
|
||
}
|
||
|
||
// 更新订单状态为已接单
|
||
$updateData = [
|
||
'order_status' => 1,
|
||
'accept_time' => date('Y-m-d H:i:s'),
|
||
'updated_at' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
$result = $riderOrderModel->updateOrder(['id' => $param['rider_order_id']], $updateData);
|
||
|
||
if ($result) {
|
||
// 同步更新原订单状态
|
||
$this->syncOrderStatus($orderInfo['bill_id'], 'accepted');
|
||
|
||
$this->ajaxReturn(callBack(statusCode()['success'], '接受订单成功'));
|
||
} else {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '接受订单失败'));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 拒绝订单
|
||
* @return void
|
||
*/
|
||
public function rejectOrder()
|
||
{
|
||
$param = I('post.');
|
||
|
||
// 验证骑手身份
|
||
$riderInfo = $this->checkRiderAuth();
|
||
if ($riderInfo['status'] != 1) {
|
||
$this->ajaxReturn($riderInfo);
|
||
}
|
||
|
||
$riderId = $riderInfo['data']['id'];
|
||
|
||
if (empty($param['rider_order_id'])) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单ID不能为空'));
|
||
}
|
||
|
||
$riderOrderModel = D('RiderOrder');
|
||
|
||
// 获取订单信息
|
||
$orderInfo = $riderOrderModel->getFind(['id' => $param['rider_order_id'], 'rider_id' => $riderId]);
|
||
if (empty($orderInfo)) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单不存在'));
|
||
}
|
||
|
||
// 检查订单状态
|
||
if ($orderInfo['order_status'] != 0) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单状态不允许拒绝'));
|
||
}
|
||
|
||
// 更新订单状态为已拒绝
|
||
$updateData = [
|
||
'order_status' => -1,
|
||
'reject_time' => date('Y-m-d H:i:s'),
|
||
'reject_reason' => $param['reject_reason'] ?? '骑手拒绝接单',
|
||
'updated_at' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
$result = $riderOrderModel->updateOrder(['id' => $param['rider_order_id']], $updateData);
|
||
|
||
if ($result) {
|
||
// 重新分配订单
|
||
$this->reassignOrder($orderInfo['bill_id'], $riderId);
|
||
|
||
$this->ajaxReturn(callBack(statusCode()['success'], '拒绝订单成功'));
|
||
} else {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '拒绝订单失败'));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 开始配送
|
||
* @return void
|
||
*/
|
||
public function startDelivery()
|
||
{
|
||
$param = I('post.');
|
||
|
||
// 验证骑手身份
|
||
$riderInfo = $this->checkRiderAuth();
|
||
if ($riderInfo['status'] != 1) {
|
||
$this->ajaxReturn($riderInfo);
|
||
}
|
||
|
||
$riderId = $riderInfo['data']['id'];
|
||
|
||
if (empty($param['rider_order_id'])) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单ID不能为空'));
|
||
}
|
||
|
||
$riderOrderModel = D('RiderOrder');
|
||
|
||
// 获取订单信息
|
||
$orderInfo = $riderOrderModel->getFind(['id' => $param['rider_order_id'], 'rider_id' => $riderId]);
|
||
if (empty($orderInfo)) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单不存在'));
|
||
}
|
||
|
||
// 检查订单状态
|
||
if ($orderInfo['order_status'] != 2) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单状态不允许开始配送'));
|
||
}
|
||
|
||
// 更新订单状态为配送中
|
||
$updateData = [
|
||
'order_status' => 3,
|
||
'delivery_start_time' => date('Y-m-d H:i:s'),
|
||
'updated_at' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
$result = $riderOrderModel->updateOrder(['id' => $param['rider_order_id']], $updateData);
|
||
|
||
if ($result) {
|
||
// 同步更新原订单状态
|
||
$this->syncOrderStatus($orderInfo['bill_id'], 'delivering');
|
||
|
||
$this->ajaxReturn(callBack(statusCode()['success'], '开始配送成功'));
|
||
} else {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '开始配送失败'));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 完成配送
|
||
* @return void
|
||
*/
|
||
public function completeDelivery()
|
||
{
|
||
$param = I('post.');
|
||
|
||
// 验证骑手身份
|
||
$riderInfo = $this->checkRiderAuth();
|
||
if ($riderInfo['status'] != 1) {
|
||
$this->ajaxReturn($riderInfo);
|
||
}
|
||
|
||
$riderId = $riderInfo['data']['id'];
|
||
|
||
if (empty($param['rider_order_id'])) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单ID不能为空'));
|
||
}
|
||
|
||
$riderOrderModel = D('RiderOrder');
|
||
|
||
// 获取订单信息
|
||
$orderInfo = $riderOrderModel->getFind(['id' => $param['rider_order_id'], 'rider_id' => $riderId]);
|
||
if (empty($orderInfo)) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单不存在'));
|
||
}
|
||
|
||
// 检查订单状态:必须处于配送中(5)才允许完成
|
||
if ($orderInfo['order_status'] != 5) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单状态不允许完成配送'));
|
||
}
|
||
|
||
// 更新订单状态为已送达(6)
|
||
$updateData = [
|
||
'order_status' => 6,
|
||
'delivery_time' => date('Y-m-d H:i:s'),
|
||
'delivery_proof' => $param['delivery_proof'] ?? '', // 配送凭证
|
||
'updated_at' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
$result = $riderOrderModel->updateOrder(['id' => $param['rider_order_id']], $updateData);
|
||
|
||
if ($result) {
|
||
// 同步更新原订单状态
|
||
$this->syncOrderStatus($orderInfo['bill_id'], 'completed');
|
||
|
||
// 更新骑手统计信息
|
||
$this->updateRiderStats($riderId, array_merge($orderInfo, ['delivery_time' => $updateData['delivery_time']]));
|
||
|
||
$this->ajaxReturn(callBack(statusCode()['success'], '完成配送成功'));
|
||
} else {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '完成配送失败'));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新骑手位置
|
||
* @return void
|
||
*/
|
||
public function updateLocation()
|
||
{
|
||
$param = I('post.');
|
||
|
||
// 验证骑手身份
|
||
$riderInfo = $this->checkRiderAuth();
|
||
if ($riderInfo['status'] != 1) {
|
||
$this->ajaxReturn($riderInfo);
|
||
}
|
||
|
||
$riderId = $riderInfo['data']['id'];
|
||
|
||
if (empty($param['lat']) || empty($param['lng'])) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '位置信息不能为空'));
|
||
}
|
||
|
||
$riderInfoModel = D('RiderInfo');
|
||
|
||
// 更新骑手位置
|
||
$updateData = [
|
||
'last_location_lat' => $param['lat'],
|
||
'last_location_lng' => $param['lng'],
|
||
'last_location_time' => date('Y-m-d H:i:s'),
|
||
'updated_at' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
$result = $riderInfoModel->updateRider(['id' => $riderId], $updateData);
|
||
|
||
if ($result) {
|
||
// 记录位置轨迹
|
||
$this->recordLocationTrack($riderId, $param['lat'], $param['lng']);
|
||
|
||
$this->ajaxReturn(callBack(statusCode()['success'], '位置更新成功'));
|
||
} else {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '位置更新失败'));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取订单详情
|
||
* @return void
|
||
*/
|
||
public function getOrderDetail()
|
||
{
|
||
$param = I('post.');
|
||
|
||
// 验证骑手身份
|
||
$riderInfo = $this->checkRiderAuth();
|
||
if ($riderInfo['status'] != 1) {
|
||
$this->ajaxReturn($riderInfo);
|
||
}
|
||
|
||
$riderId = $riderInfo['data']['id'];
|
||
|
||
if (empty($param['rider_order_id'])) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单ID不能为空'));
|
||
}
|
||
|
||
$riderOrderModel = D('RiderOrder');
|
||
|
||
// 获取订单详情
|
||
$orderDetail = $riderOrderModel->getOrderDetail($param['rider_order_id'], $riderId);
|
||
|
||
if (empty($orderDetail)) {
|
||
$this->ajaxReturn(callBack(statusCode()['error'], '订单不存在'));
|
||
}
|
||
|
||
$this->ajaxReturn(callBack(statusCode()['success'], '获取订单详情成功', $orderDetail));
|
||
}
|
||
|
||
/**
|
||
* 验证骑手身份
|
||
* @return array
|
||
*/
|
||
private function checkRiderAuth()
|
||
{
|
||
$token = I('post.token', '');
|
||
if (empty($token)) {
|
||
return callBack(statusCode()['error'], '请先登录');
|
||
}
|
||
|
||
$riderTokenModel = D('RiderToken');
|
||
$tokenInfo = $riderTokenModel->getFind(['token' => $token]);
|
||
|
||
if (empty($tokenInfo)) {
|
||
return callBack(statusCode()['error'], '登录已过期,请重新登录');
|
||
}
|
||
|
||
// 检查token是否过期
|
||
if (strtotime($tokenInfo['expire_time']) < time()) {
|
||
return callBack(statusCode()['error'], '登录已过期,请重新登录');
|
||
}
|
||
|
||
// 获取骑手信息
|
||
$riderInfoModel = D('RiderInfo');
|
||
$riderInfo = $riderInfoModel->getFind(['id' => $tokenInfo['rider_id']]);
|
||
|
||
if (empty($riderInfo)) {
|
||
return callBack(statusCode()['error'], '骑手信息不存在');
|
||
}
|
||
|
||
if ($riderInfo['status'] != 1) {
|
||
return callBack(statusCode()['error'], '账号已被禁用');
|
||
}
|
||
|
||
return callBack(statusCode()['success'], '验证成功', $riderInfo);
|
||
}
|
||
|
||
/**
|
||
* 同步订单状态到原系统
|
||
* @param int $billId 原订单ID
|
||
* @param string $action 操作类型
|
||
* @return void
|
||
*/
|
||
private function syncOrderStatus($billId, $action)
|
||
{
|
||
$billOnlineModel = D('RetailBillOnline');
|
||
|
||
switch ($action) {
|
||
case 'accepted':
|
||
// 骑手接单,更新为已发货状态
|
||
$billOnlineModel->updateBill(['bill_id' => $billId], [
|
||
'status' => 2, // 已发货
|
||
'delivery_type' => 1, // 门店自己配送
|
||
'updated_at' => date('Y-m-d H:i:s')
|
||
]);
|
||
break;
|
||
|
||
case 'delivering':
|
||
// 开始配送,保持已发货状态
|
||
break;
|
||
|
||
case 'completed':
|
||
// 配送完成,更新为已收货状态
|
||
$billOnlineModel->updateBill(['bill_id' => $billId], [
|
||
'status' => 3, // 已收货
|
||
'updated_at' => date('Y-m-d H:i:s')
|
||
]);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 重新分配订单
|
||
* @param int $billId 原订单ID
|
||
* @param int $excludeRiderId 排除的骑手ID
|
||
* @return void
|
||
*/
|
||
private function reassignOrder($billId, $excludeRiderId)
|
||
{
|
||
// 这里可以实现重新分配逻辑
|
||
// 比如分配给其他可用骑手,或者标记为待分配状态
|
||
|
||
$riderOrderDispatch = new RiderOrderDispatch();
|
||
|
||
// 获取订单信息
|
||
$billOrderModel = D('RetailBillOrder');
|
||
$orderInfo = $billOrderModel->getFind(['id' => $billId]);
|
||
|
||
if (!empty($orderInfo)) {
|
||
// 尝试自动重新分配
|
||
$param = [
|
||
'bill_id' => $billId,
|
||
'merchant_id' => $orderInfo['merchant_id'],
|
||
'store_id' => $orderInfo['store_id'],
|
||
'auto_assign' => true,
|
||
'exclude_rider_id' => $excludeRiderId
|
||
];
|
||
|
||
$riderOrderDispatch->dispatchOrder($param);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 记录位置轨迹
|
||
* @param int $riderId 骑手ID
|
||
* @param float $lat 纬度
|
||
* @param float $lng 经度
|
||
* @return void
|
||
*/
|
||
private function recordLocationTrack($riderId, $lat, $lng)
|
||
{
|
||
$riderLocationModel = D('RiderLocation');
|
||
|
||
$locationData = [
|
||
'rider_id' => $riderId,
|
||
'lat' => $lat,
|
||
'lng' => $lng,
|
||
'record_time' => date('Y-m-d H:i:s'),
|
||
'add_time' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
$riderLocationModel->addLocation($locationData);
|
||
}
|
||
|
||
/**
|
||
* 更新骑手统计信息
|
||
* @param int $riderId 骑手ID
|
||
* @param array $orderInfo 订单信息
|
||
* @return void
|
||
*/
|
||
private function updateRiderStats($riderId, $orderInfo)
|
||
{
|
||
$riderInfoModel = D('RiderInfo');
|
||
|
||
// 计算配送时长
|
||
$deliveryDuration = 0;
|
||
if (!empty($orderInfo['accept_time']) && !empty($orderInfo['delivery_time'])) {
|
||
$deliveryDuration = strtotime($orderInfo['delivery_time']) - strtotime($orderInfo['accept_time']);
|
||
}
|
||
|
||
// 更新统计信息
|
||
$riderInfoModel->updateStats($riderId, [
|
||
'total_orders' => 1,
|
||
'total_delivery_time' => $deliveryDuration,
|
||
'total_delivery_fee' => $orderInfo['delivery_fee']
|
||
]);
|
||
}
|
||
} |