CaiWuXiTong/app/Business/StoreInformationDailyArchive.php

96 lines
3.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Business;
use Carbon\CarbonInterface;
use Illuminate\Database\DatabaseManager;
use Modules\EcommerceFinance\Repositories\BusinessInformationMirrorRepository;
use RuntimeException;
class StoreInformationDailyArchive
{
public const TABLE = 'store_information_daily_archives';
public function __construct(
private readonly BusinessInformationMirrorRepository $mirror,
private readonly UpstreamBusinessInformation $information,
private readonly DatabaseManager $database,
) {}
/**
* 保存指定日期的完整店铺基础信息快照;同一天重跑时覆盖当天版本。
*/
public function capture(CarbonInterface $snapshotDate): int
{
if (! $this->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);
}
}