option('from') ? Carbon::parse($this->option('from')) : null; $to = $this->option('to') ? Carbon::parse($this->option('to')) : null; // --days=N:滚动最近 N 天(含今天)。显式 --from/--to 优先。 if (! $from && ! $to && $this->option('days')) { $days = max((int) $this->option('days'), 1); $from = now()->startOfDay()->subDays($days - 1); $to = now()->startOfDay()->addDay(); } $skipFreight = (bool) $this->option('skip-freight'); if ($skipFreight && (! $from || ! $to)) { $this->error('--skip-freight 需要指定 --from 和 --to,或使用 --days。'); return self::FAILURE; } $limit = (int) ($this->option('limit') ?: 2000); $range = ($from && $to) ? $from->toDateString() . ' ~ ' . $to->toDateString() : '最近 ' . $limit . ' 条'; $this->info('开始从副本库同步发货明细(' . $range . ')...'); $progress = function (string $msg): void { $this->info(' ' . $msg); if (function_exists('fflush')) { @fflush(STDOUT); } }; try { $result = ShippingReplicaSynchronizer::make()->sync($from, $to, $limit, $progress, $skipFreight); } catch (\Throwable $e) { $this->error('同步失败:' . $e->getMessage()); return self::FAILURE; } $expressRows = (int) ($result['processed'] ?? 0); $autoRows = (int) ($result['autoship'] ?? 0); $outboundRows = (int) ($result['outbound'] ?? 0); $purchaseOutRows = (int) ($result['purchase_out'] ?? 0); $summary = sprintf('发货明细 %d 条,代发仓 %d 条,销售出库补漏 %d 条,采购出库补漏 %d 条,合计处理 %d 条明细', $expressRows, $autoRows, $outboundRows, $purchaseOutRows, $expressRows + $autoRows + $outboundRows + $purchaseOutRows); $packageSummary = isset($result['unique_packages']) ? sprintf('唯一包裹源键 %d 个,包裹记录处理 %d 次;', $result['unique_packages'], $result['packages'] ?? 0) : ''; if ($result['freight_incomplete'] ?? false) { $this->warn('本次窗口' . $packageSummary . $summary . ';新记录运费与结算重量待补齐,空白不代表 0。'); } else { $this->info('完成:' . $packageSummary . $summary . '。'); } if (($result['packages_without_items'] ?? 0) > 0 || ($result['dws_failed_days'] ?? []) !== []) { $this->warn(sprintf( '商品或金额待核对:%d 个包裹未匹配商品,DWS 预载失败 %d 天;页面包裹数不等于商品明细完整性。', $result['packages_without_items'] ?? 0, count($result['dws_failed_days'] ?? []), )); } if (($result['packages_retained_for_missing_items'] ?? 0) > 0) { $this->warn('其中 ' . $result['packages_retained_for_missing_items'] . ' 个包裹因新商品明细缺失而保留原有商品及金额,本次未完成这些包裹的更新。'); } if (($result['packages_retained_for_unmatched_amount'] ?? 0) > 0) { $this->warn('其中 ' . $result['packages_retained_for_unmatched_amount'] . ' 个包裹因商品金额无法安全匹配而保留原记录,金额待核对。'); } if (($result['stale_mirror_packages'] ?? 0) > 0) { $this->error('本窗口仍有 ' . $result['stale_mirror_packages'] . ' 个镜像包裹未在上游扫描中出现;已保留原记录,需按源键核对后才能认定数量完整。'); return self::FAILURE; } return self::SUCCESS; } }