CaiWuXiTong/app/Business/CourierFreightDifferenceMap.php
qiuxiang a8b086766b 快递运费:提供成本运费后面新增「运费差」列(按交易单号取快递应付的运费差)
运费差是「应付款项 › 快递应付 › 运费差」页面上传的汇总快照(JSON 文件,不是数据库表),这里新增 CourierFreightDifferenceMap 读它并转成 交易单号 ⇒ 差异 映射,页面按交易单号带出新列;快照文件的修改时间进缓存键,财务重导后自动失效。源表一格多单号(逗号分隔)会逐个挂同一个差异值。
2026-10-08 14:49:55 +08:00

100 lines
3.4 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 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;
}
}