where('type', 'downgrade') ->where('status', 'pending') ->with('customer') ->orderBy('id') ->cursor(); foreach ($orders as $order) { $subscription = $contracts->contractOf($order->customer); if ($subscription === null) { continue; } try { // Asked before applying rather than left to ApplyPlanChange's own // refusal, only so that a downgrade sitting out a yearly term does // not write a line into the log every quarter of an hour for a year. if (! PlanChange::evaluate($subscription, (string) $order->plan)->allowedNow) { continue; } $due++; $apply->forOrder($order); // Counted from the order rather than from the returned run: a // contract whose machine is still being built has no resize to // start, and the change has landed all the same. if ($order->fresh()?->status === 'applied') { $applied++; } } catch (Throwable $e) { // One customer's withdrawn package must not stop everybody // else's downgrade from landing. $this->warn("Order {$order->uuid}: {$e->getMessage()}"); } } $this->info("{$due} downgrade(s) due, {$applied} applied."); return self::SUCCESS; } }