option('dry-run'); $ended = 0; $due = SubscriptionAddon::query() ->whereNull('cancelled_at') ->whereNotNull('cancels_at') ->where('cancels_at', '<=', now()) ->with('subscription') ->orderBy('id') ->get(); foreach ($due as $addon) { $this->line(sprintf( ' %s on contract %s', (string) $addon->addon_key, (string) ($addon->subscription?->uuid ?? '—'), )); if ($dryRun) { continue; } try { $bookAddon->cancel($addon); $ended++; } catch (Throwable $e) { // One customer's module must not stop everybody else's from // ending. It stays due and the next tick tries again. $this->warn(" {$addon->uuid}: {$e->getMessage()}"); } } $this->info($dryRun ? "{$due->count()} module(s) due to end. Run without --dry-run to end them." : "{$due->count()} module(s) due, {$ended} ended."); return self::SUCCESS; } }