diff --git a/resources/views/admin/platform_orders/index.blade.php b/resources/views/admin/platform_orders/index.blade.php index f3a8852..62f319c 100644 --- a/resources/views/admin/platform_orders/index.blade.php +++ b/resources/views/admin/platform_orders/index.blade.php @@ -1829,15 +1829,33 @@ + @php + $syncBlockedByGovernanceRow = (bool) ($order->isReconcileMismatch() || $order->isRefundInconsistent()); + $syncBlockedByMissingSubscriptionOnRenewalRow = ((string) ($order->order_type ?? '') === 'renewal') + && ((int) ($order->site_subscription_id ?? 0) <= 0); + + // 最短治理路径:续费缺订阅直接落到“关联订阅”面板。 + $relationFixUrlCompact = \App\Support\BackUrl::withBackAndFragment('/admin/platform-orders/' . $order->id, $selfWithoutBack, 'relation-subscription'); + + $syncBlockedRow = $syncBlockedByGovernanceRow || $syncBlockedByMissingSubscriptionOnRenewalRow; + @endphp
@csrf - +
@if(! $canActivate)
需已支付且订单状态为已生效
@elseif($alreadySynced)
该订单已完成同步(幂等保护)
+ @elseif($syncBlockedRow) +
+ 需先完成治理后再同步 + @if($syncBlockedByMissingSubscriptionOnRenewalRow) + + 去关联订阅 + @endif +
@endif @if($syncError) diff --git a/tests/Feature/AdminPlatformOrderIndexRowActivateSubscriptionButtonShouldDisableWhenGovernanceMismatchTest.php b/tests/Feature/AdminPlatformOrderIndexRowActivateSubscriptionButtonShouldDisableWhenGovernanceMismatchTest.php new file mode 100644 index 0000000..6d596ee --- /dev/null +++ b/tests/Feature/AdminPlatformOrderIndexRowActivateSubscriptionButtonShouldDisableWhenGovernanceMismatchTest.php @@ -0,0 +1,81 @@ +seed(); + + $this->post('/admin/login', [ + 'email' => 'platform.admin@demo.local', + 'password' => 'Platform@123456', + ])->assertRedirect('/admin'); + } + + public function test_row_activate_subscription_button_should_be_disabled_when_reconcile_mismatch(): void + { + $this->loginAsPlatformAdmin(); + + $merchant = Merchant::query()->firstOrFail(); + $plan = Plan::query()->create([ + 'code' => 'po_index_row_sync_disable_reconcile_mismatch_plan', + 'name' => '平台订单列表行级同步订阅禁用(对账不一致)测试套餐', + 'billing_cycle' => 'monthly', + 'price' => 30, + 'list_price' => 30, + 'status' => 'active', + 'sort' => 10, + 'published_at' => now(), + ]); + + // 制造对账不一致:payment_status=paid + payment_summary.total_amount != paid_amount + $order = PlatformOrder::query()->create([ + 'merchant_id' => $merchant->id, + 'plan_id' => $plan->id, + 'order_no' => 'PO_INDEX_ROW_SYNC_DISABLE_RECON_0001', + 'order_type' => 'new_purchase', + 'status' => 'activated', + 'payment_status' => 'paid', + 'plan_name' => $plan->name, + 'billing_cycle' => $plan->billing_cycle, + 'period_months' => 1, + 'quantity' => 1, + 'payable_amount' => 30, + 'paid_amount' => 30, + 'placed_at' => now(), + 'paid_at' => now(), + 'activated_at' => now(), + 'meta' => [ + 'payment_summary' => [ + 'count' => 1, + 'total_amount' => 29, + ], + ], + ]); + + $this->assertTrue($order->isReconcileMismatch()); + + $res = $this->get('/admin/platform-orders'); + $res->assertOk(); + + $html = (string) $res->getContent(); + $this->assertStringContainsString($order->order_no, $html); + + // 断言:该订单所在行的“同步订阅”按钮应被禁用(避免运营在列表页误触) + $pattern = '#/admin/platform-orders/' . $order->id . '/activate-subscription.*?]*disabled#s'; + $this->assertMatchesRegularExpression($pattern, $html); + + // 并且仍应存在最短治理入口(对账:去补回执) + $this->assertStringContainsString('#add-payment-receipt', $html); + } +}