This commit is contained in:
Saufi
2026-06-03 08:51:22 +08:00
commit a14d43fe34
347 changed files with 38197 additions and 0 deletions

458
docs/01-development-plan.md Normal file
View File

@@ -0,0 +1,458 @@
# 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`.