Files
prn2026/docs/01-development-plan.md
2026-06-03 08:51:22 +08:00

16 KiB

Development Plan

Delivery Approach

The system will be built in controlled phases. Each phase must update:

  • docs/progress-log.md
  • docs/changelog.md
  • docs/decision-log.md when architecture, package, database, or security decisions change

Controllers must remain thin. Business rules should live in service classes, policies, form requests, action classes, and model relationships.

Phase 0: Project Inspection and Planning

Status: Completed on 2026-05-28.

Tasks:

  • Inspect current workspace.
  • Confirm local toolchain.
  • Create required documentation files.
  • Record assumptions.
  • Propose architecture.
  • Propose database schema.
  • Document RBAC, workflows, UI/UX, tests, deployment notes, and package choices.

Exit criteria:

  • All required Phase 0 documentation files exist.
  • No application code has been created.

Phase 1: Laravel Setup and Authentication

Status: Completed on 2026-05-28.

Tasks:

  • Create Laravel application using latest stable version compatible with PHP 8.5 and the available Composer environment.
  • Configure MySQL connection.
  • Install authentication scaffolding using Laravel Breeze Blade stack.
  • Install Bootstrap 5, Bootstrap Icons, and Vite asset pipeline.
  • Install Phase 1 package baseline:
    • spatie/laravel-permission
    • spatie/laravel-activitylog
    • maatwebsite/excel
    • compatible QR code package
    • Laravel Pint if not already included
    • Larastan/PHPStan if compatible
    • SweetAlert2
    • Tom Select or Select2
    • Flatpickr
  • Configure base responsive layout.
  • Install and configure spatie/laravel-permission.
  • Create roles and permissions seeders.
  • Create role-based dashboard routes.
  • Add middleware for authenticated and role-protected areas.
  • Configure Laravel Pint and testing baseline.

Expected deliverables:

  • Running Laravel app.
  • Login flow.
  • Optional public registration path disabled for generic account creation unless needed for Pemohon flow.
  • Base dashboard per role.
  • Seeded roles and permissions.
  • Package choices recorded in docs/decision-log.md.

Manual testing:

  • Login works.
  • Seeded Admin user can access admin dashboard.
  • Users cannot access dashboards for roles they do not have.
  • Mobile navigation works.

Phase 2: Core Database and Seeders

Status: Completed on 2026-05-28.

Tasks:

  • Create migrations for elections, settings, hierarchy, positions, quotas, applications, documents, assignments, histories, representatives, wheelchair records, attendance, finance verification, export logs, and system notes.
  • Create Eloquent models and relationships.
  • Implement factories for test data.
  • Seed default positions, roles, permissions, sample election, sample Bahagian, Daerah, Pusat, and Saluran.

Expected deliverables:

  • Core schema migrated successfully.
  • Seeders create a usable baseline.
  • Model relationships verified with tests or tinker checks.

Manual testing:

  • Admin can see seeded hierarchy once UI exists.
  • Relationships return expected records.

Phase 3: Admin Setup Module

Status: Completed on 2026-05-29.

Tasks:

  • CRUD for Bahagian Pilihanraya, Daerah Mengundi, Pusat Mengundi, and Saluran Mengundi.
  • CRUD for Jawatan and quotas.
  • Assign PPM to Pusat Mengundi through the assignment model.
  • Generate or refresh QR public UUID links per Pusat Mengundi.
  • Add server-side pagination for setup lists.
  • Provide a public QR placeholder route until the full Phase 4 applicant form is implemented.
  • Keep KKM, JKM, and Police detail management for Phase 7 Admin management because those operational forms need the richer post-registration edit-note and audit flow.

Expected deliverables:

  • Admin can prepare election structure and registration links.
  • QR link format uses public UUID/ULID, not internal IDs.
  • PPM assignment writes to staff_assignments and assigns the PPM RBAC role to the selected user.

