Admin subscriptions: batch mark expired with safety guards

This commit is contained in:
萝卜
2026-03-17 00:27:04 +08:00
parent 0e8a9797b9
commit 7b143e1a11
6 changed files with 271 additions and 1 deletions

View File

@@ -384,6 +384,43 @@ class SiteSubscriptionController extends Controller
return redirect()->back()->with('success', '订阅状态已更新:' . ($this->statusLabels()[$subscription->status] ?? $subscription->status));
}
public function batchMarkExpired(Request $request): \Illuminate\Http\RedirectResponse
{
$this->ensurePlatformAdmin($request);
// 仅支持在“已过期expiry=expired集合”上执行避免误把正常订阅批量标记为已过期。
$filters = [
'status' => trim((string) $request->input('status', '')),
'keyword' => trim((string) $request->input('keyword', '')),
'merchant_id' => trim((string) $request->input('merchant_id', '')),
'plan_id' => trim((string) $request->input('plan_id', '')),
'expiry' => trim((string) $request->input('expiry', '')),
];
if ((string) ($filters['expiry'] ?? '') !== 'expired') {
return redirect()->back()->with('warning', '为避免误操作批量标记已过期仅允许在「已过期expiry=expired」集合视图下执行。');
}
// 防误操作:需要二次确认
if ((string) $request->input('confirm', '') !== 'YES') {
return redirect()->back()->with('warning', '为避免误操作,请在确认框输入 YES 后再批量标记已过期。');
}
$query = $this->applyFilters(SiteSubscription::query(), $filters);
// 再加一道硬条件ends_at 必须 < now与 expiry=expired 一致)
$query->whereNotNull('ends_at')->where('ends_at', '<', now());
// 仅把“非已过期”的订阅更新为 expired
$affected = (clone $query)
->where('status', '!=', 'expired')
->update([
'status' => 'expired',
]);
return redirect()->back()->with('success', '已批量标记已过期:' . (int) $affected . ' 条。');
}
protected function applyFilters(Builder $query, array $filters): Builder
{
return $query