CaiWuXiTong/tests/Feature/Business/OnlineDaifaPricePageTest.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

295 lines
14 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\Feature\Business;
use App\Models\Auth\Permission;
use Mockery;
use Modules\EcommerceFinance\Repositories\DingOnlineDaifaPriceMirrorRepository;
use Tests\Feature\FeatureTestCase;
class OnlineDaifaPricePageTest extends FeatureTestCase
{
public function test_online_daifa_price_page_renders_matched_product_and_amounts(): void
{
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
$repository = Mockery::mock(DingOnlineDaifaPriceMirrorRepository::class);
$repository->shouldReceive('paginate')->once()->andReturn([
'data' => [[
'process_instance_id' => 'DEMO-6927049845766979458',
'detail_index' => 0,
'product_id' => '3821829253650055444',
'daifa_trade_no' => '6927049845766979458',
'shop_trade_no' => '6927049845766979458',
'shop_name' => '抖音-HX旗舰店101',
'payee_name' => '宁波顾家望业家居有限公司',
'tag' => '刘萧代发',
'supplier_name' => '',
'material_no' => '',
'ship_qty' => 1,
'paid_amount' => 616.61,
'daifa_amount' => 375.0,
'price_diff' => 241.61,
'workflow' => [
'businessId' => '20260901001',
'title' => '线上代发业务报销',
'status' => 'COMPLETED',
'result' => 'agree',
'originatorUserName' => '扬灵',
'createAt' => '2026-09-01 10:00:00',
],
'scheme' => [['name' => '商品ID', 'value' => '3821829253650055444']],
'tasks' => [],
'status_key' => 'COMPLETED',
'status_label' => '已完成',
'matched_product' => ['matched' => true, 'name' => '演示商品', 'sku_id' => null, 'i_id' => null],
'workflow_created_at' => '2026-09-01 10:00:00',
]],
'total' => 1,
'status' => 'succeeded',
'last_synced_at' => '2026-09-08 00:00:05',
'summary' => [
'count' => 1,
'matched_count' => 1,
'daifa_amount' => 375.0,
'paid_amount' => 616.61,
'price_diff' => 241.61,
],
]);
$this->app->instance(DingOnlineDaifaPriceMirrorRepository::class, $repository);
$this->loginAs()->get(route('business.pages.show', [
'section' => 'product-inventory',
'page' => 'online-daifa-price',
]))->assertOk()
->assertSee('线上代发价格')
->assertSee('数据来源:钉钉线上代发审批、聚水潭采购单管理(已确认/已完成)')
->assertDontSee('固定收款人:')
->assertSee('宁波顾家望业家居有限公司')
->assertSee('镜像状态:succeeded')
->assertSee('3821829253650055444')
->assertSee('演示商品')
->assertSee('抖音-HX旗舰店101')
->assertSee('6927049845766979458')
->assertSee('已完成')
->assertSee('扬灵')
->assertSee('标签')
->assertSee('刘萧代发')
->assertSee('已匹配商品目录')
->assertDontSee('原始表单')
->assertDontSee('展开表单');
}
public function test_online_daifa_price_page_places_purchase_fields_in_existing_columns(): void
{
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
$repository = Mockery::mock(DingOnlineDaifaPriceMirrorRepository::class);
$repository->shouldReceive('paginate')->once()->andReturn([
'data' => [[
'source_type' => 'purchase',
'process_instance_id' => '907329',
'detail_index' => 1,
'product_id' => '',
'daifa_trade_no' => '',
'shop_trade_no' => '110212448119316609',
'shop_name' => '得物-米客米家家居旗舰店',
'payee_name' => '',
'tag' => '采购单管理',
'supplier_name' => '霸州市亚锦五金制品厂',
'material_no' => 'DF-C1ZDY000202',
'ship_qty' => 1,
'paid_amount' => null,
'daifa_amount' => 19.3,
'price_diff' => null,
'workflow' => ['businessId' => '907329', 'title' => '采购单管理'],
'status_label' => '已确认',
'matched_product' => ['matched' => false, 'name' => null],
'order_matched' => true,
'workflow_created_at' => '2026-09-22 16:30:03',
]],
'total' => 1,
'status' => 'available',
'last_synced_at' => '2026-09-22 17:35:11',
'summary' => ['count' => 1, 'purchase_count' => 1, 'matchable_count' => 0],
'source_statuses' => [
'purchase' => ['label' => '聚水潭采购单管理', 'ready' => true, 'status' => 'succeeded'],
],
]);
$this->app->instance(DingOnlineDaifaPriceMirrorRepository::class, $repository);
$this->loginAs()->get(route('business.pages.show', [
'section' => 'product-inventory',
'page' => 'online-daifa-price',
]))->assertOk()
->assertSee('110212448119316609')
->assertSee('得物-米客米家家居旗舰店')
->assertSee('霸州市亚锦五金制品厂')
->assertSee('DF-C1ZDY000202')
->assertSee('19.30')
->assertSee('采购单管理')
->assertSee('已确认')
->assertDontSee('(未匹配)');
}
public function test_online_daifa_price_page_keeps_an_unavailable_mirror_readable(): void
{
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
$repository = Mockery::mock(DingOnlineDaifaPriceMirrorRepository::class);
$repository->shouldReceive('paginate')->andThrow(new \RuntimeException('not ready'));
$this->app->instance(DingOnlineDaifaPriceMirrorRepository::class, $repository);
$this->loginAs()->get(route('business.pages.show', [
'section' => 'product-inventory',
'page' => 'online-daifa-price',
]))->assertOk()
->assertSee('线上代发价格镜像尚未完成同步,请稍后重试。')
->assertSee('镜像读取失败,请稍后重试。');
}
public function test_online_daifa_price_page_passes_filters_to_repository(): void
{
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
$repository = Mockery::mock(DingOnlineDaifaPriceMirrorRepository::class);
$repository->shouldReceive('paginate')->once()->with(
[
'keyword' => '6927049845766979458',
'product_id' => '3821829253650055444',
'shop_name' => '抖音-HX旗舰店101',
'supplier_name' => '新北供应商',
'material_no' => 'MAT-001',
'status' => '',
'created_from' => '2026-09-01',
'created_to' => '2026-09-07',
],
1,
Mockery::type('int'),
)->andReturn([
'data' => [],
'total' => 0,
'status' => 'succeeded',
'last_synced_at' => '2026-09-08 00:00:05',
'summary' => [],
]);
$this->app->instance(DingOnlineDaifaPriceMirrorRepository::class, $repository);
$this->loginAs()->get(route('business.pages.show', [
'section' => 'product-inventory',
'page' => 'online-daifa-price',
'keyword' => '6927049845766979458',
'product_id' => '3821829253650055444',
'shop_name' => '抖音-HX旗舰店101',
'supplier_name' => '新北供应商',
'material_no' => 'MAT-001',
'created_from' => '2026-09-01',
'created_to' => '2026-09-07',
]))->assertOk()
->assertSee('商品ID')
->assertSee('店铺名称')
->assertSee('供应商名称')
->assertSee('新北供应商')
->assertSee('商品编码')
->assertSee('MAT-001')
->assertSee('2026-09-01')
->assertSee('2026-09-07');
}
public function test_online_daifa_price_export_streams_all_currently_filtered_rows(): void
{
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
$filters = [
'keyword' => 'DAIFA-001',
'product_id' => 'PRODUCT-001',
'shop_name' => '抖音旗舰店',
'supplier_name' => '新北供应商',
'material_no' => 'MAT-001',
'status' => 'COMPLETED',
'created_from' => '2026-09-01',
'created_to' => '2026-09-07',
];
$repository = Mockery::mock(DingOnlineDaifaPriceMirrorRepository::class);
$repository->shouldReceive('ready')->once()->andReturnTrue();
$repository->shouldReceive('exportRows')->once()->with($filters)->andReturn((static function (): \Generator {
yield [
'process_instance_id' => 'PROCESS-001',
'product_id' => '3821829253650055444',
'daifa_trade_no' => '6927049845766979458',
'shop_trade_no' => '6927049845766979459',
'shop_name' => '抖音旗舰店',
'payee_name' => '宁波顾家望业家居有限公司',
'tag' => '刘萧代发',
'supplier_name' => '@新北供应商',
'material_no' => 'MAT-001',
'ship_qty' => 2,
'paid_amount' => 616.61,
'daifa_amount' => 375.0,
'price_diff' => 241.61,
'workflow' => [
'businessId' => '=APPROVAL-001',
'title' => '线上代发业务报销',
'originatorUserName' => '+扬灵',
],
'status_label' => '已完成',
'matched_product' => ['matched' => true, 'name' => '演示商品'],
'ship_skus' => 'VTYZ010102×1, GDYRB020102×1',
'jst_labels' => '京东供销订单,京喜',
'workflow_created_at' => '2026-09-01 10:00:00',
];
})());
$this->app->instance(DingOnlineDaifaPriceMirrorRepository::class, $repository);
$response = $this->loginAs()->get(route('business.product-inventory.online-daifa-price.export', $filters));
$response->assertOk();
$this->assertStringContainsString('attachment;', (string) $response->headers->get('content-disposition'));
$this->assertStringContainsString('text/csv', (string) $response->headers->get('content-type'));
$content = $response->streamedContent();
$this->assertStringStartsWith(chr(0xEF) . chr(0xBB) . chr(0xBF), $content);
$this->assertStringContainsString('供应商名称', $content);
$this->assertStringContainsString('商品编码', $content);
$this->assertStringContainsString('标签', $content);
$this->assertStringContainsString('刘萧代发', $content);
$this->assertStringContainsString("'=APPROVAL-001", $content);
$this->assertStringContainsString("'+扬灵", $content);
$this->assertStringContainsString("'@新北供应商", $content);
$this->assertStringContainsString("'3821829253650055444", $content);
$this->assertStringContainsString("'6927049845766979458", $content);
$this->assertStringContainsString("'6927049845766979459", $content);
$this->assertStringContainsString('MAT-001', $content);
$this->assertStringContainsString('实际发货商品编码', $content);
$this->assertStringContainsString('聚水潭标记|多标签', $content);
$this->assertStringContainsString('VTYZ010102×1, GDYRB020102×1', $content);
$this->assertStringContainsString('京东供销订单,京喜', $content);
}
public function test_online_daifa_price_export_requires_a_ready_mirror(): void
{
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
$repository = Mockery::mock(DingOnlineDaifaPriceMirrorRepository::class);
$repository->shouldReceive('ready')->once()->andReturnFalse();
$repository->shouldNotReceive('exportRows');
$this->app->instance(DingOnlineDaifaPriceMirrorRepository::class, $repository);
$this->withExceptionHandling()
->loginAs()
->get(route('business.product-inventory.online-daifa-price.export'))
->assertServiceUnavailable();
}
public function test_online_daifa_price_export_rejects_users_without_sidebar_permission(): void
{
$subject = 'user_' . $this->user->id;
$this->user->roles()->sync([\App\Models\Auth\Role::where('name', 'admin')->firstOrFail()->id]);
setting()->set('system.sidebar_permissions', json_encode([
'configured' => [$subject],
'subjects' => [
$subject => ['company-management/basic-information'],
],
], JSON_UNESCAPED_UNICODE));
$this->withExceptionHandling()
->loginAs()
->get(route('business.product-inventory.online-daifa-price.export'))
->assertForbidden();
}
}