From 462a6fa95c494eb7c082c61d3ab411dd0801aa04 Mon Sep 17 00:00:00 2001 From: WuYongJie <549727955@qq.com> Date: Tue, 8 Sep 2026 21:46:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=94=AF=E4=BB=98=E5=AE=9D?= =?UTF-8?q?=E8=B4=A6=E5=8D=95=E7=BF=BB=E9=A1=B5=E9=87=8D=E5=A4=8D=E5=85=A8?= =?UTF-8?q?=E8=A1=A8=E8=AE=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oreReceivingAlipayBillMirrorRepository.php | 10 ++++-- ...eceivingAlipayBillMirrorRepositoryTest.php | 33 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/modules/EcommerceFinance/Repositories/StoreReceivingAlipayBillMirrorRepository.php b/modules/EcommerceFinance/Repositories/StoreReceivingAlipayBillMirrorRepository.php index b9ae8095..5b7952c1 100644 --- a/modules/EcommerceFinance/Repositories/StoreReceivingAlipayBillMirrorRepository.php +++ b/modules/EcommerceFinance/Repositories/StoreReceivingAlipayBillMirrorRepository.php @@ -40,7 +40,14 @@ class StoreReceivingAlipayBillMirrorRepository $query = $this->billQuery(); $this->applyFilters($query, $filters); - $total = (clone $query)->count(); + $state = $this->mirror->state($dataset) ?? []; + // The synchronizer persists an exact COUNT in the same transaction that + // marks a run successful. Never substitute a database row estimate. + $hasFilters = collect($filters)->contains(static fn (mixed $value): bool => $value !== null && trim((string) $value) !== ''); + $recordedCount = $state['mirror_row_count'] ?? null; + $useRecordedCount = ! $hasFilters && ($state['status'] ?? null) === 'succeeded' + && $recordedCount !== null && ctype_digit((string) $recordedCount); + $total = $useRecordedCount ? (int) $recordedCount : (clone $query)->count(); $summary = $this->summary($query, $filters); $billRows = $query @@ -54,7 +61,6 @@ class StoreReceivingAlipayBillMirrorRepository $rows = collect($billRows) ->map(fn (object $row): array => $this->mapRow($row, $shopNames[(string) $row->shop_id] ?? null)) ->all(); - $state = $this->mirror->state($dataset) ?? []; $income = $summary['income']; $expense = $summary['expense']; diff --git a/tests/Unit/EcommerceFinance/StoreReceivingAlipayBillMirrorRepositoryTest.php b/tests/Unit/EcommerceFinance/StoreReceivingAlipayBillMirrorRepositoryTest.php index f5b6dfae..0b1c3355 100644 --- a/tests/Unit/EcommerceFinance/StoreReceivingAlipayBillMirrorRepositoryTest.php +++ b/tests/Unit/EcommerceFinance/StoreReceivingAlipayBillMirrorRepositoryTest.php @@ -43,6 +43,7 @@ class StoreReceivingAlipayBillMirrorRepositoryTest extends TestCase $table->dateTime('initial_completed_at')->nullable(); $table->string('status')->nullable(); $table->dateTime('last_succeeded_at')->nullable(); + $table->unsignedBigInteger('mirror_row_count')->nullable(); }); $schema->create('ops_jst_original_bill_info', function (Blueprint $table): void { $table->integer('Id'); @@ -160,6 +161,38 @@ class StoreReceivingAlipayBillMirrorRepositoryTest extends TestCase $this->assertSame(['income' => 100.25, 'expense' => 20.10, 'balance' => 80.15, 'count' => 1], $result['summary']); } + public function test_unfiltered_pages_reuse_exact_completed_count_and_observe_the_next_sync(): void + { + $this->markReady(); + $db = DB::connection('business_mirror'); + $db->table('ops_jst_original_bill_info')->insert([ + $this->row(1, 7, '2026-08-01 09:00:00', '1', 10), + $this->row(2, 7, '2026-08-02 09:00:00', '-1', 5), + ]); + $state = $db->table('business_mirror_table_states')->where('dataset_key', StoreReceivingAlipayBillMirrorRepository::DATASET); + $state->update(['mirror_row_count' => 2]); + $db->enableQueryLog(); + $first = $this->repository->paginate([], 'occurred_at', 'desc', 1, 1); + $second = $this->repository->paginate(['store_name' => '', 'start' => null], 'occurred_at', 'desc', 2, 1); + $this->assertSame(2, $first['total']); + $this->assertSame(2, $second['total']); + $this->assertNotSame($first['data'][0]['id'], $second['data'][0]['id']); + $this->assertCount(0, array_filter($db->getQueryLog(), fn ($q) => str_contains(strtolower($q['query']), 'count(*)'))); + $db->disableQueryLog(); + + $db->table('ops_jst_original_bill_info')->insert($this->row(3, 7, '2026-08-03 09:00:00', '1', 4)); + $state->update(['mirror_row_count' => 3, 'last_succeeded_at' => '2026-09-08 09:00:00']); + $this->assertSame(3, $this->repository->paginate([], 'occurred_at', 'desc', 1, 1)['total']); + $this->assertSame(1, $this->repository->paginate(['business_type' => '支出'], 'occurred_at', 'desc', 1, 1)['total']); + + $state->update(['status' => 'running', 'mirror_row_count' => 2]); + $this->assertSame(3, $this->repository->paginate([], 'occurred_at', 'desc', 1, 1)['total']); + $state->update(['status' => 'failed']); + $this->assertSame(3, $this->repository->paginate([], 'occurred_at', 'desc', 1, 1)['total']); + $state->update(['status' => 'succeeded', 'mirror_row_count' => null]); + $this->assertSame(3, $this->repository->paginate([], 'occurred_at', 'desc', 1, 1)['total']); + } + private function markReady(): void { foreach ([StoreReceivingAlipayBillMirrorRepository::DATASET, StoreReceivingAlipayBillMirrorRepository::SHOP_DATASET] as $dataset) { -- 2.47.2