应付款终版退货对账:新增「wms配货单号/创建人」列并去掉「快递名称」 (#352)

「备注」后插入 wms配货单号,末尾补创建人,删除快递名称列;导入模板/表格/导入/编辑/导出同一套字段,只作用于终版目录。
This commit is contained in:
renshen 2026-10-16 21:23:25 +08:00
parent 7fbcd061af
commit 3e1d211d1b
2 changed files with 107 additions and 7 deletions

View File

@ -35,20 +35,34 @@ class PayablesFinalRegistry
private const MONTH_FIELD = ['summary_month' => ['label' => '月份', 'type' => 'month']];
/**
* 供应商应付(终版)在基础字段前后追加的列(只影响终版目录,基础目录对应列另有口径):
* 货款对账在「月份」后补入库单号、采购单号,在末尾补未发出、对账人。
* 供应商应付(终版)在基础字段上做的增删(只影响终版目录,基础目录对应列另有口径):
* - prepend:紧跟在「月份」后的列;
* - remove:去掉的列;
* - insert:锚点列之后插入的列(锚点列名 => 列定义);
* - append:追加到末尾的列。
* 货款对账在「月份」后补入库单号、采购单号,末尾补未发出、对账人;
* 退货对账去掉「快递名称」,在「备注」后插入 wms 配货单号,末尾补创建人。
*/
private const SUPPLIER_EXTRA_FIELDS = [
private const SUPPLIER_FIELD_PATCHES = [
'payment-reconciliation' => [
'before' => [
'prepend' => [
'stockNo' => ['label' => '入库单号', 'type' => 'text'],
'purchaseNo' => ['label' => '采购单号', 'type' => 'text'],
],
'after' => [
'append' => [
'unsent' => ['label' => '未发出', 'type' => 'text'],
'reconciler' => ['label' => '对账人', 'type' => 'text'],
],
],
'return-reconciliation' => [
'remove' => ['express_name'],
'insert' => [
'remark' => ['wms_pick_no' => ['label' => 'wms配货单号', 'type' => 'text']],
],
'append' => [
'creator' => ['label' => '创建人', 'type' => 'text'],
],
],
];
public function __construct(
@ -96,8 +110,33 @@ class PayablesFinalRegistry
? $this->productPrices->templateFields()
: $this->supplier->fields($dataset);
$extra = self::SUPPLIER_EXTRA_FIELDS[$dataset] ?? [];
return self::MONTH_FIELD + $this->patchSupplierFields($dataset, $fields);
}
return self::MONTH_FIELD + ($extra['before'] ?? []) + $fields + ($extra['after'] ?? []);
/**
* @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'] ?? []);
}
}

View File

@ -135,6 +135,67 @@ class SupplierPayableFinalPagesTest extends FeatureTestCase
$this->assertStringContainsString('快递单号,未发出,对账人', $export->streamedContent());
}
public function test_final_return_reconciliation_template_adds_wms_and_creator_columns(): void
{
$response = $this->loginAs()
->get(route('business.supplier-payables-final.return-reconciliation.template'))
->assertOk()
->assertHeader('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
$path = tempnam(sys_get_temp_dir(), 'caiwu-template') . '.xlsx';
try {
file_put_contents($path, $response->streamedContent());
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($path);
$header = $spreadsheet->getSheet(0)->rangeToArray('A1:T1')[0];
$spreadsheet->disconnectWorksheets();
$this->assertSame([
'记录标识', '月份', '发货时间', '明细供应商', '条形码', '商品名称', '发货量', '单价', '金额', '预估单价',
'预估金额', '供应商条码', '备注', 'wms配货单号', '标题', '仓库名称', '快递单号', '标记多标签', '对账人', '创建人',
], $header);
$this->assertNotContains('快递名称', $header);
} finally {
@unlink($path);
}
}
public function test_final_return_reconciliation_import_keeps_wms_and_creator_columns(): void
{
$file = UploadedFile::fake()->createWithContent(
'return-reconciliation.csv',
"\xEF\xBB\xBF月份,发货时间,明细供应商,条形码,商品名称,发货量,单价,金额,预估单价,预估金额,供应商条码,备注,wms配货单号,标题,仓库名称,快递单号,标记多标签,对账人,创建人\n"
. "2026-09,2026-09-01,退货供应商,BC-1,商品甲,3,10,30,9,27,SB-1,备注甲,WMS-1,标题甲,华南仓,SF-9,多标签,对账人乙,创建人甲\n",
);
$this->loginAs()
->post(route('business.supplier-payables-final.return-reconciliation.import'), ['import' => $file])
->assertStatus(302)
->assertSessionHas('success', '导入完成:新增 1 条,更新 0 条。');
$this->assertDatabaseHas('supplier_payable_overrides', [
'company_id' => $this->company->id,
'dataset' => 'final:supplier:return-reconciliation',
]);
$this->loginAs()
->get(route('business.pages.show', [
'section' => 'supplier-payables-final',
'page' => 'return-reconciliation',
]))
->assertOk()
->assertSeeText('wms配货单号')
->assertSeeText('创建人')
->assertSeeText('WMS-1')
->assertSeeText('创建人甲')
->assertDontSeeText('快递名称');
$export = $this->loginAs()->get(route('business.supplier-payables-final.return-reconciliation.export'));
$export->assertOk();
$this->assertStringContainsString('对账人,创建人', $export->streamedContent());
$this->assertStringNotContainsString('快递名称', $export->streamedContent());
}
public function test_product_price_final_page_reuses_the_price_template_columns(): void
{
$this->loginAs()