[ 'driver' => 'sqlite', 'database' => ':memory:', 'prefix' => '', ], 'upstream_mirrors.connection' => 'business_mirror', ]); DB::purge('business_mirror'); $this->createTables(); } public function test_account_bill_page_reads_authoritative_rows_with_filters_and_totals(): void { $this->insertSucceededImport(); $this->insertRow('REC-INCOME', '得物一店', '交易收款', '2026-08-01 00:00:00', '100.00', '0.00', '100.00', 'M-100', 'O-100'); $this->insertRow('REC-EXPENSE', '得物一店', '退款', '2026-08-31 23:59:59', '0.00', '20.00', '-20.00', 'M-200', 'O-200'); $this->insertRow('REC-OTHER', '得物二店', '交易收款', '2026-08-15 12:00:00', '50.00', '0.00', '50.00', 'M-300', 'O-300'); $result = app(DewuSettlementBillRepository::class)->paginateAccountBills([ 'store_name' => '得物一店', 'start' => '2026-08-01', 'end' => '2026-08-31', ], 'occurred_at', 'desc', 1, 10); $this->assertSame(2, $result['total']); $this->assertSame(100.0, $result['summary']['income']); $this->assertSame(20.0, $result['summary']['expense']); $this->assertSame(80.0, $result['summary']['balance']); $this->assertSame('REC-EXPENSE', $result['data'][0]['record_code']); $this->assertSame('M-200', $result['data'][0]['order_no']); $this->assertSame('O-200', $result['data'][0]['payload']['online_order_no']); $this->assertSame('退货退款订单', $result['data'][0]['payload']['channel']); $this->assertSame('DewuTK', $result['data'][0]['payload']['source_channel']); $this->assertSame('2026-08-31 23:59:59', $result['data'][0]['payload']['ship_return_at']); $this->assertNull($result['data'][0]['occurred_at']); $this->assertSame(20.0, $result['data'][0]['amount']); $this->assertSame(-20.0, $result['data'][0]['balance']); $filtered = app(DewuSettlementBillRepository::class)->paginateAccountBills([ 'bill_item' => '退款', 'keyword' => 'O-200', ], 'record_code', 'asc', 1, 10); $this->assertSame(1, $filtered['total']); $this->assertSame('REC-EXPENSE', $filtered['data'][0]['record_code']); $options = app(DewuSettlementBillRepository::class)->accountBillFilterOptions(); $this->assertSame(['得物一店', '得物二店'], $options['shops']); $this->assertSame(['交易收款', '退款'], $options['bill_items']); $export = iterator_to_array(app(DewuSettlementBillRepository::class)->exportAccountBills([ 'bill_item' => '退款', ], 'record_code', 'asc')); $this->assertCount(1, $export); $this->assertSame('REC-EXPENSE', $export[0]['record_code']); } public function test_account_bill_page_fails_closed_until_a_successful_import_exists(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessage('dewu_authoritative_bills_not_ready'); app(DewuSettlementBillRepository::class)->paginateAccountBills( [], 'occurred_at', 'desc', 1, 10, ); } private function createTables(): void { $schema = Schema::connection('business_mirror'); $schema->create('dewu_settlement_bill_imports', function (Blueprint $table): void { $table->uuid('generation')->primary(); $table->string('status', 32); }); $schema->create('dewu_settlement_bill_rows', function (Blueprint $table): void { $table->string('record_code', 191)->primary(); $table->string('order_no', 191)->nullable(); $table->string('online_order_no', 191)->nullable(); $table->string('custom_remark')->nullable(); $table->string('bill_item')->nullable(); $table->string('store_name')->nullable(); $table->string('order_type')->nullable(); $table->string('goods_name', 1000)->nullable(); $table->string('goods_no', 191)->nullable(); $table->string('quantity', 64)->nullable(); $table->string('channel')->nullable(); $table->string('business_type')->nullable(); $table->decimal('income_amount', 20, 2); $table->decimal('expense_amount', 20, 2); $table->decimal('signed_amount', 20, 2); $table->string('online_real_store')->nullable(); $table->dateTime('order_created_at')->nullable(); $table->dateTime('paid_refunded_at')->nullable(); $table->dateTime('ship_return_at')->nullable(); $table->dateTime('bill_date'); $table->string('settle_status')->nullable(); $table->string('pay_period')->nullable(); $table->dateTime('pulled_at')->nullable(); $table->dateTime('source_updated_at')->nullable(); $table->string('source_modified_by')->nullable(); }); } private function insertSucceededImport(): void { DB::connection('business_mirror')->table('dewu_settlement_bill_imports')->insert([ 'generation' => '11111111-1111-1111-1111-111111111111', 'status' => 'succeeded', ]); } private function insertRow( string $recordCode, string $storeName, string $billItem, string $occurredAt, string $income, string $expense, string $signed, string $orderNo, string $onlineOrderNo, ): void { DB::connection('business_mirror')->table('dewu_settlement_bill_rows')->insert([ 'record_code' => $recordCode, 'order_no' => $orderNo, 'online_order_no' => $onlineOrderNo, 'store_name' => $storeName, 'custom_remark' => '自定义备注', 'bill_item' => $billItem, 'order_type' => '普通订单', 'goods_name' => '测试商品', 'goods_no' => 'SKU-1', 'quantity' => '1', 'channel' => $expense === '0.00' ? '得物' : '退货退款订单', 'business_type' => $expense === '0.00' ? '收入' : '支出', 'income_amount' => $income, 'expense_amount' => $expense, 'signed_amount' => $signed, 'online_real_store' => $storeName, 'ship_return_at' => $occurredAt, 'bill_date' => $occurredAt, 'settle_status' => '已结算', 'pay_period' => '2026-08', 'pulled_at' => '2026-09-01 07:30:00', 'source_updated_at' => '2026-09-01 08:00:00', 'source_modified_by' => '聚胜算', ]); } }