[ 'driver' => 'sqlite', 'database' => ':memory:', 'prefix' => '', ], 'upstream_mirrors.connection' => 'business_mirror', 'upstream_mirrors.datasets' => [ StoreReceivingDewuBillMirrorRepository::DATASET => [ 'source_key' => 'jiansun', 'schema' => 'dbo', 'object' => 'jst_originalBillInfo', 'target' => 'js_jst_dewu_receiving_bill_rows', 'keys' => ['Id'], 'fixed_filters' => ['channel' => StoreReceivingDewuBillMirrorRepository::SOURCE_CHANNELS], ], StoreReceivingAlipayBillMirrorRepository::SHOP_DATASET => [ 'source_key' => 'operations_replica', 'schema' => 'rpt', 'object' => 'jst_shopInfo', 'target' => 'ops_jst_shop_info', 'keys' => ['Id'], ], ], ]); DB::purge('business_mirror'); $schema = Schema::connection('business_mirror'); $schema->create('business_mirror_table_states', function (Blueprint $table): void { $table->string('dataset_key')->primary(); $table->dateTime('initial_completed_at')->nullable(); $table->string('status')->nullable(); $table->dateTime('last_succeeded_at')->nullable(); $table->unsignedBigInteger('mirror_row_count')->nullable(); $table->boolean('mirror_row_count_is_exact')->default(false); }); $schema->create('js_jst_dewu_receiving_bill_rows', function (Blueprint $table): void { $table->integer('Id'); $table->integer('shop_id')->nullable(); foreach (['channel', 'primary_key', 'fee_name', 'inout_type', 'p_auto_id', 'shop_i_id', 'shop_sku_id', 'sku_id', 'so_id', 'combine_type'] as $column) { $table->string($column)->nullable(); } $table->dateTime('fee_time')->nullable(); $table->dateTime('createTime')->nullable(); $table->dateTime('updateTime')->nullable(); $table->bigInteger('auto_id')->nullable(); $table->decimal('amount', 20, 6)->nullable(); }); $schema->create('ops_jst_shop_info', function (Blueprint $table): void { $table->integer('Id'); $table->integer('shop_id')->nullable(); $table->string('shop_name')->nullable(); }); $source = new StoreReceivingAlipayBillMirrorRepository( new BusinessMirrorDatasetRegistry(), new GenericBusinessMirrorRepository(app('db')), ); $this->repository = new StoreReceivingDewuBillMirrorRepository($source); $this->markReady(); } public function test_it_reads_all_three_dewu_channels_and_excludes_deposit_rows(): void { DB::connection('business_mirror')->table('ops_jst_shop_info')->insert([ ['Id' => 10, 'shop_id' => 7, 'shop_name' => '得物-测试店'], ['Id' => 11, 'shop_id' => 8, 'shop_name' => '其他店'], ]); DB::connection('business_mirror')->table('js_jst_dewu_receiving_bill_rows')->insert([ $this->row(1, 7, '2026-09-13 18:48:12', '1', 21.00, '交易收入', 'Dewu'), $this->row(2, 7, '2026-09-13 19:00:00', '-1', 18.07, '退款', 'DewuTK'), $this->row(3, 7, '2026-09-13 19:30:00', '-1', 3.50, '其他费用', 'DewuKJ'), $this->row(4, 8, '2026-09-13 20:00:00', '1', 100.00, '保证金充值', 'Dewubzj'), ]); $result = $this->repository->paginate([], 'occurred_at', 'desc', 1, 10); $rowsBySource = collect($result['data'])->keyBy('payload.source_channel'); $this->assertSame(3, $result['total']); $this->assertSame(['DewuKJ', 'DewuTK', 'Dewu'], collect($result['data'])->pluck('payload.source_channel')->all()); $this->assertSame('得物', $rowsBySource['Dewu']['payload']['channel']); $this->assertSame('退货退款订单', $rowsBySource['DewuTK']['payload']['channel']); $this->assertSame('扣减其他费用明细', $rowsBySource['DewuKJ']['payload']['channel']); $this->assertSame('得物-测试店', $rowsBySource['DewuTK']['store_name']); $this->assertSame('110211-ORDER-2', $rowsBySource['DewuTK']['order_no']); $this->assertSame('支出', $rowsBySource['DewuTK']['payload']['business_type']); $this->assertSame('SKU-2', $rowsBySource['DewuTK']['payload']['goods_no']); $this->assertSame('聚水潭', $rowsBySource['DewuTK']['modifier']); $this->assertSame(21.0, $result['summary']['income']); $this->assertSame(21.57, $result['summary']['expense']); $this->assertSame(-0.57, $result['summary']['balance']); } public function test_filters_options_export_and_exact_total_use_the_fixed_channel_slice(): void { DB::connection('business_mirror')->table('ops_jst_shop_info')->insert([ ['Id' => 10, 'shop_id' => 7, 'shop_name' => '得物-A店'], ['Id' => 11, 'shop_id' => 8, 'shop_name' => '得物-B店'], ]); DB::connection('business_mirror')->table('js_jst_dewu_receiving_bill_rows')->insert([ $this->row(1, 7, '2026-08-12 09:00:00', '1', 22.80, '交易收入', 'Dewu'), $this->row(2, 8, '2026-08-13 09:00:00', '-1', 0.14, '退货退款', 'DewuTK'), $this->row(3, 8, '2026-08-14 09:00:00', '-1', 1.26, '扣减其他费用', 'DewuKJ'), $this->row(4, 8, '2026-08-15 09:00:00', '-1', 8.88, '保证金扣减', 'Dewubzj'), ]); $connection = DB::connection('business_mirror'); $connection->table('business_mirror_table_states') ->where('dataset_key', StoreReceivingDewuBillMirrorRepository::DATASET) ->update(['mirror_row_count' => 3, 'mirror_row_count_is_exact' => true]); $connection->enableQueryLog(); $connection->flushQueryLog(); $unfiltered = $this->repository->paginate([], 'record_code', 'asc', 1, 10); $filtered = $this->repository->paginate([ 'store_name' => 'A店', 'bill_item' => '交易', 'start' => '2026-08-12', 'end' => '2026-08-12', 'keyword' => '110211-ORDER-1', ], 'record_code', 'asc', 1, 10); $options = $this->repository->filterOptions(); $export = iterator_to_array($this->repository->exportRows(['bill_item' => '扣减其他费用'])); $this->assertSame(3, $unfiltered['total']); $this->assertSame(1, $filtered['total']); $this->assertSame('200000000000000001', $filtered['data'][0]['record_code']); $this->assertSame(['得物-A店', '得物-B店'], $options['shops']); $this->assertSame(['交易收入', '扣减其他费用', '退货退款'], $options['bill_items']); $this->assertCount(1, $export); $this->assertSame('200000000000000003', $export[0]['record_code']); $this->assertSame('扣减其他费用明细', $export[0]['payload']['channel']); $this->assertSame('DewuKJ', $export[0]['payload']['source_channel']); $targetQueries = array_filter( $connection->getQueryLog(), static fn (array $query): bool => str_contains($query['query'], 'js_jst_dewu_receiving_bill_rows'), ); $this->assertNotEmpty($targetQueries); $this->assertNotEmpty(array_filter( $targetQueries, static fn (array $query): bool => str_contains($query['query'], '"b"."channel" in (?, ?, ?)'), )); $connection->disableQueryLog(); } private function markReady(): void { foreach ([StoreReceivingDewuBillMirrorRepository::DATASET, StoreReceivingAlipayBillMirrorRepository::SHOP_DATASET] as $dataset) { DB::connection('business_mirror')->table('business_mirror_table_states')->insert([ 'dataset_key' => $dataset, 'initial_completed_at' => '2026-09-14 09:00:00', 'status' => 'succeeded', 'last_succeeded_at' => '2026-09-14 09:00:00', ]); } } private function row( int $id, int $shopId, string $time, string $direction, float $amount, string $feeName, string $channel, ): array { return [ 'Id' => $id, 'shop_id' => $shopId, 'channel' => $channel, 'primary_key' => 'KEY-' . $id, 'fee_name' => $feeName, 'inout_type' => $direction, 'p_auto_id' => 'P-' . $id, 'shop_i_id' => 'ITEM-' . $id, 'shop_sku_id' => 'SHOP-SKU-' . $id, 'sku_id' => 'SKU-' . $id, 'so_id' => '110211-ORDER-' . $id, 'combine_type' => 'normal', 'fee_time' => $time, 'createTime' => '2026-09-14 13:00:48', 'updateTime' => '2026-09-14 13:02:32', 'auto_id' => 200000000000000000 + $id, 'amount' => $amount, ]; } }