811 行
26 KiB
PHP
811 行
26 KiB
PHP
<?php
|
||
namespace Common\Business;
|
||
|
||
use Common\Business\RiderOrderDispatch;
|
||
|
||
/**
|
||
* 订单自动分配业务类
|
||
* Class OrderAutoDispatch
|
||
* @package Common\Business
|
||
*/
|
||
class OrderAutoDispatch
|
||
{
|
||
/**
|
||
* 处理支付成功后的自动分配
|
||
* @param int $billId 订单ID
|
||
* @param array $orderInfo 订单信息
|
||
* @return array
|
||
*/
|
||
public function handlePaymentSuccess($billId, $orderInfo = [])
|
||
{
|
||
try {
|
||
// 检查订单是否需要配送
|
||
if (!$this->needDelivery($billId, $orderInfo)) {
|
||
return ['status' => 0, 'msg' => '订单不需要配送'];
|
||
}
|
||
|
||
// 检查是否已经分配
|
||
if ($this->isAlreadyDispatched($billId)) {
|
||
return ['status' => 0, 'msg' => '订单已分配'];
|
||
}
|
||
|
||
// 获取配送配置
|
||
$config = $this->getDeliveryConfig($orderInfo);
|
||
|
||
// 根据配置决定分配方式
|
||
if ($config['auto_dispatch']) {
|
||
return $this->autoDispatchOrder($billId, $orderInfo, $config);
|
||
} else {
|
||
return $this->markPendingDispatch($billId, $orderInfo);
|
||
}
|
||
|
||
} catch (Exception $e) {
|
||
$this->logError('订单自动分配异常', [
|
||
'bill_id' => $billId,
|
||
'error' => $e->getMessage(),
|
||
'trace' => $e->getTraceAsString()
|
||
]);
|
||
return ['status' => 0, 'msg' => '分配失败:' . $e->getMessage()];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查订单是否需要配送
|
||
* @param int $billId 订单ID
|
||
* @param array $orderInfo 订单信息
|
||
* @return bool
|
||
*/
|
||
private function needDelivery($billId, $orderInfo = [])
|
||
{
|
||
if (empty($orderInfo)) {
|
||
$billOrderModel = D('RetailBillOrder');
|
||
$orderInfo = $billOrderModel->getFind(['id' => $billId]);
|
||
}
|
||
|
||
if (empty($orderInfo)) {
|
||
return false;
|
||
}
|
||
|
||
// 获取订单配送信息
|
||
$billOnlineModel = D('RetailBillOnline');
|
||
$onlineInfo = $billOnlineModel->getFind(['bill_id' => $billId]);
|
||
|
||
if (empty($onlineInfo)) {
|
||
return false;
|
||
}
|
||
|
||
// 检查是否为配送订单
|
||
return $onlineInfo['pickup_type'] == 2 && $orderInfo['type'] == 1 && $orderInfo['pay_state'] == 1;
|
||
}
|
||
|
||
/**
|
||
* 检查订单是否已分配
|
||
* @param int $billId 订单ID
|
||
* @return bool
|
||
*/
|
||
private function isAlreadyDispatched($billId)
|
||
{
|
||
$riderOrderModel = D('RiderOrder');
|
||
$riderOrder = $riderOrderModel->getFind([
|
||
'bill_id' => $billId,
|
||
'order_status' => ['neq', -1] // 排除已拒绝的
|
||
]);
|
||
|
||
return !empty($riderOrder);
|
||
}
|
||
|
||
/**
|
||
* 获取配送配置
|
||
* @param array $orderInfo 订单信息
|
||
* @return array
|
||
*/
|
||
private function getDeliveryConfig($orderInfo)
|
||
{
|
||
// 默认配置
|
||
$config = [
|
||
'auto_dispatch' => true,
|
||
'dispatch_delay' => 0, // 延迟分配时间(分钟)
|
||
'max_distance' => 10, // 最大配送距离(公里)
|
||
'priority_riders' => [], // 优先骑手
|
||
'dispatch_strategy' => 'nearest' // 分配策略:nearest(最近), rating(评分), balanced(均衡)
|
||
];
|
||
|
||
// 根据门店获取配置
|
||
if (!empty($orderInfo['store_id'])) {
|
||
$storeConfigModel = D('StoreDeliveryConfig');
|
||
$storeConfig = $storeConfigModel->getFind(['store_id' => $orderInfo['store_id']]);
|
||
|
||
if (!empty($storeConfig)) {
|
||
$config = array_merge($config, json_decode($storeConfig['config'], true) ?: []);
|
||
}
|
||
}
|
||
|
||
return $config;
|
||
}
|
||
|
||
/**
|
||
* 自动分配订单
|
||
* @param int $billId 订单ID
|
||
* @param array $orderInfo 订单信息
|
||
* @param array $config 配送配置
|
||
* @return array
|
||
*/
|
||
private function autoDispatchOrder($billId, $orderInfo, $config)
|
||
{
|
||
// 如果有延迟配置,则延迟分配
|
||
if ($config['dispatch_delay'] > 0) {
|
||
return $this->scheduleDelayedDispatch($billId, $orderInfo, $config);
|
||
}
|
||
|
||
// 立即分配
|
||
return $this->executeDispatch($billId, $orderInfo, $config);
|
||
}
|
||
|
||
/**
|
||
* 执行订单分配
|
||
* @param int $billId 订单ID
|
||
* @param array $orderInfo 订单信息
|
||
* @param array $config 配送配置
|
||
* @return array
|
||
*/
|
||
private function executeDispatch($billId, $orderInfo, $config)
|
||
{
|
||
try {
|
||
$riderOrderDispatch = new RiderOrderDispatch();
|
||
|
||
$dispatchParam = [
|
||
'bill_id' => $billId,
|
||
'merchant_id' => $orderInfo['merchant_id'],
|
||
'store_id' => $orderInfo['store_id'],
|
||
'auto_assign' => true,
|
||
'config' => $config
|
||
];
|
||
|
||
$result = $riderOrderDispatch->dispatchOrder($dispatchParam);
|
||
|
||
// 记录分配结果
|
||
$this->logDispatchResult($billId, $result, 'auto');
|
||
|
||
return $result;
|
||
|
||
} catch (Exception $e) {
|
||
return $this->handleDispatchException($billId, $e);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 安排延迟分配
|
||
* @param int $billId 订单ID
|
||
* @param array $orderInfo 订单信息
|
||
* @param array $config 配送配置
|
||
* @return array
|
||
*/
|
||
private function scheduleDelayedDispatch($billId, $orderInfo, $config)
|
||
{
|
||
// 创建延迟任务记录
|
||
$delayedDispatchModel = D('DelayedDispatch');
|
||
|
||
$delayedData = [
|
||
'bill_id' => $billId,
|
||
'merchant_id' => $orderInfo['merchant_id'],
|
||
'store_id' => $orderInfo['store_id'],
|
||
'config' => json_encode($config),
|
||
'scheduled_time' => date('Y-m-d H:i:s', strtotime('+' . $config['dispatch_delay'] . ' minutes')),
|
||
'status' => 0, // 待执行
|
||
'created_at' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
$result = $delayedDispatchModel->add($delayedData);
|
||
|
||
if ($result) {
|
||
return ['status' => 1, 'msg' => '订单已安排延迟分配', 'delay_minutes' => $config['dispatch_delay']];
|
||
} else {
|
||
return ['status' => 0, 'msg' => '延迟分配安排失败'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 标记为待分配
|
||
* @param int $billId 订单ID
|
||
* @param array $orderInfo 订单信息
|
||
* @return array
|
||
*/
|
||
private function markPendingDispatch($billId, $orderInfo)
|
||
{
|
||
// 创建待分配记录
|
||
$pendingDispatchModel = D('PendingDispatch');
|
||
|
||
$pendingData = [
|
||
'bill_id' => $billId,
|
||
'merchant_id' => $orderInfo['merchant_id'],
|
||
'store_id' => $orderInfo['store_id'],
|
||
'status' => 0, // 待分配
|
||
'created_at' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
$result = $pendingDispatchModel->add($pendingData);
|
||
|
||
if ($result) {
|
||
return ['status' => 1, 'msg' => '订单已标记为待分配'];
|
||
} else {
|
||
return ['status' => 0, 'msg' => '标记待分配失败'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理延迟分配任务
|
||
* @return void
|
||
*/
|
||
public function processScheduledDispatch()
|
||
{
|
||
$delayedDispatchModel = D('DelayedDispatch');
|
||
|
||
// 获取到期的延迟分配任务
|
||
$tasks = $delayedDispatchModel->getList([
|
||
'status' => 0,
|
||
'scheduled_time' => ['elt', date('Y-m-d H:i:s')]
|
||
]);
|
||
|
||
foreach ($tasks as $task) {
|
||
try {
|
||
// 标记任务为处理中
|
||
$delayedDispatchModel->updateData(['id' => $task['id']], ['status' => 1]);
|
||
|
||
// 获取订单信息
|
||
$billOrderModel = D('RetailBillOrder');
|
||
$orderInfo = $billOrderModel->getFind(['id' => $task['bill_id']]);
|
||
|
||
if (empty($orderInfo)) {
|
||
$delayedDispatchModel->updateData(['id' => $task['id']], [
|
||
'status' => -1,
|
||
'error_msg' => '订单不存在',
|
||
'processed_at' => date('Y-m-d H:i:s')
|
||
]);
|
||
continue;
|
||
}
|
||
|
||
// 检查是否已分配
|
||
if ($this->isAlreadyDispatched($task['bill_id'])) {
|
||
$delayedDispatchModel->updateData(['id' => $task['id']], [
|
||
'status' => 2,
|
||
'error_msg' => '订单已分配',
|
||
'processed_at' => date('Y-m-d H:i:s')
|
||
]);
|
||
continue;
|
||
}
|
||
|
||
// 执行分配
|
||
$config = json_decode($task['config'], true) ?: [];
|
||
$result = $this->executeDispatch($task['bill_id'], $orderInfo, $config);
|
||
|
||
// 更新任务状态
|
||
$delayedDispatchModel->updateData(['id' => $task['id']], [
|
||
'status' => $result['status'] == 1 ? 2 : -1,
|
||
'result' => json_encode($result),
|
||
'processed_at' => date('Y-m-d H:i:s')
|
||
]);
|
||
|
||
} catch (Exception $e) {
|
||
// 标记任务失败
|
||
$delayedDispatchModel->updateData(['id' => $task['id']], [
|
||
'status' => -1,
|
||
'error_msg' => $e->getMessage(),
|
||
'processed_at' => date('Y-m-d H:i:s')
|
||
]);
|
||
|
||
$this->logError('延迟分配任务处理异常', [
|
||
'task_id' => $task['id'],
|
||
'bill_id' => $task['bill_id'],
|
||
'error' => $e->getMessage()
|
||
]);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理分配失败
|
||
* @param int $billId 订单ID
|
||
* @param string $reason 失败原因
|
||
* @return array
|
||
*/
|
||
private function handleDispatchFailure($billId, $reason)
|
||
{
|
||
// 记录失败日志
|
||
$this->logError('订单分配失败', [
|
||
'bill_id' => $billId,
|
||
'reason' => $reason
|
||
]);
|
||
|
||
// 标记为待人工处理
|
||
return $this->markPendingDispatch($billId, []);
|
||
}
|
||
|
||
/**
|
||
* 处理分配异常
|
||
* @param int $billId 订单ID
|
||
* @param Exception $e 异常对象
|
||
* @return array
|
||
*/
|
||
private function handleDispatchException($billId, $e)
|
||
{
|
||
$this->logError('订单分配异常', [
|
||
'bill_id' => $billId,
|
||
'error' => $e->getMessage(),
|
||
'trace' => $e->getTraceAsString()
|
||
]);
|
||
|
||
return ['status' => 0, 'msg' => '分配异常:' . $e->getMessage()];
|
||
}
|
||
|
||
/**
|
||
* 记录分配结果
|
||
* @param int $billId 订单ID
|
||
* @param array $result 分配结果
|
||
* @param string $type 分配类型
|
||
* @return void
|
||
*/
|
||
private function logDispatchResult($billId, $result, $type = 'auto')
|
||
{
|
||
$logModel = D('DispatchLog');
|
||
|
||
$logData = [
|
||
'bill_id' => $billId,
|
||
'dispatch_type' => $type,
|
||
'result' => json_encode($result),
|
||
'status' => $result['status'],
|
||
'message' => $result['msg'],
|
||
'created_at' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
$logModel->add($logData);
|
||
}
|
||
|
||
/**
|
||
* 记录错误日志
|
||
* @param string $message 错误信息
|
||
* @param array $context 上下文数据
|
||
* @return void
|
||
*/
|
||
private function logError($message, $context = [])
|
||
{
|
||
$logData = [
|
||
'level' => 'error',
|
||
'message' => $message,
|
||
'context' => json_encode($context),
|
||
'created_at' => date('Y-m-d H:i:s')
|
||
];
|
||
|
||
// 写入系统日志
|
||
error_log(sprintf('[%s] %s %s', date('Y-m-d H:i:s'), $message, json_encode($context)));
|
||
|
||
// 写入数据库日志
|
||
$logModel = D('SystemLog');
|
||
$logModel->add($logData);
|
||
}
|
||
}
|
||
/**
|
||
* 订单自动分配触发器
|
||
* 用于在订单支付完成后自动触发分配到骑手端
|
||
*/
|
||
class OrderAutoDispatch
|
||
{
|
||
/**
|
||
* 订单支付完成后的自动分配处理
|
||
* @param array $orderInfo 订单信息
|
||
* @return array
|
||
*/
|
||
public static function handlePaymentSuccess($orderInfo)
|
||
{
|
||
try {
|
||
// 检查订单是否需要配送
|
||
if (!self::needDelivery($orderInfo)) {
|
||
return array(
|
||
'status' => 1,
|
||
'msg' => '订单无需配送',
|
||
'data' => array('skip_reason' => 'no_delivery_needed')
|
||
);
|
||
}
|
||
|
||
// 检查是否已经分配过
|
||
if (self::isAlreadyDispatched($orderInfo['id'])) {
|
||
return array(
|
||
'status' => 1,
|
||
'msg' => '订单已分配',
|
||
'data' => array('skip_reason' => 'already_dispatched')
|
||
);
|
||
}
|
||
|
||
// 获取订单配送配置
|
||
$deliveryConfig = self::getDeliveryConfig($orderInfo['merchant_id'], $orderInfo['store_id']);
|
||
|
||
// 如果启用了自动分配
|
||
if ($deliveryConfig['auto_dispatch_enabled']) {
|
||
return self::autoDispatchOrder($orderInfo, $deliveryConfig);
|
||
} else {
|
||
// 记录待分配订单
|
||
return self::markPendingDispatch($orderInfo);
|
||
}
|
||
|
||
} catch (Exception $e) {
|
||
// 记录错误日志
|
||
self::logError('OrderAutoDispatch::handlePaymentSuccess', $e->getMessage(), $orderInfo);
|
||
|
||
return array(
|
||
'status' => 0,
|
||
'msg' => '自动分配处理失败:' . $e->getMessage(),
|
||
'data' => array('error' => $e->getMessage())
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查订单是否需要配送
|
||
* @param array $orderInfo
|
||
* @return bool
|
||
*/
|
||
private static function needDelivery($orderInfo)
|
||
{
|
||
// 检查订单类型和配送方式
|
||
if (isset($orderInfo['pickup_type']) && $orderInfo['pickup_type'] == 1) {
|
||
// 自提订单不需要配送
|
||
return false;
|
||
}
|
||
|
||
if (isset($orderInfo['delivery_type']) && in_array($orderInfo['delivery_type'], [1, 5])) {
|
||
// 商家配送(1)或码科配送(5)需要分配骑手
|
||
return true;
|
||
}
|
||
|
||
// 检查是否有配送地址
|
||
if (empty($orderInfo['delivery_address']) && empty($orderInfo['address_address'])) {
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 检查订单是否已经分配
|
||
* @param int $orderId
|
||
* @return bool
|
||
*/
|
||
private static function isAlreadyDispatched($orderId)
|
||
{
|
||
$riderOrderModel = M('rider_order');
|
||
$existingDispatch = $riderOrderModel->where(array(
|
||
'order_id' => $orderId,
|
||
'is_deleted' => 0
|
||
))->find();
|
||
|
||
return !empty($existingDispatch);
|
||
}
|
||
|
||
/**
|
||
* 获取配送配置
|
||
* @param int $merchantId
|
||
* @param int $storeId
|
||
* @return array
|
||
*/
|
||
private static function getDeliveryConfig($merchantId, $storeId)
|
||
{
|
||
$configModel = M('delivery_config');
|
||
$config = $configModel->where(array(
|
||
'merchant_id' => $merchantId,
|
||
'store_id' => $storeId,
|
||
'status' => 1
|
||
))->find();
|
||
|
||
if (empty($config)) {
|
||
// 返回默认配置
|
||
return array(
|
||
'auto_dispatch_enabled' => true,
|
||
'dispatch_delay' => 0, // 延迟分配时间(分钟)
|
||
'max_retry_times' => 3,
|
||
'retry_interval' => 5 // 重试间隔(分钟)
|
||
);
|
||
}
|
||
|
||
return array(
|
||
'auto_dispatch_enabled' => $config['auto_dispatch_enabled'] == 1,
|
||
'dispatch_delay' => intval($config['dispatch_delay']),
|
||
'max_retry_times' => intval($config['max_retry_times']),
|
||
'retry_interval' => intval($config['retry_interval'])
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 自动分配订单
|
||
* @param array $orderInfo
|
||
* @param array $config
|
||
* @return array
|
||
*/
|
||
private static function autoDispatchOrder($orderInfo, $config)
|
||
{
|
||
// 如果设置了延迟分配
|
||
if ($config['dispatch_delay'] > 0) {
|
||
return self::scheduleDelayedDispatch($orderInfo, $config);
|
||
}
|
||
|
||
// 立即分配
|
||
return self::executeDispatch($orderInfo);
|
||
}
|
||
|
||
/**
|
||
* 执行订单分配
|
||
* @param array $orderInfo
|
||
* @return array
|
||
*/
|
||
private static function executeDispatch($orderInfo)
|
||
{
|
||
// 使用现有的订单分配类
|
||
$riderOrderDispatch = new RiderOrderDispatch();
|
||
|
||
$dispatchParams = array(
|
||
'order_id' => $orderInfo['id'],
|
||
'store_id' => $orderInfo['store_id'],
|
||
'auto_assign' => true,
|
||
'trigger_source' => 'payment_success'
|
||
);
|
||
|
||
$result = $riderOrderDispatch->dispatchOrder($dispatchParams);
|
||
|
||
// 记录分配日志
|
||
self::logDispatchResult($orderInfo['id'], $result, 'auto_dispatch');
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 安排延迟分配
|
||
* @param array $orderInfo
|
||
* @param array $config
|
||
* @return array
|
||
*/
|
||
private static function scheduleDelayedDispatch($orderInfo, $config)
|
||
{
|
||
$scheduleModel = M('dispatch_schedule');
|
||
|
||
$scheduleData = array(
|
||
'order_id' => $orderInfo['id'],
|
||
'merchant_id' => $orderInfo['merchant_id'],
|
||
'store_id' => $orderInfo['store_id'],
|
||
'schedule_time' => date('Y-m-d H:i:s', time() + $config['dispatch_delay'] * 60),
|
||
'retry_times' => 0,
|
||
'max_retry_times' => $config['max_retry_times'],
|
||
'retry_interval' => $config['retry_interval'],
|
||
'status' => 0, // 0-待执行 1-已执行 2-执行失败
|
||
'create_time' => date('Y-m-d H:i:s'),
|
||
'order_data' => json_encode($orderInfo)
|
||
);
|
||
|
||
$result = $scheduleModel->add($scheduleData);
|
||
|
||
if ($result) {
|
||
return array(
|
||
'status' => 1,
|
||
'msg' => '订单已安排延迟分配',
|
||
'data' => array(
|
||
'schedule_id' => $result,
|
||
'schedule_time' => $scheduleData['schedule_time']
|
||
)
|
||
);
|
||
} else {
|
||
return array(
|
||
'status' => 0,
|
||
'msg' => '安排延迟分配失败'
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 标记为待分配订单
|
||
* @param array $orderInfo
|
||
* @return array
|
||
*/
|
||
private static function markPendingDispatch($orderInfo)
|
||
{
|
||
$pendingModel = M('pending_dispatch_order');
|
||
|
||
$pendingData = array(
|
||
'order_id' => $orderInfo['id'],
|
||
'merchant_id' => $orderInfo['merchant_id'],
|
||
'store_id' => $orderInfo['store_id'],
|
||
'order_no' => $orderInfo['order_no'],
|
||
'customer_name' => $orderInfo['customer_name'] ?? '',
|
||
'customer_phone' => $orderInfo['customer_phone'] ?? '',
|
||
'delivery_address' => $orderInfo['delivery_address'] ?? $orderInfo['address_address'] ?? '',
|
||
'order_amount' => $orderInfo['order_amount'] ?? $orderInfo['all_money'] ?? 0,
|
||
'create_time' => date('Y-m-d H:i:s'),
|
||
'status' => 0 // 0-待分配
|
||
);
|
||
|
||
$result = $pendingModel->add($pendingData);
|
||
|
||
if ($result) {
|
||
return array(
|
||
'status' => 1,
|
||
'msg' => '订单已加入待分配队列',
|
||
'data' => array('pending_id' => $result)
|
||
);
|
||
} else {
|
||
return array(
|
||
'status' => 0,
|
||
'msg' => '加入待分配队列失败'
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理延迟分配任务(定时任务调用)
|
||
* @return array
|
||
*/
|
||
public static function processScheduledDispatch()
|
||
{
|
||
$scheduleModel = M('dispatch_schedule');
|
||
|
||
// 获取到期的分配任务
|
||
$schedules = $scheduleModel->where(array(
|
||
'status' => 0,
|
||
'schedule_time' => array('ELT', date('Y-m-d H:i:s'))
|
||
))->select();
|
||
|
||
$processedCount = 0;
|
||
$successCount = 0;
|
||
$failedCount = 0;
|
||
|
||
foreach ($schedules as $schedule) {
|
||
$processedCount++;
|
||
|
||
try {
|
||
$orderInfo = json_decode($schedule['order_data'], true);
|
||
$result = self::executeDispatch($orderInfo);
|
||
|
||
if ($result['status'] == 1) {
|
||
// 分配成功
|
||
$scheduleModel->where(array('id' => $schedule['id']))->save(array(
|
||
'status' => 1,
|
||
'execute_time' => date('Y-m-d H:i:s'),
|
||
'result' => json_encode($result)
|
||
));
|
||
$successCount++;
|
||
} else {
|
||
// 分配失败,检查是否需要重试
|
||
self::handleDispatchFailure($schedule, $result);
|
||
$failedCount++;
|
||
}
|
||
|
||
} catch (Exception $e) {
|
||
// 处理异常
|
||
self::handleDispatchException($schedule, $e);
|
||
$failedCount++;
|
||
}
|
||
}
|
||
|
||
return array(
|
||
'status' => 1,
|
||
'msg' => '延迟分配任务处理完成',
|
||
'data' => array(
|
||
'processed' => $processedCount,
|
||
'success' => $successCount,
|
||
'failed' => $failedCount
|
||
)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 处理分配失败
|
||
* @param array $schedule
|
||
* @param array $result
|
||
*/
|
||
private static function handleDispatchFailure($schedule, $result)
|
||
{
|
||
$scheduleModel = M('dispatch_schedule');
|
||
|
||
if ($schedule['retry_times'] < $schedule['max_retry_times']) {
|
||
// 安排重试
|
||
$nextRetryTime = date('Y-m-d H:i:s', time() + $schedule['retry_interval'] * 60);
|
||
$scheduleModel->where(array('id' => $schedule['id']))->save(array(
|
||
'retry_times' => $schedule['retry_times'] + 1,
|
||
'schedule_time' => $nextRetryTime,
|
||
'last_error' => json_encode($result)
|
||
));
|
||
} else {
|
||
// 超过最大重试次数,标记为失败
|
||
$scheduleModel->where(array('id' => $schedule['id']))->save(array(
|
||
'status' => 2,
|
||
'execute_time' => date('Y-m-d H:i:s'),
|
||
'result' => json_encode($result)
|
||
));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理分配异常
|
||
* @param array $schedule
|
||
* @param Exception $e
|
||
*/
|
||
private static function handleDispatchException($schedule, $e)
|
||
{
|
||
$scheduleModel = M('dispatch_schedule');
|
||
|
||
$errorResult = array(
|
||
'status' => 0,
|
||
'msg' => '分配异常:' . $e->getMessage(),
|
||
'error' => $e->getMessage(),
|
||
'trace' => $e->getTraceAsString()
|
||
);
|
||
|
||
if ($schedule['retry_times'] < $schedule['max_retry_times']) {
|
||
// 安排重试
|
||
$nextRetryTime = date('Y-m-d H:i:s', time() + $schedule['retry_interval'] * 60);
|
||
$scheduleModel->where(array('id' => $schedule['id']))->save(array(
|
||
'retry_times' => $schedule['retry_times'] + 1,
|
||
'schedule_time' => $nextRetryTime,
|
||
'last_error' => json_encode($errorResult)
|
||
));
|
||
} else {
|
||
// 超过最大重试次数,标记为失败
|
||
$scheduleModel->where(array('id' => $schedule['id']))->save(array(
|
||
'status' => 2,
|
||
'execute_time' => date('Y-m-d H:i:s'),
|
||
'result' => json_encode($errorResult)
|
||
));
|
||
}
|
||
|
||
// 记录错误日志
|
||
self::logError('OrderAutoDispatch::handleDispatchException', $e->getMessage(), $schedule);
|
||
}
|
||
|
||
/**
|
||
* 记录分配结果日志
|
||
* @param int $orderId
|
||
* @param array $result
|
||
* @param string $type
|
||
*/
|
||
private static function logDispatchResult($orderId, $result, $type = 'manual')
|
||
{
|
||
$logModel = M('dispatch_log');
|
||
|
||
$logData = array(
|
||
'order_id' => $orderId,
|
||
'dispatch_type' => $type,
|
||
'result_status' => $result['status'],
|
||
'result_msg' => $result['msg'],
|
||
'result_data' => json_encode($result),
|
||
'create_time' => date('Y-m-d H:i:s')
|
||
);
|
||
|
||
$logModel->add($logData);
|
||
}
|
||
|
||
/**
|
||
* 记录错误日志
|
||
* @param string $method
|
||
* @param string $error
|
||
* @param array $context
|
||
*/
|
||
private static function logError($method, $error, $context = array())
|
||
{
|
||
$logData = array(
|
||
'method' => $method,
|
||
'error_msg' => $error,
|
||
'context' => json_encode($context),
|
||
'create_time' => date('Y-m-d H:i:s')
|
||
);
|
||
|
||
// 写入错误日志文件
|
||
$logFile = RUNTIME_PATH . 'Logs/order_auto_dispatch_' . date('Y-m-d') . '.log';
|
||
$logContent = date('Y-m-d H:i:s') . " [{$method}] {$error} Context: " . json_encode($context) . PHP_EOL;
|
||
file_put_contents($logFile, $logContent, FILE_APPEND | LOCK_EX);
|
||
|
||
// 同时写入数据库
|
||
try {
|
||
$errorLogModel = M('dispatch_error_log');
|
||
$errorLogModel->add($logData);
|
||
} catch (Exception $e) {
|
||
// 如果数据库写入失败,只记录到文件
|
||
error_log("Failed to write dispatch error to database: " . $e->getMessage());
|
||
}
|
||
}
|
||
}
|
||
?>
|