Manual testing:

  • Admin can create hierarchy from top to bottom.
  • QR URL resolves to intended Pusat Mengundi.
  • Internal IDs are not exposed in public URLs.
  • Admin can create or update position quotas for pusat-level and saluran-level roles.
  • Non-Admin users cannot access setup routes.

Phase 4: Public Application Module

Status: Completed on 2026-05-29.

Tasks:

  • Self-registers with public QR link.
  • Public QR route /pohon/{pusat_mengundi_uuid}.
  • Application form for KTM, KP, KPDP, and PAPM.
  • Dynamic KTM selection for KP/KPDP based on approved KTM with vacancy.
  • Secure private upload for IC document and bank statement.
  • Duplicate IC validation within current election.
  • Block self-registration when a KTM-created applicant exists for the same IC.
  • Registration period enforcement.
  • Create pending bank verification record for submitted public applications.
  • Record application submission, document upload, and status history.

Expected deliverables:

  • Public applicant form works during registration period only.
  • Required documents are stored privately.
  • Clear blocked/closed messages.
  • QR route continues to use public UUID and never exposes internal Pusat Mengundi IDs.

Manual testing:

  • Submit valid application.
  • Try duplicate IC.
  • Try missing documents.
  • Try after registration closes.
  • Try KP with a KTM that has remaining vacancy.
  • Try KP with a KTM whose KP quota is full.

Phase 5: PPM Module

Status: Completed on 2026-05-29.

Tasks:

  • PPM dashboard scoped to assigned Pusat Mengundi.
  • Application review listing and details.
  • Approve/reject applications.
  • Change applicant role before approval.
  • Assign KTM to Saluran.
  • Assign KP/KPDP to approved KTM under same Pusat Mengundi.
  • View Police, KKM, and JKM information.
  • Audit role and assignment changes.
  • Download uploaded applicant documents through authorized PPM route.
  • Record-level authorization through policy and PPM assignment scope.
  • Polling-day attendance remains in Phase 10 to keep the later attendance reporting/export design together.

Expected deliverables:

  • PPM can manage only own Pusat Mengundi.
  • Approval requires IC and bank statement documents.
  • Approval creates active staff_assignments and assignment history.

Manual testing:

  • PPM cannot view another Pusat Mengundi.
  • PPM cannot approve missing-document applicants.
  • Assignment changes are audited.
  • PPM can approve KTM into an available Saluran.
  • PPM can change role and assign KP/KPDP to an active KTM with vacancy.

Phase 6: KTM Module

Status: Completed on 2026-05-29.

Tasks:

  • KTM dashboard for assigned Saluran.
  • View KP team.
  • Register KP only.
  • Approve KP only under own team.
  • Delete KTM-created applicant where appropriate.
  • Send email notification to applicant for KTM-created record.
  • Enforce registration period.
  • Prevent KTM from managing non-KP roles or other KTM teams.
  • Prevent KTM from deleting assigned applications.

Expected deliverables:

  • KTM cannot register or approve non-KP roles.
  • KTM cannot manage another KTM team.
  • Email notification is queued or sent through Laravel mail.
  • KTM-created records use source = created_by_ktm.

Manual testing:

  • KTM creates KP.
  • Applicant receives email in local mail log/mailpit equivalent.
  • KTM cannot create KP after registration closes.
  • KTM can approve only KP under own Saluran/team.
  • KTM can delete own unassigned KTM-created applicant so public self-registration can proceed.

Phase 7: Admin Management and Manual Entry

Status: Completed on 2026-05-29.

Tasks:

  • Admin global list of applications and assignments.
  • Manual staff entry.
  • Edit approved staff records.
  • Direct assignment to Pusat and Saluran.
  • Police, KKM, and JKM management.
  • Post-registration edit notes.
  • Full audit trail for Admin changes.

