targetMonth($connection); if ($month === null) { return $this->writeResult([ 'status' => 'blocked', 'message' => '未找到已成功导入的进销存月份。', ]); } $weightedPath = tempnam(sys_get_temp_dir(), 'weighted-result-') . '.json'; $costPath = tempnam(sys_get_temp_dir(), 'product-cost-result-') . '.json'; try { $weightedExit = $this->call('product:monthly-weighted-average:auto', [ '--month' => $month->format('Y-m'), '--result-json' => $weightedPath, ]); $weighted = $this->readJson($weightedPath); if ( $weightedExit !== self::SUCCESS || in_array($weighted['status'] ?? 'failed', ['blocked', 'failed'], true) ) { return $this->writeResult([ 'status' => 'failed', 'report_month' => $month->toDateString(), 'message' => '商品月加权平均单价未完成,商品成本未执行。', 'weighted_average' => $weighted, 'product_cost' => null, ]); } $costExit = $this->call('store-receipt:product-cost:sync', [ 'month' => $month->format('Y-m'), '--result-json' => $costPath, ]); $cost = $this->readJson($costPath); $status = $costExit !== self::SUCCESS ? 'failed' : ((int) ($cost['pending_cost_rows'] ?? 0) > 0 ? 'review_required' : 'success'); return $this->writeResult([ 'status' => $status, 'report_month' => $month->toDateString(), 'message' => match ($status) { 'success' => '月加权平均单价与商品成本已按顺序完成。', 'review_required' => '月加权平均单价与商品成本已完成,存在待核验成本。', default => '商品成本同步失败。', }, 'weighted_average' => $weighted, 'product_cost' => $cost, ]); } finally { @unlink($weightedPath); @unlink($costPath); } } private function targetMonth(string $connection): ?CarbonImmutable { $requested = trim((string) $this->option('month')); if ($requested !== '') { return CarbonImmutable::parse($requested)->startOfMonth(); } $latest = DB::connection($connection)->table('inventory_report_authoritative_months') ->where('dataset_key', 'jiansun.inventory-report.authoritative-month') ->where('status', 'succeeded') ->whereNotNull('active_generation') ->orderByDesc('source_month') ->value('source_month'); return $latest === null ? null : CarbonImmutable::parse((string) $latest)->startOfMonth(); } /** @return array */ private function readJson(string $path): array { if (! is_file($path)) { return ['status' => 'failed', 'message' => '子任务未生成结果文件。']; } $decoded = json_decode((string) file_get_contents($path), true); return is_array($decoded) ? $decoded : ['status' => 'failed', 'message' => '子任务结果文件无法解析。']; } /** @param array $result */ private function writeResult(array $result): int { $path = trim((string) $this->option('result-json')); if ($path !== '') { File::ensureDirectoryExists(dirname($path)); File::put( $path, json_encode( $result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT, ) . PHP_EOL, ); } if (isset($result['message'])) { $this->line((string) $result['message']); } return in_array($result['status'] ?? 'failed', ['success', 'review_required'], true) ? self::SUCCESS : self::FAILURE; } }