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(); } }