customer; if (! $customer) { return false; } $dedupeKey = sprintf('auto-renew-failed:%d:%s', $invoice->id, now()->toDateString()); if (! Cache::add($dedupeKey, true, now()->endOfDay())) { return false; } $invoice->loadMissing('order'); $name = $service->server_name ?: $service->product?->name ?: 'Dịch vụ'; Notification::notifyCustomer($customer, [ 'type' => AutoRenewFailedMail::SCENARIO, 'title' => 'Tự động gia hạn chưa thành công', 'body' => sprintf( 'Số dư không đủ để tự động gia hạn %s. Cần %s VNĐ, hiện có %s VNĐ. Nạp thêm tiền để hệ thống tự trừ ở lần kiểm tra kế tiếp.', $name, number_format(InvoicePaymentService::outstanding($invoice), 0, ',', '.'), number_format((int) $customer->total, 0, ',', '.'), ), 'link' => '/nap-tien', 'data' => ['invoice_number' => $invoice->invoice_number, 'service_id' => $service->id], ]); if (filled($customer->email) && AutoEmailGate::allows(AutoRenewFailedMail::SCENARIO)) { $this->sendMail($service, $invoice); } return true; } private function sendMail(Service $service, Invoice $invoice): void { try { $template = $this->templates->loadTemplate(AutoRenewFailedMail::SCENARIO); } catch (ModelNotFoundException) { return; } $service->loadMissing('product'); $mail = new AutoRenewFailedMail($service->customer, $service, $invoice); MailLog::create([ 'template_id' => $template->id, 'subject' => $mail->envelope()->subject, 'from_address' => $template->mailConfig()['from_email'] ?? config('mail.from.address'), 'to' => $service->customer->email, 'customer_id' => $service->customer_id, 'message' => $mail->render(), ]); Mail::to($service->customer->email)->queue($mail); } }