diff --git a/app/Jobs/SendCertificateEmailJob.php b/app/Jobs/SendCertificateEmailJob.php index 32b54e1..b77e99a 100644 --- a/app/Jobs/SendCertificateEmailJob.php +++ b/app/Jobs/SendCertificateEmailJob.php @@ -2,26 +2,69 @@ namespace App\Jobs; +use App\Mail\CertificateReadyMail; use App\Models\Certificate; +use App\Models\EmailLog; use App\Models\Program; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Mail; class SendCertificateEmailJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public int $tries = 3; + public int $tries = 3; public int $backoff = 60; public function __construct(public readonly Certificate $certificate) {} public function handle(): void { - // Implemented in Fasa 8 — email blast + $cert = $this->certificate->refresh(); + $cert->load(['participant', 'program']); + + $email = $cert->participant->email; + + if (! $email) { + return; + } + + try { + Mail::to($email)->send(new CertificateReadyMail($cert)); + + $cert->update([ + 'status' => 'emailed', + 'emailed_at' => now(), + ]); + + EmailLog::create([ + 'program_id' => $cert->program_id, + 'participant_id' => $cert->participant_id, + 'certificate_id' => $cert->id, + 'recipient_email'=> $email, + 'subject' => 'Sijil Digital Program — ' . $cert->program->title, + 'email_type' => 'certificate_ready', + 'status' => 'sent', + 'sent_at' => now(), + ]); + } catch (\Throwable $e) { + EmailLog::create([ + 'program_id' => $cert->program_id, + 'participant_id' => $cert->participant_id, + 'certificate_id' => $cert->id, + 'recipient_email'=> $email, + 'subject' => 'Sijil Digital Program — ' . $cert->program->title, + 'email_type' => 'certificate_ready', + 'status' => 'failed', + 'error_message' => $e->getMessage(), + ]); + + throw $e; + } } public static function dispatchBatch(Program $program): void @@ -29,6 +72,11 @@ class SendCertificateEmailJob implements ShouldQueue $program->certificates() ->whereIn('status', ['generated']) ->whereNull('emailed_at') - ->each(fn($cert) => static::dispatch($cert)); + ->with('participant') + ->each(function (Certificate $cert) { + if ($cert->participant->email) { + static::dispatch($cert); + } + }); } } diff --git a/app/Mail/CertificateReadyMail.php b/app/Mail/CertificateReadyMail.php new file mode 100644 index 0000000..71b10ca --- /dev/null +++ b/app/Mail/CertificateReadyMail.php @@ -0,0 +1,31 @@ +certificate->program->title, + ); + } + + public function content(): Content + { + return new Content( + view: 'emails.certificate-ready', + ); + } +} diff --git a/resources/views/emails/certificate-ready.blade.php b/resources/views/emails/certificate-ready.blade.php new file mode 100644 index 0000000..d0efcc0 --- /dev/null +++ b/resources/views/emails/certificate-ready.blade.php @@ -0,0 +1,87 @@ + + +
+ + +{{ $certificate->program->organizer ?? config('app.name') }}
+Salam sejahtera, {{ $certificate->participant->name }},
+ ++ Terima kasih kerana menghadiri program di bawah. Sijil digital anda telah sedia untuk dimuat turun. +
+ +| Program | +{{ $certificate->program->title }} | +
| Tarikh Program | +{{ $certificate->program->start_date->format('d M Y') }} | +
| No. Sijil | +{{ $certificate->certificate_no }} | +
Klik butang di bawah untuk memuat turun sijil anda:
+ + + ++ Pautan di atas adalah unik untuk anda. Sila simpan emel ini sebagai rujukan. + Jika anda menghadapi sebarang masalah, sila hubungi penganjur program. +
+