CaiWuXiTong/modules/EcommerceFinance/Http/Concerns/DecoratesLedgerRemarks.php

123 lines
4.0 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 Modules\EcommerceFinance\Http\Concerns;
use Modules\EcommerceFinance\Services\AccountLedgerRemarkMap;
/**
* 店铺收款账户账单:给每行账单补「总账备注」(按平台 + 账单项目匹配映射表)。
*
* 只在读取时补齐,不改动上游账单与镜像数据。
*/
trait DecoratesLedgerRemarks
{
/** 「总账备注」在本页签没有对应账单项目时的占位条件(保证命中 0 行)。 */
private const LEDGER_REMARK_NO_MATCH_ITEM = '__no_such_ledger_remark_item__';
/**
* 导出进度 token(前端生成,随导出的 URL 一起传回来)。
* 只接受安全字符,避免把缓存键写脏。
*/
protected function exportProgressToken(\Illuminate\Http\Request $request): string
{
$token = trim((string) $request->get('token', ''));
return preg_match('/^[A-Za-z0-9_-]{8,64}$/', $token) === 1 ? $token : '';
}
/** 导出进度缓存键:按当前用户隔离。 */
protected static function exportProgressKey(string $token): string
{
return 'account-bills-export:' . (int) user()->id . ':' . $token;
}
/**
* 写导出进度,供前端轮询显示(token 为空时什么都不做)。
*
* @param int $rows 已写入行数
* @param int $total 预计总行数(前端传过来的列表总数,用于算百分比)
*/
protected function putExportProgress(string $token, int $rows, int $total, string $status = 'running', ?string $error = null): void
{
if ($token === '') {
return;
}
$state = ['status' => $status, 'rows' => $rows, 'total' => max($total, $rows)];
if ($error !== null) {
$state['error'] = $error;
}
\Illuminate\Support\Facades\Cache::put(self::exportProgressKey($token), $state, now()->addMinutes(30));
}
protected function ledgerRemarkMap(): AccountLedgerRemarkMap
{
return app(AccountLedgerRemarkMap::class);
}
/**
* 把「总账备注」筛选翻译成账单项目集合。
*
* 页面、列设置与导出都调用这里,保证同一份筛选口径;
* bill_items 供各仓库 whereIn(账单项目) 使用,bill_item_groups 供
* 淘系这种同一页签混多平台的仓库按店铺名前缀再细分。
*
* @param array<string,mixed> $filters
* @return array<string,mixed>
*/
protected function withLedgerRemarkFilter(array $filters, string $tab): array
{
$remark = trim((string) ($filters['ledger_remark'] ?? ''));
if ($remark === '') {
return $filters;
}
$groups = $this->ledgerRemarkMap()->billItemGroupsForTab($tab, $remark);
$filters['bill_item_groups'] = $groups;
$items = [];
foreach ($groups as $group) {
foreach ($group['items'] as $item) {
$items[$item] = true;
}
}
$filters['bill_items'] = array_keys($items);
if ($filters['bill_items'] === []) {
$filters['bill_items'] = [self::LEDGER_REMARK_NO_MATCH_ITEM];
}
return $filters;
}
/**
* 分页结果(含 data 行数组)补总账备注。
*
* @param array<string,mixed> $data
* @return array<string,mixed>
*/
protected function withLedgerRemarks(array $data, string $tab): array
{
if (! empty($data['data']) && is_array($data['data'])) {
$map = $this->ledgerRemarkMap();
$data['data'] = array_map(
static fn (mixed $row): mixed => is_array($row) ? $map->decorate($row, $tab) : $row,
$data['data'],
);
}
return $data;
}
/**
* 导出/流式行补总账备注。
*
* @param iterable<int,array<string,mixed>> $rows
* @return iterable<int,array<string,mixed>>
*/
protected function ledgerRemarkRows(iterable $rows, string $tab): iterable
{
return $this->ledgerRemarkMap()->decorateAll($rows, $tab);
}
}