文件
mashangyoujiu/Application/Cli/Controller/OrderSyncController.class.php

251 行
9.4 KiB
PHP

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<?php
namespace Cli\Controller;
use Think\Controller;
use Common\Business\OrderSyncService;
/**
* 订单同步定时任务控制器
* 用于定时同步骑手订单状态到原始订单系统
*
* 使用方法:
* CLI模式:php index.php /Cli/OrderSync/syncRiderOrderStatus
* Cron示例:* * * * * cd /path/to/project && php index.php /Cli/OrderSync/syncRiderOrderStatus
*/
class OrderSyncController extends Controller {
/**
* 同步骑手订单状态到原始订单
* 当骑手接单后,修改原始订单状态为发货
* 当骑手配送完成后,修改原始订单状态为完成
*/
public function syncRiderOrderStatus() {
$startTime = microtime(true);
echo "===== 订单状态同步任务开始 =====\n";
echo "开始时间:" . date('Y-m-d H:i:s') . "\n\n";
try {
// 1. 检查是否启用自动同步
if (!$this->isAutoSyncEnabled()) {
echo "自动同步未启用,任务终止\n";
$this->log('自动同步未启用,任务终止');
return;
}
echo "自动同步已启用,开始执行...\n\n";
// 2. 同步骑手接单状态(将原始订单状态改为发货)
$acceptResult = $this->syncAcceptedOrders();
echo "接单状态同步:成功 {$acceptResult['success']} 个,失败 {$acceptResult['fail']} 个\n";
// 注意:骑手配送完成状态的同步已移至骑手端完成订单接口中实时同步
// 3. 输出总结
$totalSuccess = $acceptResult['success'];
$totalFail = $acceptResult['fail'];
echo "\n===== 同步任务完成 =====\n";
echo "总计:成功 {$totalSuccess} 个,失败 {$totalFail} 个\n";
echo "耗时:" . round(microtime(true) - $startTime, 2) . " 秒\n";
echo "结束时间:" . date('Y-m-d H:i:s') . "\n";
// 记录日志
$this->log("同步任务完成,成功 {$totalSuccess} 个,失败 {$totalFail} 个");
} catch (\Exception $e) {
echo "错误:" . $e->getMessage() . "\n";
echo "堆栈:" . $e->getTraceAsString() . "\n";
$this->log('同步任务异常:' . $e->getMessage());
}
}
/**
* 检查是否启用自动同步
* @return bool
*/
private function isAutoSyncEnabled() {
$config = M('rider_config')->where(array('merchant_id' => 0))->find();
if (!$config) {
// 如果没有配置,尝试获取任意一个商户的配置
$config = M('rider_config')->where(array('auto_sync_enabled' => 1))->find();
}
return $config && $config['auto_sync_enabled'] == 1;
}
/**
* 同步骑手接单状态
* 将原始订单状态更新为发货(status=2)
*
* @return array 统计结果
*/
private function syncAcceptedOrders() {
$successCount = 0;
$failCount = 0;
// 查询已接单但原订单未发货的骑手订单
$where = array();
$where['ro.order_status'] = array('in', array(1, 2, 3, 4, 5)); // 已接单到配送中的状态
$where['o.status'] = 1; // 原订单状态为未发货
$orders = M('rider_order')->alias('ro')
->join('LEFT JOIN ls_retail_bill_online o ON ro.bill_id = o.bill_id')
->where($where)
->field('ro.id as rider_order_id, ro.bill_id, ro.order_status, ro.rider_id, o.status as original_status')
->select();
if (empty($orders)) {
echo "没有需要同步的接单订单\n";
return array('success' => 0, 'fail' => 0);
}
echo "找到 " . count($orders) . " 个待同步的接单订单\n";
foreach ($orders as $order) {
try {
// 更新原始订单状态为发货(status=2)
$result = M('retail_bill_online')->where(array('bill_id' => $order['bill_id']))->save(array(
'status' => 2,
'send_time' => date('Y-m-d H:i:s')
));
if ($result !== false) {
$successCount++;
echo " ✓ 订单 {$order['bill_id']} 状态已更新为发货\n";
// 记录同步日志
$this->logSyncStatus(
$order['bill_id'],
$order['rider_order_id'],
$order['rider_id'],
'accept',
$order['original_status'],
2,
1,
''
);
} else {
$failCount++;
echo " ✗ 订单 {$order['bill_id']} 状态更新失败\n";
$this->logSyncStatus(
$order['bill_id'],
$order['rider_order_id'],
$order['rider_id'],
'accept',
$order['original_status'],
2,
0,
'数据库更新失败'
);
}
} catch (\Exception $e) {
$failCount++;
echo " ✗ 订单 {$order['bill_id']} 处理异常:{$e->getMessage()}\n";
$this->logSyncStatus(
$order['bill_id'],
$order['rider_order_id'],
$order['rider_id'],
'accept',
$order['original_status'],
2,
0,
$e->getMessage()
);
}
}
return array('success' => $successCount, 'fail' => $failCount);
}
/**
* 记录同步状态日志
*
* @param int $billId 原订单ID
* @param int $riderOrderId 骑手订单ID
* @param int $riderId 骑手ID
* @param string $operationType 操作类型
* @param int $oldStatus 原状态
* @param int $newStatus 新状态
* @param int $syncResult 同步结果
* @param string $errorMsg 错误信息
*/
private function logSyncStatus($billId, $riderOrderId, $riderId, $operationType, $oldStatus, $newStatus, $syncResult, $errorMsg = '') {
$now = date('Y-m-d H:i:s');
$logData = array(
'bill_id' => intval($billId),
'rider_order_id' => intval($riderOrderId),
'rider_id' => intval($riderId),
'operation_type' => $operationType,
'old_status' => intval($oldStatus),
'new_status' => intval($newStatus),
'sync_result' => intval($syncResult),
'error_msg' => $errorMsg ? $errorMsg : null,
'sync_time' => $now,
'retry_count' => 0,
'add_time' => $now,
'update_time' => $now,
);
M('rider_order_sync_log')->add($logData);
}
/**
* 记录运行日志到文件
*
* @param string $message 日志消息
*/
private function log($message) {
$logFile = RUNTIME_PATH . 'Logs/OrderSync/' . date('Y-m-d') . '.log';
$logDir = dirname($logFile);
if (!is_dir($logDir)) {
mkdir($logDir, 0755, true);
}
$logContent = '[' . date('Y-m-d H:i:s') . '] ' . $message . "\n";
file_put_contents($logFile, $logContent, FILE_APPEND);
}
/**
* 手动触发批量同步(供管理员使用)
* 用于将原始订单同步创建为骑手订单
*/
public function batchSync() {
echo "===== 批量订单同步任务开始 =====\n";
echo "开始时间:" . date('Y-m-d H:i:s') . "\n\n";
try {
$syncService = new OrderSyncService();
$result = $syncService->batchSyncOrders();
if ($result['success']) {
echo "同步成功:{$result['message']}\n";
echo "详细信息:\n";
echo " 成功:{$result['details']['success_count']} 个\n";
echo " 失败:{$result['details']['fail_count']} 个\n";
echo " 跳过:{$result['details']['skip_count']} 个\n";
if (!empty($result['details']['errors'])) {
echo "\n错误列表:\n";
foreach ($result['details']['errors'] as $error) {
echo " - {$error}\n";
}
}
} else {
echo "同步失败:{$result['message']}\n";
}
$this->log("批量同步完成:{$result['message']}");
} catch (\Exception $e) {
echo "错误:" . $e->getMessage() . "\n";
$this->log('批量同步异常:' . $e->getMessage());
}
echo "\n结束时间:" . date('Y-m-d H:i:s') . "\n";
}
}