Files
eCert-MBIP/docs/execution-plan.md
Saufi 5b85822b78 chore: initial Laravel 13 project setup for eCert MBIP
- Laravel 13.9 + PHP 8.5 + MySQL
- Bootstrap 5.3 + jQuery 3.7 + Chart.js (replacing Alpine/Tailwind)
- Packages: intervention/image, dompdf, simple-qrcode, league/csv, laravel/breeze, laravel/boost
- 17 database migrations: users, programs, qr_codes, participants, attendances, certificates, questionnaires, email_logs, audit_logs
- 13 Eloquent models with full relationships
- Admin layout (Bootstrap 5 sidebar) + public layout (mobile-first)
- Rate limiters: checkin (60/min), certificate (30/min)
- Admin seeder: admin@mbip.gov.my
- Storage directories + symlink configured

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:44:19 +08:00

13 KiB

eCert MBIP — Execution Plan (Phased)

Pre-requisites (Sebelum Fasa 1)

  • Sahkan "Laravel Boost" — package apa yang dimaksudkan
  • Sahkan MySQL server credentials (host, port, db name, user, password)
  • Sahkan SMTP settings untuk email
  • Sahkan storage path boleh write
  • Sahkan Git SSH key berfungsi ke git.mbip.my

Fasa 1: Foundation & Authentication

Anggaran: 1-2 jam

Tasks

  • Install Laravel 12 via composer create-project
  • Setup .env (DB, queue, mail, app URL)
  • Install Laravel Breeze (Blade stack)
  • Install Composer packages (intervention/image, simple-qrcode, dompdf, league/csv)
  • Buat semua 15 migrations
  • Buat admin layout Blade (sidebar, navbar) dengan Bootstrap 5
  • Buat public layout Blade (mobile-first) dengan Bootstrap 5
  • Setup Queue (database driver → create jobs table)
  • Setup Storage symlink
  • Buat Seeder: admin user
  • Commit: chore: initial Laravel project setup
  • Commit: feat: admin authentication and layout

Files Utama

