From 688ae307472392cc09e8583f8c82a2e14e35be57 Mon Sep 17 00:00:00 2001 From: renshen <1005457301@qq.com> Date: Fri, 16 Oct 2026 22:17:05 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=BA=94=E4=BB=98=E6=AC=BE=E7=BB=88?= =?UTF-8?q?=E7=89=88=E9=80=80=E8=B4=A7=E5=AF=B9=E8=B4=A6=EF=BC=9Awms?= =?UTF-8?q?=E9=85=8D=E8=B4=A7=E5=8D=95=E5=8F=B7=E8=B0=83=E6=95=B4=E5=88=B0?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E5=90=8E=20(#355)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 「标题」在前、「wms配货单号」在后(与基础页面一致),导入模板与页面/导出同步;其他页签不受影响。 --- .../EcommerceFinance/Services/PayablesFinalRegistry.php | 4 ++-- tests/Feature/Business/SupplierPayableFinalPagesTest.php | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/EcommerceFinance/Services/PayablesFinalRegistry.php b/modules/EcommerceFinance/Services/PayablesFinalRegistry.php index e5467670..98c9e9bb 100644 --- a/modules/EcommerceFinance/Services/PayablesFinalRegistry.php +++ b/modules/EcommerceFinance/Services/PayablesFinalRegistry.php @@ -41,7 +41,7 @@ class PayablesFinalRegistry * - insert:锚点列之后插入的列(锚点列名 => 列定义); * - append:追加到末尾的列。 * 货款对账在「月份」后补入库单号、采购单号,末尾补未发出、对账人; - * 退货对账去掉「快递名称」,在「备注」后插入 wms 配货单号,在「标记多标签」后补创建人。 + * 退货对账去掉「快递名称」,在「标题」后插入 wms 配货单号,在「标记多标签」后补创建人。 */ private const SUPPLIER_FIELD_PATCHES = [ 'payment-reconciliation' => [ @@ -57,7 +57,7 @@ class PayablesFinalRegistry 'return-reconciliation' => [ 'remove' => ['express_name'], 'insert' => [ - 'remark' => ['wms_pick_no' => ['label' => 'wms配货单号', 'type' => 'text']], + 'title' => ['wms_pick_no' => ['label' => 'wms配货单号', 'type' => 'text']], 'labels' => ['creator' => ['label' => '创建人', 'type' => 'text']], ], ], diff --git a/tests/Feature/Business/SupplierPayableFinalPagesTest.php b/tests/Feature/Business/SupplierPayableFinalPagesTest.php index f107b3b1..40ed0237 100644 --- a/tests/Feature/Business/SupplierPayableFinalPagesTest.php +++ b/tests/Feature/Business/SupplierPayableFinalPagesTest.php @@ -152,7 +152,7 @@ class SupplierPayableFinalPagesTest extends FeatureTestCase $this->assertSame([ '记录标识', '月份', '发货时间', '明细供应商', '条形码', '商品名称', '发货量', '单价', '金额', '预估单价', - '预估金额', '供应商条码', '备注', 'wms配货单号', '标题', '仓库名称', '快递单号', '标记多标签', '创建人', '对账人', + '预估金额', '供应商条码', '备注', '标题', 'wms配货单号', '仓库名称', '快递单号', '标记多标签', '创建人', '对账人', ], $header); $this->assertNotContains('快递名称', $header); } finally { @@ -164,8 +164,8 @@ class SupplierPayableFinalPagesTest extends FeatureTestCase { $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", + "\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() @@ -192,6 +192,7 @@ class SupplierPayableFinalPagesTest extends FeatureTestCase $export = $this->loginAs()->get(route('business.supplier-payables-final.return-reconciliation.export')); $export->assertOk(); + $this->assertStringContainsString('备注,标题,wms配货单号', $export->streamedContent()); $this->assertStringContainsString('标记多标签,创建人,对账人', $export->streamedContent()); $this->assertStringNotContainsString('快递名称', $export->streamedContent()); } From b26ab9f85d8d12c5cbc0e204b823001e5a310166 Mon Sep 17 00:00:00 2001 From: limeng <1131177064@qq.com> Date: Fri, 16 Oct 2026 22:17:52 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=BF=AB=E9=80=92=E5=BA=94=E4=BB=98?= =?UTF-8?q?=EF=BC=9A=E9=A6=96=E5=8F=91=E4=BF=A1=E6=81=AF=E6=8B=86=E5=88=97?= =?UTF-8?q?=E5=8F=8A=E6=98=8E=E7=BB=86=E5=AD=97=E6=AE=B5=E7=AD=9B=E9=80=89?= =?UTF-8?q?=20(#356)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/配件补发扣款.md | 2 ++ .../View/AccessoryReshipPageData.php | 36 +++++++++++++++++-- .../accessory-reship-deductions.blade.php | 19 ++++++---- tests/Unit/AccessoryReshipPageDataTest.php | 28 +++++++++++++++ 4 files changed, 76 insertions(+), 9 deletions(-) diff --git a/docs/配件补发扣款.md b/docs/配件补发扣款.md index 6e05f117..15839847 100644 --- a/docs/配件补发扣款.md +++ b/docs/配件补发扣款.md @@ -17,3 +17,5 @@ - 实际Blade页面检查:分类局部切换、分页、多候选提示、异常金额及手机/桌面布局。 - 导出检查:路由优先级、本页权限、后台鉴权、UTF-8 BOM及公式保护。 - 使用现有数据连接进行了真实业务月份只读匹配及性能验证。 + +首发快递、首发单号、所属月份以独立三列显示,多候选按同一顺序对应。支持交易单号、补发单号、补发快递、补发日期、原始/处理后条码、补发运费、匹配状态、首发快递、首发单号、所属月份及可扣金额筛选;文本和金额支持包含匹配。筛选覆盖全部业务月记录,汇总、分类数量、分页和CSV导出沿用相同条件。多个首发筛选必须由同一候选满足;清空筛选保留业务月份。 diff --git a/modules/EcommerceFinance/View/AccessoryReshipPageData.php b/modules/EcommerceFinance/View/AccessoryReshipPageData.php index 242fa5a1..a52f118e 100644 --- a/modules/EcommerceFinance/View/AccessoryReshipPageData.php +++ b/modules/EcommerceFinance/View/AccessoryReshipPageData.php @@ -15,17 +15,49 @@ class AccessoryReshipPageData $month = request()->query('month', now()->format('Y-m')); abort_unless(is_string($month) && preg_match('/^\d{4}-(0[1-9]|1[0-2])$/', $month) && (int) substr($month, 0, 4) >= 2000, 422, '请选择有效业务月份。'); $status = request()->query('match_status', 'matched'); - return ['month' => $month, 'match_status' => in_array($status, ['matched', 'unmatched', 'all'], true) ? $status : 'matched']; + $filters = ['month' => $month, 'match_status' => in_array($status, ['matched', 'unmatched', 'all'], true) ? $status : 'matched']; + foreach (['trade_no','express_no','courier','ship_date','barcode','normalized_barcode','freight','original_courier','original_express_no','original_month','deduction_amount'] as $field) { + $value = request()->query($field, ''); + abort_unless(is_string($value) && mb_strlen($value) <= 200, 422, '筛选条件格式无效。'); + $filters[$field] = trim($value); + } + return $filters; } public function rows(array $filters): \Generator { $start = \Carbon\Carbon::createFromFormat('!Y-m', $filters['month']); foreach ($this->shipping->accessoryReshipBatches($start->format('Y-m-d'), $start->copy()->addMonth()->format('Y-m-d'), $start->copy()->subMonths(2)->format('Y-m-d')) as $batch) { - foreach ($this->matcher->match($batch['accessories'], $batch['originals']) as $row) yield $row; + foreach ($this->matcher->match($batch['accessories'], $batch['originals']) as $row) { + if ($this->matchesFilters($row, $filters)) yield $row; + } } } + public function matchesFilters(array $row, array $filters): bool + { + $values = [ + 'trade_no' => $row['trade_no'], 'express_no' => ($row['express_no'] ?? ''), + 'courier' => ($row['express_name1'] ?? '') ?: ($row['express_name2'] ?? ''), + 'ship_date' => substr((string) ($row['ship_time'] ?? ''), 0, 10), + 'barcode' => $row['barcode'], 'normalized_barcode' => $row['normalized_barcode'], + 'freight' => $row['freight_cents'] === null ? '待核实' : number_format($row['freight_cents'] / 100, 2, '.', ''), + 'deduction_amount' => $row['deduction_cents'] === null ? '待核实' : number_format($row['deduction_cents'] / 100, 2, '.', ''), + ]; + foreach ($values as $field => $value) { + if (($filters[$field] ?? '') !== '' && mb_stripos((string) $value, $filters[$field]) === false) return false; + } + $originalFilters = array_filter(['courier' => $filters['original_courier'] ?? '', 'express_no' => $filters['original_express_no'] ?? '', 'month' => $filters['original_month'] ?? ''], static fn ($value) => $value !== ''); + if (!$originalFilters) return true; + foreach ($row['matches'] as $match) { + foreach ($originalFilters as $field => $value) { + if (mb_stripos((string) $match[$field], $value) === false) continue 2; + } + return true; + } + return false; + } + public function page(): array { $filters = $this->filters(); diff --git a/resources/views/business/pages/courier-payables/accessory-reship-deductions.blade.php b/resources/views/business/pages/courier-payables/accessory-reship-deductions.blade.php index 53d26dbd..8325d9d9 100644 --- a/resources/views/business/pages/courier-payables/accessory-reship-deductions.blade.php +++ b/resources/views/business/pages/courier-payables/accessory-reship-deductions.blade.php @@ -8,9 +8,13 @@

配件补发扣款

按交易单号及条形码匹配首发快递,核算配件补发运费。

快递应付
- - - @if (!$reshipError)导出当前分类@endif + @foreach (['trade_no'=>'交易单号','express_no'=>'补发快递单号','courier'=>'补发快递','ship_date'=>'补发日期','barcode'=>'原始条形码','normalized_barcode'=>'处理后条形码','freight'=>'补发运费','original_courier'=>'首发快递','original_express_no'=>'首发单号','original_month'=>'所属月份','deduction_amount'=>'可扣金额'] as $field => $label) + + @endforeach + + + 清空筛选 + @if (!$reshipError)导出筛选结果@endif 匹配范围:{{ $startMonth }} 至 {{ \Carbon\Carbon::createFromFormat('!Y-m', $filters['month'])->format('Y年n月') }}
@@ -29,19 +33,20 @@ @endforeach
- @foreach (['交易单号','补发快递单号','补发快递','补发日期','原始条形码','处理后条形码','补发运费','匹配状态','首发快递 / 单号 / 所属月份','可扣金额','说明'] as $heading)@endforeach + @foreach (['交易单号','补发快递单号','补发快递','补发日期','原始条形码','处理后条形码','补发运费','匹配状态','首发快递','首发单号','所属月份','可扣金额','说明'] as $heading)@endforeach @forelse ($reshipRows as $row) - @empty@endforelse + @empty@endforelse
{{ $heading }}{{ $heading }}
{{ $row['trade_no'] }}{{ $row['express_no'] }}{{ $row['express_name1'] ?: $row['express_name2'] }}{{ substr((string) $row['ship_time'], 0, 10) }}{{ $row['barcode'] }}{{ $row['normalized_barcode'] }}{{ $row['freight_cents'] === null ? '待核实' : number_format($row['freight_cents'] / 100, 2) }}{{ $row['status'] === 'matched' ? '可扣款' : '未匹配不扣款' }} - @forelse ($row['matches'] as $match)
{{ $match['courier'] ?: '快递名称待核实' }}
{{ $match['express_no'] }} ({{ $match['month'] }})
@empty — @endforelse + @forelse ($row['matches'] as $match)
{{ $match['courier'] ?: '快递名称待核实' }}
@empty — @endforelse +
@forelse ($row['matches'] as $match)
{{ $match['express_no'] }}
@empty — @endforelse
@forelse ($row['matches'] as $match)
{{ $match['month'] }}
@empty — @endforelse
{{ $row['deduction_cents'] === null ? '待核实' : number_format($row['deduction_cents'] / 100, 2) }}{{ $row['freight_cents'] === null ? '运费缺失或异常' : (count($row['matches']) > 1 ? '多候选,确认归属后扣款;仅计一次' : ($row['status'] === 'unmatched' ? '三个月内未匹配首发快递单号' : '待核对')) }}
{{ $reshipError ?: '当前月份及分类暂无记录,请调整业务月份或分类。' }}
{{ $reshipError ?: '当前筛选条件下暂无记录,请清空筛选或调整业务月份、分类。' }}
@push('body_end')