> runtime/log/gancao_sync.log 2>&1 */ class GancaoSyncLogisticsRoute extends Command { protected function configure() { $this->setName('gancao:sync-logistics') ->setDescription('同步甘草订单的物流路由(GET_TASK_ROUTE_LIST)到本地物流追踪表') ->addOption('limit', 'l', Option::VALUE_OPTIONAL, '本次最多处理多少条订单', 100) ->addOption('order-id', null, Option::VALUE_OPTIONAL, '只同步指定 prescription_order.id', null) ->addOption('detail', 'd', Option::VALUE_NONE, '打印每单详细结果'); } protected function execute(Input $input, Output $output) { $limit = max(1, (int) $input->getOption('limit')); $onlyOrderId = $input->getOption('order-id'); $onlyOrderId = $onlyOrderId !== null ? (int) $onlyOrderId : null; $verbose = (bool) $input->getOption('detail'); $output->writeln('========================================'); $output->writeln('甘草物流路由同步'); $output->writeln('========================================'); if (!GancaoScmRecipelService::isConfigured()) { $output->error('甘草 SCM 未配置:' . GancaoScmRecipelService::whyNotConfigured()); return 1; } $start = microtime(true); $output->writeln('开始同步...(limit=' . $limit . ($onlyOrderId ? ', order_id=' . $onlyOrderId : '') . ')'); try { $stats = GancaoLogisticsRouteService::syncBatch($limit, $onlyOrderId); } catch (\Throwable $e) { $output->error('同步异常:' . $e->getMessage()); return 1; } $duration = round(microtime(true) - $start, 2); if ($verbose && !empty($stats['details'])) { $output->writeln(''); $output->writeln('--- 详细 ---'); foreach ($stats['details'] as $row) { $tag = !empty($row['success']) ? '[OK]' : '[FAIL]'; $line = sprintf( '%s order_id=%s order_no=%s app_order_no=%s tn=%s state=%s traces=+%s msg=%s', $tag, $row['order_id'] ?? '', $row['order_no'] ?? '', $row['app_order_no'] ?? '', $row['tracking_number'] ?? '', $row['state'] ?? '', $row['traces'] ?? 0, $row['message'] ?? '' ); $output->writeln($line); } } $output->writeln(''); $output->writeln('========================================'); $output->writeln('同步完成'); $output->writeln('========================================'); $output->writeln('总数:' . $stats['total']); $output->writeln('成功:' . $stats['success']); $output->writeln('失败:' . $stats['failed']); $output->writeln('医助已移除:' . (int) ($stats['assistant_cleared'] ?? 0)); $output->writeln('医助保留(有指派记录):' . (int) ($stats['assistant_skipped_assign_log'] ?? 0)); $lines = $stats['assistant_lines'] ?? []; if ($lines === []) { $output->writeln('医助明细:(无)'); } else { $output->writeln('医助明细:'); foreach ($lines as $line) { $output->writeln(' ' . $line); } } $output->writeln('耗时:' . $duration . 's'); return 0; } }