From 07689f756b383589c6abbf53cda055a3599559a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=9D=E5=8D=9C?= Date: Wed, 11 Mar 2026 04:52:20 +0000 Subject: [PATCH] =?UTF-8?q?=E5=A5=97=E9=A4=90=E7=AE=A1=E7=90=86=EF=BC=9A?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20summaryStats=20sum(subscriptions=5Fcount)?= =?UTF-8?q?=20=E6=9C=AA=E7=9F=A5=E5=88=97=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Admin/PlanController.php | 22 ++++- .../AdminPlanSummaryStatsCountTest.php | 87 +++++++++++++++++++ 2 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 tests/Feature/AdminPlanSummaryStatsCountTest.php diff --git a/app/Http/Controllers/Admin/PlanController.php b/app/Http/Controllers/Admin/PlanController.php index a593e11..40c6f02 100644 --- a/app/Http/Controllers/Admin/PlanController.php +++ b/app/Http/Controllers/Admin/PlanController.php @@ -5,6 +5,8 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Concerns\ResolvesPlatformAdminContext; use App\Http\Controllers\Controller; use App\Models\Plan; +use App\Models\PlatformOrder; +use App\Models\SiteSubscription; use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -112,8 +114,24 @@ class PlanController extends Controller 'published_plans' => (clone $plansQuery)->whereNotNull('published_at')->count(), 'unpublished_plans' => (clone $plansQuery)->whereNull('published_at')->count(), // 治理联动:当前筛选范围内关联订阅/订单总量 - 'subscriptions_count' => (clone $plansQuery)->sum('subscriptions_count'), - 'platform_orders_count' => (clone $plansQuery)->sum('platform_orders_count'), + // 注意:subscriptions_count/platform_orders_count 是 withCount() 的别名列,不能直接 sum('subscriptions_count'), + // 否则 MySQL 会报 Unknown column。 + 'subscriptions_count' => (function () use ($plansQuery) { + $planIds = (clone $plansQuery)->pluck('id')->all(); + if (count($planIds) === 0) { + return 0; + } + + return (int) SiteSubscription::query()->whereIn('plan_id', $planIds)->count(); + })(), + 'platform_orders_count' => (function () use ($plansQuery) { + $planIds = (clone $plansQuery)->pluck('id')->all(); + if (count($planIds) === 0) { + return 0; + } + + return (int) PlatformOrder::query()->whereIn('plan_id', $planIds)->count(); + })(), ], 'statusLabels' => $this->statusLabels(), 'billingCycleLabels' => $this->billingCycleLabels(), diff --git a/tests/Feature/AdminPlanSummaryStatsCountTest.php b/tests/Feature/AdminPlanSummaryStatsCountTest.php new file mode 100644 index 0000000..cdb1657 --- /dev/null +++ b/tests/Feature/AdminPlanSummaryStatsCountTest.php @@ -0,0 +1,87 @@ +seed(); + + $this->post('/admin/login', [ + 'email' => 'platform.admin@demo.local', + 'password' => 'Platform@123456', + ])->assertRedirect('/admin'); + } + + public function test_plan_index_page_can_show_summary_stats_without_unknown_column_error(): void + { + $this->loginAsPlatformAdmin(); + + $merchant = Merchant::query()->firstOrFail(); + + $planA = Plan::query()->create([ + 'code' => 'plan_summary_a', + 'name' => '套餐A', + 'billing_cycle' => 'monthly', + 'price' => 10, + 'list_price' => 10, + 'status' => 'active', + 'sort' => 10, + 'published_at' => now(), + ]); + + $planB = Plan::query()->create([ + 'code' => 'plan_summary_b', + 'name' => '套餐B', + 'billing_cycle' => 'monthly', + 'price' => 20, + 'list_price' => 20, + 'status' => 'active', + 'sort' => 20, + 'published_at' => now(), + ]); + + SiteSubscription::query()->create([ + 'merchant_id' => $merchant->id, + 'plan_id' => $planA->id, + 'subscription_no' => 'SUB_PLAN_SUMMARY_0001', + 'status' => 'active', + 'starts_at' => now(), + 'ends_at' => now()->addMonth(), + ]); + + PlatformOrder::query()->create([ + 'merchant_id' => $merchant->id, + 'plan_id' => $planA->id, + 'order_no' => 'PO_PLAN_SUMMARY_0001', + 'order_type' => 'new_purchase', + 'status' => 'activated', + 'payment_status' => 'paid', + 'plan_name' => $planA->name, + 'billing_cycle' => $planA->billing_cycle, + 'period_months' => 1, + 'quantity' => 1, + 'payable_amount' => 10, + 'paid_amount' => 10, + 'placed_at' => now(), + 'paid_at' => now(), + 'activated_at' => now(), + 'meta' => [], + ]); + + $this->get('/admin/plans') + ->assertOk() + ->assertSee('套餐管理') + ->assertSee('1'); + } +}