fix(plans): prevent deletion of plans with active subscriptions

- Fix bulk delete and individual delete actions using before() hook with halt()
  - Add daily/weekly billing cycle options to plan resource and Polar provider
  - Enhance payment confirmation with dynamic polling and loading states
  - Add graceful handling for deleted plans in subscription display
  - Update Polar provider to support dynamic billing cycles
This commit is contained in:
idevakk
2025-12-07 02:23:14 -08:00
parent 1b438cbf89
commit 5fabec1f9d
7 changed files with 225 additions and 93 deletions

View File

@@ -56,11 +56,13 @@ class PlanResource extends Resource
Select::make('billing_cycle_days')
->label('Billing Cycle')
->options([
1 => 'Daily',
7 => 'Weekly',
30 => 'Monthly',
90 => 'Quarterly',
365 => 'Yearly',
60 => 'Bi-Monthly',
90 => 'Quarterly',
180 => 'Semi-Annual',
365 => 'Yearly',
])
->default(30)
->required(),
@@ -225,8 +227,12 @@ class PlanResource extends Resource
Tables\Filters\SelectFilter::make('billing_cycle_days')
->label('Billing Cycle')
->options([
1 => 'Daily',
7 => 'Weekly',
30 => 'Monthly',
60 => 'Bi-Monthly',
90 => 'Quarterly',
180 => 'Semi-Annual',
365 => 'Yearly',
]),
@@ -239,22 +245,76 @@ class PlanResource extends Resource
ViewAction::make(),
EditAction::make(),
DeleteAction::make()
->before(function (Plan $record) {
// Prevent deletion if plan has active subscriptions
if ($record->subscriptions()->where('status', 'active')->exists()) {
Log::error('Cannot delete plan with active subscriptions');
->requiresConfirmation()
->before(function (DeleteAction $action, Plan $record) {
// Prevent deletion if plan has any subscriptions (active, cancelled, etc.)
if ($record->subscriptions()->exists()) {
Log::warning('Attempted to delete plan with existing subscriptions', [
'plan_id' => $record->id,
'plan_name' => $record->name,
'subscription_count' => $record->subscriptions()->count(),
]);
// Show warning notification
\Filament\Notifications\Notification::make()
->warning()
->title('Cannot Delete Plan')
->body("Plan '{$record->name}' has {$record->subscriptions()->count()} subscription(s). Please cancel or remove all subscriptions first.")
->persistent()
->send();
// Halt the deletion process
$action->halt();
}
})
->action(function (Plan $record) {
// This action will only run if not halted
$record->delete();
// Show success notification
\Filament\Notifications\Notification::make()
->success()
->title('Plan Deleted')
->body("Plan '{$record->name}' has been deleted successfully.")
->send();
}),
])
->toolbarActions([
->bulkActions([
BulkActionGroup::make([
DeleteBulkAction::make()
->before(function ($records) {
->requiresConfirmation()
->before(function (DeleteBulkAction $action, $records) {
foreach ($records as $record) {
if ($record->subscriptions()->where('status', 'active')->exists()) {
Log::error('Cannot delete plan(s) with active subscriptions');
if ($record->subscriptions()->exists()) {
Log::warning('Attempted to bulk delete plan with existing subscriptions', [
'plan_id' => $record->id,
'plan_name' => $record->name,
'subscription_count' => $record->subscriptions()->count(),
]);
\Filament\Notifications\Notification::make()
->warning()
->title('Cannot Delete Plans')
->body("Plan '{$record->name}' has {$record->subscriptions()->count()} subscription(s). Please cancel or remove all subscriptions first.")
->persistent()
->send();
// Halt the bulk deletion process
$action->halt();
return;
}
}
})
->action(function ($records) {
foreach ($records as $record) {
$record->delete();
}
\Filament\Notifications\Notification::make()
->success()
->title('Plans Deleted')
->body(count($records).' plan(s) have been deleted successfully.')
->send();
}),
]),
])