459 lines
16 KiB
Markdown
459 lines
16 KiB
Markdown
# 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`.
|