From 6790771364ac29095bef11db91060aca24584ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=9D=E5=8D=9C?= Date: Mon, 16 Mar 2026 20:59:52 +0800 Subject: [PATCH] chore(governance): block batch activate when syncable_only conflicts with sync status --- app/Support/PlatformOrderToolsGuard.php | 9 +++++ ...ncableOnlyButSyncStatusNotUnsyncedTest.php | 36 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 tests/Feature/AdminPlatformOrderIndexBatchActivateButtonShouldDisableWhenSyncableOnlyButSyncStatusNotUnsyncedTest.php diff --git a/app/Support/PlatformOrderToolsGuard.php b/app/Support/PlatformOrderToolsGuard.php index c7d21a3..66fc1dd 100644 --- a/app/Support/PlatformOrderToolsGuard.php +++ b/app/Support/PlatformOrderToolsGuard.php @@ -53,6 +53,15 @@ class PlatformOrderToolsGuard if ((string) ($filters['syncable_only'] ?? '') !== '1') { return '请先勾选「只看可同步」再执行批量同步。'; } + // 口径一致:可同步集合语义为 unsynced(未同步且非失败)。 + // 若用户手工叠加了 sync_status=failed/synced 等互斥筛选,按钮应直接禁用,避免误解“当前会同步哪些单”。 + $syncStatus = (string) ($filters['sync_status'] ?? ''); + if ($syncStatus !== '' && $syncStatus !== 'unsynced') { + return '当前已勾选「只看可同步」,但同步状态筛选不是「未同步」。请先切回 sync_status=unsynced(或清空同步状态筛选)后再批量同步。'; + } + if ((string) ($filters['fail_only'] ?? '') === '1' || trim((string) ($filters['sync_error_keyword'] ?? '')) !== '') { + return '当前筛选包含「同步失败/失败原因」。请先治理失败原因或切回未同步集合,再批量同步。'; + } if ((string) ($filters['receipt_status'] ?? '') === 'none') { return '当前集合为「无回执」:建议先补齐支付回执留痕后再批量同步。'; } diff --git a/tests/Feature/AdminPlatformOrderIndexBatchActivateButtonShouldDisableWhenSyncableOnlyButSyncStatusNotUnsyncedTest.php b/tests/Feature/AdminPlatformOrderIndexBatchActivateButtonShouldDisableWhenSyncableOnlyButSyncStatusNotUnsyncedTest.php new file mode 100644 index 0000000..9db8b18 --- /dev/null +++ b/tests/Feature/AdminPlatformOrderIndexBatchActivateButtonShouldDisableWhenSyncableOnlyButSyncStatusNotUnsyncedTest.php @@ -0,0 +1,36 @@ +seed(); + + $this->post('/admin/login', [ + 'email' => 'platform.admin@demo.local', + 'password' => 'Platform@123456', + ])->assertRedirect('/admin'); + } + + public function test_batch_activate_button_should_disable_when_syncable_only_checked_but_sync_status_is_failed(): void + { + $this->loginAsPlatformAdmin(); + + $res = $this->get('/admin/platform-orders?syncable_only=1&sync_status=failed'); + $res->assertOk(); + + $html = (string) $res->getContent(); + + $this->assertStringContainsString('批量同步订阅(当前筛选范围)', $html); + $this->assertStringContainsString('disabled', $html); + $this->assertStringContainsString('data-role="batch-activate-subscriptions-blocked-hint"', $html); + $this->assertStringContainsString('sync_status=unsynced', $html); + } +}