Expected deliverables:

  • Admin can correct and maintain all operational data.
  • Edits after registration period require catatan.
  • Manual Admin-created records use source = admin_manual and do not trigger KTM/applicant bank request email behavior.
  • Direct Admin assignment uses source = admin_direct or admin_update and writes assignment history, application status history, system notes when required, and activity log entries.

Manual testing:

  • Admin edits before and after registration closing.
  • Post-closing edit without note is rejected.
  • Audit record includes note.
  • Admin can create Police, KKM, and JKM representative records.
  • Admin Kewangan cannot access placement management routes.

Phase 8: Finance Module

Status: Completed on 2026-05-29.

Tasks:

  • Admin Kewangan dashboard.
  • Bank verification listing and filters.
  • Mark bank record as pending, verified, rejected, or requires correction.
  • Add finance note.
  • Export finance checking list.
  • Prevent assignment modification by Admin Kewangan.

Expected deliverables:

  • Finance users can verify bank data but cannot alter placement.
  • Finance list includes approved/assigned staff only.
  • Export creates export_logs row and stores XLSX file in private storage.

Manual testing:

  • Finance status changes are audited.
  • Finance user cannot access assignment edit routes.
  • Filter by Pusat Mengundi, role, bank status, missing bank statement, missing account number, and keyword.
  • Download finance verification export and confirm export log is created.

Phase 9: Wheelchair Module

Status: Completed on 2026-05-29.

Tasks:

  • Admin manages wheelchair allocation per Pusat Mengundi.
  • Record taken quantity, taken time, person taking.
  • Record return quantity, return time, condition, and notes.
  • Audit wheelchair transactions.

Expected deliverables:

  • Wheelchair movement is traceable by Pusat Mengundi and election.
  • Taken quantity cannot exceed allocation available balance.
  • Returned quantity cannot exceed outstanding taken quantity.
  • Allocation cannot be reduced below outstanding quantity.

Manual testing:

  • Quantity cannot exceed allocation without an explicit business exception.
  • Transaction history displays clearly.
  • Admin Kewangan cannot access wheelchair management routes.

Phase 10: Attendance Module

Status: Completed on 2026-05-29.

Tasks:

  • PPM attendance screen scoped to own Pusat Mengundi.
  • Attendance status: present, absent, not recorded.
  • Check-in time, recorded by, and note.
  • Admin attendance dashboard by Pusat Mengundi.
  • Attendance summary and detail exports.

Expected deliverables:

  • PPM can record polling-day attendance.
  • Admin can monitor attendance by role and Pusat.
  • Attendance recording is blocked unless election_settings.is_attendance_active is true.
  • Attendance detail export creates export_logs row.

Manual testing:

  • PPM cannot record attendance outside own Pusat.
  • Attendance summary totals match detail records.
  • Excel export creates export log.
  • Admin Kewangan cannot access Admin attendance dashboard.

Phase 11: Testing, Polish, and Hardening

Status: Completed on 2026-05-29.

Tasks:

  • Complete feature and unit tests.
  • Review authorization coverage.
  • Review upload and private document access.
  • Review masking of sensitive data.
  • Run Laravel Pint.
  • Run static analysis if installed and compatible.
  • Performance review for large lists and exports.
  • Final documentation update.

Expected deliverables:

  • Production-ready baseline with documented deployment steps.
  • Authorized Admin and Admin Kewangan document downloads for sensitive uploaded files.
  • Final quality gate run with tests, Pint, PHPStan, route list, and Vite build.

Manual testing:

  • End-to-end rehearsal from setup to attendance export.
  • Mobile checks for Admin, PPM, KTM, and public application forms.
  • Verify Admin can download IC and bank documents.
  • Verify Admin Kewangan can download bank statement only.

Phase 12: Critical Fixes and Security Hardening

Status: Not started.

Scope: Address issues identified during post-Phase 11 code review that could cause data inconsistency, silent authorization bypass, or require direct database edits in production. Full detail in docs/09-improvement-plan.md.

