运费差是「应付款项 › 快递应付 › 运费差」页面上传的汇总快照(JSON 文件,不是数据库表),这里新增 CourierFreightDifferenceMap 读它并转成 交易单号 ⇒ 差异 映射,页面按交易单号带出新列;快照文件的修改时间进缓存键,财务重导后自动失效。源表一格多单号(逗号分隔)会逐个挂同一个差异值。
100 lines
3.4 KiB
PHP
100 lines
3.4 KiB
PHP
<?php
|
||
|
||
namespace App\Business;
|
||
|
||
use Illuminate\Support\Facades\Cache;
|
||
use Illuminate\Support\Facades\Storage;
|
||
use Throwable;
|
||
|
||
/**
|
||
* 快递应付 › 运费差 → 「交易单号 ⇒ 差异(结算运费-提供成本运费)」映射。
|
||
*
|
||
* 运费差是财务在「应付款项 › 快递应付 › 运费差」页面上传的汇总快照(JSON 文件,不是数据库表),
|
||
* 快递运费页面按交易单号把差异带出来展示。快照重新导入后文件时间会变,缓存键跟着变,自动失效。
|
||
*/
|
||
class CourierFreightDifferenceMap
|
||
{
|
||
/** 对应 CourierPayableSummaryStore::PAGES 里的运费差页面。 */
|
||
public const PAGE = 'freight-difference';
|
||
|
||
private const CACHE_MINUTES = 10;
|
||
|
||
public function __construct(private readonly CourierPayableSummaryStore $store) {}
|
||
|
||
/**
|
||
* @return array<string,string> 交易单号 => 运费差(保留源文件里的原值字符串)
|
||
*/
|
||
public function map(int $companyId): array
|
||
{
|
||
$disk = Storage::disk('uploads');
|
||
$path = $this->store->path($companyId, self::PAGE);
|
||
if (! $disk->exists($path)) {
|
||
return [];
|
||
}
|
||
|
||
// 文件时间戳进缓存键:财务重新导入运费差后不用等缓存过期。
|
||
$key = sprintf('courier-freight-difference:v1:%d:%d', $companyId, (int) $disk->lastModified($path));
|
||
|
||
return Cache::remember($key, now()->addMinutes(self::CACHE_MINUTES), function () use ($companyId): array {
|
||
try {
|
||
return $this->build($companyId);
|
||
} catch (Throwable $exception) {
|
||
report($exception);
|
||
|
||
return [];
|
||
}
|
||
});
|
||
}
|
||
|
||
/** @return array<string,string> */
|
||
private function build(int $companyId): array
|
||
{
|
||
$snapshot = $this->store->snapshot($companyId, self::PAGE);
|
||
if ($snapshot === null) {
|
||
return [];
|
||
}
|
||
|
||
$headers = array_map(static fn ($value): string => trim((string) $value), (array) $snapshot['headers']);
|
||
$orderColumn = $this->columnIndex($headers, '交易单号');
|
||
$differenceColumn = $this->columnIndex($headers, '差异');
|
||
if ($orderColumn === null || $differenceColumn === null) {
|
||
return [];
|
||
}
|
||
|
||
$map = [];
|
||
foreach ((array) $snapshot['rows'] as $row) {
|
||
$orderNos = trim((string) ($row[$orderColumn] ?? ''));
|
||
if ($orderNos === '') {
|
||
continue;
|
||
}
|
||
|
||
$difference = trim((string) ($row[$differenceColumn] ?? ''));
|
||
if ($difference === '') {
|
||
continue;
|
||
}
|
||
|
||
// 源表一个格子可能放多个交易单号(逗号分隔),逐个挂到同一个差异值上。
|
||
foreach (explode(',', $orderNos) as $orderNo) {
|
||
$orderNo = trim($orderNo);
|
||
if ($orderNo !== '' && ! isset($map[$orderNo])) {
|
||
$map[$orderNo] = $difference;
|
||
}
|
||
}
|
||
}
|
||
|
||
return $map;
|
||
}
|
||
|
||
/** 按表头名模糊定位(表头可能是「差异(结算运费-提供成本运费)」等写法)。 */
|
||
private function columnIndex(array $headers, string $needle): ?int
|
||
{
|
||
foreach ($headers as $index => $header) {
|
||
if ($header !== '' && mb_strpos($header, $needle) !== false) {
|
||
return (int) $index;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|