CaiWuXiTong/modules/EcommerceFinance/Services/SupplierStatementStore.php
renshen 87eaf48c2c 供应商对账:应付款项下新增对账页面(财务端数据 / 厂家端数据) (#364)
新增供应商对账目录:财务端实时上传情况与行级差异(条码+单价匹配,四类口径),厂家端严格按模板上传(表头不一致/必填缺失/非数字/串厂一律失败);复用终版存储与流式读取。
2026-10-17 08:49:17 +08:00

62 lines
2.2 KiB
PHP

<?php
namespace Modules\EcommerceFinance\Services;
/**
* 厂家对账单的存放:整份替换(以最新一版为准)+ 上传记录。
* 数据放在与「终版」目录同一张按表数据表里,数据集键带 statement: 前缀。
*/
class SupplierStatementStore
{
public const PREFIX = 'statement:';
public const LOG_PREFIX = 'statement-log:';
public function __construct(
private readonly SupplierPayableOverrideStore $store,
) {
}
/** 保存厂家对账单(整份替换)并记录一次上传。 */
public function save(string $supplier, array $records, string $filename, int $companyId, ?int $userId): int
{
$rows = [];
foreach ($records as $index => $record) {
$rows[sprintf('line:%06d', $index + 1)] = $record;
}
$this->store->replaceAll(self::PREFIX . $supplier, $rows, $companyId, $userId);
$this->store->save(self::LOG_PREFIX . $supplier, 'upload:' . now()->format('YmdHis'), [
'uploaded_at' => now()->toDateTimeString(),
'filename' => $filename,
'rows' => count($records),
], $companyId, $userId, 'import');
return count($records);
}
/** @return list<array<string,mixed>> 最新的对账单行 */
public function rows(string $supplier, int $companyId): array
{
return $this->store->listRows(self::PREFIX . $supplier, $companyId);
}
/** @return list<array<string,mixed>> 最近的上传记录(新到旧) */
public function uploads(string $supplier, int $companyId, int $limit = 10): array
{
$uploads = $this->store->listRows(self::LOG_PREFIX . $supplier, $companyId);
usort($uploads, static fn (array $a, array $b): int => strcmp((string) ($b['uploaded_at'] ?? ''), (string) ($a['uploaded_at'] ?? '')));
return array_slice($uploads, 0, $limit);
}
/** @return list<string> 已经上传过对账单的厂家名称 */
public function uploadedSuppliers(int $companyId): array
{
return array_values(array_map(
static fn (string $dataset): string => substr($dataset, strlen(self::LOG_PREFIX)),
$this->store->datasetsWithPrefix(self::LOG_PREFIX, $companyId),
));
}
}