1257 lines
52 KiB
Markdown
1257 lines
52 KiB
Markdown
# Progress Log
|
||
|
||
## 2026-05-28 - Phase 0: Project Inspection and Planning
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Inspected workspace.
|
||
- Confirmed workspace is currently empty.
|
||
- Confirmed no git repository is initialized.
|
||
- Confirmed no existing Laravel application is present.
|
||
- Confirmed no `AGENTS.md` project instruction file is present.
|
||
- Checked local tooling:
|
||
- PHP 8.5.1 available.
|
||
- Composer 2.9.4 available.
|
||
- Node 25.1.0 available.
|
||
- `npm.cmd` 11.14.1 available.
|
||
- `npm` PowerShell shim blocked by execution policy.
|
||
- MySQL CLI not available in PATH.
|
||
- Created Phase 0 planning documentation.
|
||
|
||
Changed files:
|
||
|
||
- `docs/00-project-brief.md`
|
||
- `docs/01-development-plan.md`
|
||
- `docs/02-architecture.md`
|
||
- `docs/03-database-design.md`
|
||
- `docs/04-rbac-permission-matrix.md`
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/06-ui-ux-plan.md`
|
||
- `docs/07-testing-plan.md`
|
||
- `docs/08-deployment-notes.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Pending items:
|
||
|
||
- Initialize or create Laravel project in Phase 1.
|
||
- Confirm exact Laravel version during install.
|
||
- Confirm MySQL server credentials and connectivity.
|
||
- Verify package compatibility during Composer/npm installation.
|
||
- Initialize git repository if desired.
|
||
|
||
Next step:
|
||
|
||
- Proceed to Phase 1 only after approval: Laravel setup, authentication scaffolding, Bootstrap 5 base layout, roles, permissions, and base dashboards.
|
||
|
||
Manual testing for this phase:
|
||
|
||
- Review documentation files for completeness.
|
||
- Confirm assumptions in `docs/decision-log.md`.
|
||
|
||
## 2026-05-28 - Phase 0 Review Before Implementation
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Reviewed all Phase 0 documentation files against the original requirement.
|
||
- Confirmed the required documentation set is present.
|
||
- Clarified Phase 1 package baseline in the development plan.
|
||
- Clarified `election_settings.is_registration_open` in database and workflow design.
|
||
- Recorded optional Telescope and DOMPDF decisions.
|
||
|
||
Changed files:
|
||
|
||
- `docs/01-development-plan.md`
|
||
- `docs/03-database-design.md`
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
|
||
Pending items:
|
||
|
||
- Proceed with Phase 1 implementation.
|
||
|
||
Next step:
|
||
|
||
- Scaffold Laravel, install packages, configure authentication, Bootstrap layout, roles/permissions, and base dashboards.
|
||
|
||
## 2026-05-28 - Phase 1: Laravel Setup and Authentication
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Scaffolded Laravel application.
|
||
- Installed Laravel framework 13.12.0.
|
||
- Installed Laravel Breeze authentication scaffolding.
|
||
- Disabled generic public account registration route.
|
||
- Installed and configured Bootstrap 5 layout through Vite.
|
||
- Installed Bootstrap Icons, jQuery, SweetAlert2, Tom Select, Flatpickr, and DataTables Bootstrap packages.
|
||
- Installed `spatie/laravel-permission` and published migrations/config.
|
||
- Installed `spatie/laravel-activitylog` and published migrations/config.
|
||
- Installed `simplesoftwareio/simple-qrcode`.
|
||
- Attempted `maatwebsite/excel`; Composer rejected it for PHP 8.5.1/Laravel 13 compatibility.
|
||
- Installed `openspout/openspout` as compatible spreadsheet export foundation.
|
||
- Installed Larastan/PHPStan.
|
||
- Added role middleware aliases.
|
||
- Added User `HasRoles` support.
|
||
- Added role and permission seeder.
|
||
- Added default Admin seeding through `config/prn.php`.
|
||
- Added role-based dashboard routes and base dashboard UI.
|
||
- Updated auth/profile/welcome views to Bootstrap.
|
||
- Updated `.env.example` for MySQL.
|
||
- Set application timezone to `Asia/Kuala_Lumpur`.
|
||
- Kept local `.env` on SQLite because MySQL server credentials are not yet available.
|
||
- Added tests for disabled registration and dashboard role protection.
|
||
|
||
Changed files:
|
||
|
||
- Laravel application scaffold files.
|
||
- `app/Http/Controllers/DashboardController.php`
|
||
- `app/Models/User.php`
|
||
- `bootstrap/app.php`
|
||
- `config/activitylog.php`
|
||
- `config/permission.php`
|
||
- `config/prn.php`
|
||
- `config/app.php`
|
||
- `database/migrations/*permission*`
|
||
- `database/migrations/*activity_log*`
|
||
- `database/seeders/DatabaseSeeder.php`
|
||
- `database/seeders/RolePermissionSeeder.php`
|
||
- `resources/css/app.css`
|
||
- `resources/js/app.js`
|
||
- `resources/views/auth/*.blade.php`
|
||
- `resources/views/dashboards/index.blade.php`
|
||
- `resources/views/layouts/*.blade.php`
|
||
- `resources/views/profile/edit.blade.php`
|
||
- `resources/views/welcome.blade.php`
|
||
- `routes/auth.php`
|
||
- `routes/web.php`
|
||
- `tests/Feature/Auth/RegistrationTest.php`
|
||
- `tests/Feature/DashboardAccessTest.php`
|
||
- `.env.example`
|
||
- `.gitignore`
|
||
- `composer.json`
|
||
- `composer.lock`
|
||
- `package.json`
|
||
- `package-lock.json`
|
||
- `phpstan.neon`
|
||
- `docs/*`
|
||
|
||
Verification:
|
||
|
||
- `php artisan migrate --seed` completed after seeder correction.
|
||
- `php artisan db:seed` completed.
|
||
- `npm.cmd run build` passed.
|
||
- `php artisan route:list` passed.
|
||
- `php artisan test` passed: 27 tests, 64 assertions.
|
||
- `vendor\bin\pint.bat --test` passed.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` passed.
|
||
|
||
Pending items:
|
||
|
||
- Confirm MySQL database credentials and switch local `.env` to MySQL when available.
|
||
- Implement Phase 2 core domain migrations/models/seeders.
|
||
- Replace OpenSpout with `maatwebsite/excel` only if a compatible release becomes available or runtime PHP target changes.
|
||
|
||
Manual testing:
|
||
|
||
- Visit `/`.
|
||
- Log in as seeded Admin:
|
||
- email: `admin@prn.local`
|
||
- password: `password`
|
||
- Confirm `/dashboard` redirects Admin to `/admin/dashboard`.
|
||
- Confirm `/register` is not available.
|
||
- Resize browser to confirm mobile navbar behavior.
|
||
|
||
Next step:
|
||
|
||
- Phase 2: Core database and seeders for election hierarchy, positions, quotas, applications, assignments, and operational records.
|
||
|
||
## 2026-05-28 - Phase 2: Core Database and Seeders
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Added core election-domain migration.
|
||
- Added `user_profiles`, election hierarchy, position/quota, application/document/history, assignment/history, representative, wheelchair, attendance, finance, export, and note tables.
|
||
- Added domain models and Eloquent relationships.
|
||
- Added baseline factories for election hierarchy, positions, applications, and assignments.
|
||
- Added `PositionSeeder`.
|
||
- Added `SampleElectionSeeder`.
|
||
- Updated `DatabaseSeeder` to seed roles, positions, Admin user, and sample election data.
|
||
- Seeded sample election `PRN2026`.
|
||
- Seeded one Bahagian Pilihanraya, one Daerah Mengundi, one Pusat Mengundi, and three Saluran Mengundi.
|
||
- Seeded 9 default positions and 17 sample quotas.
|
||
- Seeded sample Admin Kewangan, PPM, and KTM users.
|
||
- Seeded sample dual-role assignment where one user is both PPM and KTM.
|
||
- Seeded sample wheelchair allocation.
|
||
- Added feature test for core domain seeder output and dual-role assignment.
|
||
- Confirmed MySQL connection through Laravel/PDO.
|
||
- Shortened long composite index names for MySQL compatibility.
|
||
|
||
Changed files:
|
||
|
||
- `database/migrations/2026_05_28_030000_create_phase2_core_domain_tables.php`
|
||
- `app/Models/*.php`
|
||
- `database/factories/*.php`
|
||
- `database/seeders/DatabaseSeeder.php`
|
||
- `database/seeders/PositionSeeder.php`
|
||
- `database/seeders/SampleElectionSeeder.php`
|
||
- `tests/Feature/CoreDomainSeederTest.php`
|
||
- `docs/00-project-brief.md`
|
||
- `docs/01-development-plan.md`
|
||
- `docs/03-database-design.md`
|
||
- `docs/07-testing-plan.md`
|
||
- `docs/08-deployment-notes.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Verification:
|
||
|
||
- `php artisan migrate:fresh --seed` passed on MySQL database `prn2026`.
|
||
- `php artisan test` passed: 28 tests, 80 assertions.
|
||
- `vendor\bin\pint.bat --test` passed.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` passed.
|
||
|
||
Manual testing:
|
||
|
||
- Log in as `admin@prn.local` / `password`.
|
||
- Confirm base dashboard loads after fresh seed.
|
||
- Optional sample accounts:
|
||
- `kewangan@prn.local` / `password`
|
||
- `ppm@prn.local` / `password`
|
||
- `ktm@prn.local` / `password`
|
||
- Confirm `/dashboard` redirects based on each user's role.
|
||
|
||
Pending items:
|
||
|
||
- Phase 3 Admin setup module UI and CRUD.
|
||
- Implement policy-level ownership checks when domain UI routes are added.
|
||
- Add business-rule services for vacancy and registration period calculations in later phases.
|
||
|
||
Next step:
|
||
|
||
- Phase 3: Admin setup module for CRUD Bahagian, Daerah, Pusat, Saluran, Jawatan/quota setup, PPM assignment, and QR generation.
|
||
|
||
## 2026-05-29 - Phase 3: Admin Setup Module
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Added Admin setup routes under `/admin/setup`.
|
||
- Added setup overview page.
|
||
- Added CRUD controllers, Form Requests, and Blade views for Bahagian Pilihanraya, Daerah Mengundi, Pusat Mengundi, Saluran Mengundi, Jawatan, and Kekosongan Jawatan.
|
||
- Added Pusat Mengundi detail page with saluran list, QR registration link, QR preview, and PPM assignment form.
|
||
- Added QR generation service using public UUID registration URLs.
|
||
- Added Admin-protected QR SVG serving route.
|
||
- Added public QR placeholder route `/pohon/{pusatMengundi:public_uuid}`.
|
||
- Added PPM assignment service using `staff_assignments`, assignment history, RBAC role assignment, and activity logging.
|
||
- Added quota validation to prevent assigning a Saluran Mengundi from a different Pusat Mengundi.
|
||
- Added public Blade layout for QR-facing pages.
|
||
- Linked Admin dashboard action to Election setup.
|
||
- Added feature tests for Admin setup module behavior.
|
||
|
||
Changed files:
|
||
|
||
- `app/Http/Controllers/Admin/Setup/AdminSetupController.php`
|
||
- `app/Http/Controllers/Admin/Setup/BahagianPilihanrayaController.php`
|
||
- `app/Http/Controllers/Admin/Setup/DaerahMengundiController.php`
|
||
- `app/Http/Controllers/Admin/Setup/PositionController.php`
|
||
- `app/Http/Controllers/Admin/Setup/PositionQuotaController.php`
|
||
- `app/Http/Controllers/Admin/Setup/PusatMengundiController.php`
|
||
- `app/Http/Controllers/Admin/Setup/SaluranMengundiController.php`
|
||
- `app/Http/Controllers/DashboardController.php`
|
||
- `app/Http/Controllers/PublicApplicationPlaceholderController.php`
|
||
- `app/Http/Requests/Admin/Setup/*.php`
|
||
- `app/Services/Admin/PpmAssignmentService.php`
|
||
- `app/Services/Admin/PusatQrCodeService.php`
|
||
- `resources/views/admin/setup/**/*.blade.php`
|
||
- `resources/views/dashboards/index.blade.php`
|
||
- `resources/views/layouts/public.blade.php`
|
||
- `resources/views/public/application-placeholder.blade.php`
|
||
- `routes/web.php`
|
||
- `tests/Feature/AdminSetupTest.php`
|
||
- `docs/01-development-plan.md`
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Verification:
|
||
|
||
- `php artisan route:list --except-vendor` passed and shows 65 routes.
|
||
- `php artisan test --filter=AdminSetupTest` passed: 4 tests, 24 assertions.
|
||
- `php artisan test` passed: 32 tests, 104 assertions.
|
||
- `vendor\bin\pint.bat --test` passed.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` passed.
|
||
- `npm.cmd run build` passed.
|
||
|
||
Manual testing:
|
||
|
||
- Log in as `admin@prn.local` / `password`.
|
||
- Open `/admin/setup`.
|
||
- Create or edit Bahagian, Daerah, Pusat, Saluran, Jawatan, and Kuota records.
|
||
- Open a Pusat Mengundi detail page, generate QR, and assign PPM.
|
||
- Open the generated `/pohon/{uuid}` public link and confirm it shows the intended Pusat Mengundi.
|
||
- Log in as `ktm@prn.local` / `password` and confirm `/admin/setup` is forbidden.
|
||
|
||
Pending items:
|
||
|
||
- Full public application form and document upload in Phase 4.
|
||
- Registration-period enforcement for public and KTM-created applications in Phase 4 and Phase 6.
|
||
- Representative management for Police, KKM, and JKM in the later Admin management phase.
|
||
- Rich filters for very large setup lists if operational data volume requires them.
|
||
|
||
Next step:
|
||
|
||
- Phase 4: Public application module using QR link, registration-period rules, document uploads, KTM selection for KP/KPDP, and duplicate IC blocking.
|
||
|
||
## 2026-05-29 - Phase 4: Public Application Module
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Replaced QR placeholder flow with public application form on `/pohon/{pusatMengundi:public_uuid}`.
|
||
- Added public success page using application public UUID.
|
||
- Added `RegistrationPeriodService` for registration open/closed checks.
|
||
- Added `KtmVacancyService` for KP/KPDP KTM selection and vacancy calculation.
|
||
- Added `PublicApplicationSubmissionService` for transactional application creation, private document storage, status history, bank verification initialization, and activity logging.
|
||
- Added `StorePublicApplicationRequest` with validation for applicant fields, IC normalization, required documents, public roles, duplicate IC, KTM-created blocking rule, and KTM vacancy recheck.
|
||
- Added responsive public Blade form for applicant details, role selection, KTM selection, bank data, and document upload.
|
||
- Added closed-registration page.
|
||
- Stored IC document and bank statement metadata in `application_documents`.
|
||
- Created pending `bank_verifications` row for public submissions.
|
||
- Added Phase 4 feature tests and unit tests.
|
||
|
||
Changed files:
|
||
|
||
- `app/Http/Controllers/PublicApplicationController.php`
|
||
- `app/Http/Requests/Public/StorePublicApplicationRequest.php`
|
||
- `app/Services/RegistrationPeriodService.php`
|
||
- `app/Services/Public/KtmVacancyService.php`
|
||
- `app/Services/Public/PublicApplicationSubmissionService.php`
|
||
- `resources/views/layouts/public.blade.php`
|
||
- `resources/views/public/applications/create.blade.php`
|
||
- `resources/views/public/applications/closed.blade.php`
|
||
- `resources/views/public/applications/success.blade.php`
|
||
- `routes/web.php`
|
||
- `tests/Feature/PublicApplicationTest.php`
|
||
- `tests/Unit/KtmVacancyServiceTest.php`
|
||
- `tests/Unit/RegistrationPeriodServiceTest.php`
|
||
- `docs/01-development-plan.md`
|
||
- `docs/03-database-design.md`
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/07-testing-plan.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Verification:
|
||
|
||
- `php artisan route:list --except-vendor` passed and shows 67 routes.
|
||
- `php artisan test --filter=PublicApplicationTest` passed: 6 tests, 27 assertions.
|
||
- `php artisan test` passed: 41 tests, 137 assertions.
|
||
- `vendor\bin\pint.bat --test` passed.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` passed.
|
||
- `npm.cmd run build` passed.
|
||
|
||
Manual testing:
|
||
|
||
- Open a generated `/pohon/{uuid}` QR link.
|
||
- Submit a KTM or PAPM application with IC document and bank statement.
|
||
- Submit KP with an available KTM selection.
|
||
- Try submitting without IC document or bank statement and confirm validation blocks it.
|
||
- Set registration end date to a past date and confirm public form shows closed-registration message.
|
||
- Create a `created_by_ktm` application for an IC and confirm public self-registration with the same IC is blocked.
|
||
|
||
Pending items:
|
||
|
||
- Phase 5 PPM review, approval/rejection, role change, and assignment of submitted public applications.
|
||
- Phase 6 KTM-created application deletion flow and email notification.
|
||
- Authorized document viewing/downloading for PPM/Admin/Admin Kewangan.
|
||
- Public application status portal if later required.
|
||
|
||
Next step:
|
||
|
||
- Phase 5: PPM review and assignment module.
|
||
|
||
## 2026-05-29 - Phase 5: PPM Review and Assignment Module
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Added PPM application review routes under `/ppm/applications`.
|
||
- Added PPM-scoped application list and detail screens.
|
||
- Added `ApplicationPolicy` and `PpmScopeService` for record-level PPM access control.
|
||
- Added `PpmApplicationReviewService` for transactional approve/reject behavior.
|
||
- Added `AssignmentVacancyService` for Pusat/Saluran quota checks.
|
||
- Extended `KtmVacancyService` to ignore the current application during PPM approval vacancy checks.
|
||
- Added PPM approval form allowing role change before approval.
|
||
- Implemented KTM assignment to available Saluran Mengundi.
|
||
- Implemented KP/KPDP assignment to active KTM with remaining vacancy.
|
||
- Implemented PAPM assignment at Pusat Mengundi level.
|
||
- Implemented rejection with required reason.
|
||
- Added authorized private document download for PPM-owned applications.
|
||
- Added PPM dashboard metrics and link to the review queue.
|
||
- Added representative display sections for Police, KKM, and JKM records.
|
||
- Added `AuthorizesRequests` to the base controller for policy authorization.
|
||
- Added Phase 5 feature tests.
|
||
|
||
Changed files:
|
||
|
||
- `app/Http/Controllers/Controller.php`
|
||
- `app/Http/Controllers/DashboardController.php`
|
||
- `app/Http/Controllers/Ppm/ApplicationReviewController.php`
|
||
- `app/Http/Requests/Ppm/ApproveApplicationRequest.php`
|
||
- `app/Http/Requests/Ppm/RejectApplicationRequest.php`
|
||
- `app/Models/PusatMengundi.php`
|
||
- `app/Policies/ApplicationPolicy.php`
|
||
- `app/Services/Ppm/AssignmentVacancyService.php`
|
||
- `app/Services/Ppm/PpmApplicationReviewService.php`
|
||
- `app/Services/Ppm/PpmScopeService.php`
|
||
- `app/Services/Public/KtmVacancyService.php`
|
||
- `resources/views/ppm/applications/index.blade.php`
|
||
- `resources/views/ppm/applications/show.blade.php`
|
||
- `routes/web.php`
|
||
- `tests/Feature/PpmApplicationReviewTest.php`
|
||
- `docs/01-development-plan.md`
|
||
- `docs/04-rbac-permission-matrix.md`
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/07-testing-plan.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Verification:
|
||
|
||
- `php artisan route:list --except-vendor` passed and shows 72 routes.
|
||
- `php artisan test --filter=PpmApplicationReviewTest` passed: 6 tests, 24 assertions.
|
||
- `php artisan test` passed: 47 tests, 161 assertions.
|
||
- `vendor\bin\pint.bat --test` passed.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` passed.
|
||
- `npm.cmd run build` passed.
|
||
|
||
Manual testing:
|
||
|
||
- Log in as `ppm@prn.local` / `password`.
|
||
- Open `/ppm/applications`.
|
||
- Submit a public application through QR first, then confirm it appears in the PPM queue.
|
||
- Open the application detail page and download uploaded documents.
|
||
- Approve a KTM application into an available Saluran.
|
||
- Approve a KP/KPDP application under an active KTM.
|
||
- Change an applicant role before approval and confirm assignment is created.
|
||
- Reject an application with a reason.
|
||
- Confirm a PPM cannot access an application outside their assigned Pusat Mengundi.
|
||
|
||
Pending items:
|
||
|
||
- Phase 6 KTM flow for KP registration/approval, deletion of KTM-created records, and email notification.
|
||
- Admin/Admin Kewangan document viewing routes.
|
||
- Admin global management and post-registration notes in Phase 7.
|
||
- Attendance module in Phase 10.
|
||
|
||
Next step:
|
||
|
||
- Phase 6: KTM flow for assigned Saluran, KP registration, KP approval, KTM-created deletion, and email notification.
|
||
|
||
## 2026-05-29 - Phase 6: KTM Flow
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Added KTM application routes under `/ktm/applications`.
|
||
- Added `KtmScopeService` for active KTM assignment ownership checks.
|
||
- Added `KtmApplicationService` for KTM KP registration, KP approval, and KTM-created deletion.
|
||
- Added queued Markdown Mailable `KtmCreatedApplicantMail`.
|
||
- Added KTM team list showing assigned Saluran, active KP team members, and KP vacancy.
|
||
- Added KTM KP registration form.
|
||
- Added KTM application detail page with approve/delete actions.
|
||
- Enforced KTM registration period on KP registration and approval.
|
||
- Enforced KP-only creation and approval for KTM.
|
||
- Enforced own-team-only approval/deletion.
|
||
- Implemented `source = created_by_ktm` for KTM-created records.
|
||
- Implemented delete flow that sets `deleted_by_ktm`, records status history, and soft deletes the KTM-created application.
|
||
- Updated KTM dashboard with live metrics and navigation links.
|
||
- Added Phase 6 feature tests.
|
||
|
||
Changed files:
|
||
|
||
- `app/Http/Controllers/DashboardController.php`
|
||
- `app/Http/Controllers/Ktm/TeamController.php`
|
||
- `app/Http/Requests/Ktm/RegisterKpApplicantRequest.php`
|
||
- `app/Mail/KtmCreatedApplicantMail.php`
|
||
- `app/Services/Ktm/KtmApplicationService.php`
|
||
- `app/Services/Ktm/KtmScopeService.php`
|
||
- `app/Services/Public/KtmVacancyService.php`
|
||
- `resources/views/emails/ktm/created-applicant.blade.php`
|
||
- `resources/views/ktm/applications/create.blade.php`
|
||
- `resources/views/ktm/applications/index.blade.php`
|
||
- `resources/views/ktm/applications/show.blade.php`
|
||
- `routes/web.php`
|
||
- `tests/Feature/KtmFlowTest.php`
|
||
- `docs/01-development-plan.md`
|
||
- `docs/04-rbac-permission-matrix.md`
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/07-testing-plan.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Verification:
|
||
|
||
- `php artisan route:list --except-vendor` passed and shows 78 routes.
|
||
- `php artisan test --filter=KtmFlowTest` passed: 6 tests, 25 assertions.
|
||
- `php artisan test` passed: 53 tests, 186 assertions.
|
||
- `vendor\bin\pint.bat --test` passed.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` passed.
|
||
- `npm.cmd run build` passed.
|
||
|
||
Manual testing:
|
||
|
||
- Log in as `ktm@prn.local` / `password`.
|
||
- Open `/ktm/applications`.
|
||
- Confirm assigned Saluran and KP vacancy are shown.
|
||
- Register a KP and confirm email is queued/sent according to local mail configuration.
|
||
- Approve a KP under own team and confirm active assignment is created.
|
||
- Try approving KP from another KTM team and confirm it is blocked.
|
||
- Try approving a non-KP application and confirm it is blocked.
|
||
- Set registration end date to the past and confirm KTM registration/approval is blocked.
|
||
- Delete an unassigned KTM-created applicant and confirm public self-registration with the same IC is no longer blocked.
|
||
|
||
Pending items:
|
||
|
||
- Phase 7 Admin global management/manual entry and post-registration notes.
|
||
- Admin/Admin Kewangan document viewing routes.
|
||
- Finance verification module in Phase 8.
|
||
- Attendance module in Phase 10.
|
||
|
||
Next step:
|
||
|
||
- Phase 7: Admin management and manual entry.
|
||
|
||
## 2026-05-29 - Phase 7: Admin Management and Manual Entry
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Added Admin management routes under `/admin/management`.
|
||
- Added Admin management overview dashboard.
|
||
- Added global application list with filters.
|
||
- Added Admin manual application entry with `source = admin_manual`.
|
||
- Added Admin application edit screen.
|
||
- Added direct assignment from Admin application edit screen.
|
||
- Added global staff assignment list and assignment edit screen.
|
||
- Added post-registration catatan enforcement through `AdminPostCloseNoteService`.
|
||
- Added `system_notes` records for accepted post-closing Admin changes.
|
||
- Added assignment/application history and activity log entries for Admin changes.
|
||
- Added Police, KKM, and JKM representative entry/deletion screen.
|
||
- Updated Admin dashboard with live counts and management module links.
|
||
- Added Phase 7 feature tests.
|
||
|
||
Changed files:
|
||
|
||
- `app/Http/Controllers/Admin/Management/AdminManagementController.php`
|
||
- `app/Http/Controllers/Admin/Management/ManagedApplicationController.php`
|
||
- `app/Http/Controllers/Admin/Management/RepresentativeController.php`
|
||
- `app/Http/Controllers/Admin/Management/StaffAssignmentController.php`
|
||
- `app/Http/Controllers/DashboardController.php`
|
||
- `app/Http/Requests/Admin/Management/*.php`
|
||
- `app/Services/Admin/Management/*.php`
|
||
- `resources/views/admin/management/**/*.blade.php`
|
||
- `routes/web.php`
|
||
- `tests/Feature/AdminManagementTest.php`
|
||
- `docs/01-development-plan.md`
|
||
- `docs/04-rbac-permission-matrix.md`
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/07-testing-plan.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Verification:
|
||
|
||
- `php artisan route:list --except-vendor` passed and shows 91 routes.
|
||
- `php artisan test --filter=AdminManagementTest` passed: 5 tests, 18 assertions.
|
||
- `php artisan test` passed: 58 tests, 204 assertions.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` passed.
|
||
- `vendor\bin\pint.bat --test` passed.
|
||
- `npm.cmd run build` passed.
|
||
|
||
Manual testing:
|
||
|
||
- Log in as `admin@prn.local` / `password`.
|
||
- Open `/admin/management`.
|
||
- Create a manual application.
|
||
- Edit a manual or public application.
|
||
- Direct assign an application to a Pusat, Saluran, or KTM team.
|
||
- Edit an existing staff assignment.
|
||
- Create Police, KKM, and JKM representative records.
|
||
- Close the registration period for the election and confirm Admin changes require catatan.
|
||
- Log in as `kewangan@prn.local` / `password` and confirm `/admin/management/assignments` is forbidden.
|
||
|
||
Pending items:
|
||
|
||
- Admin document viewing route for IC/bank statement remains for the finance/document module.
|
||
- Excel export implementation remains in later finance/export phases.
|
||
- More granular representative edit forms can be added if operational users need inline correction instead of delete/recreate.
|
||
|
||
Next step:
|
||
|
||
- Phase 8: Admin Kewangan module for bank verification, finance filters, and finance export.
|
||
|
||
## 2026-05-29 - Phase 8: Admin Kewangan
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Added finance bank verification routes under `/kewangan/bank`.
|
||
- Added Admin Kewangan list of approved/assigned staff bank records.
|
||
- Added filters for status, Pusat Mengundi, role, missing bank statement, missing account number, and keyword.
|
||
- Added bank verification detail screen.
|
||
- Added finance status update with finance note, verified by, and verified at.
|
||
- Added activity log for finance verification changes.
|
||
- Added sensitive display masking helper.
|
||
- Added finance XLSX export using OpenSpout.
|
||
- Added export log creation for finance exports.
|
||
- Updated Admin Kewangan dashboard with live counts and module links.
|
||
- Added Phase 8 feature tests.
|
||
|
||
Changed files:
|
||
|
||
- `app/Exports/FinanceVerificationExport.php`
|
||
- `app/Http/Controllers/DashboardController.php`
|
||
- `app/Http/Controllers/Kewangan/BankVerificationController.php`
|
||
- `app/Http/Requests/Kewangan/UpdateBankVerificationRequest.php`
|
||
- `app/Services/Finance/BankVerificationService.php`
|
||
- `app/Services/Finance/FinanceExportService.php`
|
||
- `app/Services/Finance/FinanceVerificationQuery.php`
|
||
- `app/Support/SensitiveData.php`
|
||
- `resources/views/kewangan/bank/index.blade.php`
|
||
- `resources/views/kewangan/bank/show.blade.php`
|
||
- `routes/web.php`
|
||
- `tests/Feature/FinanceModuleTest.php`
|
||
- `docs/01-development-plan.md`
|
||
- `docs/04-rbac-permission-matrix.md`
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/07-testing-plan.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Verification:
|
||
|
||
- `php artisan route:list --except-vendor` passed and shows 95 routes.
|
||
- `php artisan test --filter=FinanceModuleTest` passed: 5 tests, 18 assertions.
|
||
- `php artisan test` passed: 63 tests, 222 assertions.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` passed.
|
||
- `vendor\bin\pint.bat --test` passed.
|
||
- `npm.cmd run build` passed.
|
||
|
||
Manual testing:
|
||
|
||
- Log in as `kewangan@prn.local` / `password`.
|
||
- Open `/kewangan/bank`.
|
||
- Filter records by Pusat, role, status, missing bank statement, and missing account number.
|
||
- Open a bank verification record.
|
||
- Mark it verified, rejected, or requires correction with a finance note.
|
||
- Export the finance list and confirm a file downloads.
|
||
- Confirm `/admin/management/assignments` is forbidden for Admin Kewangan.
|
||
|
||
Pending items:
|
||
|
||
- Admin/Admin Kewangan authorized document download for bank statement remains to be added when document review UX is finalized.
|
||
- Additional finance export formats can be added if official template is provided.
|
||
|
||
Next step:
|
||
|
||
- Phase 9: Wheelchair management.
|
||
|
||
## 2026-05-29 - Phase 9: Wheelchair Management
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Added Admin wheelchair management routes under `/admin/management/wheelchairs`.
|
||
- Added allocation upsert per election and Pusat Mengundi.
|
||
- Added wheelchair management service for allocation and transaction rules.
|
||
- Added taken transaction recording with quantity, time, person taking, and notes.
|
||
- Added return transaction recording with quantity, time, condition, and notes.
|
||
- Added quantity guards for allocation, available balance, and outstanding return balance.
|
||
- Added activity logging for allocation and transaction changes.
|
||
- Added wheelchair list and detail screens.
|
||
- Updated Admin management dashboard and navigation.
|
||
- Added Phase 9 feature tests.
|
||
|
||
Changed files:
|
||
|
||
- `app/Http/Controllers/Admin/Management/AdminManagementController.php`
|
||
- `app/Http/Controllers/Admin/Management/WheelchairController.php`
|
||
- `app/Http/Requests/Admin/Management/StoreWheelchairTransactionRequest.php`
|
||
- `app/Http/Requests/Admin/Management/UpsertWheelchairAllocationRequest.php`
|
||
- `app/Services/Admin/Management/WheelchairManagementService.php`
|
||
- `resources/views/admin/management/_nav.blade.php`
|
||
- `resources/views/admin/management/index.blade.php`
|
||
- `resources/views/admin/management/wheelchairs/index.blade.php`
|
||
- `resources/views/admin/management/wheelchairs/show.blade.php`
|
||
- `routes/web.php`
|
||
- `tests/Feature/WheelchairManagementTest.php`
|
||
- `docs/01-development-plan.md`
|
||
- `docs/04-rbac-permission-matrix.md`
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/07-testing-plan.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Verification:
|
||
|
||
- `php artisan route:list --except-vendor` passed and shows 100 routes.
|
||
- `php artisan test --filter=WheelchairManagementTest` passed: 6 tests, 16 assertions.
|
||
- `php artisan test` passed: 69 tests, 238 assertions.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` passed.
|
||
- `vendor\bin\pint.bat --test` passed.
|
||
- `npm.cmd run build` passed.
|
||
|
||
Manual testing:
|
||
|
||
- Log in as `admin@prn.local` / `password`.
|
||
- Open `/admin/management/wheelchairs`.
|
||
- Create or update a wheelchair allocation for a Pusat Mengundi.
|
||
- Open the allocation detail screen.
|
||
- Record wheelchair taken transaction.
|
||
- Record wheelchair returned transaction with condition `baik` or `rosak`.
|
||
- Try taking more than available and confirm validation blocks it.
|
||
- Try returning more than outstanding and confirm validation blocks it.
|
||
- Try lowering allocation below outstanding and confirm validation blocks it.
|
||
- Log in as `kewangan@prn.local` / `password` and confirm wheelchair management is forbidden.
|
||
|
||
Pending items:
|
||
|
||
- Phase 10 attendance module.
|
||
- Optional wheelchair export/report if later required.
|
||
|
||
Next step:
|
||
|
||
- Phase 10: Attendance module.
|
||
|
||
## 2026-05-29 - Phase 10: Attendance Module
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Added PPM attendance routes under `/ppm/attendance`.
|
||
- Added PPM attendance list for assigned Pusat Mengundi.
|
||
- Added PPM attendance recording screen for active staff under own Pusat Mengundi.
|
||
- Added attendance activation guard using `election_settings.is_attendance_active`.
|
||
- Added bulk attendance recording service.
|
||
- Added activity log entries for attendance updates.
|
||
- Added Admin attendance routes under `/admin/attendance`.
|
||
- Added Admin attendance dashboard by Pusat Mengundi.
|
||
- Added Admin attendance detail view with staff, role, Saluran, status, check-in time, notes, and recorded by.
|
||
- Added attendance summary service with totals and role-level summary.
|
||
- Added attendance detail XLSX export using OpenSpout.
|
||
- Added export log creation for attendance exports.
|
||
- Updated Admin and PPM dashboard links/metrics.
|
||
- Added Phase 10 feature and unit tests.
|
||
|
||
Changed files:
|
||
|
||
- `app/Exports/AttendanceDetailExport.php`
|
||
- `app/Http/Controllers/Admin/AttendanceController.php`
|
||
- `app/Http/Controllers/DashboardController.php`
|
||
- `app/Http/Controllers/Ppm/AttendanceController.php`
|
||
- `app/Http/Requests/Ppm/RecordAttendanceRequest.php`
|
||
- `app/Services/Attendance/AttendanceExportService.php`
|
||
- `app/Services/Attendance/AttendanceRecordingService.php`
|
||
- `app/Services/Attendance/AttendanceSummaryService.php`
|
||
- `resources/views/admin/attendance/index.blade.php`
|
||
- `resources/views/admin/attendance/show.blade.php`
|
||
- `resources/views/ppm/attendance/index.blade.php`
|
||
- `resources/views/ppm/attendance/show.blade.php`
|
||
- `routes/web.php`
|
||
- `tests/Feature/AttendanceModuleTest.php`
|
||
- `tests/Unit/AttendanceSummaryServiceTest.php`
|
||
- `docs/01-development-plan.md`
|
||
- `docs/04-rbac-permission-matrix.md`
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/07-testing-plan.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Verification:
|
||
|
||
- `php artisan route:list --except-vendor` passed and shows 106 routes.
|
||
- `php artisan test --filter=Attendance` passed: 7 tests, 21 assertions.
|
||
- `php artisan test` passed: 76 tests, 259 assertions.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` passed.
|
||
- `vendor\bin\pint.bat --test` passed.
|
||
- `npm.cmd run build` passed.
|
||
|
||
Manual testing:
|
||
|
||
- Activate attendance for the election in database/settings.
|
||
- Log in as `ppm@prn.local` / `password`.
|
||
- Open `/ppm/attendance`.
|
||
- Record present/absent/not recorded statuses for staff under own Pusat Mengundi.
|
||
- Confirm PPM cannot access or record another Pusat Mengundi.
|
||
- Log in as `admin@prn.local` / `password`.
|
||
- Open `/admin/attendance`.
|
||
- View Pusat Mengundi summary and detail.
|
||
- Export attendance detail and confirm file downloads.
|
||
- Log in as `kewangan@prn.local` / `password` and confirm Admin attendance dashboard is forbidden.
|
||
|
||
Pending items:
|
||
|
||
- Admin settings UI to toggle `is_attendance_active` if operational users need UI control.
|
||
- Official attendance report template can replace the current export layout when provided.
|
||
|
||
Next step:
|
||
|
||
- Phase 11: Testing, polish, security review, performance review, and final hardening.
|
||
|
||
## 2026-05-29 - Phase 11: Testing, Polish, and Hardening
|
||
|
||
Status: Completed
|
||
|
||
Completed:
|
||
|
||
- Reviewed authorization, private document access, sensitive data masking, exports, and quality gates.
|
||
- Added Admin document download route for private application documents.
|
||
- Added Admin Kewangan bank statement download route.
|
||
- Restricted finance document downloads to `bank_statement` only.
|
||
- Added activity logging for Admin and finance document downloads.
|
||
- Added secure document links to Admin application edit and finance bank detail screens.
|
||
- Added feature tests for Admin/Admin Kewangan/unauthorized document access.
|
||
- Added unit test for sensitive data masking.
|
||
- Updated deployment notes with final quality gate commands and document storage hardening notes.
|
||
- Updated Phase 11 documentation and release notes.
|
||
|
||
Changed files:
|
||
|
||
- `app/Http/Controllers/DocumentDownloadController.php`
|
||
- `app/Http/Controllers/Admin/Management/ManagedApplicationController.php`
|
||
- `resources/views/admin/management/applications/edit.blade.php`
|
||
- `resources/views/kewangan/bank/show.blade.php`
|
||
- `routes/web.php`
|
||
- `tests/Feature/DocumentDownloadAuthorizationTest.php`
|
||
- `tests/Unit/SensitiveDataTest.php`
|
||
- `docs/01-development-plan.md`
|
||
- `docs/07-testing-plan.md`
|
||
- `docs/08-deployment-notes.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Verification:
|
||
|
||
- `php artisan test --filter=DocumentDownloadAuthorizationTest` passed: 3 tests, 4 assertions.
|
||
- `php artisan test --filter=SensitiveDataTest` passed: 1 test, 4 assertions.
|
||
- `php artisan route:list --except-vendor` passed and shows 108 routes.
|
||
- `php artisan test` passed: 80 tests, 267 assertions.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` passed.
|
||
- `vendor\bin\pint.bat --test` passed.
|
||
- `npm.cmd run build` passed.
|
||
|
||
Manual testing:
|
||
|
||
- Log in as `admin@prn.local` / `password`.
|
||
- Open an application with uploaded documents and download IC/bank documents.
|
||
- Log in as `kewangan@prn.local` / `password`.
|
||
- Open bank verification detail and download bank statement.
|
||
- Confirm Admin Kewangan cannot download IC document through finance document route.
|
||
- Run end-to-end smoke test from QR application to attendance export.
|
||
|
||
Pending items:
|
||
|
||
- Replace current exports with official report templates if/when provided.
|
||
- Add Admin UI toggle for attendance activation if operational users need it outside database/settings maintenance.
|
||
|
||
Next step:
|
||
|
||
- Production readiness review with real environment credentials, mail transport, queue worker, HTTPS, backup plan, and user acceptance testing.
|
||
## 2026-05-31 - Penambahbaikan daftar Pusat Mengundi
|
||
|
||
### Selesai
|
||
|
||
- Membuang keperluan nama Saluran daripada borang dan validasi setup Saluran.
|
||
- Menambah sepuluh input bilangan operasi pada borang daftar Pusat Mengundi.
|
||
- Menjana Saluran bernombor serta kuota Pusat dan Saluran secara automatik semasa daftar Pusat.
|
||
- Menukar istilah Calon Simpanan kepada Calon Tambahan dengan migrasi data.
|
||
- Menambah ujian ciri untuk penciptaan Pusat, Saluran tanpa nama dan kuota operasi.
|
||
|
||
### Fail berubah
|
||
|
||
- `app/Services/Admin/PusatOperationalSetupService.php`
|
||
- `app/Http/Controllers/Admin/Setup/PusatMengundiController.php`
|
||
- `app/Http/Requests/Admin/Setup/UpsertPusatMengundiRequest.php`
|
||
- `app/Http/Requests/Admin/Setup/UpsertSaluranMengundiRequest.php`
|
||
- `resources/views/admin/setup/pusat/_form.blade.php`
|
||
- `resources/views/admin/setup/saluran/_form.blade.php`
|
||
- `database/migrations/2026_05_31_000000_rename_calon_simpanan_position_to_calon_tambahan.php`
|
||
- `database/seeders/PositionSeeder.php`
|
||
- `database/seeders/SampleElectionSeeder.php`
|
||
- `tests/Feature/Admin/PusatOperationalSetupTest.php`
|
||
|
||
### Semakan manual
|
||
|
||
- Buka `/admin/setup/pusat/create`, pastikan sepuluh medan bilangan operasi dipaparkan.
|
||
- Daftar Pusat baharu dan pastikan Saluran bernombor dijana tanpa meminta nama Saluran.
|
||
|
||
### Seterusnya
|
||
|
||
- Jalankan migrasi, ujian automatik dan semakan statik selepas shell runner tersedia.
|
||
|
||
## 2026-06-02 - Perancangan Fasa 12–15: Pembetulan dan Penambahbaikan
|
||
|
||
Status: Selesai (perancangan)
|
||
|
||
Selesai:
|
||
|
||
- Menjalankan semakan kod menyeluruh ke atas keseluruhan sistem selepas Phase 11 dan penambahbaikan 2026-05-31.
|
||
- Mengenal pasti lapan isu meliputi keselamatan, prestasi, pengalaman pengguna, dan pengurusan data.
|
||
- Menyusun isu-isu tersebut kepada empat fasa penambahbaikan berprioritikan (Fasa 12–15).
|
||
- Mendokumentasikan plan penuh dalam `docs/09-improvement-plan.md`.
|
||
- Mengemas kini `docs/01-development-plan.md` dengan ringkasan Fasa 12–15.
|
||
|
||
Fail berubah:
|
||
|
||
- `docs/09-improvement-plan.md` (baharu)
|
||
- `docs/01-development-plan.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Isu yang dikenal pasti:
|
||
|
||
- 12-A: Tiada UI toggle untuk `is_attendance_active` dan `is_registration_open_override` — memerlukan edit database terus dalam produksi.
|
||
- 12-B: Semakan IC duplikasi mungkin tidak mengecualikan soft-deleted records secara eksplisit dan konsisten.
|
||
- 12-C: `AdminPostCloseNoteService` boleh dipintas jika controller baharu lupa memanggilnya.
|
||
- 12-D: `SampleElectionSeeder` mungkin masih mengandungi rujukan kepada `CALON_SIMPANAN` selepas migration rename Phase 11.
|
||
- 12-E: Semakan jenis dokumen pada path download tidak sepenuhnya konsisten antara peranan.
|
||
- 13-A: Composite indexes belum wujud pada `applications`, `staff_assignments`, `bank_verifications` — boleh perlahan apabila data besar.
|
||
- 14-A: Tiada halaman status permohonan untuk pemohon awam — mereka perlu hubungi Admin untuk semak status.
|
||
- 15-A: Fail XLSX eksport sensitif disimpan tanpa had masa — polisi purge automatik diperlukan.
|
||
|
||
Seterusnya:
|
||
|
||
- Mulakan Fasa 12 dengan 12-A (Admin Settings UI) kerana ia paling mendesak untuk kebolehgunaan dalam persekitaran produksi.
|
||
|
||
## 2026-06-02 - Fasa 12-A: Admin Settings UI dan 12-D: Pembetulan Seeder
|
||
|
||
Status: Selesai
|
||
|
||
Selesai:
|
||
|
||
- Tambah halaman Admin Settings di `/admin/setup/settings/{election}` untuk toggle `is_attendance_active` dan `is_registration_open_override` tanpa perlu edit database.
|
||
- Tambah `ElectionSettingsController`, `ElectionSettingsService`, `UpdateElectionSettingsRequest`.
|
||
- Tambah view `admin/setup/settings/edit.blade.php` dengan toggle radio untuk kedua-dua tetapan, badge status semasa, dan amaran override aktif.
|
||
- Tambah pautan "Tetapan" (kuning) ke `admin/setup/_nav.blade.php` dan setup index actions.
|
||
- Perubahan tetapan direkod dalam `activity_log` dengan nilai sebelum dan selepas.
|
||
- Betulkan bug 12-D: `SampleElectionSeeder::seedQuotas()` masih query `CALON_SIMPANAN` — ditukar kepada `CALON_TAMBAHAN`.
|
||
- Betulkan `AdminSetupTest`: tambah medan operasi yang diperlukan untuk pusat.store, dan tukar nombor saluran dari '1' ke '3' untuk elak konflik dengan saluran auto-jana.
|
||
- Betulkan anotasi PHPDoc pada `UpdateElectionSettingsRequest::prepareForValidation()`.
|
||
- Tambah anotasi `@var ElectionSetting` pada `ElectionSettingsService` untuk PHPStan.
|
||
- Jalankan `pint` (auto-fix 2 fail) dan `phpstan` (0 error).
|
||
|
||
Fail berubah:
|
||
|
||
- `app/Http/Controllers/Admin/Setup/ElectionSettingsController.php` (baharu)
|
||
- `app/Http/Requests/Admin/Setup/UpdateElectionSettingsRequest.php` (baharu)
|
||
- `app/Services/Admin/ElectionSettingsService.php` (baharu)
|
||
- `resources/views/admin/setup/settings/edit.blade.php` (baharu)
|
||
- `resources/views/admin/setup/_nav.blade.php`
|
||
- `resources/views/admin/setup/index.blade.php`
|
||
- `routes/web.php`
|
||
- `database/seeders/SampleElectionSeeder.php`
|
||
- `tests/Feature/Admin/ElectionSettingsTest.php` (baharu)
|
||
- `tests/Feature/AdminSetupTest.php`
|
||
- `docs/04-rbac-permission-matrix.md`
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/09-improvement-plan.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Semakan:
|
||
|
||
- `php artisan route:list --except-vendor` — 110 routes (tambah 2).
|
||
- `php artisan test` — 90 tests, 310 assertions (**selesai, semua lulus**).
|
||
- `vendor\bin\pint.bat --test` — lulus.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` — lulus, 0 error.
|
||
|
||
Seterusnya:
|
||
|
||
- 12-B: Semak dan betulkan query IC duplikasi untuk pastikan soft-deleted records dikecualikan.
|
||
- 12-C: Perkukuh enforcement nota catatan post-pendaftaran.
|
||
- 12-E: Konsistensikan semakan jenis dokumen download.
|
||
|
||
## 2026-06-02 - Fasa 12-B: Pembetulan Semakan IC Soft-Deleted
|
||
|
||
Status: Selesai
|
||
|
||
Selesai:
|
||
|
||
- Audit menyeluruh semua lokasi semakan IC duplikasi: `StorePublicApplicationRequest::validateDuplicateIc()`, `KtmApplicationService::registerKp()`, `KtmVacancyService::remainingVacancy()`, dan `AssignmentVacancyService`.
|
||
- Disahkan bahawa kedua-dua query IC menggunakan SoftDeletes scope (mengecualikan `deleted_at IS NOT NULL`) DAN `whereNotIn('status', ['cancelled', 'deleted_by_ktm'])` — perlindungan dua lapis yang betul.
|
||
- `cancelled` records: dikecualikan oleh `whereNotIn` sahaja (bukan soft-deleted).
|
||
- `deleted_by_ktm` records: dikecualikan oleh kedua-dua SoftDeletes scope DAN `whereNotIn` (redundant safety layer).
|
||
- Tambah comment eksplisit pada kedua-dua query IC untuk mendokumentasikan intent perlindungan dua lapis ini.
|
||
- Tambah 2 ujian baharu dalam `PublicApplicationTest`:
|
||
- `test_public_registration_is_unblocked_after_ktm_deletes_applicant`: KTM cipta rekod, KTM delete (soft-delete + status deleted_by_ktm), pemohon awam dengan IC yang sama boleh daftar semula.
|
||
- `test_cancelled_application_does_not_block_new_registration`: Rekod `cancelled` (bukan soft-deleted) tidak menyekat pendaftaran IC yang sama.
|
||
- `KtmVacancyService` dan `AssignmentVacancyService` disahkan betul — menggunakan whitelist status dan `StaffAssignment` queries tidak melibatkan soft-deleted `Application` records secara salah.
|
||
|
||
Fail berubah:
|
||
|
||
- `app/Http/Requests/Public/StorePublicApplicationRequest.php` — tambah comment
|
||
- `app/Services/Ktm/KtmApplicationService.php` — tambah comment
|
||
- `tests/Feature/PublicApplicationTest.php` — tambah 2 ujian
|
||
- `docs/09-improvement-plan.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Semakan:
|
||
|
||
- `php artisan test` — 92 tests, 316 assertions (**semua lulus**).
|
||
- `vendor\bin\pint.bat --test` — lulus.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` — lulus, 0 error.
|
||
|
||
Seterusnya:
|
||
|
||
- 12-C: Perkukuh enforcement nota catatan post-pendaftaran.
|
||
- 12-E: Konsistensikan semakan jenis dokumen download.
|
||
|
||
## 2026-06-02 - Fasa 12-C: Perkukuh Enforcement Nota Catatan Post-Pendaftaran
|
||
|
||
Status: Selesai
|
||
|
||
Selesai:
|
||
|
||
- Audit semua 6 service methods yang mengubah rekod domain selepas pendaftaran tutup — kesemua sudah memanggil `AdminPostCloseNoteService::requireIfClosed()` dengan betul.
|
||
- Masalah: enforcement bergantung pada konvensyen — controller baharu boleh lupa panggil service tersebut.
|
||
- Tambah middleware `RequireAdminPostCloseNote` sebagai safety net automatik pada route group `admin/management`.
|
||
- Middleware menyemak `election_id` dari request body (untuk create routes) atau active election (untuk edit/delete routes). Jika pendaftaran ditutup dan `note` kosong, redirect balik dengan ralat validasi.
|
||
- Daftarkan alias `admin.post_close_note` dalam `bootstrap/app.php`.
|
||
- Apply middleware ke `['auth', 'role:Admin', 'admin.post_close_note']` dalam `routes/web.php`.
|
||
- Tambah 5 ujian baharu dalam `AdminManagementTest`:
|
||
- `test_admin_create_application_after_registration_closed_requires_catatan`
|
||
- `test_admin_update_assignment_after_registration_closed_requires_catatan`
|
||
- `test_admin_create_representative_after_registration_closed_requires_catatan`
|
||
- `test_admin_delete_representative_after_registration_closed_requires_catatan`
|
||
- `test_middleware_does_not_block_when_registration_is_open`
|
||
|
||
Fail berubah:
|
||
|
||
- `app/Http/Middleware/RequireAdminPostCloseNote.php` (baharu)
|
||
- `bootstrap/app.php` — alias middleware baharu
|
||
- `routes/web.php` — middleware pada route group management
|
||
- `tests/Feature/AdminManagementTest.php` — tambah 5 ujian
|
||
- `docs/decision-log.md`
|
||
- `docs/09-improvement-plan.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Semakan:
|
||
|
||
- `php artisan test` — 97 tests, 337 assertions (**semua lulus**).
|
||
- `vendor\bin\pint.bat --test` — lulus.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` — lulus, 0 error.
|
||
|
||
Seterusnya:
|
||
|
||
- 12-E: Konsistensikan semakan jenis dokumen download.
|
||
|
||
## 2026-06-02 - Fasa 13-A: Composite Indexes Pangkalan Data
|
||
|
||
Status: Selesai
|
||
|
||
Selesai:
|
||
|
||
- Audit index sedia ada berbanding query kritikal dalam `KtmVacancyService`, `AssignmentVacancyService`, `ManagedApplicationController`, dan `DashboardController`.
|
||
- Dapatan: dua index yang disenaraikan dalam plan sudah wujud — `(election_id, ic_number)` dan `(election_id, pusat_mengundi_id, status)` pada `applications`, serta dua index komposit pada `staff_assignments`.
|
||
- `bank_verifications` tiada kolum `election_id` — index `(election_id, status)` yang diancangkan dalam plan tidak relevan dan tidak ditambah.
|
||
- Tiga index baharu yang benar-benar diperlukan ditambah melalui migration `2026_06_02_000000_add_performance_indexes.php`:
|
||
- `applications.app_election_status_idx` — `(election_id, status)` untuk dashboard count queries
|
||
- `applications.app_ktm_position_idx` — `(selected_ktm_assignment_id, requested_position_id)` untuk `KtmVacancyService` reserved count
|
||
- `staff_assignments.sa_reports_to_pos_status_idx` — `(reports_to_assignment_id, position_id, status)` untuk `KtmVacancyService` assigned count
|
||
- Dokumentasi index lengkap ditambah dalam `docs/03-database-design.md`.
|
||
- Arahan verifikasi index dengan `SHOW INDEX` dan `EXPLAIN` ditambah dalam `docs/08-deployment-notes.md`.
|
||
|
||
Fail berubah:
|
||
|
||
- `database/migrations/2026_06_02_000000_add_performance_indexes.php` (baharu)
|
||
- `docs/03-database-design.md`
|
||
- `docs/08-deployment-notes.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/09-improvement-plan.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Semakan:
|
||
|
||
- `php artisan migrate` — lulus, 2 migration dijalankan.
|
||
- `php artisan test` — 97 tests, 337 assertions (**semua lulus**).
|
||
- `vendor\bin\pint.bat --test` — lulus.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` — lulus, 0 error.
|
||
|
||
Seterusnya:
|
||
|
||
- 12-E: Konsistensikan semakan jenis dokumen download.
|
||
- Fasa 14: Portal status permohonan pemohon awam.
|
||
- Fasa 15: Purge automatik fail eksport sensitif.
|
||
|
||
## 2026-06-02 - Fasa 12-E: Konsistensikan Semakan Jenis Dokumen Download
|
||
|
||
Status: Selesai
|
||
|
||
Selesai:
|
||
|
||
- Audit tiga path download dokumen — PPM, Admin, Finance (Admin Kewangan).
|
||
- Dapatan:
|
||
- PPM: tiada type check eksplisit, tiada activity log, ownership failure pakai 404 (patut 403).
|
||
- Admin: tiada type check eksplisit (senyap allow semua jenis).
|
||
- Finance: sudah betul — explicit `bank_statement` check, log activity, pakai 403.
|
||
- Tambah `ApplicationDocument::TYPE_IC_DOCUMENT`, `TYPE_BANK_STATEMENT`, `ALLOWED_FOR_ADMIN`, `ALLOWED_FOR_PPM`, `ALLOWED_FOR_FINANCE` sebagai constants dalam model — satu tempat yang autoriti untuk semua rules.
|
||
- Kemaskini `DocumentDownloadController::admin()` guna `ALLOWED_FOR_ADMIN` — jenis baharu perlu didaftarkan secara eksplisit untuk Admin dapat akses.
|
||
- Kemaskini `DocumentDownloadController::finance()` guna `ALLOWED_FOR_FINANCE` — logik sama, kini guna constant.
|
||
- Kemaskini `ApplicationReviewController::downloadDocument()`:
|
||
- Tambah `ALLOWED_FOR_PPM` type check → 403 jika jenis tidak dibenarkan.
|
||
- Tukar ownership check dari 404 → 403 (tidak mendedahkan kewujudan ID dokumen).
|
||
- Tambah activity log `document_downloaded_by_ppm`.
|
||
- Tambah 9 ujian baharu dalam `DocumentDownloadAuthorizationTest` meliputi semua tiga path dan kes utama:
|
||
- Admin: ic_document ✓, bank_statement ✓, peranan tidak dibenarkan ✗.
|
||
- Finance: bank_statement ✓, ic_document ✗.
|
||
- PPM: ic_document (pusat sendiri) ✓, bank_statement (pusat sendiri) ✓, dokumen pusat lain ✗, activity log disimpan.
|
||
|
||
Fail berubah:
|
||
|
||
- `app/Models/ApplicationDocument.php` — tambah type constants dan allowlist
|
||
- `app/Http/Controllers/DocumentDownloadController.php` — explicit type checks via constants
|
||
- `app/Http/Controllers/Ppm/ApplicationReviewController.php` — type check, 403, activity log
|
||
- `tests/Feature/DocumentDownloadAuthorizationTest.php` — tulis semula dengan 9 ujian komprehensif
|
||
- `docs/04-rbac-permission-matrix.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/09-improvement-plan.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Semakan:
|
||
|
||
- `php artisan test` — 103 tests, 342 assertions (**semua lulus**).
|
||
- `vendor\bin\pint.bat --test` — lulus.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` — lulus, 0 error.
|
||
|
||
Seterusnya:
|
||
|
||
- Fasa 14: Portal status permohonan pemohon awam.
|
||
- Fasa 15: Purge automatik fail eksport sensitif.
|
||
|
||
## 2026-06-02 - Fasa 14-A: Portal Status Permohonan Pemohon Awam
|
||
|
||
Status: Selesai
|
||
|
||
Selesai:
|
||
|
||
- Tambah route `GET /permohonan/{publicUuid}/status` tanpa route model binding untuk elak 404 mendedahkan kewujudan UUID.
|
||
- Tambah `PublicApplicationController::status()` yang mengendalikan semua kes dengan selamat:
|
||
- UUID tidak wujud → 200 dengan mesej generik.
|
||
- Rekod soft-deleted → 200 dengan mesej generik.
|
||
- Status `deleted_by_ktm` → 200 dengan mesej generik (tidak dedahkan status dalaman).
|
||
- Rekod aktif → 200 dengan data terhad.
|
||
- Tambah `SensitiveData::maskName()` — tunjuk 3 aksara pertama sahaja.
|
||
- Cipta view `public/applications/status.blade.php` memaparkan: nama disamarkan, jawatan dipohon, jawatan diluluskan (jika berbeza), pusat mengundi, badge status dengan warna, sebab penolakan (jika ditolak), nombor rujukan UUID.
|
||
- Kemaskini `success.blade.php` dengan panel simpan pautan status dan butang salin URL ke clipboard.
|
||
- Tambah 9 ujian baharu dalam `PublicApplicationStatusTest`:
|
||
- submitted, assigned, rejected (dengan sebab), UUID tidak dikenali, deleted_by_ktm, soft-deleted — semuanya.
|
||
- Nama penuh tidak dipaparkan, IC tidak dipaparkan.
|
||
- Halaman boleh dicapai tanpa log masuk.
|
||
- Success page paparkan pautan status.
|
||
|
||
Fail berubah:
|
||
|
||
- `app/Http/Controllers/PublicApplicationController.php` — tambah `status()`
|
||
- `app/Support/SensitiveData.php` — tambah `maskName()`
|
||
- `resources/views/public/applications/status.blade.php` (baharu)
|
||
- `resources/views/public/applications/success.blade.php` — tambah panel pautan status
|
||
- `routes/web.php` — route baharu
|
||
- `tests/Feature/PublicApplicationStatusTest.php` (baharu)
|
||
- `docs/05-workflow-design.md`
|
||
- `docs/06-ui-ux-plan.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/09-improvement-plan.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Semakan:
|
||
|
||
- `php artisan test` — 112 tests, 364 assertions (**semua lulus**).
|
||
- `vendor\bin\pint.bat --test` — lulus.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` — lulus, 0 error.
|
||
|
||
Seterusnya:
|
||
|
||
- Fasa 15: Purge automatik fail eksport sensitif.
|
||
|
||
## 2026-06-02 - Fasa 15-A: Purge Automatik Fail Eksport Sensitif
|
||
|
||
Status: Selesai
|
||
|
||
Selesai:
|
||
|
||
- Tambah kolum `purged_at` (nullable timestamp) dan `purged_by_user_id` (nullable FK) pada `export_logs` melalui migration `2026_06_02_000001_add_purged_at_to_export_logs.php`.
|
||
- Kemaskini model `ExportLog` dengan cast `purged_at` dan relationship `purgedBy()`.
|
||
- Cipta Artisan command `ExportPurgeCommand` (`php artisan exports:purge --days=30`):
|
||
- Query `export_logs` di mana `created_at < now - days` DAN `purged_at IS NULL`.
|
||
- Padam fail dari storage disk yang berkaitan.
|
||
- Rekod yang filenya sudah tiada di disk tetap ditandakan `purged_at` supaya tidak diproses semula.
|
||
- Log aktiviti `export_file_purged` untuk setiap rekod.
|
||
- Lapor bilangan fail dipadamkan dan rekod tiada fail.
|
||
- Daftarkan command sebagai scheduled task harian pada `00:00` dalam `routes/console.php` (`--days=30`, withoutOverlapping, runInBackground).
|
||
- Tambah 7 ujian baharu dalam `ExportPurgeCommandTest`:
|
||
- Fail lama dipadamkan, `purged_at` ditetapkan.
|
||
- Fail dalam tempoh simpanan tidak disentuh.
|
||
- Rekod tanpa fail (`missing`) tetap ditandakan `purged_at`.
|
||
- Rekod yang sudah `purged_at` tidak diproses semula.
|
||
- `--days` custom berfungsi.
|
||
- Activity log direkod.
|
||
- `--days=0` gagal dengan exit code bukan 0.
|
||
|
||
Fail berubah:
|
||
|
||
- `database/migrations/2026_06_02_000001_add_purged_at_to_export_logs.php` (baharu)
|
||
- `app/Models/ExportLog.php` — tambah cast + relationship
|
||
- `app/Console/Commands/ExportPurgeCommand.php` (baharu)
|
||
- `routes/console.php` — scheduled task
|
||
- `tests/Feature/ExportPurgeCommandTest.php` (baharu)
|
||
- `docs/03-database-design.md`
|
||
- `docs/08-deployment-notes.md`
|
||
- `docs/decision-log.md`
|
||
- `docs/09-improvement-plan.md`
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
|
||
Semakan:
|
||
|
||
- `php artisan migrate` — lulus.
|
||
- `php artisan test` — 119 tests, 388 assertions (**semua lulus**).
|
||
- `vendor\bin\pint.bat --test` — lulus.
|
||
- `vendor\bin\phpstan.bat analyse --memory-limit=1G` — lulus, 0 error.
|
||
|
||
Semua fasa selesai (12-A hingga 15-A). Sistem sedia untuk UAT.
|