customer(); // Target the ACTIVE package explicitly — a newer failed/deprovisioned // record must not shadow an older active instance (v1: one active/customer). $instance = $customer?->instances()->where('status', 'active')->latest('id')->first(); if ($instance === null) { return $this->redirectRoute('settings', navigate: true); } // Typed confirmation must match the instance subdomain. if (trim($this->confirmName) !== (string) $instance->subdomain) { $this->addError('confirmName', __('settings.cancel_mismatch')); return; } $instance->update([ 'status' => 'cancellation_scheduled', 'cancel_requested_at' => now(), 'service_ends_at' => $this->currentPeriodEnd($instance), ]); return $this->redirectRoute('settings', navigate: true); } /** * End of the current monthly billing period, anchored on the subscription * start (the order date) rather than assuming calendar-month billing. */ private function currentPeriodEnd(Instance $instance): \Illuminate\Support\Carbon { $start = $instance->order?->created_at ?? $instance->created_at ?? now(); // Always add from the immutable start so the billing-day anchor is kept // (chaining addMonth would drift a Jan-31 start to Feb-28 → Mar-28). $months = 1; while ($start->copy()->addMonthsNoOverflow($months)->lessThanOrEqualTo(now())) { $months++; } return $start->copy()->addMonthsNoOverflow($months); } private function customer(): ?Customer { $user = auth()->user(); if (! $user) { return null; } return Customer::query()->where('user_id', $user->id)->first() ?? Customer::query()->where('email', $user->email)->first(); } public function render() { $instance = $this->customer()?->instances()->where('status', 'active')->latest('id')->first(); return view('livewire.confirm-cancel-package', [ 'subdomain' => $instance?->subdomain ?? '', ]); } }