店铺收款账户账单:总账备注优先取「科目映射表」的财务备注
账单项目在「科目映射表」里能匹到(同平台+同项目)时,总账备注取该规则的「财务备注」; 多规则时按业务备注/商品名称关键词取最具体的一条;匹不到则保留原有总账备注映射。规则按平台+项目预索引,避免逐行扫全表。
This commit is contained in:
parent
db2ee47fd8
commit
1cbc8312a6
@ -17,6 +17,9 @@ class AccountLedgerRemarkMap
|
||||
{
|
||||
public const CACHE_KEY = 'ec_account_ledger_remarks_map_v1';
|
||||
|
||||
/** 「平台 + 账单项目」→ 科目映射表规则(请求内缓存,避免逐行扫描全部规则)。 */
|
||||
private ?array $accountMappingIndex = null;
|
||||
|
||||
/** 页签默认平台(店铺名没有平台前缀时使用)。 */
|
||||
private const TAB_PLATFORM = [
|
||||
'taobao-alipay' => '淘宝',
|
||||
@ -241,20 +244,44 @@ class AccountLedgerRemarkMap
|
||||
return $tabPlatform;
|
||||
}
|
||||
|
||||
/** 查总账备注;没有匹配返回 null。 */
|
||||
public function remark(?string $storeName, ?string $tabPlatform, ?string $billItem): ?string
|
||||
/**
|
||||
* 查总账备注;没有匹配返回 null。
|
||||
*
|
||||
* 取值顺序:
|
||||
* ①「财务规则 › 科目映射表」里同平台同账单项目的「财务备注」(匹配器按业务备注/商品名称关键词取最具体的一条)
|
||||
* ② 上面没匹到时,回落到本表(账单项目 → 总账备注)原有的口径
|
||||
*/
|
||||
public function remark(
|
||||
?string $storeName,
|
||||
?string $tabPlatform,
|
||||
?string $billItem,
|
||||
array $businessRemarks = [],
|
||||
string $goodsName = '',
|
||||
): ?string
|
||||
{
|
||||
$item = trim((string) $billItem);
|
||||
if ($item === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$platforms = [$this->platform($storeName, $tabPlatform), $tabPlatform];
|
||||
|
||||
foreach ($platforms as $platform) {
|
||||
if ($platform === null || $platform === '') {
|
||||
continue;
|
||||
}
|
||||
$fromRule = $this->accountMappingRemark($platform, $item, $businessRemarks, $goodsName);
|
||||
if ($fromRule !== null) {
|
||||
return $fromRule;
|
||||
}
|
||||
}
|
||||
|
||||
$map = $this->map();
|
||||
if ($map === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ([$this->platform($storeName, $tabPlatform), $tabPlatform] as $platform) {
|
||||
foreach ($platforms as $platform) {
|
||||
if ($platform === null || $platform === '') {
|
||||
continue;
|
||||
}
|
||||
@ -266,6 +293,59 @@ class AccountLedgerRemarkMap
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 科目映射表按「平台 + 账单项目」预索引,避免逐行扫全部规则。 */
|
||||
private function accountMappingIndex(): array
|
||||
{
|
||||
if ($this->accountMappingIndex !== null) {
|
||||
return $this->accountMappingIndex;
|
||||
}
|
||||
|
||||
$index = [];
|
||||
try {
|
||||
foreach (app(AccountMappingStore::class)->all() as $rule) {
|
||||
if (! is_array($rule)) {
|
||||
continue;
|
||||
}
|
||||
$platform = trim((string) ($rule['platform'] ?? ''));
|
||||
$item = trim((string) ($rule['item'] ?? ''));
|
||||
if ($platform === '' || $item === '') {
|
||||
continue;
|
||||
}
|
||||
$index[$platform][$item][] = $rule;
|
||||
}
|
||||
} catch (Throwable) {
|
||||
$index = [];
|
||||
}
|
||||
|
||||
return $this->accountMappingIndex = $index;
|
||||
}
|
||||
|
||||
/** 同平台同账单项目的「财务备注」;没有规则或财务备注为空时返回 null(由调用方回落)。 */
|
||||
private function accountMappingRemark(string $platform, string $item, array $businessRemarks, string $goodsName): ?string
|
||||
{
|
||||
$rules = $this->accountMappingIndex()[$platform][$item] ?? [];
|
||||
if ($rules === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (count($rules) === 1) {
|
||||
$remark = trim((string) ($rules[0]['memo'] ?? ''));
|
||||
|
||||
return $remark === '' ? null : $remark;
|
||||
}
|
||||
|
||||
// 同一账单项目有多条规则时,用映射表自己的匹配器(按商品名称/业务备注关键词取最具体的)
|
||||
try {
|
||||
$result = app(AccountMappingMatcher::class)->match($platform, $item, $businessRemarks, $goodsName);
|
||||
} catch (Throwable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$remark = trim((string) ($result['rule']['memo'] ?? ''));
|
||||
|
||||
return $remark === '' ? null : $remark;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给一行账单补上 payload.ledger_remark(内部字段名 ledger_remark)。
|
||||
*
|
||||
@ -279,6 +359,8 @@ class AccountLedgerRemarkMap
|
||||
$row['store_name'] ?? null,
|
||||
$tabPlatform,
|
||||
$row['bill_item'] ?? null,
|
||||
$this->businessRemarks($row),
|
||||
$this->goodsName($row),
|
||||
);
|
||||
if ($remark === null) {
|
||||
return $row;
|
||||
@ -293,6 +375,53 @@ class AccountLedgerRemarkMap
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* 账单上的业务备注(用于科目映射表的「业务备注关键词」条件)。
|
||||
*
|
||||
* @param array<string,mixed> $row
|
||||
* @return list<string>
|
||||
*/
|
||||
private function businessRemarks(array $row): array
|
||||
{
|
||||
$payload = is_array($row['payload'] ?? null) ? $row['payload'] : [];
|
||||
|
||||
$values = [
|
||||
$row['custom_remark'] ?? null,
|
||||
$row['finance_remark'] ?? null,
|
||||
$payload['second_remark'] ?? null,
|
||||
$payload['business_description'] ?? null,
|
||||
$payload['move_summary'] ?? null,
|
||||
$payload['settle_remark'] ?? null,
|
||||
$payload['tx_remark'] ?? null,
|
||||
$payload['cost_name'] ?? null,
|
||||
];
|
||||
|
||||
$remarks = [];
|
||||
foreach ($values as $value) {
|
||||
$text = trim((string) $value);
|
||||
if ($text !== '') {
|
||||
$remarks[] = $text;
|
||||
}
|
||||
}
|
||||
|
||||
return $remarks;
|
||||
}
|
||||
|
||||
/** 商品名称(用于科目映射表的「商品名称关键词」条件)。 */
|
||||
private function goodsName(array $row): string
|
||||
{
|
||||
$payload = is_array($row['payload'] ?? null) ? $row['payload'] : [];
|
||||
|
||||
foreach (['goods_name', 'product_name', 'goods_title'] as $key) {
|
||||
$value = trim((string) ($payload[$key] ?? ''));
|
||||
if ($value !== '') {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param iterable<int,array<string,mixed>> $rows
|
||||
* @return \Generator<int,array<string,mixed>>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user