142 lines
5.2 KiB
PHP
142 lines
5.2 KiB
PHP
<?php
|
||
|
||
namespace Modules\EcommerceFinance\Services;
|
||
|
||
use Illuminate\Validation\ValidationException;
|
||
|
||
/**
|
||
* 「终版」目录的按表数据登记:确定每个页签的字段(决定导入模板与表格列)
|
||
* 以及数据标题;数据本身独立存放,与基础目录互不影响。
|
||
*/
|
||
class PayablesFinalRegistry
|
||
{
|
||
public const SECTION_SUPPLIER = 'supplier-payables-final';
|
||
|
||
public const SECTION_COURIER = 'courier-payables-final';
|
||
|
||
/** @var array<string,string> 供应商应付(终版)页签 */
|
||
private const SUPPLIER_TITLES = [
|
||
'product-prices' => '商品价格',
|
||
'payment-reconciliation' => '货款对账',
|
||
'return-reconciliation' => '退货对账',
|
||
'invoice-deductions' => '发票扣款',
|
||
'board-deductions' => '板材扣款',
|
||
'compensation-details' => '赔偿明细',
|
||
'advance-details' => '借支明细',
|
||
'sample-deductions' => '样品扣款',
|
||
'other-adjustments' => '其他扣款补款',
|
||
'delivery-unpriced' => '送货未定价',
|
||
'return-unpriced' => '退货未定价',
|
||
'dropshipping-express' => '代发快递',
|
||
'supplier-payables-report' => '供应商应付表',
|
||
];
|
||
|
||
/** 所有终版导入模板都带“月份”列,方便按月导入和查看。 */
|
||
private const MONTH_FIELD = ['summary_month' => ['label' => '月份', 'type' => 'month']];
|
||
|
||
/**
|
||
* 供应商应付(终版)在基础字段上做的增删(只影响终版目录,基础目录对应列另有口径):
|
||
* - prepend:紧跟在「月份」后的列;
|
||
* - remove:去掉的列;
|
||
* - insert:锚点列之后插入的列(锚点列名 => 列定义);
|
||
* - append:追加到末尾的列。
|
||
* 货款对账在「月份」后补入库单号、采购单号、日期,末尾补未发出、对账人;
|
||
* 退货对账去掉「快递名称」,在「标题」后插入 wms 配货单号,在「标记多标签」后补创建人。
|
||
*/
|
||
private const SUPPLIER_FIELD_PATCHES = [
|
||
'payment-reconciliation' => [
|
||
'prepend' => [
|
||
'stockNo' => ['label' => '入库单号', 'type' => 'text'],
|
||
'purchaseNo' => ['label' => '采购单号', 'type' => 'text'],
|
||
'date' => ['label' => '日期', 'type' => 'date'],
|
||
],
|
||
'append' => [
|
||
'unsent' => ['label' => '未发出', 'type' => 'text'],
|
||
'reconciler' => ['label' => '对账人', 'type' => 'text'],
|
||
],
|
||
],
|
||
'return-reconciliation' => [
|
||
'remove' => ['express_name'],
|
||
'insert' => [
|
||
'title' => ['wms_pick_no' => ['label' => 'wms配货单号', 'type' => 'text']],
|
||
'labels' => ['creator' => ['label' => '创建人', 'type' => 'text']],
|
||
],
|
||
],
|
||
];
|
||
|
||
public function __construct(
|
||
private readonly SupplierPayableMaintenanceRegistry $supplier,
|
||
private readonly ProductPriceWorkbookImporter $productPrices,
|
||
private readonly CourierPayableFinalRegistry $courier,
|
||
) {
|
||
}
|
||
|
||
public function supports(string $section, string $dataset): bool
|
||
{
|
||
return array_key_exists($dataset, $this->titles($section));
|
||
}
|
||
|
||
/** @return array<string,string> */
|
||
public function titles(string $section): array
|
||
{
|
||
return match ($section) {
|
||
self::SECTION_SUPPLIER => self::SUPPLIER_TITLES,
|
||
self::SECTION_COURIER => $this->courier->titles(),
|
||
default => [],
|
||
};
|
||
}
|
||
|
||
public function title(string $section, string $dataset): string
|
||
{
|
||
$titles = $this->titles($section);
|
||
if (! array_key_exists($dataset, $titles)) {
|
||
throw ValidationException::withMessages(['dataset' => '不支持该终版目录页面。']);
|
||
}
|
||
|
||
return $titles[$dataset];
|
||
}
|
||
|
||
/** @return array<string,array{label:string,type:string}> */
|
||
public function fields(string $section, string $dataset): array
|
||
{
|
||
$this->title($section, $dataset);
|
||
|
||
if ($section === self::SECTION_COURIER) {
|
||
return self::MONTH_FIELD + $this->courier->fields($dataset);
|
||
}
|
||
|
||
$fields = $dataset === 'product-prices'
|
||
? $this->productPrices->templateFields()
|
||
: $this->supplier->fields($dataset);
|
||
|
||
return self::MONTH_FIELD + $this->patchSupplierFields($dataset, $fields);
|
||
}
|
||
|
||
/**
|
||
* @param array<string,array{label:string,type:string}> $fields
|
||
* @return array<string,array{label:string,type:string}>
|
||
*/
|
||
private function patchSupplierFields(string $dataset, array $fields): array
|
||
{
|
||
$patch = self::SUPPLIER_FIELD_PATCHES[$dataset] ?? [];
|
||
|
||
foreach ($patch['remove'] ?? [] as $key) {
|
||
unset($fields[$key]);
|
||
}
|
||
|
||
$inserts = $patch['insert'] ?? [];
|
||
if ($inserts !== []) {
|
||
$ordered = [];
|
||
foreach ($fields as $key => $definition) {
|
||
$ordered[$key] = $definition;
|
||
foreach ($inserts[$key] ?? [] as $insertedKey => $insertedDefinition) {
|
||
$ordered[$insertedKey] = $insertedDefinition;
|
||
}
|
||
}
|
||
$fields = $ordered;
|
||
}
|
||
|
||
return ($patch['prepend'] ?? []) + $fields + ($patch['append'] ?? []);
|
||
}
|
||
}
|