diff --git a/modules/EcommerceFinance/Services/PayablesFinalRegistry.php b/modules/EcommerceFinance/Services/PayablesFinalRegistry.php index 2024cf02..d58c8c51 100644 --- a/modules/EcommerceFinance/Services/PayablesFinalRegistry.php +++ b/modules/EcommerceFinance/Services/PayablesFinalRegistry.php @@ -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 $fields + * @return array + */ + 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'] ?? []); } } diff --git a/tests/Feature/Business/SupplierPayableFinalPagesTest.php b/tests/Feature/Business/SupplierPayableFinalPagesTest.php index e7e9208b..d526531a 100644 --- a/tests/Feature/Business/SupplierPayableFinalPagesTest.php +++ b/tests/Feature/Business/SupplierPayableFinalPagesTest.php @@ -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()