app/Http/Controllers/Admin/DashboardController.php
resources/views/layouts/admin.blade.php
resources/views/layouts/public.blade.php
resources/views/admin/dashboard.blade.php
database/migrations/* (15 migration files)
database/seeders/AdminSeeder.php

Commands Selepas Fasa 1

php artisan migrate
php artisan db:seed --class=AdminSeeder
php artisan storage:link
php artisan queue:table && php artisan migrate

Manual Test

  • Login admin berjaya
  • Dashboard papar (walaupun kosong)
  • Logout berjaya

Fasa 2: Program Management

Anggaran: 2-3 jam

Tasks

  • ProgramController — CRUD penuh
  • StoreProgramRequest + UpdateProgramRequest — validation
  • Program index view (table + badge status)
  • Program create/edit form
  • Program show view (tab: details, participants, qr, template, questionnaire, stats)
  • Status management (draft → published → closed)
  • Protect delete jika ada kehadiran
  • Commit: feat: program management

Files Utama

app/Http/Controllers/Admin/ProgramController.php
app/Http/Requests/Admin/StoreProgramRequest.php
app/Http/Requests/Admin/UpdateProgramRequest.php
app/Models/Program.php
resources/views/admin/programs/*

Manual Test

  • Tambah program
  • Edit program
  • Tukar status
  • Cuba padam program yang ada kehadiran (mesti gagal)

Fasa 3: QR Code Generation

Anggaran: 1-2 jam

Tasks

  • QrCodeController — generate, show, download
  • QrCodeService — generate token, buat QR image, simpan storage
  • QR code preview dalam admin
  • Download QR sebagai PNG
  • Commit: feat: qr code generation

Files Utama

app/Http/Controllers/Admin/QrCodeController.php
app/Services/QrCodeService.php
app/Models/ProgramQrCode.php
resources/views/admin/programs/qr.blade.php

Manual Test

  • Generate QR code untuk program
  • QR code papar dalam admin
  • Download QR sebagai PNG berjaya
  • Scan QR code → bawa ke /p/{token} (walaupun page belum siap)

Fasa 4: Participant Management & CSV Import

Anggaran: 2-3 jam

Tasks

  • ParticipantController — add manual, import, list, export
  • ParticipantImport service — parse CSV, validate, bulk insert
  • Import summary: berjaya, duplicate, gagal
  • Export CSV senarai peserta
  • Commit: feat: participant management

Files Utama

app/Http/Controllers/Admin/ParticipantController.php
app/Services/ParticipantImportService.php
app/Models/Participant.php
app/Models/ProgramParticipant.php
resources/views/admin/programs/participants/*

CSV Template Headers

name,no_kp,email,phone,agency

Manual Test

  • Tambah peserta manual
  • Import CSV (normal)
  • Import CSV dengan duplicate (summary papar betul)
  • Import CSV dengan row kosong/invalid
  • Export CSV peserta

Fasa 5: Public Check-in Flow

Anggaran: 3-4 jam

Tasks

  • CheckinController — show, staffCheckin, externalRegister
  • AttendanceService — rekod kehadiran, cegah duplicate
  • Public check-in page (mobile-first, Bootstrap 5)
  • Staff check-in form + validation
  • Walk-in registration form + validation
  • Status page selepas check-in
  • Rate limiting pada routes
  • Commit: feat: participant registration and attendance

Files Utama

app/Http/Controllers/Public/CheckinController.php
app/Services/AttendanceService.php
resources/views/public/checkin/*

Manual Test

  • Scan QR → buka page check-in
  • Staff check-in dengan no_kp betul
  • Staff check-in dengan no_kp salah
  • Staff check-in yang sudah hadir (mesej duplicate)
  • Walk-in daftar baru
  • Walk-in dengan no_kp sama → error duplicate
  • Test rate limit (cuba submit banyak kali)

Fasa 6: Questionnaire Management

Anggaran: 3-4 jam

Tasks

  • QuestionnaireSetController — CRUD
  • QuestionController — CRUD, reorder
  • ProgramQuestionnaireController — attach, confirm, detach
  • Public questionnaire form (semua jenis soalan)
  • Submit response + answers
  • Semak sudah jawab (cegah double submit)
  • Commit: feat: questionnaire management

Files Utama

app/Http/Controllers/Admin/QuestionnaireSetController.php
app/Http/Controllers/Admin/QuestionController.php
app/Http/Controllers/Admin/ProgramQuestionnaireController.php
app/Http/Controllers/Public/QuestionnaireController.php
app/Models/QuestionnaireSet.php
app/Models/QuestionnaireQuestion.php
app/Models/QuestionnaireResponse.php
app/Models/QuestionnaireAnswer.php
resources/views/admin/questionnaires/*
resources/views/public/questionnaire/*

Manual Test

  • Cipta questionnaire set
  • Tambah pelbagai jenis soalan
  • Attach questionnaire ke program
  • Confirm questionnaire
  • Peserta boleh akses questionnaire (selepas check-in)
  • Submit soalselidik berjaya
  • Cuba submit semula → error (sudah jawab)

Fasa 7: Certificate Template & Generation

Anggaran: 4-5 jam

Tasks

  • CertificateTemplateController — upload, config, preview, test generate
  • CertificateService — image overlay (Intervention Image), PDF wrap (DOMPDF)
  • Font auto-scale berdasarkan panjang nama
  • Preview template dalam admin
  • Test generate dengan nama sample
  • GenerateCertificateJob — queue job
  • AttendanceCheckController — public semak kehadiran
  • CertificateController — public, show, download gate
  • Certificate gate: soalselidik dijawab + masa download aktif
  • Rekod downloaded_at dan download_count
  • Commit: feat: certificate template upload
  • Commit: feat: certificate generation and download

Files Utama

app/Http/Controllers/Admin/CertificateTemplateController.php
app/Http/Controllers/Public/CertificateController.php
app/Http/Controllers/Public/AttendanceCheckController.php
app/Services/CertificateService.php
app/Jobs/GenerateCertificateJob.php
app/Models/Certificate.php
app/Models/CertificateTemplate.php
resources/views/admin/programs/template/*
resources/views/public/certificate/*
resources/fonts/                 ← bundel NotoSans TTF

Manual Test

  • Upload template imej
  • Set koordinat nama + no_kp
  • Preview template
  • Test generate → papar hasil
  • Peserta scan QR (masa download) → semak kehadiran
  • Peserta download sijil (selepas soalselidik)
  • Peserta cuba download sebelum jawab soalselidik → redirect

Fasa 8: Email & Queue

Anggaran: 2-3 jam

Tasks

  • CertificateReadyMail — Mailable class
  • Email template Blade (HTML + text)
  • SendCertificateEmailJob — queue job
  • BlastCertificateLinkJob — mass email untuk semua peserta hadir
  • Admin trigger: "Email semua peserta" button
  • email_logs rekod semua attempt
  • Commit: feat: email certificate link

Files Utama

app/Mail/CertificateReadyMail.php
app/Jobs/SendCertificateEmailJob.php
app/Jobs/BlastCertificateLinkJob.php
resources/views/emails/certificate-ready.blade.php
resources/views/emails/certificate-ready.text.blade.php

Manual Test

  • Trigger email untuk satu peserta
  • Email diterima dengan link betul
  • Link dalam email bawa ke certificate page
  • email_logs rekod status sent
  • Test email SMTP failure → status failed dalam email_logs

Fasa 9: Statistics Dashboard

Anggaran: 2-3 jam

Tasks

  • StatisticsController — dashboard + per-program
  • Dashboard cards (counts)
  • Per-program breakdown (attendance by type, session, soalselidik)
  • Chart.js integration (rating chart, attendance trend)
  • Export CSV statistik
  • Commit: feat: admin statistics dashboard

Files Utama

app/Http/Controllers/Admin/StatisticsController.php
app/Http/Controllers/Admin/DashboardController.php (update)
resources/views/admin/dashboard.blade.php (update)
resources/views/admin/programs/statistics.blade.php

Manual Test

  • Dashboard papar kiraan betul
  • Per-program statistik betul
  • Chart.js render tanpa error
  • Export CSV berjaya

Fasa 10: Security Hardening & Audit Log

Anggaran: 1-2 jam

Tasks

  • AuditLogService — log admin actions
  • Hook audit log ke key events
  • Review semua route ada proper validation
  • Semak file upload hanya benarkan jpg/png
  • Semak no_kp tidak expose dalam URL
  • Rate limiting final review
  • Commit: feat: audit logging and security hardening

Fasa 11: Testing

Anggaran: 3-4 jam

Tasks

  • Setup Pest
  • Admin can create program
  • QR token valid opens check-in page
  • Staff pre-registered can check-in
  • External participant can register and check-in
  • Duplicate no_kp for same program rejected
  • Participant cannot download certificate before questionnaire
  • Participant can download certificate after questionnaire
  • Admin can view basic statistics
  • Commit: test: core attendance and certificate flow

Environment Variables Checklist

APP_NAME="eCert MBIP"
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ecert_mbip
DB_USERNAME=root
DB_PASSWORD=

QUEUE_CONNECTION=database

MAIL_MAILER=smtp
MAIL_HOST=
MAIL_PORT=587
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@mbip.gov.my
MAIL_FROM_NAME="eCert MBIP"

FILESYSTEM_DISK=local

SESSION_DRIVER=database
SESSION_LIFETIME=120

Git Commit Sequence

# Fasa 1
git commit -m "chore: initial Laravel project setup"
git commit -m "feat: admin authentication and layout"

# Fasa 2
git commit -m "feat: program management"

# Fasa 3
git commit -m "feat: qr code generation"

# Fasa 4
git commit -m "feat: participant management and csv import"

# Fasa 5
git commit -m "feat: public check-in flow and attendance"

# Fasa 6
git commit -m "feat: questionnaire management"

# Fasa 7
git commit -m "feat: certificate template upload"
git commit -m "feat: certificate generation and download"

# Fasa 8
git commit -m "feat: email certificate link"

# Fasa 9
git commit -m "feat: admin statistics dashboard"

# Fasa 10
git commit -m "feat: audit logging and security hardening"

# Fasa 11
git commit -m "test: core attendance and certificate flow"

# Production push (HANYA apabila diarahkan)
# git push -u origin master

Risiko Teknikal

# Risiko Kemungkinan Impak Mitigasi
1 GD font rendering — perlu TTF, tidak ada jika lupa bundel Sederhana Tinggi Bundel Noto Sans TTF dalam resources/fonts/, test awal
2 Queue worker tidak berjalan di Windows production Tinggi Tinggi Guna Task Scheduler Windows atau switch ke Linux server
3 CSV import gagal handle UTF-8 BOM (Excel export) Tinggi Sederhana Detect dan strip BOM dalam import service
4 SMTP kerajaan — TLS/SSL config berbeza Sederhana Tinggi Test awal dengan real SMTP, fallback ke log driver
5 Concurrent check-in race condition Rendah Sederhana DB unique constraint + try-catch pada insert
6 PDF certificate kualiti rendah jika gambar template kecil Sederhana Sederhana Minta admin upload template minimum 1240px lebar
7 "Laravel Boost" tidak jelas Rendah Perlu penjelasan sebelum install
8 Session tidak persistent untuk public (no login) Sederhana Guna certificate token + signed URL, bukan session
9 Storage permissions pada Windows production Sederhana Tinggi Pastikan storage/ dan bootstrap/cache/ writable
10 PDPA — no_kp exposure dalam log/debug Rendah Tinggi Disable query log production, redact no_kp dalam audit_logs