diff --git a/app/Livewire/Admin/Maintenance.php b/app/Livewire/Admin/Maintenance.php index b066c30..afe3de8 100644 --- a/app/Livewire/Admin/Maintenance.php +++ b/app/Livewire/Admin/Maintenance.php @@ -129,10 +129,13 @@ class Maintenance extends Component ['email' => $customer->email], ); if ($delivery->wasRecentlyCreated) { + // The ledger row (created here) is the idempotency marker so we + // queue at most once per customer. sent_at stays null until the + // mail is actually delivered — a MessageSent listener could stamp + // it later; we never claim delivery merely on dispatch. Mail::to($customer->email) ->locale($customer->locale ?: config('app.locale')) ->queue(new MaintenanceAnnouncementMail($window, $customer)); - $delivery->update(['sent_at' => now()]); } } } diff --git a/app/Livewire/Admin/Settings.php b/app/Livewire/Admin/Settings.php index a75a330..df0865b 100644 --- a/app/Livewire/Admin/Settings.php +++ b/app/Livewire/Admin/Settings.php @@ -49,6 +49,15 @@ class Settings extends Component 'name' => 'required|string|max:255', 'email' => 'required|email|max:255|unique:users,email,'.$user->id, ]); + + // An operator email must never collide with a customer's — that would + // block the customer from ever obtaining a portal login (ensureUser). + if (Customer::query()->where('email', $data['email'])->exists()) { + $this->addError('email', __('admin_settings.is_customer')); + + return; + } + $user->update($data); $this->dispatch('notify', message: __('admin_settings.account_saved')); }