From 75d64195d65d6fb46ed7b6dd884b0f9965869c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=9D=E5=8D=9C?= Date: Mon, 16 Mar 2026 23:16:25 +0800 Subject: [PATCH] chore(governance): block batch mark activated when reconcile/refund inconsistent --- .../Admin/PlatformOrderController.php | 5 +++ app/Support/PlatformOrderToolsGuard.php | 3 ++ ...ActivatedReceiptStatusFilterFieldsTest.php | 5 ++- ...vatedReconcileMismatchFilterFieldsTest.php | 3 +- ...dShouldBlockWhenRefundInconsistentTest.php | 38 +++++++++++++++++++ ...houldDisableWhenRefundInconsistentTest.php | 37 ++++++++++++++++++ 6 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 tests/Feature/AdminPlatformOrderBatchMarkActivatedShouldBlockWhenRefundInconsistentTest.php create mode 100644 tests/Feature/AdminPlatformOrderIndexBatchMarkActivatedButtonShouldDisableWhenRefundInconsistentTest.php diff --git a/app/Http/Controllers/Admin/PlatformOrderController.php b/app/Http/Controllers/Admin/PlatformOrderController.php index 0505003..402beb7 100644 --- a/app/Http/Controllers/Admin/PlatformOrderController.php +++ b/app/Http/Controllers/Admin/PlatformOrderController.php @@ -1884,6 +1884,11 @@ class PlatformOrderController extends Controller if ((string) ($filters['syncable_only'] ?? '') === '1') { return redirect()->back()->with('warning', '当前已勾选「只看可同步」:该集合语义为“已生效(activated)+未同步”,与本动作处理的“待处理(pending)”互斥。请先取消只看可同步后再执行。'); } + + // 治理优先:当筛选集合命中“对账不一致/退款不一致”时,不允许直接批量生效 + if ((string) ($filters['reconcile_mismatch'] ?? '') === '1' || (string) ($filters['refund_inconsistent'] ?? '') === '1') { + return redirect()->back()->with('warning', '当前筛选集合包含「对账不一致/退款不一致」订单,为避免带病推进,请先完成金额/状态治理(补回执/核对退款/修正状态)后再执行批量仅标记为已生效。'); + } } // 防误操作:scope=all 需要二次确认 diff --git a/app/Support/PlatformOrderToolsGuard.php b/app/Support/PlatformOrderToolsGuard.php index a1641f9..f64c346 100644 --- a/app/Support/PlatformOrderToolsGuard.php +++ b/app/Support/PlatformOrderToolsGuard.php @@ -132,6 +132,9 @@ class PlatformOrderToolsGuard if ((string) ($filters['syncable_only'] ?? '') === '1') { return '当前已勾选「只看可同步」:该集合语义为“已生效(activated)+未同步”,与本动作处理的“待处理(pending)”互斥。请先取消只看可同步后再执行。'; } + if (((string) ($filters['reconcile_mismatch'] ?? '') === '1') || ((string) ($filters['refund_inconsistent'] ?? '') === '1')) { + return '当前集合包含「对账不一致/退款不一致」治理集合:建议先完成金额/状态治理(补回执/核对退款/修正状态)后再批量生效。'; + } return ''; } diff --git a/tests/Feature/AdminPlatformOrderBatchMarkActivatedReceiptStatusFilterFieldsTest.php b/tests/Feature/AdminPlatformOrderBatchMarkActivatedReceiptStatusFilterFieldsTest.php index d237d72..e64a223 100644 --- a/tests/Feature/AdminPlatformOrderBatchMarkActivatedReceiptStatusFilterFieldsTest.php +++ b/tests/Feature/AdminPlatformOrderBatchMarkActivatedReceiptStatusFilterFieldsTest.php @@ -73,7 +73,10 @@ class AdminPlatformOrderBatchMarkActivatedReceiptStatusFilterFieldsTest extends $res->assertRedirect(); + // 口径升级:批量生效不再允许在“收费闭环缺口/需治理”的集合上直接推进 + $res->assertSessionHas('warning'); + $order->refresh(); - $this->assertSame('activated', $order->status); + $this->assertSame('pending', $order->status); } } diff --git a/tests/Feature/AdminPlatformOrderBatchMarkActivatedReconcileMismatchFilterFieldsTest.php b/tests/Feature/AdminPlatformOrderBatchMarkActivatedReconcileMismatchFilterFieldsTest.php index 1e2ea23..53e7d8e 100644 --- a/tests/Feature/AdminPlatformOrderBatchMarkActivatedReconcileMismatchFilterFieldsTest.php +++ b/tests/Feature/AdminPlatformOrderBatchMarkActivatedReconcileMismatchFilterFieldsTest.php @@ -77,8 +77,9 @@ class AdminPlatformOrderBatchMarkActivatedReconcileMismatchFilterFieldsTest exte ]); $res->assertRedirect(); + $res->assertSessionHas('warning'); $order->refresh(); - $this->assertSame('activated', $order->status); + $this->assertSame('pending', $order->status); } } diff --git a/tests/Feature/AdminPlatformOrderBatchMarkActivatedShouldBlockWhenRefundInconsistentTest.php b/tests/Feature/AdminPlatformOrderBatchMarkActivatedShouldBlockWhenRefundInconsistentTest.php new file mode 100644 index 0000000..1ea0070 --- /dev/null +++ b/tests/Feature/AdminPlatformOrderBatchMarkActivatedShouldBlockWhenRefundInconsistentTest.php @@ -0,0 +1,38 @@ +seed(); + + $this->post('/admin/login', [ + 'email' => 'platform.admin@demo.local', + 'password' => 'Platform@123456', + ])->assertRedirect('/admin'); + } + + public function test_batch_mark_activated_should_block_when_refund_inconsistent_is_set(): void + { + $this->loginAsPlatformAdmin(); + + $res = $this->post('/admin/platform-orders/batch-mark-activated', [ + 'scope' => 'filtered', + 'payment_status' => 'paid', + 'status' => 'pending', + 'sync_status' => 'unsynced', + 'refund_inconsistent' => '1', + 'limit' => 50, + ]); + + $res->assertRedirect(); + $res->assertSessionHas('warning'); + } +} diff --git a/tests/Feature/AdminPlatformOrderIndexBatchMarkActivatedButtonShouldDisableWhenRefundInconsistentTest.php b/tests/Feature/AdminPlatformOrderIndexBatchMarkActivatedButtonShouldDisableWhenRefundInconsistentTest.php new file mode 100644 index 0000000..35b33f9 --- /dev/null +++ b/tests/Feature/AdminPlatformOrderIndexBatchMarkActivatedButtonShouldDisableWhenRefundInconsistentTest.php @@ -0,0 +1,37 @@ +seed(); + + $this->post('/admin/login', [ + 'email' => 'platform.admin@demo.local', + 'password' => 'Platform@123456', + ])->assertRedirect('/admin'); + } + + public function test_batch_mark_activated_button_should_disable_when_refund_inconsistent_is_set_even_if_paid_pending(): void + { + $this->loginAsPlatformAdmin(); + + $res = $this->get('/admin/platform-orders?payment_status=paid&status=pending&sync_status=unsynced&refund_inconsistent=1'); + $res->assertOk(); + + $html = (string) $res->getContent(); + + $this->assertStringContainsString('批量仅标记为已生效(当前筛选范围)', $html); + $this->assertStringContainsString('data-role="batch-mark-activated-blocked-hint"', $html); + $this->assertStringContainsString('退款不一致', $html); + + $this->assertTrue(str_contains($html, 'type="submit" disabled') || str_contains($html, 'disabled="disabled"')); + } +}