324 lines
15 KiB
Markdown
324 lines
15 KiB
Markdown
# Improvement Plan
|
||
|
||
Dokumen ini mencatat pelan pembetulan dan penambahbaikan sistem PRN2026 selepas semakan kod menyeluruh selepas Phase 11 selesai. Setiap fasa mengikut susunan keutamaan: kritikal → prestasi → pengalaman pengguna → pengurusan data.
|
||
|
||
Setiap pembetulan dan perubahan wajib kemaskini:
|
||
|
||
- `docs/progress-log.md`
|
||
- `docs/changelog.md`
|
||
- `docs/decision-log.md` jika ada keputusan seni bina, pakej, pangkalan data atau keselamatan yang berubah
|
||
|
||
---
|
||
|
||
## Fasa 12: Pembetulan Kritikal dan Keselamatan
|
||
|
||
Status: Belum dimulakan.
|
||
|
||
Skop fasa ini ialah menangani kelemahan yang boleh menyebabkan data tidak konsisten, kawalan akses bocor, atau keperluan edit database secara manual dalam persekitaran produksi.
|
||
|
||
### 12-A: Admin Settings UI — Toggle Kehadiran dan Override Pendaftaran
|
||
|
||
Masalah semasa:
|
||
|
||
- `election_settings.is_attendance_active` hanya boleh diubah melalui edit database secara terus.
|
||
- `election_settings.is_registration_open_override` juga tiada UI khusus; bergantung pada pengaturan tarikh semata-mata.
|
||
- Ini tidak selamat dan tidak praktikal dalam persekitaran produksi semasa hari mengundi.
|
||
|
||
Tugas:
|
||
|
||
- Tambah halaman Admin Settings di bawah `/admin/settings` atau `/admin/setup/settings`.
|
||
- Paparkan toggle untuk `is_attendance_active` dengan label jelas dan amaran impak.
|
||
- Paparkan toggle atau dropdown untuk `is_registration_open_override` (null / buka paksa / tutup paksa).
|
||
- Paparkan tarikh buka dan tarikh tutup pendaftaran semasa sebagai konteks.
|
||
- Tambah `AdminSettingsController` dan `UpdateElectionSettingsRequest`.
|
||
- Tambah `ElectionSettingsService` untuk enkapsulasi logik kemaskini.
|
||
- Rekod perubahan dalam activity log: siapa, nilai lama, nilai baru, masa.
|
||
- Tambah ujian ciri untuk kemaskini setiap toggle, halaman diakses Admin sahaja.
|
||
- Tambah pautan ke Admin Settings dari Admin dashboard.
|
||
|
||
Kriteria keluar:
|
||
|
||
- Admin boleh toggle kehadiran dan override pendaftaran dari UI tanpa sentuh database.
|
||
- Perubahan direkod dalam activity log.
|
||
- Admin Kewangan, PPM, KTM tidak boleh akses halaman settings.
|
||
|
||
Dokumentasi yang perlu dikemaskini:
|
||
|
||
- `docs/01-development-plan.md` — tambah Fasa 12 dengan semua tugas dan kriteria keluar.
|
||
- `docs/04-rbac-permission-matrix.md` — tambah permission `manage election settings` untuk Admin.
|
||
- `docs/05-workflow-design.md` — tambah bahagian pengurusan tetapan pilihan raya.
|
||
- `docs/progress-log.md` — rekod selepas siap.
|
||
- `docs/changelog.md` — rekod selepas siap.
|
||
- `docs/decision-log.md` — rekod keputusan reka bentuk halaman settings.
|
||
|
||
---
|
||
|
||
### 12-B: Pembetulan Semakan IC Duplikasi untuk Rekod Soft-Deleted
|
||
|
||
Masalah semasa:
|
||
|
||
- Semakan IC duplikasi dalam `StorePublicApplicationRequest` menapis rekod aktif sahaja, tetapi soft-deleted KTM-created records masih wujud dalam pangkalan data.
|
||
- Jika KTM delete rekod pemohon (`deleted_by_ktm`), rekod tersebut soft-deleted tetapi IC dalam `applications` masih boleh menyebabkan konflik bergantung kepada cara query dikodkan.
|
||
- Risiko: pemohon awam mungkin diblock padahal KTM sudah delete rekod mereka.
|
||
|
||
Tugas:
|
||
|
||
- Semak semula query semakan IC duplikasi dalam `StorePublicApplicationRequest` dan mana-mana service yang menjalankan semakan serupa.
|
||
- Pastikan rekod `deleted_at IS NOT NULL` (soft-deleted) tidak diambil kira sebagai "aktif" dalam semakan duplikasi.
|
||
- Pastikan `withTrashed()` atau scoped query digunakan secara eksplisit dan konsisten.
|
||
- Tambah kes ujian: KTM delete rekod → pemohon awam dengan IC sama boleh mohon semula.
|
||
- Semak `KtmVacancyService` dan `AssignmentVacancyService` juga untuk memastikan tiada pengiraan yang termasuk soft-deleted rows secara tidak sengaja.
|
||
|
||
Kriteria keluar:
|
||
|
||
- Ujian baru lulus: soft-deleted KTM record tidak menghalang permohonan awam baharu.
|
||
- Semua semakan IC dalam system menggunakan kaedah yang sama dan konsisten.
|
||
|
||
Dokumentasi yang perlu dikemaskini:
|
||
|
||
- `docs/05-workflow-design.md` — perjelas bahawa soft-deleted records dikecualikan dari semakan IC aktif.
|
||
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
|
||
|
||
---
|
||
|
||
### 12-C: Perkukuh Enforcement Nota Catatan Post-Pendaftaran
|
||
|
||
Masalah semasa:
|
||
|
||
- `AdminPostCloseNoteService` menguatkuasakan keperluan `catatan` pada peringkat service layer.
|
||
- Jika ada controller baru yang lupa panggil service ini, semakan tidak berlaku dan Admin boleh edit rekod tanpa nota selepas pendaftaran ditutup tanpa sebarang amaran.
|
||
- Enforcement bergantung sepenuhnya pada konvensyen pemanggilan, bukan pada mekanisme framework.
|
||
|
||
Tugas:
|
||
|
||
- Semak semua controller Admin yang boleh mengubah `Application`, `StaffAssignment`, `PoliceEscort`, `KkmRepresentative`, atau `JkmRepresentative` selepas pendaftaran ditutup.
|
||
- Tambah senarai semak di `AdminPostCloseNoteService` yang boleh dipanggil secara konsisten.
|
||
- Pertimbangkan untuk tambah `middleware` khusus pada route group Admin management yang secara automatik menjalankan semakan ini, dan reject request tanpa `catatan` apabila pendaftaran ditutup.
|
||
- Jika middleware digunakan, dokumentasikan dalam `docs/decision-log.md`.
|
||
- Tambah ujian integrasi untuk setiap route Admin management yang sepatutnya enforce semakan ini.
|
||
|
||
Kriteria keluar:
|
||
|
||
- Semua route management Admin yang mengubah rekod domain enforce catatan secara konsisten apabila pendaftaran ditutup.
|
||
- Ujian baru mengesahkan enforcement pada setiap route yang berkenaan.
|
||
- Tiada jalan pintas yang boleh bypass semakan ini tanpa sengaja.
|
||
|
||
Dokumentasi yang perlu dikemaskini:
|
||
|
||
- `docs/05-workflow-design.md` — dokumentasikan mekanisme enforcement yang dipilih.
|
||
- `docs/decision-log.md` — rekod keputusan sama ada guna middleware atau service pattern.
|
||
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
|
||
|
||
---
|
||
|
||
### 12-D: Pembetulan SampleElectionSeeder dan Konsistensi Nama Jawatan
|
||
|
||
Masalah semasa:
|
||
|
||
- Selepas migrasi Phase 11 menukar `CALON_SIMPANAN` kepada `CALON_TAMBAHAN`, ada kemungkinan `SampleElectionSeeder.php` masih mengandungi rujukan kepada nama atau slug lama.
|
||
- Jika seeder dijalankan semula (fresh seed untuk UAT atau persekitaran baharu), data yang dijana mungkin tidak konsisten dengan `PositionSeeder`.
|
||
|
||
Tugas:
|
||
|
||
- Buka dan audit `SampleElectionSeeder.php` secara menyeluruh.
|
||
- Cari semua rujukan kepada `CALON_SIMPANAN` atau string berkaitan dan gantikan dengan `CALON_TAMBAHAN`.
|
||
- Pastikan semua slug jawatan dalam seeder sepadan tepat dengan apa yang `PositionSeeder` jana.
|
||
- Jalankan `php artisan migrate:fresh --seed` dan pastikan tiada ralat.
|
||
- Jalankan `php artisan test` dan pastikan semua 80 ujian lulus.
|
||
|
||
Kriteria keluar:
|
||
|
||
- `php artisan migrate:fresh --seed` selesai tanpa ralat.
|
||
- `php artisan test` lulus sepenuhnya.
|
||
- Tiada rujukan kepada `CALON_SIMPANAN` dalam mana-mana seeder.
|
||
|
||
Dokumentasi yang perlu dikemaskini:
|
||
|
||
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
|
||
|
||
---
|
||
|
||
### 12-E: Konsistensikan Semakan Jenis Dokumen pada Semua Path Download
|
||
|
||
Masalah semasa:
|
||
|
||
- Admin Kewangan route download secara eksplisit mengehad kepada `bank_statement` sahaja.
|
||
- Route download PPM, Admin, dan Admin Kewangan masing-masing menggunakan implementasi yang berbeza.
|
||
- Jika ada ketidakkonsistenan dalam cara jenis dokumen disahkan, pengguna yang dibenarkan mungkin boleh download jenis dokumen yang sepatutnya terhad untuk mereka.
|
||
|
||
Tugas:
|
||
|
||
- Audit semua route download dokumen: PPM, Admin, dan Admin Kewangan.
|
||
- Cipta satu senarai jenis dokumen yang dibenarkan per peranan (`document_type` allowlist).
|
||
- Refactor semakan jenis dokumen ke dalam satu tempat — boleh dalam `DocumentDownloadController` atau policy `ApplicationPolicy`.
|
||
- Tambah ujian untuk setiap peranan mengesahkan mereka:
|
||
- Boleh download dokumen yang dibenarkan.
|
||
- Tidak boleh download dokumen di luar skop mereka walaupun ID dokumen diketahui.
|
||
- Pastikan 403 dikembalikan, bukan 404, untuk download yang diblock (supaya mesej ralat tidak mendedahkan kewujudan dokumen).
|
||
|
||
Kriteria keluar:
|
||
|
||
- Semua path download dokumen menggunakan semakan jenis yang konsisten.
|
||
- Ujian baru mengesahkan boundary setiap peranan.
|
||
- Tiada path yang boleh bypass semakan jenis dokumen.
|
||
|
||
Dokumentasi yang perlu dikemaskini:
|
||
|
||
- `docs/04-rbac-permission-matrix.md` — tambah baris untuk akses dokumen per peranan.
|
||
- `docs/decision-log.md` — rekod keputusan centralize semakan jenis dokumen.
|
||
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
|
||
|
||
---
|
||
|
||
## Fasa 13: Indeks Pangkalan Data dan Prestasi
|
||
|
||
Status: Belum dimulakan.
|
||
|
||
Skop fasa ini ialah menambah composite indexes yang diperlukan sebelum sistem mula menerima data sebenar dalam kuantiti besar.
|
||
|
||
### 13-A: Tambah Composite Indexes untuk Query Kerap
|
||
|
||
Masalah semasa:
|
||
|
||
- Query senarai Admin global (`/admin/management/applications`) menyaring mengikut `election_id`, `status`, dan `pusat_mengundi_id` tanpa composite index.
|
||
- Query `AssignmentVacancyService` dan `KtmVacancyService` menyaring `staff_assignments` mengikut `election_id`, `pusat_mengundi_id`, `position_id`, dan `is_active` tanpa composite index.
|
||
- Untuk pilihan raya dengan 5,000–20,000 permohonan, query ini boleh menjadi lambat secara signifikan.
|
||
|
||
Tugas:
|
||
|
||
- Cipta migration baharu untuk menambah indexes (jangan ubah migration sedia ada).
|
||
- Tambah pada jadual `applications`:
|
||
- `(election_id, status)`
|
||
- `(election_id, pusat_mengundi_id, status)`
|
||
- `(election_id, ic_number)` — untuk semakan IC duplikasi
|
||
- Tambah pada jadual `staff_assignments`:
|
||
- `(election_id, pusat_mengundi_id, position_id, is_active)`
|
||
- `(election_id, saluran_mengundi_id, position_id, is_active)`
|
||
- `(reports_to_assignment_id, is_active)` — untuk KtmVacancyService
|
||
- Tambah pada jadual `bank_verifications`:
|
||
- `(election_id, status)`
|
||
- Gunakan nama index yang pendek dan eksplisit (ikut konvensyen sedia ada dalam sistem).
|
||
- Jalankan `php artisan migrate` dan sahkan indexes wujud.
|
||
- Jalankan `php artisan test` dan pastikan semua ujian lulus.
|
||
|
||
Kriteria keluar:
|
||
|
||
- Migration berjaya tanpa ralat.
|
||
- Semua ujian lulus.
|
||
- Query utama pada senarai admin menggunakan indexes (boleh disahkan dengan `EXPLAIN` dalam MySQL Workbench).
|
||
|
||
Dokumentasi yang perlu dikemaskini:
|
||
|
||
- `docs/03-database-design.md` — tambah bahagian indexes dan justifikasi.
|
||
- `docs/decision-log.md` — rekod keputusan indexes yang ditambah dan sebab.
|
||
- `docs/08-deployment-notes.md` — tambah arahan semak indexes semasa deployment.
|
||
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
|
||
|
||
---
|
||
|
||
## Fasa 14: Portal Status Permohonan Pemohon Awam
|
||
|
||
Status: Belum dimulakan.
|
||
|
||
Skop fasa ini ialah memberi pemohon awam cara untuk semak status permohonan mereka tanpa perlu login atau hubungi Admin.
|
||
|
||
### 14-A: Halaman Status Permohonan via UUID Awam
|
||
|
||
Masalah semasa:
|
||
|
||
- Pemohon awam hanya menerima redirect ke `/permohonan/{uuid}/berjaya` selepas mohon.
|
||
- Tiada cara untuk semak status kemudian (diluluskan? ditolak? kenapa ditolak?).
|
||
- Ini menyebabkan beban sokongan kepada Admin dan PPM.
|
||
|
||
Tugas:
|
||
|
||
- Tambah route `GET /permohonan/{application:public_uuid}/status`.
|
||
- Halaman ini tidak memerlukan login — cukup UUID awam permohonan sebagai pengecam.
|
||
- Paparkan maklumat terhad: nama pemohon (sebahagian), jawatan dipohon, pusat mengundi, status semasa, tarikh kemaskini terakhir.
|
||
- Jika status `rejected`, paparkan sebab penolakan jika ada.
|
||
- Jika status `assigned`, paparkan pengesahan penempatan tanpa mendedahkan butiran dalaman (saluran ID, dsb.).
|
||
- Jangan paparkan nombor IC penuh, nombor akaun bank, atau data sensitif lain.
|
||
- Gunakan `SensitiveData` helper untuk mask nama sebahagian jika perlu.
|
||
- Tambah ujian untuk: permohonan berstatus submitted, approved, assigned, rejected, dan UUID tidak wujud.
|
||
|
||
Kriteria keluar:
|
||
|
||
- Pemohon boleh semak status dengan hanya URL yang mengandungi UUID awam.
|
||
- Data sensitif tidak didedahkan.
|
||
- Halaman tidak mendedahkan sama ada UUID wujud atau tidak kepada orang lain (status 200 dengan mesej umum untuk UUID tidak dikenali, bukan 404).
|
||
|
||
Dokumentasi yang perlu dikemaskini:
|
||
|
||
- `docs/05-workflow-design.md` — tambah bahagian portal status pemohon.
|
||
- `docs/06-ui-ux-plan.md` — tambah reka bentuk halaman status.
|
||
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
|
||
- `docs/decision-log.md` — rekod keputusan reka bentuk privacy (status 200 vs 404 untuk UUID tidak dikenali).
|
||
|
||
---
|
||
|
||
## Fasa 15: Pengurusan Eksport dan Data Sensitif
|
||
|
||
Status: Belum dimulakan.
|
||
|
||
Skop fasa ini ialah memastikan fail eksport yang mengandungi data sensitif tidak kekal dalam storage tanpa had masa.
|
||
|
||
### 15-A: Purge Automatik Fail Eksport Lama
|
||
|
||
Masalah semasa:
|
||
|
||
- Fail XLSX eksport kewangan (disimpan di `exports/finance`) dan eksport kehadiran (disimpan di `exports/attendance`) disimpan dalam private storage tanpa had masa.
|
||
- Fail-fail ini mengandungi data bank, nombor IC, dan maklumat peribadi lain.
|
||
- Tiada mekanisme untuk padam fail lama secara automatik.
|
||
|
||
Tugas:
|
||
|
||
- Tambah `ExportPurgeCommand` (`php artisan exports:purge`) sebagai Artisan command.
|
||
- Command menerima parameter `--days=` (default: 30) untuk menentukan tempoh simpanan.
|
||
- Command akan:
|
||
- Query `export_logs` untuk rekod lebih lama daripada tempoh yang ditetapkan.
|
||
- Padam fail dari storage disk yang berkaitan.
|
||
- Kemaskini `export_logs` dengan `purged_at` dan `purged_by` (system).
|
||
- Log aktiviti purge.
|
||
- Daftarkan command dalam `bootstrap/app.php` atau `routes/console.php` sebagai scheduled task (contoh: harian pada tengah malam).
|
||
- Tambah kolum `purged_at` pada jadual `export_logs` melalui migration baharu.
|
||
- Tambah ujian untuk: command berjaya padam fail lama, fail baru tidak terpadam, `export_logs` dikemaskini.
|
||
|
||
Kriteria keluar:
|
||
|
||
- Command boleh dijalankan secara manual dan secara scheduled.
|
||
- Fail lebih lama dari tempoh yang ditetapkan dipadamkan dari storage.
|
||
- `export_logs` menunjukkan rekod purge.
|
||
- Fail yang masih dalam tempoh simpanan tidak terpadam.
|
||
|
||
Dokumentasi yang perlu dikemaskini:
|
||
|
||
- `docs/03-database-design.md` — tambah kolum `purged_at` dalam jadual `export_logs`.
|
||
- `docs/08-deployment-notes.md` — tambah arahan konfigurasi scheduler dan polisi simpanan eksport.
|
||
- `docs/decision-log.md` — rekod keputusan tempoh simpanan default dan strategi purge.
|
||
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
|
||
|
||
---
|
||
|
||
## Ringkasan Keutamaan
|
||
|
||
| Fasa | Tajuk | Keutamaan | Status |
|
||
|------|-------|-----------|--------|
|
||
| 12-A | Admin Settings UI (toggle kehadiran/pendaftaran) | Kritikal | **Selesai 2026-06-02** |
|
||
| 12-B | Pembetulan semakan IC soft-deleted | Kritikal | **Selesai 2026-06-02** |
|
||
| 12-C | Perkukuh enforcement nota catatan | Kritikal | **Selesai 2026-06-02** |
|
||
| 12-D | Pembetulan SampleElectionSeeder | Kritikal | **Selesai 2026-06-02** |
|
||
| 12-E | Konsistensikan semakan jenis dokumen download | Kritikal | **Selesai 2026-06-02** |
|
||
| 13-A | Tambah composite indexes pangkalan data | Prestasi | **Selesai 2026-06-02** |
|
||
| 14-A | Portal status permohonan pemohon awam | UX | **Selesai 2026-06-02** |
|
||
| 15-A | Purge automatik fail eksport sensitif | Data | **Selesai 2026-06-02** |
|
||
|
||
---
|
||
|
||
## Nota Pelaksanaan
|
||
|
||
- Setiap item dalam Fasa 12 boleh dilaksanakan secara bebas dan tidak perlu tunggu item lain selesai.
|
||
- Fasa 13 patut dilaksanakan sebelum data sebenar mula dimasukkan ke dalam sistem.
|
||
- Fasa 14 dan 15 boleh dilaksanakan secara selari kerana tidak ada kebergantungan antara satu sama lain.
|
||
- Setiap pembetulan mesti menjalankan semula suite ujian penuh (`php artisan test`) sebelum dianggap selesai.
|
||
- Jalankan `vendor\bin\pint.bat --test` dan `vendor\bin\phpstan.bat analyse --memory-limit=1G` selepas setiap fasa.
|