allowPage(); $filters = [ 'store_name' => '得物-测试店', 'bill_item' => '交易收入', 'start' => '2026-08-01', 'end' => '2026-08-31', 'keyword' => '110211', ]; $repository = Mockery::mock(DewuSettlementBillRepository::class); $repository->shouldReceive('paginateAccountBills')->once()->with( $filters, 'occurred_at', 'desc', 2, 20, )->andReturn([ 'current_page' => 2, 'last_page' => 3, 'per_page' => 20, 'total' => 41, 'data' => [[ 'record_code' => '2000000001248775179', 'store_name' => '得物-测试店', 'income' => 21.0, 'expense' => 0.0, 'payload' => ['channel' => '得物', 'source_channel' => 'Dewu'], ], [ 'record_code' => '2000000001248775180', 'store_name' => '得物-测试店', 'income' => 0.0, 'expense' => 18.07, 'payload' => ['channel' => '退货退款订单', 'source_channel' => 'DewuTK'], ], [ 'record_code' => '2000000001248775181', 'store_name' => '得物-测试店', 'income' => 0.0, 'expense' => 3.50, 'payload' => ['channel' => '扣减其他费用明细', 'source_channel' => 'DewuKJ'], ]], 'summary' => ['income' => 21.0, 'expense' => 21.57, 'balance' => -0.57, 'count' => 41], ]); $this->app->instance(DewuSettlementBillRepository::class, $repository); $this->withExceptionHandling() ->loginAs() ->getJson(route('ecommerce-finance.account-bills.index', [ 'bill_type' => 'dewu', ...$filters, 'page' => 2, 'limit' => 20, ])) ->assertOk() ->assertJsonPath('data.0.payload.source_channel', 'Dewu') ->assertJsonPath('data.1.payload.channel', '退货退款订单') ->assertJsonPath('data.2.payload.channel', '扣减其他费用明细') ->assertJsonPath('columns.title', '得物账户') ->assertJsonPath('summary.count', 41); } public function test_filter_options_and_selected_column_export_use_the_authoritative_table(): void { $this->allowPage(); $repository = Mockery::mock(DewuSettlementBillRepository::class); $repository->shouldReceive('accountBillFilterOptions')->once()->andReturn([ 'shops' => ['得物-A店', '得物-B店'], 'bill_items' => ['交易收入', '平台服务费'], ]); $repository->shouldReceive('exportAccountBills')->once()->with( ['store_name' => '得物-A店'], 'record_code', 'asc', )->andReturn([[ 'record_code' => '2000000001248775179', 'store_name' => '得物-A店', 'payload' => ['channel' => '退货退款订单', 'source_channel' => 'DewuTK'], ]]); $this->app->instance(DewuSettlementBillRepository::class, $repository); $this->loginAs() ->withHeader('X-Requested-With', 'XMLHttpRequest') ->get(route('ecommerce-finance.account-bills.filter-options', ['bill_type' => 'dewu'])) ->assertOk() ->assertExactJson([ 'shops' => ['得物-A店', '得物-B店'], 'bill_items' => ['交易收入', '平台服务费'], 'ledger_remarks' => [], ]); $response = $this->loginAs()->get(route('ecommerce-finance.account-bills.export', [ 'bill_type' => 'dewu', 'store_name' => '得物-A店', 'sort' => 'record_code', 'dir' => 'asc', 'columns' => 'payload.channel,payload.source_channel,record_code,store_name', ])); $response->assertOk() ->assertHeader('content-type', 'text/csv; charset=UTF-8') ->assertDownload('dewu_account_bills.csv'); $csv = $response->streamedContent(); $this->assertStringContainsString('渠道,源渠道代码,记录编码,店铺', $csv); $this->assertStringContainsString('退货退款订单,DewuTK,"=""2000000001248775179""",得物-A店', $csv); } public function test_unready_authoritative_table_returns_a_clear_retryable_response(): void { $this->allowPage(); $repository = Mockery::mock(DewuSettlementBillRepository::class); $repository->shouldReceive('paginateAccountBills')->once()->andThrow( new RuntimeException('dewu_authoritative_bills_not_ready') ); $this->app->instance(DewuSettlementBillRepository::class, $repository); $this->loginAs() ->withHeader('X-Requested-With', 'XMLHttpRequest') ->get(route('ecommerce-finance.account-bills.index', ['bill_type' => 'dewu'])) ->assertStatus(503) ->assertJsonPath('message', '得物完整账单尚未完成首次导入,当前不会回退到不完整的聚水潭辅助表。'); } public function test_invalid_date_range_is_rejected_before_reading_the_repository(): void { $this->allowPage(); $repository = Mockery::mock(DewuSettlementBillRepository::class); $repository->shouldNotReceive('paginateAccountBills'); $this->app->instance(DewuSettlementBillRepository::class, $repository); $this->withExceptionHandling() ->loginAs() ->getJson(route('ecommerce-finance.account-bills.index', [ 'bill_type' => 'dewu', 'start' => '2026-09-10', 'end' => '2026-08-12', ])) ->assertStatus(422); } private function allowPage(): void { $this->user->attachPermission( Permission::where('name', 'read-admin-panel')->firstOrFail() ); } }