Files
portal-api/app/Jobs/Mail/SendInvoiceMailJob.php
T
baodev0andClaude Opus 5.5 94614d9cb3 feat: khởi tạo/huỷ domain Plesk qua job, gửi mail hoá đơn qua queue, đính kèm triển khai
- ProvisionDnsDomainJob/SuspendDnsDomainJob: tạo domain admin lên Plesk, huỷ = suspend (is_created=3)
- Khách xem zone DNS được gán ở /dich-vu/domain, quản lý bản ghi A/AAAA/CNAME/TXT/MX/SRV
- send-mail hoá đơn đẩy SendInvoiceMailJob, preview + sửa nội dung, ghi mail.order_id
- invoice_attachments.type (payment_proof/deployment)
- CacheService xoá theo SCAN pattern, Redis không persistent mặc định
- Backfill transactions.public_code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:56:18 +07:00

97 lines
3.6 KiB
PHP

<?php
namespace App\Jobs\Mail;
use App\Mail\GenericTemplateMail;
use App\Mail\InvoiceNotificationMail;
use App\Models\Invoice;
use App\Models\Mail as MailLog;
use App\Services\Email\EmailTemplateService;
use App\Services\InvoicePdfService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Throwable;
class SendInvoiceMailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 1;
public function __construct(
public readonly int $invoiceId,
public readonly string $type,
public readonly ?string $message,
public readonly ?string $subject,
public readonly ?string $html,
public readonly ?int $sentBy,
) {}
public function handle(InvoicePdfService $pdfService, EmailTemplateService $templates): void
{
$invoice = Invoice::with('customer')->find($this->invoiceId);
if (!$invoice?->customer?->email) {
return;
}
$mail = null;
try {
$pdf = $pdfService->generate($invoice);
$pdfFileName = $pdfService->generateFileName($invoice);
$mail = $this->html !== null
? $this->editedMail($templates, $pdf, $pdfFileName)
: InvoiceNotificationMail::forInvoice($invoice, $this->type, $this->message, $pdf, $pdfFileName);
$sent = Mail::to($invoice->customer->email)->send($mail);
$this->log($templates, $invoice, $mail, $sent === null ? 'failed' : 'sent');
} catch (Throwable $e) {
Log::error('SendInvoiceMailJob failed', [
'invoice_id' => $invoice->id,
'customer_email' => $invoice->customer->email,
'type' => $this->type,
'error' => $e->getMessage(),
]);
if ($mail) {
$this->log($templates, $invoice, $mail, 'failed');
}
throw $e;
}
}
private function editedMail(EmailTemplateService $templates, string $pdf, string $pdfFileName): GenericTemplateMail
{
return (new GenericTemplateMail(
$this->subject,
$this->html,
$templates->loadTemplate(InvoiceNotificationMail::SCENARIO)->mailConfig(),
InvoiceNotificationMail::SCENARIO,
))->attachData($pdf, $pdfFileName, ['mime' => 'application/pdf']);
}
private function log(EmailTemplateService $templates, Invoice $invoice, Mailable $mail, string $status): void
{
$envelope = $mail->envelope();
$addresses = fn (array $list) => implode(', ', array_map(fn ($a) => is_string($a) ? $a : $a->address, $list));
MailLog::create([
'template_id' => $templates->loadTemplate(InvoiceNotificationMail::SCENARIO)->id,
'subject' => $envelope->subject,
'from_address' => $envelope->from?->address ?? config('mail.from.address'),
'to' => $invoice->customer->email,
'cc' => $addresses($envelope->cc),
'bcc' => $addresses($envelope->bcc),
'customer_id' => $invoice->customer_id,
'order_id' => $invoice->order_id,
'sent_by' => $this->sentBy,
'message' => $mail->render(),
'status' => $status,
]);
}
}