52 KiB
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.mdproject instruction file is present. - Checked local tooling:
- PHP 8.5.1 available.
- Composer 2.9.4 available.
- Node 25.1.0 available.
npm.cmd11.14.1 available.npmPowerShell shim blocked by execution policy.- MySQL CLI not available in PATH.
- Created Phase 0 planning documentation.
Changed files:
docs/00-project-brief.mddocs/01-development-plan.mddocs/02-architecture.mddocs/03-database-design.mddocs/04-rbac-permission-matrix.mddocs/05-workflow-design.mddocs/06-ui-ux-plan.mddocs/07-testing-plan.mddocs/08-deployment-notes.mddocs/decision-log.mddocs/progress-log.mddocs/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_openin database and workflow design. - Recorded optional Telescope and DOMPDF decisions.
Changed files:
docs/01-development-plan.mddocs/03-database-design.mddocs/05-workflow-design.mddocs/decision-log.mddocs/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-permissionand published migrations/config. - Installed
spatie/laravel-activitylogand published migrations/config. - Installed
simplesoftwareio/simple-qrcode. - Attempted
maatwebsite/excel; Composer rejected it for PHP 8.5.1/Laravel 13 compatibility. - Installed
openspout/openspoutas compatible spreadsheet export foundation. - Installed Larastan/PHPStan.
- Added role middleware aliases.
- Added User
HasRolessupport. - 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.examplefor MySQL. - Set application timezone to
Asia/Kuala_Lumpur. - Kept local
.envon 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.phpapp/Models/User.phpbootstrap/app.phpconfig/activitylog.phpconfig/permission.phpconfig/prn.phpconfig/app.phpdatabase/migrations/*permission*database/migrations/*activity_log*database/seeders/DatabaseSeeder.phpdatabase/seeders/RolePermissionSeeder.phpresources/css/app.cssresources/js/app.jsresources/views/auth/*.blade.phpresources/views/dashboards/index.blade.phpresources/views/layouts/*.blade.phpresources/views/profile/edit.blade.phpresources/views/welcome.blade.phproutes/auth.phproutes/web.phptests/Feature/Auth/RegistrationTest.phptests/Feature/DashboardAccessTest.php.env.example.gitignorecomposer.jsoncomposer.lockpackage.jsonpackage-lock.jsonphpstan.neondocs/*
Verification:
php artisan migrate --seedcompleted after seeder correction.php artisan db:seedcompleted.npm.cmd run buildpassed.php artisan route:listpassed.php artisan testpassed: 27 tests, 64 assertions.vendor\bin\pint.bat --testpassed.vendor\bin\phpstan.bat analyse --memory-limit=1Gpassed.
Pending items:
- Confirm MySQL database credentials and switch local
.envto MySQL when available. - Implement Phase 2 core domain migrations/models/seeders.
- Replace OpenSpout with
maatwebsite/excelonly 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
- email:
- Confirm
/dashboardredirects Admin to/admin/dashboard. - Confirm
/registeris 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
DatabaseSeederto 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.phpapp/Models/*.phpdatabase/factories/*.phpdatabase/seeders/DatabaseSeeder.phpdatabase/seeders/PositionSeeder.phpdatabase/seeders/SampleElectionSeeder.phptests/Feature/CoreDomainSeederTest.phpdocs/00-project-brief.mddocs/01-development-plan.mddocs/03-database-design.mddocs/07-testing-plan.mddocs/08-deployment-notes.mddocs/decision-log.mddocs/progress-log.mddocs/changelog.md
Verification:
php artisan migrate:fresh --seedpassed on MySQL databaseprn2026.php artisan testpassed: 28 tests, 80 assertions.vendor\bin\pint.bat --testpassed.vendor\bin\phpstan.bat analyse --memory-limit=1Gpassed.
Manual testing:
- Log in as
admin@prn.local/password. - Confirm base dashboard loads after fresh seed.
- Optional sample accounts:
kewangan@prn.local/passwordppm@prn.local/passwordktm@prn.local/password
- Confirm
/dashboardredirects 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.phpapp/Http/Controllers/Admin/Setup/BahagianPilihanrayaController.phpapp/Http/Controllers/Admin/Setup/DaerahMengundiController.phpapp/Http/Controllers/Admin/Setup/PositionController.phpapp/Http/Controllers/Admin/Setup/PositionQuotaController.phpapp/Http/Controllers/Admin/Setup/PusatMengundiController.phpapp/Http/Controllers/Admin/Setup/SaluranMengundiController.phpapp/Http/Controllers/DashboardController.phpapp/Http/Controllers/PublicApplicationPlaceholderController.phpapp/Http/Requests/Admin/Setup/*.phpapp/Services/Admin/PpmAssignmentService.phpapp/Services/Admin/PusatQrCodeService.phpresources/views/admin/setup/**/*.blade.phpresources/views/dashboards/index.blade.phpresources/views/layouts/public.blade.phpresources/views/public/application-placeholder.blade.phproutes/web.phptests/Feature/AdminSetupTest.phpdocs/01-development-plan.mddocs/05-workflow-design.mddocs/decision-log.mddocs/progress-log.mddocs/changelog.md
Verification:
php artisan route:list --except-vendorpassed and shows 65 routes.php artisan test --filter=AdminSetupTestpassed: 4 tests, 24 assertions.php artisan testpassed: 32 tests, 104 assertions.vendor\bin\pint.bat --testpassed.vendor\bin\phpstan.bat analyse --memory-limit=1Gpassed.npm.cmd run buildpassed.
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/passwordand confirm/admin/setupis 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
RegistrationPeriodServicefor registration open/closed checks. - Added
KtmVacancyServicefor KP/KPDP KTM selection and vacancy calculation. - Added
PublicApplicationSubmissionServicefor transactional application creation, private document storage, status history, bank verification initialization, and activity logging. - Added
StorePublicApplicationRequestwith 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_verificationsrow for public submissions. - Added Phase 4 feature tests and unit tests.
Changed files:
app/Http/Controllers/PublicApplicationController.phpapp/Http/Requests/Public/StorePublicApplicationRequest.phpapp/Services/RegistrationPeriodService.phpapp/Services/Public/KtmVacancyService.phpapp/Services/Public/PublicApplicationSubmissionService.phpresources/views/layouts/public.blade.phpresources/views/public/applications/create.blade.phpresources/views/public/applications/closed.blade.phpresources/views/public/applications/success.blade.phproutes/web.phptests/Feature/PublicApplicationTest.phptests/Unit/KtmVacancyServiceTest.phptests/Unit/RegistrationPeriodServiceTest.phpdocs/01-development-plan.mddocs/03-database-design.mddocs/05-workflow-design.mddocs/07-testing-plan.mddocs/decision-log.mddocs/progress-log.mddocs/changelog.md
Verification:
php artisan route:list --except-vendorpassed and shows 67 routes.php artisan test --filter=PublicApplicationTestpassed: 6 tests, 27 assertions.php artisan testpassed: 41 tests, 137 assertions.vendor\bin\pint.bat --testpassed.vendor\bin\phpstan.bat analyse --memory-limit=1Gpassed.npm.cmd run buildpassed.
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_ktmapplication 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
ApplicationPolicyandPpmScopeServicefor record-level PPM access control. - Added
PpmApplicationReviewServicefor transactional approve/reject behavior. - Added
AssignmentVacancyServicefor Pusat/Saluran quota checks. - Extended
KtmVacancyServiceto 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
AuthorizesRequeststo the base controller for policy authorization. - Added Phase 5 feature tests.
Changed files:
app/Http/Controllers/Controller.phpapp/Http/Controllers/DashboardController.phpapp/Http/Controllers/Ppm/ApplicationReviewController.phpapp/Http/Requests/Ppm/ApproveApplicationRequest.phpapp/Http/Requests/Ppm/RejectApplicationRequest.phpapp/Models/PusatMengundi.phpapp/Policies/ApplicationPolicy.phpapp/Services/Ppm/AssignmentVacancyService.phpapp/Services/Ppm/PpmApplicationReviewService.phpapp/Services/Ppm/PpmScopeService.phpapp/Services/Public/KtmVacancyService.phpresources/views/ppm/applications/index.blade.phpresources/views/ppm/applications/show.blade.phproutes/web.phptests/Feature/PpmApplicationReviewTest.phpdocs/01-development-plan.mddocs/04-rbac-permission-matrix.mddocs/05-workflow-design.mddocs/07-testing-plan.mddocs/decision-log.mddocs/progress-log.mddocs/changelog.md
Verification:
php artisan route:list --except-vendorpassed and shows 72 routes.php artisan test --filter=PpmApplicationReviewTestpassed: 6 tests, 24 assertions.php artisan testpassed: 47 tests, 161 assertions.vendor\bin\pint.bat --testpassed.vendor\bin\phpstan.bat analyse --memory-limit=1Gpassed.npm.cmd run buildpassed.
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
KtmScopeServicefor active KTM assignment ownership checks. - Added
KtmApplicationServicefor 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_ktmfor 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.phpapp/Http/Controllers/Ktm/TeamController.phpapp/Http/Requests/Ktm/RegisterKpApplicantRequest.phpapp/Mail/KtmCreatedApplicantMail.phpapp/Services/Ktm/KtmApplicationService.phpapp/Services/Ktm/KtmScopeService.phpapp/Services/Public/KtmVacancyService.phpresources/views/emails/ktm/created-applicant.blade.phpresources/views/ktm/applications/create.blade.phpresources/views/ktm/applications/index.blade.phpresources/views/ktm/applications/show.blade.phproutes/web.phptests/Feature/KtmFlowTest.phpdocs/01-development-plan.mddocs/04-rbac-permission-matrix.mddocs/05-workflow-design.mddocs/07-testing-plan.mddocs/decision-log.mddocs/progress-log.mddocs/changelog.md
Verification:
php artisan route:list --except-vendorpassed and shows 78 routes.php artisan test --filter=KtmFlowTestpassed: 6 tests, 25 assertions.php artisan testpassed: 53 tests, 186 assertions.vendor\bin\pint.bat --testpassed.vendor\bin\phpstan.bat analyse --memory-limit=1Gpassed.npm.cmd run buildpassed.
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_notesrecords 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.phpapp/Http/Controllers/Admin/Management/ManagedApplicationController.phpapp/Http/Controllers/Admin/Management/RepresentativeController.phpapp/Http/Controllers/Admin/Management/StaffAssignmentController.phpapp/Http/Controllers/DashboardController.phpapp/Http/Requests/Admin/Management/*.phpapp/Services/Admin/Management/*.phpresources/views/admin/management/**/*.blade.phproutes/web.phptests/Feature/AdminManagementTest.phpdocs/01-development-plan.mddocs/04-rbac-permission-matrix.mddocs/05-workflow-design.mddocs/07-testing-plan.mddocs/decision-log.mddocs/progress-log.mddocs/changelog.md
Verification:
php artisan route:list --except-vendorpassed and shows 91 routes.php artisan test --filter=AdminManagementTestpassed: 5 tests, 18 assertions.php artisan testpassed: 58 tests, 204 assertions.vendor\bin\phpstan.bat analyse --memory-limit=1Gpassed.vendor\bin\pint.bat --testpassed.npm.cmd run buildpassed.
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/passwordand confirm/admin/management/assignmentsis 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.phpapp/Http/Controllers/DashboardController.phpapp/Http/Controllers/Kewangan/BankVerificationController.phpapp/Http/Requests/Kewangan/UpdateBankVerificationRequest.phpapp/Services/Finance/BankVerificationService.phpapp/Services/Finance/FinanceExportService.phpapp/Services/Finance/FinanceVerificationQuery.phpapp/Support/SensitiveData.phpresources/views/kewangan/bank/index.blade.phpresources/views/kewangan/bank/show.blade.phproutes/web.phptests/Feature/FinanceModuleTest.phpdocs/01-development-plan.mddocs/04-rbac-permission-matrix.mddocs/05-workflow-design.mddocs/07-testing-plan.mddocs/decision-log.mddocs/progress-log.mddocs/changelog.md
Verification:
php artisan route:list --except-vendorpassed and shows 95 routes.php artisan test --filter=FinanceModuleTestpassed: 5 tests, 18 assertions.php artisan testpassed: 63 tests, 222 assertions.vendor\bin\phpstan.bat analyse --memory-limit=1Gpassed.vendor\bin\pint.bat --testpassed.npm.cmd run buildpassed.
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/assignmentsis 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.phpapp/Http/Controllers/Admin/Management/WheelchairController.phpapp/Http/Requests/Admin/Management/StoreWheelchairTransactionRequest.phpapp/Http/Requests/Admin/Management/UpsertWheelchairAllocationRequest.phpapp/Services/Admin/Management/WheelchairManagementService.phpresources/views/admin/management/_nav.blade.phpresources/views/admin/management/index.blade.phpresources/views/admin/management/wheelchairs/index.blade.phpresources/views/admin/management/wheelchairs/show.blade.phproutes/web.phptests/Feature/WheelchairManagementTest.phpdocs/01-development-plan.mddocs/04-rbac-permission-matrix.mddocs/05-workflow-design.mddocs/07-testing-plan.mddocs/decision-log.mddocs/progress-log.mddocs/changelog.md
Verification:
php artisan route:list --except-vendorpassed and shows 100 routes.php artisan test --filter=WheelchairManagementTestpassed: 6 tests, 16 assertions.php artisan testpassed: 69 tests, 238 assertions.vendor\bin\phpstan.bat analyse --memory-limit=1Gpassed.vendor\bin\pint.bat --testpassed.npm.cmd run buildpassed.
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
baikorrosak. - 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/passwordand 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.phpapp/Http/Controllers/Admin/AttendanceController.phpapp/Http/Controllers/DashboardController.phpapp/Http/Controllers/Ppm/AttendanceController.phpapp/Http/Requests/Ppm/RecordAttendanceRequest.phpapp/Services/Attendance/AttendanceExportService.phpapp/Services/Attendance/AttendanceRecordingService.phpapp/Services/Attendance/AttendanceSummaryService.phpresources/views/admin/attendance/index.blade.phpresources/views/admin/attendance/show.blade.phpresources/views/ppm/attendance/index.blade.phpresources/views/ppm/attendance/show.blade.phproutes/web.phptests/Feature/AttendanceModuleTest.phptests/Unit/AttendanceSummaryServiceTest.phpdocs/01-development-plan.mddocs/04-rbac-permission-matrix.mddocs/05-workflow-design.mddocs/07-testing-plan.mddocs/decision-log.mddocs/progress-log.mddocs/changelog.md
Verification:
php artisan route:list --except-vendorpassed and shows 106 routes.php artisan test --filter=Attendancepassed: 7 tests, 21 assertions.php artisan testpassed: 76 tests, 259 assertions.vendor\bin\phpstan.bat analyse --memory-limit=1Gpassed.vendor\bin\pint.bat --testpassed.npm.cmd run buildpassed.
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/passwordand confirm Admin attendance dashboard is forbidden.
Pending items:
- Admin settings UI to toggle
is_attendance_activeif 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_statementonly. - 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.phpapp/Http/Controllers/Admin/Management/ManagedApplicationController.phpresources/views/admin/management/applications/edit.blade.phpresources/views/kewangan/bank/show.blade.phproutes/web.phptests/Feature/DocumentDownloadAuthorizationTest.phptests/Unit/SensitiveDataTest.phpdocs/01-development-plan.mddocs/07-testing-plan.mddocs/08-deployment-notes.mddocs/decision-log.mddocs/progress-log.mddocs/changelog.md
Verification:
php artisan test --filter=DocumentDownloadAuthorizationTestpassed: 3 tests, 4 assertions.php artisan test --filter=SensitiveDataTestpassed: 1 test, 4 assertions.php artisan route:list --except-vendorpassed and shows 108 routes.php artisan testpassed: 80 tests, 267 assertions.vendor\bin\phpstan.bat analyse --memory-limit=1Gpassed.vendor\bin\pint.bat --testpassed.npm.cmd run buildpassed.
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.phpapp/Http/Controllers/Admin/Setup/PusatMengundiController.phpapp/Http/Requests/Admin/Setup/UpsertPusatMengundiRequest.phpapp/Http/Requests/Admin/Setup/UpsertSaluranMengundiRequest.phpresources/views/admin/setup/pusat/_form.blade.phpresources/views/admin/setup/saluran/_form.blade.phpdatabase/migrations/2026_05_31_000000_rename_calon_simpanan_position_to_calon_tambahan.phpdatabase/seeders/PositionSeeder.phpdatabase/seeders/SampleElectionSeeder.phptests/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.mddengan ringkasan Fasa 12–15.
Fail berubah:
docs/09-improvement-plan.md(baharu)docs/01-development-plan.mddocs/progress-log.mddocs/changelog.md
Isu yang dikenal pasti:
- 12-A: Tiada UI toggle untuk
is_attendance_activedanis_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:
AdminPostCloseNoteServiceboleh dipintas jika controller baharu lupa memanggilnya. - 12-D:
SampleElectionSeedermungkin masih mengandungi rujukan kepadaCALON_SIMPANANselepas 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 toggleis_attendance_activedanis_registration_open_overridetanpa perlu edit database. - Tambah
ElectionSettingsController,ElectionSettingsService,UpdateElectionSettingsRequest. - Tambah view
admin/setup/settings/edit.blade.phpdengan toggle radio untuk kedua-dua tetapan, badge status semasa, dan amaran override aktif. - Tambah pautan "Tetapan" (kuning) ke
admin/setup/_nav.blade.phpdan setup index actions. - Perubahan tetapan direkod dalam
activity_logdengan nilai sebelum dan selepas. - Betulkan bug 12-D:
SampleElectionSeeder::seedQuotas()masih queryCALON_SIMPANAN— ditukar kepadaCALON_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 ElectionSettingpadaElectionSettingsServiceuntuk PHPStan. - Jalankan
pint(auto-fix 2 fail) danphpstan(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.phpresources/views/admin/setup/index.blade.phproutes/web.phpdatabase/seeders/SampleElectionSeeder.phptests/Feature/Admin/ElectionSettingsTest.php(baharu)tests/Feature/AdminSetupTest.phpdocs/04-rbac-permission-matrix.mddocs/05-workflow-design.mddocs/09-improvement-plan.mddocs/decision-log.mddocs/progress-log.mddocs/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(), danAssignmentVacancyService. - Disahkan bahawa kedua-dua query IC menggunakan SoftDeletes scope (mengecualikan
deleted_at IS NOT NULL) DANwhereNotIn('status', ['cancelled', 'deleted_by_ktm'])— perlindungan dua lapis yang betul. cancelledrecords: dikecualikan olehwhereNotInsahaja (bukan soft-deleted).deleted_by_ktmrecords: dikecualikan oleh kedua-dua SoftDeletes scope DANwhereNotIn(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: Rekodcancelled(bukan soft-deleted) tidak menyekat pendaftaran IC yang sama.
KtmVacancyServicedanAssignmentVacancyServicedisahkan betul — menggunakan whitelist status danStaffAssignmentqueries tidak melibatkan soft-deletedApplicationrecords secara salah.
Fail berubah:
app/Http/Requests/Public/StorePublicApplicationRequest.php— tambah commentapp/Services/Ktm/KtmApplicationService.php— tambah commenttests/Feature/PublicApplicationTest.php— tambah 2 ujiandocs/09-improvement-plan.mddocs/progress-log.mddocs/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
RequireAdminPostCloseNotesebagai safety net automatik pada route groupadmin/management. - Middleware menyemak
election_iddari request body (untuk create routes) atau active election (untuk edit/delete routes). Jika pendaftaran ditutup dannotekosong, redirect balik dengan ralat validasi. - Daftarkan alias
admin.post_close_notedalambootstrap/app.php. - Apply middleware ke
['auth', 'role:Admin', 'admin.post_close_note']dalamroutes/web.php. - Tambah 5 ujian baharu dalam
AdminManagementTest:test_admin_create_application_after_registration_closed_requires_catatantest_admin_update_assignment_after_registration_closed_requires_catatantest_admin_create_representative_after_registration_closed_requires_catatantest_admin_delete_representative_after_registration_closed_requires_catatantest_middleware_does_not_block_when_registration_is_open
Fail berubah:
app/Http/Middleware/RequireAdminPostCloseNote.php(baharu)bootstrap/app.php— alias middleware baharuroutes/web.php— middleware pada route group managementtests/Feature/AdminManagementTest.php— tambah 5 ujiandocs/decision-log.mddocs/09-improvement-plan.mddocs/progress-log.mddocs/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, danDashboardController. - Dapatan: dua index yang disenaraikan dalam plan sudah wujud —
(election_id, ic_number)dan(election_id, pusat_mengundi_id, status)padaapplications, serta dua index komposit padastaff_assignments. bank_verificationstiada kolumelection_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 queriesapplications.app_ktm_position_idx—(selected_ktm_assignment_id, requested_position_id)untukKtmVacancyServicereserved countstaff_assignments.sa_reports_to_pos_status_idx—(reports_to_assignment_id, position_id, status)untukKtmVacancyServiceassigned count
- Dokumentasi index lengkap ditambah dalam
docs/03-database-design.md. - Arahan verifikasi index dengan
SHOW INDEXdanEXPLAINditambah dalamdocs/08-deployment-notes.md.
Fail berubah:
database/migrations/2026_06_02_000000_add_performance_indexes.php(baharu)docs/03-database-design.mddocs/08-deployment-notes.mddocs/decision-log.mddocs/09-improvement-plan.mddocs/progress-log.mddocs/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_statementcheck, log activity, pakai 403.
- Tambah
ApplicationDocument::TYPE_IC_DOCUMENT,TYPE_BANK_STATEMENT,ALLOWED_FOR_ADMIN,ALLOWED_FOR_PPM,ALLOWED_FOR_FINANCEsebagai constants dalam model — satu tempat yang autoriti untuk semua rules. - Kemaskini
DocumentDownloadController::admin()gunaALLOWED_FOR_ADMIN— jenis baharu perlu didaftarkan secara eksplisit untuk Admin dapat akses. - Kemaskini
DocumentDownloadController::finance()gunaALLOWED_FOR_FINANCE— logik sama, kini guna constant. - Kemaskini
ApplicationReviewController::downloadDocument():- Tambah
ALLOWED_FOR_PPMtype 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
- Tambah 9 ujian baharu dalam
DocumentDownloadAuthorizationTestmeliputi 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 allowlistapp/Http/Controllers/DocumentDownloadController.php— explicit type checks via constantsapp/Http/Controllers/Ppm/ApplicationReviewController.php— type check, 403, activity logtests/Feature/DocumentDownloadAuthorizationTest.php— tulis semula dengan 9 ujian komprehensifdocs/04-rbac-permission-matrix.mddocs/decision-log.mddocs/09-improvement-plan.mddocs/progress-log.mddocs/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}/statustanpa 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.phpmemaparkan: nama disamarkan, jawatan dipohon, jawatan diluluskan (jika berbeza), pusat mengundi, badge status dengan warna, sebab penolakan (jika ditolak), nombor rujukan UUID. - Kemaskini
success.blade.phpdengan 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— tambahstatus()app/Support/SensitiveData.php— tambahmaskName()resources/views/public/applications/status.blade.php(baharu)resources/views/public/applications/success.blade.php— tambah panel pautan statusroutes/web.php— route baharutests/Feature/PublicApplicationStatusTest.php(baharu)docs/05-workflow-design.mddocs/06-ui-ux-plan.mddocs/decision-log.mddocs/09-improvement-plan.mddocs/progress-log.mddocs/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) danpurged_by_user_id(nullable FK) padaexport_logsmelalui migration2026_06_02_000001_add_purged_at_to_export_logs.php. - Kemaskini model
ExportLogdengan castpurged_atdan relationshippurgedBy(). - Cipta Artisan command
ExportPurgeCommand(php artisan exports:purge --days=30):- Query
export_logsdi manacreated_at < now - daysDANpurged_at IS NULL. - Padam fail dari storage disk yang berkaitan.
- Rekod yang filenya sudah tiada di disk tetap ditandakan
purged_atsupaya tidak diproses semula. - Log aktiviti
export_file_purgeduntuk setiap rekod. - Lapor bilangan fail dipadamkan dan rekod tiada fail.
- Query
- Daftarkan command sebagai scheduled task harian pada
00:00dalamroutes/console.php(--days=30, withoutOverlapping, runInBackground). - Tambah 7 ujian baharu dalam
ExportPurgeCommandTest:- Fail lama dipadamkan,
purged_atditetapkan. - Fail dalam tempoh simpanan tidak disentuh.
- Rekod tanpa fail (
missing) tetap ditandakanpurged_at. - Rekod yang sudah
purged_attidak diproses semula. --dayscustom berfungsi.- Activity log direkod.
--days=0gagal dengan exit code bukan 0.
- Fail lama dipadamkan,
Fail berubah:
database/migrations/2026_06_02_000001_add_purged_at_to_export_logs.php(baharu)app/Models/ExportLog.php— tambah cast + relationshipapp/Console/Commands/ExportPurgeCommand.php(baharu)routes/console.php— scheduled tasktests/Feature/ExportPurgeCommandTest.php(baharu)docs/03-database-design.mddocs/08-deployment-notes.mddocs/decision-log.mddocs/09-improvement-plan.mddocs/progress-log.mddocs/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.