mirror->ready('store-information.read')) { throw new RuntimeException('店铺基础信息共享镜像尚未完成首次同步。'); } $rows = $this->information->storesWithAccountOwnership( $this->mirror->allStores(), true, ); if ($rows === []) { throw new RuntimeException('店铺基础信息共享镜像没有可存档的数据。'); } $snapshotDateValue = $snapshotDate->format('Y-m-d'); $capturedAt = now('Asia/Shanghai')->format('Y-m-d H:i:s.u'); $values = []; foreach ($rows as $row) { $recordId = trim((string) ($row['id'] ?? '')); if ($recordId === '') { continue; } $values[] = [ 'snapshot_date' => $snapshotDateValue, 'store_record_id' => mb_substr($recordId, 0, 64), 'erp_store_name' => mb_substr(trim((string) ($row['erp_store_name'] ?? '')), 0, 191), 'store_name' => $this->nullable($row['store_name'] ?? null, 191), 'company_name' => $this->nullable($row['company_name'] ?? null, 255), 'store_manager' => $this->nullable($row['store_manager'] ?? null, 191), 'department_manager' => $this->nullable($row['department_manager'] ?? null, 191), 'profit_center' => $this->nullable($row['profit_center'] ?? null, 191), 'store_status' => $this->nullable($row['store_status'] ?? null, 64), 'payload' => json_encode( $row, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR, ), 'captured_at' => $capturedAt, 'created_at' => $capturedAt, 'updated_at' => $capturedAt, ]; } if ($values === []) { throw new RuntimeException('店铺基础信息缺少可用的店铺记录 ID,未写入快照。'); } $connection = $this->database->connection( (string) config('upstream_mirrors.connection', 'business_mirror'), ); $connection->transaction(function () use ($connection, $values): void { foreach (array_chunk($values, 250) as $chunk) { $connection->table(self::TABLE)->upsert( $chunk, ['snapshot_date', 'store_record_id'], [ 'erp_store_name', 'store_name', 'company_name', 'store_manager', 'department_manager', 'profit_center', 'store_status', 'payload', 'captured_at', 'updated_at', ], ); } }); return count($values); } private function nullable(mixed $value, int $limit): ?string { $text = trim((string) $value); return $text === '' ? null : mb_substr($text, 0, $limit); } }