Tasks:

  • 12-A: Add Admin Settings UI for toggling is_attendance_active and is_registration_open_override.
  • 12-B: Fix IC duplicate check to explicitly exclude soft-deleted records.
  • 12-C: Harden AdminPostCloseNoteService catatan enforcement so it cannot be bypassed by new controllers.
  • 12-D: Audit and fix SampleElectionSeeder for stale position name references after Phase 11 rename migration.
  • 12-E: Centralize and consistently enforce document type checks across all download paths.

Expected deliverables:

  • Admin can toggle attendance activation and registration override from UI without touching the database.
  • Soft-deleted KTM-created records do not block public re-registration.
  • Post-closing catatan enforcement is consistent across all Admin management routes.
  • Seeder runs cleanly on a fresh database without errors.
  • All document download routes enforce role-specific type restrictions consistently.

Exit criteria:

  • php artisan migrate:fresh --seed passes.
  • php artisan test passes with new tests for each fix.
  • vendor\bin\pint.bat --test passes.
  • vendor\bin\phpstan.bat analyse --memory-limit=1G passes.

Docs to update on completion: docs/progress-log.md, docs/changelog.md, docs/decision-log.md, docs/04-rbac-permission-matrix.md, docs/05-workflow-design.md.

Phase 13: Database Indexes and Performance

Status: Not started.

Scope: Add composite indexes before real election data is loaded. Full detail in docs/09-improvement-plan.md.

Tasks:

  • 13-A: Add composite indexes on applications, staff_assignments, and bank_verifications for common Admin and service-layer queries.

Expected deliverables:

  • New migration with explicit short-named indexes.
  • Admin global list and vacancy service queries confirmed to use indexes.

Exit criteria:

  • php artisan migrate passes.
  • php artisan test passes.
  • Key queries verified with MySQL EXPLAIN.

Docs to update on completion: docs/03-database-design.md, docs/08-deployment-notes.md, docs/decision-log.md, docs/progress-log.md, docs/changelog.md.

Phase 14: Applicant Status Portal

Status: Not started.

Scope: Give public applicants a read-only status page accessible via their application UUID, with no login required. Full detail in docs/09-improvement-plan.md.

Tasks:

  • 14-A: Add GET /permohonan/{application:public_uuid}/status route and controller.
  • Display limited, masked applicant data: partial name, role applied, pusat, current status, rejection reason if applicable.
  • Do not expose sensitive fields (full IC, bank account) or internal IDs.
  • Return 200 with a generic message for unknown UUIDs rather than 404 to avoid enumeration.

Expected deliverables:

  • Applicants can check their status without logging in.
  • Sensitive data is not revealed.

Exit criteria:

  • Feature tests for submitted, approved, assigned, rejected, and unknown UUID states.
  • php artisan test passes.

Docs to update on completion: docs/05-workflow-design.md, docs/06-ui-ux-plan.md, docs/decision-log.md, docs/progress-log.md, docs/changelog.md.

Phase 15: Export Retention and Sensitive Data Purge

Status: Not started.

Scope: Automatically purge old export files that contain sensitive bank and personal data. Full detail in docs/09-improvement-plan.md.

Tasks:

  • 15-A: Add ExportPurgeCommand Artisan command with configurable --days= retention period.
  • Command deletes files from private storage and marks export_logs rows with purged_at.
  • Add purged_at column to export_logs via new migration.
  • Register command as a scheduled daily task.

Expected deliverables:

  • Old export files are purged automatically.
  • export_logs reflects purge status.
  • Scheduler configuration is documented in deployment notes.

Exit criteria:

  • php artisan exports:purge runs without error.
  • Files older than retention period are deleted; newer files are kept.
  • php artisan test passes.

Docs to update on completion: docs/03-database-design.md, docs/08-deployment-notes.md, docs/decision-log.md, docs/progress-log.md, docs/changelog.md.