[ 'driver' => 'sqlite', 'database' => ':memory:', 'prefix' => '', ]]); DB::purge('business_mirror'); Schema::connection('business_mirror')->create('business_mirror_table_states', function ($table): void { $table->string('dataset_key')->primary(); $table->string('status')->nullable(); $table->dateTime('initial_completed_at')->nullable(); $table->dateTime('last_succeeded_at')->nullable(); }); Schema::connection('business_mirror')->create('ops_jst_orders', function ($table): void { $table->integer('Id')->primary(); $table->bigInteger('o_id')->nullable(); $table->string('so_id')->nullable(); $table->string('shop_name')->nullable(); $table->dateTime('order_date')->nullable(); $table->text('labels')->nullable(); $table->text('remark')->nullable(); }); Schema::connection('business_mirror')->create('ops_jst_order_item', function ($table): void { $table->integer('Id')->primary(); $table->bigInteger('o_id')->nullable(); $table->string('sku_id')->nullable(); $table->string('item_status')->nullable(); }); DB::connection('business_mirror')->table('business_mirror_table_states')->insert([ 'dataset_key' => 'operations_replica.rpt.jst_Orders', 'status' => 'succeeded', 'initial_completed_at' => '2026-10-01 00:00:00', 'last_succeeded_at' => '2026-10-04 05:00:00', ]); } protected function tearDown(): void { Carbon::setTestNow(); parent::tearDown(); } public function test_backfills_missing_history_then_refreshes_recent_days(): void { $this->orders([ ['o_id' => 1, 'so_id' => 'A', 'order_date' => '2026-10-01 10:00:00', 'labels' => '标签甲,标签乙'], ['o_id' => 2, 'so_id' => 'B', 'order_date' => '2026-10-02 10:00:00', 'labels' => ''], ['o_id' => 3, 'so_id' => 'C', 'order_date' => '2026-10-03 10:00:00', 'labels' => '标签丙'], ]); $this->artisan('jst-order-labels:sync-daily', [ '--from' => '2026-10-01', '--to' => '2026-10-03', '--company' => $this->company->id, '--refresh-days' => 1, '--json' => true, ])->assertSuccessful(); $rows = JstOrderLabel::query()->where('company_id', $this->company->id)->orderBy('id')->get(); $this->assertCount(4, $rows); $this->assertSame(['标签甲', '标签乙', '(无标签)', '标签丙'], $rows->pluck('label')->all()); $this->assertSame(2, $rows->where('order_no', 'A')->count()); } public function test_does_not_pull_new_data_when_history_source_is_missing(): void { $this->orders([ ['o_id' => 3, 'so_id' => 'C', 'order_date' => '2026-10-03 10:00:00', 'labels' => '标签丙'], ]); $this->artisan('jst-order-labels:sync-daily', [ '--from' => '2026-10-01', '--to' => '2026-10-03', '--company' => $this->company->id, '--refresh-days' => 1, ])->assertFailed(); $this->assertSame(0, JstOrderLabel::query()->where('company_id', $this->company->id)->count()); } public function test_second_run_skips_complete_history_and_only_refreshes_latest_day(): void { $this->orders([ ['o_id' => 1, 'so_id' => 'A', 'order_date' => '2026-10-01 10:00:00', 'labels' => '标签甲'], ['o_id' => 2, 'so_id' => 'B', 'order_date' => '2026-10-02 10:00:00', 'labels' => '标签乙'], ]); app(JstOrderLabelImporter::class)->import( '2026-10-01', '2026-10-01', $this->company->id, true, 'test', ); $oldCreatedAt = JstOrderLabel::query()->where('order_no', 'A')->value('created_at')?->toDateTimeString(); $this->artisan('jst-order-labels:sync-daily', [ '--from' => '2026-10-01', '--to' => '2026-10-02', '--company' => $this->company->id, '--refresh-days' => 1, '--json' => true, ])->assertSuccessful(); $this->assertSame( $oldCreatedAt, JstOrderLabel::query()->where('order_no', 'A')->value('created_at')?->toDateTimeString(), ); $this->assertSame(1, JstOrderLabel::query()->where('order_no', 'B')->count()); } public function test_refuses_to_run_when_source_mirror_is_not_ready(): void { DB::connection('business_mirror')->table('business_mirror_table_states') ->where('dataset_key', 'operations_replica.rpt.jst_Orders') ->update(['status' => 'failed']); $this->orders([ ['o_id' => 1, 'so_id' => 'A', 'order_date' => '2026-10-01 10:00:00', 'labels' => '标签甲'], ]); $this->artisan('jst-order-labels:sync-daily', [ '--from' => '2026-10-01', '--to' => '2026-10-01', '--company' => $this->company->id, ])->assertFailed(); $this->assertSame(0, JstOrderLabel::query()->where('company_id', $this->company->id)->count()); } private function orders(array $rows): void { foreach ($rows as $index => $row) { DB::connection('business_mirror')->table('ops_jst_orders')->insert([ 'Id' => $index + 1, 'o_id' => $row['o_id'], 'so_id' => $row['so_id'], 'shop_name' => '测试店铺', 'order_date' => $row['order_date'], 'labels' => $row['labels'], 'remark' => '', ]); } } }