[ 'driver' => 'sqlite', 'database' => ':memory:', 'prefix' => '', ], 'upstream_mirrors.connection' => 'business_mirror', 'upstream_mirrors.datasets' => [ CourierInformationMirrorRepository::DATASET_KEY => $this->definition('wp_express', 'js_wp_express', ['Id'], 'modified'), CourierInformationMirrorRepository::NETWORK_DATASET_KEY => $this->definition('wp_express_expNet', 'js_wp_express_exp_net', ['id']), CourierInformationMirrorRepository::ACCOUNT_DATASET_KEY => $this->definition('wp_express_account', 'js_wp_express_account', ['Id']), CourierInformationMirrorRepository::LOG_DATASET_KEY => $this->definition('wp_express_extension', 'js_wp_express_extension', ['Id'], 'modifyTime'), ], ]); DB::purge('business_mirror'); Schema::connection('business_mirror')->create('business_mirror_table_states', function (Blueprint $table): void { $table->string('dataset_key')->primary(); $table->string('status')->nullable(); $table->string('run_mode')->nullable(); $table->json('cursor')->nullable(); $table->json('high_watermark')->nullable(); $table->dateTime('initial_completed_at')->nullable(); $table->dateTime('last_succeeded_at')->nullable(); $table->unsignedBigInteger('mirror_row_count')->default(0); }); $this->createExpressTable(); $this->createRelatedTables(); $this->repository = new CourierInformationMirrorRepository( new BusinessMirrorDatasetRegistry(), new GenericBusinessMirrorRepository(app('db')), ); } public function test_it_filters_and_pages_mirrored_courier_records(): void { $this->markReady(2); $this->insertExpress(1, ['expcode' => 'SF', 'expname' => '顺丰', 'status' => 1]); $this->insertExpress(2, ['expcode' => 'YD', 'expname' => '韵达', 'status' => 0]); $result = $this->repository->paginate([ 'expcode' => 'SF', 'expname' => '', 'undefined1' => '', 'undefined2' => '', 'undefined3' => '', 'tradebtime_from' => '', 'tradebtime_to' => '', 'status' => '1', ], 1, 1); $this->assertSame(1, $result['total']); $this->assertSame('SF', $result['data'][0]->expcode); $this->assertTrue($this->repository->available()); $this->assertTrue($this->repository->ready()); } public function test_it_reads_networks_and_accounts_by_courier_code(): void { $this->markReady(1); $this->markDatasetReady(CourierInformationMirrorRepository::NETWORK_DATASET_KEY); $this->markDatasetReady(CourierInformationMirrorRepository::ACCOUNT_DATASET_KEY); $this->markDatasetReady(CourierInformationMirrorRepository::LOG_DATASET_KEY); DB::connection('business_mirror')->table('js_wp_express_exp_net')->insert([ '_mirror_key' => 'network-1', 'id' => 1, 'expid' => 1, 'expcode' => 'SF', 'netname' => '浦东网点', ]); DB::connection('business_mirror')->table('js_wp_express_account')->insert([ '_mirror_key' => 'account-1', 'Id' => 1, 'expcode' => 'SF', 'accountName' => '顺丰账户', ]); DB::connection('business_mirror')->table('js_wp_express_extension')->insert([ '_mirror_key' => 'log-1', 'Id' => 1, 'expcode' => 'SF', 'doTime' => 2, 'createTime' => '2026-08-28 10:00:00', 'modifyTime' => '2026-08-28 10:00:00', ]); $networks = $this->repository->paginateNetworks('SF', 1, 20); $accounts = $this->repository->paginateAccounts('SF', 1, 20); $logs = $this->repository->paginateLogs('SF', 1, 20); $this->assertSame(1, $networks['total']); $this->assertSame('浦东网点', $networks['data'][0]->netname); $this->assertSame(1, $accounts['total']); $this->assertSame('顺丰账户', $accounts['data'][0]->accountName); $this->assertSame(1, $logs['total']); $this->assertSame(2, $logs['data'][0]->doTime); } public function test_it_reads_esign_accounts_from_the_dzqzjbr_field(): void { $this->markReady(2); $this->insertExpress(1, [ 'expname' => '常州圆通其他', 'dzqzjbr' => '13800000001', ]); $this->insertExpress(2, [ 'expname' => '没有账号的快递', 'dzqzjbr' => null, ]); $accounts = $this->repository->signingAccountsByName([ '常州圆通其他', '没有账号的快递', ]); $this->assertSame(['常州圆通其他' => '13800000001'], $accounts); } public function test_it_returns_distinct_non_empty_courier_names_from_mirror_data(): void { $this->markReady(4); $this->insertExpress(1, ['expname' => '顺丰']); $this->insertExpress(2, ['expname' => '']); $this->insertExpress(3, ['expname' => '顺丰']); $this->insertExpress(4, ['expname' => '韵达']); $this->assertSame(['顺丰', '韵达'], $this->repository->names()); } private function createExpressTable(): void { Schema::connection('business_mirror')->create('js_wp_express', function (Blueprint $table): void { $table->string('_mirror_key')->primary(); $table->integer('Id'); foreach (['expcode', 'expname', 'outcode', 'scexpcode', 'paymethod', 'signcom', 'signmode', 'linker', 'linkmobile', 'paytype', 'undefined1', 'undefined2', 'undefined3', 'undefinedtype', 'undefined4', 'undefined5', 'dzqzjbr', 'guid', 'exp_properties'] as $column) { $table->string($column)->nullable(); } foreach (['status', 'addvalidsgn', 'kuaiyunsgn', 'autonosgn', 'packnosgn', 'skucountsplitsgn', 'weight0sgn', 'volume0sgn', 'handnosgn', 'decryptsgn', 'pj1sgn', 'is_delete'] as $column) { $table->integer($column)->nullable(); } foreach (['stopdate', 'tradebtime', 'tradeetime', 'modified'] as $column) { $table->dateTime($column)->nullable(); } }); } private function createRelatedTables(): void { Schema::connection('business_mirror')->create('js_wp_express_exp_net', function (Blueprint $table): void { $table->string('_mirror_key')->primary(); $table->integer('id'); $table->integer('expid')->nullable(); foreach (['expcode', 'netcode', 'netno', 'netname', 'isbill', 'province', 'city', 'area', 'town', 'address', 'linker', 'linkermobile', 'status', 'apitype', 'apipltmname', 'created', 'expnum'] as $column) { $table->string($column)->nullable(); } }); Schema::connection('business_mirror')->create('js_wp_express_account', function (Blueprint $table): void { $table->string('_mirror_key')->primary(); $table->integer('Id'); foreach (['expcode', 'expname', 'accountType', 'account', 'accountName', 'accountkhh', 'createTime', 'invoice', 'erpId', 'erpAccountId'] as $column) { $table->string($column)->nullable(); } }); Schema::connection('business_mirror')->create('js_wp_express_extension', function (Blueprint $table): void { $table->string('_mirror_key')->primary(); $table->integer('Id'); $table->string('expcode')->nullable(); $table->integer('doTime')->nullable(); $table->dateTime('createTime')->nullable(); $table->dateTime('modifyTime')->nullable(); }); } private function insertExpress(int $id, array $overrides): void { DB::connection('business_mirror')->table('js_wp_express')->insert(array_merge([ '_mirror_key' => 'express-' . $id, 'Id' => $id, 'expcode' => 'EXP-' . $id, 'expname' => '测试快递', 'status' => 1, 'modified' => '2026-08-28 10:00:00', ], $overrides)); } private function markReady(int $rows): void { $this->markDatasetReady(CourierInformationMirrorRepository::DATASET_KEY, $rows); } private function markDatasetReady(string $key, int $rows = 1): void { DB::connection('business_mirror')->table('business_mirror_table_states')->insert([ 'dataset_key' => $key, 'status' => 'succeeded', 'initial_completed_at' => '2026-08-28 10:00:00', 'last_succeeded_at' => '2026-08-28 10:00:00', 'mirror_row_count' => $rows, ]); } private function definition(string $object, string $target, array $keys, ?string $watermark = null): array { return [ 'source_key' => 'jiansun', 'schema' => 'dbo', 'object' => $object, 'target' => $target, 'keys' => $keys, 'watermark' => $watermark, ]; } }