Files
prn2026/docs/02-architecture.md
2026-06-03 08:51:22 +08:00

6.8 KiB

Initial Architecture

Technology Stack

  • Backend: Laravel 13.12.0, installed through laravel/laravel 13.8.0.
  • Database: MySQL.
  • Views: Blade.
  • Styling: Bootstrap 5 with Bootstrap Icons.
  • JavaScript: Vite-managed assets, jQuery where it improves progressive enhancement, plus selected UI helpers.
  • Queue: Laravel queue system for email and heavier export-related tasks where useful.
  • Mail: Laravel Mail and Notifications with Markdown mail templates.
  • Authorization: Laravel policies, gates, middleware, and spatie/laravel-permission.
  • Auditing: spatie/laravel-activitylog plus domain-specific history tables where a structured audit timeline is needed.
  • Export: OpenSpout for current PHP 8.5 compatibility. maatwebsite/excel remains the preferred package from the original requirement but was not installable in this environment during Phase 1.

Phase 1 Implemented Structure

Implemented:

  • Breeze auth controllers and routes.
  • Generic /register routes disabled.
  • Bootstrap-based layouts.app, layouts.guest, and navigation.
  • Role-aware dashboards:
    • /admin/dashboard
    • /kewangan/dashboard
    • /ppm/dashboard
    • /ktm/dashboard
    • /pemohon/dashboard
  • /dashboard role redirect.
  • Spatie role middleware aliases:
    • role
    • permission
    • role_or_permission
  • RolePermissionSeeder.
  • Default Admin seed account from config/prn.php.

Application Structure

Planned directories:

app/
  Actions/
  Exports/
  Http/
    Controllers/
    Requests/
    Middleware/
  Models/
  Notifications/
  Policies/
  Services/
  Support/

Guidelines:

  • Controllers orchestrate requests and responses only.
  • Form Request classes validate input and authorize request-specific actions.
  • Policies enforce model-level access.
  • Services hold business rules and transactional workflows.
  • Action classes may be used for high-value operations such as approving applications, changing assignments, registering KTM-created KP, and recording attendance.
  • Export classes live in app/Exports.
  • Report filters and query preparation live in services, not controllers.

Architectural Layers

Presentation Layer

  • Blade templates with Bootstrap 5.
  • Responsive layouts for desktop, tablet, and mobile.
  • Shared layout components for navigation, cards, filters, badges, breadcrumbs, tables, empty states, and modals.
  • Mobile-friendly table alternatives for high-density data.

HTTP Layer

  • Named routes.
  • Route groups by role and module.
  • Middleware for authentication, role, registration period, and public QR validation.
  • Route model binding using internal IDs for authenticated admin areas where safe.
  • Public routes use UUID/ULID identifiers only.

Domain Layer

Core services:

  • RegistrationPeriodService
  • VacancyService
  • ApplicationService
  • AssignmentService
  • KtmTeamService
  • PpmScopeService
  • BankVerificationService
  • AttendanceService
  • WheelchairService
  • ExportLoggingService
  • SensitiveDataMaskingService

Potential action classes:

  • SubmitPublicApplication
  • CreateKtmApplicant
  • ApproveApplication
  • RejectApplication
  • ChangeApplicantRole
  • AssignStaffToSaluran
  • RecordAttendance
  • VerifyBankDetails
  • RecordWheelchairTransaction

Data Layer

  • Eloquent models and relationships.
  • Foreign keys for domain integrity.
  • Soft deletes for records that should remain auditable.
  • Domain history tables for applications and assignments.
  • Activity log for actor/value snapshots and operational traceability.

Role-Based Areas

Planned route groups:

/dashboard
/admin/...
/ppm/...
/ktm/...
/kewangan/...
/pohon/{pusat_mengundi_uuid}

Expected access:

  • Admin: full operational management.
  • Admin Kewangan: finance verification and finance exports only.
  • PPM: assigned Pusat Mengundi only.
  • KTM: assigned Saluran/team only.
  • Pemohon: public form and own submission flow only if login is later required.

Public Identifier Strategy

  • Public QR links must use UUID or ULID stored on pusat_mengundis.public_uuid or equivalent.
  • Internal auto-increment IDs must not appear in public application URLs.
  • Uploaded documents are accessed only through authenticated authorization checks and signed/temporary download responses where needed.

Dual-Role Assignment Strategy

The system must support a PPM who is also KTM. This should not be modeled as a single role column on a user or application.

Planned approach:

  • Use users for login identity.
  • Use applications or staff records for applicant/staff biographical and banking data.
  • Use staff_assignments as the canonical placement table.
  • A person can have multiple active staff_assignments within the same election when business rules allow it.
  • staff_assignments references position_id, pusat_mengundi_id, optional saluran_mengundi_id, and optional supervisor/team references.
  • Uniqueness constraints prevent invalid duplicate active assignments, while allowing explicitly permitted dual role such as PPM + KTM.

Audit Strategy

Use two audit levels:

  • Structured domain histories for application status and assignment changes.
  • General activity log for before/after data changes, actor, timestamp, source, and notes.

Audit targets:

  • Application approval/rejection.
  • Role changes.
  • Assignment changes.
  • Document upload/change.
  • Bank verification.
  • Admin edits after registration closes.
  • Attendance updates.
  • Wheelchair transactions.
  • Excel exports.

File Storage Strategy

  • IC documents and bank statements are stored on Laravel private storage disk.
  • Public symlink storage must not expose sensitive uploads.
  • File validation must restrict MIME type, size, and extension.
  • Document access must pass policy checks.
  • File records should be stored in application_documents with document type, disk, path, original name, MIME type, size, uploader, and timestamps.

Export Strategy

  • maatwebsite/excel will generate XLSX exports.
  • Every export inserts a row into export_logs.
  • Export logs include generated_by, generated_at, report_type, filter parameters, and file name.
  • Export services prepare queries and filters.
  • Export classes only shape spreadsheet data.

Queue and Mail Strategy

  • KTM-created applicant email notification should use Laravel Notifications or Mailables.
  • Queue should be enabled for mail in production.
  • Local development can use log mailer or local mail catcher.
  • Admin-keyed records do not trigger bank account email requests.

Security Principles

  • Use CSRF protection for all form submissions.
  • Use policies and middleware for every protected module.
  • Validate uploads strictly.
  • Store sensitive files privately.
  • Mask IC, bank account, phone, and email where full values are unnecessary.
  • Avoid raw SQL unless justified and documented.
  • Use transactions for approval, assignment, finance verification, and attendance updates.