CaiWuXiTong/tests/Unit/EcommerceFinance/OnlineDaifaShipSkuLabelsTest.php
limeng a20af2e067 feat(线上代发价格): 新增实际发货商品编码与聚水潭标记|多标签两列 (#730)
## 做了什么
线上代发价格页面与 CSV 导出新增两列:
- **实际发货商品编码**:按店铺交易单号(钉钉行)/内部单号(采购单行)关联聚水潭订单(非淘系 + 淘系),列出组合装拆开后的子商品编码×数量;优先只取本行商品编码拆出的子商品,普通商品取自身,对不上时列整单;忽略被拆分/合并/作废原单,拆单合并显示
- **聚水潭标记|多标签**:订单 labels

## 修改文件
- modules/EcommerceFinance/Repositories/DingOnlineDaifaPriceMirrorRepository.php
- app/Http/Controllers/Business/Pages.php(导出加列)
- resources/views/business/pages/product-inventory/online-daifa-price.blade.php
- tests/Unit/EcommerceFinance/OnlineDaifaShipSkuLabelsTest.php(新增)、tests/Feature/Business/OnlineDaifaPricePageTest.php

## 验证
- 新增 4 个单测(组合装、混合订单、拆单、无订单)+ 原采购单单测在精简 Laravel 环境通过;Feature 测试新增断言未在完整环境运行
- 只按当前页/导出每 200 行的单号做 so_id/o_id 索引等值查询,不扫全表

## 风险
不涉及金额计算、权限、数据库结构或配置;只读镜像表。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_012AvVQFrueqWakFKTdSyu5q

Reviewed-on: #730
2026-10-28 14:34:05 +08:00

165 lines
8.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Tests\Unit\EcommerceFinance;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Modules\EcommerceFinance\Repositories\DingOnlineDaifaPriceMirrorRepository;
use Tests\TestCase;
class OnlineDaifaShipSkuLabelsTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
config([
'database.connections.business_mirror' => ['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => ''],
'upstream_mirrors.connection' => 'business_mirror',
]);
DB::purge('business_mirror');
$this->createSchema();
$this->seedRows();
}
public function test_combo_row_lists_the_child_skus_and_order_labels(): void
{
$row = $this->row('3634442001971995');
$this->assertSame('VTYZ010102×1, GDYRB020102×1', $row['ship_skus']);
$this->assertSame('店铺-京东供销,京东供销订单,京东快递,京喜,线上发货,以旧换新·国家补贴,指定快递', $row['jst_labels']);
}
public function test_only_the_children_of_this_rows_combo_are_listed_when_the_order_mixes_items(): void
{
$this->assertSame('CHAIR-A×2', $this->row('5000000000000001', 'ZH-CHAIR-A-2')['ship_skus']);
$this->assertSame('DESK-B×1', $this->row('5000000000000001', 'DESK-B')['ship_skus']);
$this->assertSame('CHAIR-A×2, DESK-B×1', $this->row('5000000000000001', 'UNKNOWN-CODE')['ship_skus']);
}
public function test_split_parent_orders_are_ignored_and_children_are_merged(): void
{
$row = $this->row('6000000000000001');
$this->assertSame('SOFA-L×1, SOFA-R×1', $row['ship_skus']);
$this->assertSame('拆分', $row['jst_labels']);
}
public function test_rows_without_a_jst_order_stay_blank_and_export_matches_page(): void
{
$repository = app(DingOnlineDaifaPriceMirrorRepository::class);
$this->assertSame('', $this->row('9999999999999999')['ship_skus']);
$this->assertSame('', $this->row('9999999999999999')['jst_labels']);
$page = $repository->paginate([], 1, 100)['data'];
$export = iterator_to_array($repository->exportRows([]), false);
$this->assertSame(array_column($page, 'ship_skus'), array_column($export, 'ship_skus'));
$this->assertSame(array_column($page, 'jst_labels'), array_column($export, 'jst_labels'));
}
/** @return array<string,mixed> */
private function row(string $shopTradeNo, ?string $materialNo = null): array
{
$data = app(DingOnlineDaifaPriceMirrorRepository::class)->paginate(['keyword' => $shopTradeNo], 1, 100)['data'];
foreach ($data as $row) {
if ($materialNo === null || $row['material_no'] === $materialNo) {
return $row;
}
}
$this->fail('row not found');
}
private function createSchema(): void
{
$schema = Schema::connection('business_mirror');
$schema->create('business_mirror_table_states', function (Blueprint $table): void {
$table->string('dataset_key')->primary();
$table->string('status');
$table->dateTime('initial_completed_at')->nullable();
$table->dateTime('last_succeeded_at')->nullable();
});
$schema->create(DingOnlineDaifaPriceMirrorRepository::TARGET_TABLE, function (Blueprint $table): void {
$table->string('process_instance_id');
$table->unsignedInteger('detail_index');
$table->string('product_id')->nullable();
$table->string('product_name')->nullable();
$table->string('daifa_trade_no')->nullable();
$table->string('shop_trade_no')->nullable();
$table->string('shop_name')->nullable();
$table->string('payee_name')->nullable();
$table->string('supplier_name')->nullable();
$table->string('material_no')->nullable();
$table->integer('ship_qty')->nullable();
$table->decimal('paid_amount', 20, 2)->nullable();
$table->decimal('daifa_amount', 20, 2)->nullable();
$table->decimal('price_diff', 20, 2)->nullable();
$table->text('workflow_payload')->nullable();
$table->text('scheme_payload')->nullable();
$table->text('task_payload')->nullable();
$table->dateTime('workflow_created_at')->nullable();
});
$schema->create('ops_jst_orders', function (Blueprint $table): void {
$table->unsignedBigInteger('Id')->primary();
$table->unsignedBigInteger('o_id')->index();
$table->string('so_id')->nullable()->index();
$table->string('shop_name')->nullable();
$table->string('status')->nullable();
$table->text('labels')->nullable();
});
$schema->create('ops_jst_order_item', function (Blueprint $table): void {
$table->unsignedBigInteger('Id')->primary();
$table->unsignedBigInteger('o_id')->index();
$table->string('sku_id')->nullable();
$table->decimal('qty', 20, 4)->nullable();
$table->string('src_combine_sku_id')->nullable();
});
}
private function seedRows(): void
{
$db = DB::connection('business_mirror');
$db->table('business_mirror_table_states')->insert([
'dataset_key' => DingOnlineDaifaPriceMirrorRepository::DATASET_KEY,
'status' => 'succeeded',
'initial_completed_at' => '2026-10-01 00:00:00',
'last_succeeded_at' => '2026-10-28 09:00:00',
]);
$ding = static fn (string $id, int $index, string $soId, string $material): array => [
'process_instance_id' => $id, 'detail_index' => $index, 'shop_trade_no' => $soId,
'shop_name' => '店铺-京东供销', 'material_no' => $material, 'ship_qty' => 1,
'workflow_payload' => '{"status":"COMPLETED","result":"agree"}', 'scheme_payload' => '[]', 'task_payload' => '[]',
'workflow_created_at' => '2026-10-0' . $index . ' 10:00:00',
];
$db->table(DingOnlineDaifaPriceMirrorRepository::TARGET_TABLE)->insert([
$ding('P1', 1, '3634442001971995', 'ZH-GDYRB020102-1-VTYZ010102-1'),
$ding('P2', 1, '5000000000000001', 'ZH-CHAIR-A-2'),
$ding('P2', 2, '5000000000000001', 'DESK-B'),
$ding('P2', 3, '5000000000000001', 'UNKNOWN-CODE'),
$ding('P3', 1, '6000000000000001', 'ZH-SOFA'),
$ding('P4', 1, '9999999999999999', 'NONE'),
]);
$db->table('ops_jst_orders')->insert([
['Id' => 1, 'o_id' => 9557207, 'so_id' => '3634442001971995', 'shop_name' => '店铺-京东供销', 'status' => 'Sent',
'labels' => '店铺-京东供销,京东供销订单,京东快递,京喜,线上发货,以旧换新·国家补贴,指定快递'],
['Id' => 2, 'o_id' => 100, 'so_id' => '5000000000000001', 'shop_name' => 'x', 'status' => 'Sent', 'labels' => null],
['Id' => 3, 'o_id' => 200, 'so_id' => '6000000000000001', 'shop_name' => 'x', 'status' => 'Split', 'labels' => '原单'],
['Id' => 4, 'o_id' => 201, 'so_id' => '6000000000000001', 'shop_name' => 'x', 'status' => 'Sent', 'labels' => '拆分'],
['Id' => 5, 'o_id' => 202, 'so_id' => '6000000000000001', 'shop_name' => 'x', 'status' => 'Sent', 'labels' => '拆分'],
]);
$db->table('ops_jst_order_item')->insert([
['Id' => 1, 'o_id' => 9557207, 'sku_id' => 'VTYZ010102', 'qty' => 1, 'src_combine_sku_id' => 'ZH-GDYRB020102-1-VTYZ010102-1'],
['Id' => 2, 'o_id' => 9557207, 'sku_id' => 'GDYRB020102', 'qty' => 1, 'src_combine_sku_id' => 'ZH-GDYRB020102-1-VTYZ010102-1'],
['Id' => 3, 'o_id' => 100, 'sku_id' => 'CHAIR-A', 'qty' => 2, 'src_combine_sku_id' => 'ZH-CHAIR-A-2'],
['Id' => 4, 'o_id' => 100, 'sku_id' => 'DESK-B', 'qty' => 1, 'src_combine_sku_id' => null],
['Id' => 5, 'o_id' => 200, 'sku_id' => 'SOFA-L', 'qty' => 1, 'src_combine_sku_id' => 'ZH-SOFA'],
['Id' => 6, 'o_id' => 200, 'sku_id' => 'SOFA-R', 'qty' => 1, 'src_combine_sku_id' => 'ZH-SOFA'],
['Id' => 7, 'o_id' => 201, 'sku_id' => 'SOFA-L', 'qty' => 1, 'src_combine_sku_id' => 'ZH-SOFA'],
['Id' => 8, 'o_id' => 202, 'sku_id' => 'SOFA-R', 'qty' => 1, 'src_combine_sku_id' => 'ZH-SOFA'],
]);
}
}