- 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>
97 lines
3.6 KiB
PHP
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,
|
|
]);
|
|
}
|
|
}
|