300 lines
14 KiB
Markdown
300 lines
14 KiB
Markdown
# Workflow Design
|
|
|
|
## Application Status Lifecycle
|
|
|
|
Final initial statuses:
|
|
|
|
```text
|
|
draft
|
|
submitted
|
|
under_ppm_review
|
|
approved
|
|
rejected
|
|
assigned
|
|
cancelled
|
|
deleted_by_ktm
|
|
```
|
|
|
|
## Application Status Meaning
|
|
|
|
| Status | Meaning |
|
|
|---|---|
|
|
| `draft` | Created but not fully submitted. Used only if partial saves are implemented. |
|
|
| `submitted` | Applicant or actor submitted the application for review. |
|
|
| `under_ppm_review` | PPM has opened or started reviewing the application. |
|
|
| `approved` | Application approved for a position but not necessarily assigned to final Saluran/team. |
|
|
| `rejected` | Application rejected with reason. |
|
|
| `assigned` | Approved applicant has active staff assignment. |
|
|
| `cancelled` | Application cancelled by Admin or workflow rule. |
|
|
| `deleted_by_ktm` | KTM-created placeholder/application removed so applicant can self-register. |
|
|
|
|
## Public QR Application Flow
|
|
|
|
Phase 4 implementation behavior:
|
|
|
|
- `/pohon/{pusat_mengundi_uuid}` resolves by public UUID and shows the public application form when registration is open.
|
|
- If registration is closed, the same QR route shows a closed-registration page.
|
|
- Successful submissions redirect to `/permohonan/{application_uuid}/berjaya`.
|
|
- Uploaded IC documents and bank statements are stored on the private local disk under the application UUID path.
|
|
- Submitted applications immediately create `application_documents`, `application_status_histories`, and pending `bank_verifications` records.
|
|
|
|
1. Applicant scans QR code for a Pusat Mengundi.
|
|
2. System resolves `/pohon/{pusat_mengundi_uuid}`.
|
|
3. System checks election and registration period.
|
|
4. If registration is closed, show clear closed-registration message.
|
|
5. Applicant selects role: KTM, KP, KPDP, or PAPM.
|
|
6. If selected role is KP or KPDP, system shows approved KTM list for that Pusat Mengundi with available vacancy.
|
|
7. Applicant fills personal, contact, bank, and address details.
|
|
8. Applicant uploads IC document and bank statement.
|
|
9. System validates IC uniqueness for current election.
|
|
10. If an active KTM-created applicant exists for the same IC, system blocks self-registration and explains that KTM must delete the pre-created record first.
|
|
11. System stores documents privately.
|
|
12. Application status becomes `submitted`.
|
|
13. Bank verification starts as `pending`.
|
|
14. PPM reviews the application in Phase 5.
|
|
|
|
## Registration Period Rules
|
|
|
|
During registration period:
|
|
|
|
- Public Pemohon can register through QR.
|
|
- KTM can register KP.
|
|
- PPM can review and assign.
|
|
|
|
After registration period:
|
|
|
|
- Public self-registration is closed.
|
|
- KTM cannot register new KP.
|
|
- PPM cannot register new applicants.
|
|
- Only Admin can register, edit, or assign staff.
|
|
- Admin changes after closing require catatan.
|
|
- System must show clear closed-registration messages.
|
|
|
|
Registration open calculation:
|
|
|
|
- `registration_start_date <= today <= registration_end_date`
|
|
- plus `is_registration_open = true`.
|
|
- if `is_registration_open_override` is not null, it explicitly opens or closes registration regardless of the normal date window.
|
|
|
|
## Applicant Status Portal
|
|
|
|
Pemohon awam boleh semak status permohonan melalui `/permohonan/{uuid}/status` tanpa perlu log masuk.
|
|
|
|
- UUID awam permohonan digunakan sebagai pengecam — tiada login diperlukan.
|
|
- Pautan status dipaparkan pada halaman kejayaan permohonan dan boleh disalin.
|
|
- Maklumat yang dipaparkan: nama (disamarkan 3 aksara pertama), jawatan dipohon, pusat mengundi, status, sebab penolakan (jika ditolak), nombor rujukan UUID.
|
|
- Maklumat yang TIDAK dipaparkan: IC, akaun bank, nombor telefon, ID dalaman, saluran, nama KTM.
|
|
- UUID tidak dikenali → 200 dengan mesej generik ("status tidak dapat dipaparkan") — tidak mendedahkan sama ada UUID pernah wujud.
|
|
- Rekod `deleted_by_ktm` dan rekod soft-deleted juga mengembalikan mesej generik.
|
|
|
|
Status display mapping:
|
|
|
|
| Status DB | Paparan |
|
|
|---|---|
|
|
| `submitted` | Menunggu Semakan |
|
|
| `under_ppm_review` | Sedang Disemak |
|
|
| `approved` | Diluluskan |
|
|
| `assigned` | Diluluskan & Ditempatkan |
|
|
| `rejected` | Ditolak (+ sebab penolakan) |
|
|
| `cancelled` | Dibatalkan |
|
|
|
|
## Admin Election Settings
|
|
|
|
Admin can manage the following settings per election via `/admin/setup/settings/{election}`:
|
|
|
|
- `is_attendance_active` — Toggle attendance recording on/off. Should only be activated on polling day. PPM cannot record attendance when this is false. Toggling is recorded in activity log with before/after values.
|
|
- `is_registration_open_override` — Three states: null (Auto — follows date window), true (Force Open — opens even outside date window), false (Force Closed — closes even inside date window). Use override only in exceptional circumstances. When override is active, a warning badge is shown on the settings page.
|
|
|
|
Changes to election settings require Admin role and are written to `activity_log` with `log_name = 'admin_settings'`, recording who changed what and when.
|
|
|
|
Note: `is_registration_open` (the base toggle) is still set in the database during initial setup. The `is_registration_open_override` is the runtime control available via the Admin Settings UI.
|
|
|
|
## KTM Vacancy Rule for Public KP/KPDP Selection
|
|
|
|
For public KP or KPDP applications:
|
|
|
|
- Candidate KTM options come from active `staff_assignments` with position `KTM`, same election, same Pusat Mengundi, and assigned Saluran Mengundi.
|
|
- Remaining vacancy is calculated from `position_quotas` for the KTM's Saluran Mengundi and requested role.
|
|
- Used vacancy counts active team assignments under that KTM plus reserved public applications in `submitted`, `under_ppm_review`, or `approved` status.
|
|
- If no vacancy remains, the KTM cannot be selected.
|
|
|
|
## PPM Review Flow
|
|
|
|
Phase 5 implementation behavior:
|
|
|
|
- PPM application URLs use application public UUID.
|
|
- PPM list and detail views are scoped by active PPM `staff_assignments`.
|
|
- `ApplicationPolicy` blocks PPM access to applications outside assigned Pusat Mengundi.
|
|
- Approved applications are moved directly to `assigned` because Phase 5 approval also creates the active staff assignment.
|
|
- Private document download is available only through the authorized PPM review route.
|
|
|
|
1. PPM opens own dashboard.
|
|
2. System lists applications only for PPM's assigned Pusat Mengundi.
|
|
3. PPM reviews applicant detail and documents.
|
|
4. PPM may change applicant role before approval.
|
|
5. System records any role change in audit trail.
|
|
6. PPM approves only if IC document and bank statement exist.
|
|
7. If approved as KTM, PPM assigns KTM to a Saluran Mengundi.
|
|
8. If approved as KP or KPDP, PPM assigns applicant to an approved KTM under the same Pusat Mengundi.
|
|
9. If approved as PAPM, system assigns at Pusat Mengundi level.
|
|
10. System creates or updates `staff_assignments`.
|
|
11. System records assignment history and activity log.
|
|
|
|
## KTM Flow
|
|
|
|
Phase 6 implementation behavior:
|
|
|
|
- KTM routes are under `/ktm/applications`.
|
|
- KTM scope is based on active `staff_assignments` with position `KTM`, status `active`, and a Saluran Mengundi.
|
|
- KTM can create only KP applicant records.
|
|
- KTM-created records are stored as `source = created_by_ktm` and `status = submitted`.
|
|
- Creating a KP applicant queues a Markdown email to the applicant.
|
|
- KTM approval creates an active KP `staff_assignments` row under the KTM assignment and changes application status to `assigned`.
|
|
- KTM can delete only unassigned records they created through the KTM flow, changing status to `deleted_by_ktm` before soft delete.
|
|
|
|
1. KTM logs in and opens own dashboard.
|
|
2. System identifies active KTM assignment and Saluran.
|
|
3. KTM views own KP list and remaining KP vacancy.
|
|
4. During registration period, KTM can register KP only.
|
|
5. KTM-created KP has `source = created_by_ktm`.
|
|
6. System sends email notification to applicant.
|
|
7. KTM can approve KP application only under own team while registration is open.
|
|
8. If applicant wants to self-register with the same IC, system blocks until KTM deletes the KTM-created record.
|
|
9. Deleting a KTM-created applicant changes status to `deleted_by_ktm`, records status history, and soft deletes the record.
|
|
|
|
## Admin Manual Entry and Management Flow
|
|
|
|
Phase 7 implementation behavior:
|
|
|
|
- Admin management routes are under `/admin/management`.
|
|
- Admin can list all applications with filters for status, Pusat Mengundi, jawatan, and keyword.
|
|
- Admin can create manual application records with `source = admin_manual`.
|
|
- Manual Admin-created records create pending bank verification state but do not send KTM-created applicant email.
|
|
- Admin can edit application personal, role, bank, status, and placement-related fields.
|
|
- Admin can direct-assign an application to Pusat/Saluran/KTM team; this creates or updates `staff_assignments`, sets application status to `assigned`, and writes status/assignment history.
|
|
- Admin can edit existing `staff_assignments`; changes are mirrored back to the related application where applicable.
|
|
- Admin can key in and delete Police, KKM, and JKM representative records.
|
|
- If registration is closed, Admin changes require `catatan`; the system stores it in `system_notes`.
|
|
|
|
1. Admin opens global application/staff list.
|
|
2. Admin can create or edit application/staff records.
|
|
3. Admin can directly assign staff to Pusat Mengundi and Saluran Mengundi.
|
|
4. Admin can key in Police, KKM, and JKM records.
|
|
5. If registration period has ended, Admin must provide `catatan` for any register/edit/assign action.
|
|
6. System saves note in `system_notes`.
|
|
7. System records activity log and assignment/application history.
|
|
|
|
## Admin Kewangan Flow
|
|
|
|
Phase 8 implementation behavior:
|
|
|
|
- Finance routes are under `/kewangan/bank`.
|
|
- Finance list shows applications in `approved` or `assigned` status.
|
|
- Filters support Pusat Mengundi, role, bank verification status, missing bank statement, missing bank account number, and keyword search.
|
|
- Admin Kewangan can update only `bank_verifications.status` and `finance_note`.
|
|
- Updating verification records sets `verified_by_user_id` and `verified_at` and writes activity log.
|
|
- Admin Kewangan cannot access Admin assignment management routes.
|
|
- Finance export creates an XLSX file in private storage using OpenSpout and inserts an `export_logs` row.
|
|
|
|
1. Admin Kewangan opens finance dashboard.
|
|
2. System lists approved staff and bank verification status.
|
|
3. Admin Kewangan filters by Pusat Mengundi, role, status, missing bank statement, or missing account number.
|
|
4. Admin Kewangan marks bank verification as pending, verified, rejected, or requires correction.
|
|
5. Admin Kewangan adds finance note.
|
|
6. System records bank verification activity log.
|
|
7. Admin Kewangan can export finance verification list.
|
|
|
|
## Wheelchair Flow
|
|
|
|
Phase 9 implementation behavior:
|
|
|
|
- Wheelchair management routes are under `/admin/management/wheelchairs`.
|
|
- Admin can upsert one allocation record per election and Pusat Mengundi.
|
|
- Admin can record `taken` transactions with quantity, date/time, person taking, and notes.
|
|
- Admin can record `returned` transactions with quantity, date/time, return condition, and notes.
|
|
- System calculates total taken, total returned, outstanding quantity, and available quantity.
|
|
- Taken quantity is blocked when it exceeds available allocation.
|
|
- Returned quantity is blocked when it exceeds outstanding quantity.
|
|
- Allocation quantity is blocked when it is lower than outstanding quantity.
|
|
- Allocation changes and transactions are recorded in activity log.
|
|
|
|
1. Admin enters allocated wheelchair quantity per Pusat Mengundi.
|
|
2. Admin records taken quantity, date/time, and person taking.
|
|
3. Admin records returned quantity, date/time, condition, and notes.
|
|
4. System stores each movement in `wheelchair_transactions`.
|
|
5. System records activity log.
|
|
|
|
## Attendance Flow
|
|
|
|
Phase 10 implementation behavior:
|
|
|
|
- PPM attendance routes are under `/ppm/attendance`.
|
|
- PPM can only access Pusat Mengundi assigned through active PPM `staff_assignments`.
|
|
- PPM can record attendance only when `election_settings.is_attendance_active = true`.
|
|
- Attendance is recorded per active `staff_assignments` row and uses statuses `present`, `absent`, or `not_recorded`.
|
|
- Present records store check-in time; absent and not-recorded records clear check-in time.
|
|
- Attendance updates write activity log with actor, staff assignment, status, and check-in time.
|
|
- Admin attendance routes are under `/admin/attendance`.
|
|
- Admin first view lists Pusat Mengundi with total staff, present, absent, and not recorded.
|
|
- Admin detail view shows staff name, role, Saluran, status, check-in time, notes, and recorded by.
|
|
- Admin detail export generates XLSX with OpenSpout and writes `export_logs`.
|
|
|
|
1. Attendance module becomes active based on election setting.
|
|
2. PPM opens attendance screen for own Pusat Mengundi.
|
|
3. System lists all assigned staff under that Pusat Mengundi.
|
|
4. PPM marks each staff as present or absent.
|
|
5. If present, check-in time is stored.
|
|
6. System stores recorded by and note.
|
|
7. Admin dashboard shows first-level list of Pusat Mengundi.
|
|
8. Admin clicks Pusat Mengundi to see staff-level attendance details.
|
|
9. Admin exports summary or detail attendance reports.
|
|
|
|
Attendance statuses:
|
|
|
|
```text
|
|
present
|
|
absent
|
|
not_recorded
|
|
```
|
|
|
|
## Bank Verification Status
|
|
|
|
```text
|
|
pending
|
|
verified
|
|
rejected
|
|
requires_correction
|
|
```
|
|
|
|
Status meaning:
|
|
|
|
- `pending`: Not yet checked by finance.
|
|
- `verified`: Bank details accepted.
|
|
- `rejected`: Bank details are invalid or unusable.
|
|
- `requires_correction`: Applicant/staff record needs correction or additional document.
|
|
|
|
## Audit Events
|
|
|
|
Must be audited:
|
|
|
|
- Application submission.
|
|
- Application approval/rejection.
|
|
- Role change.
|
|
- Assignment creation/change/cancellation.
|
|
- Document upload/change.
|
|
- Bank verification update.
|
|
- Admin edit after registration closes.
|
|
- Attendance update.
|
|
- Wheelchair transaction.
|
|
- Excel export.
|
|
|
|
Audit record should include:
|
|
|
|
- actor
|
|
- action
|
|
- subject
|
|
- previous value
|
|
- new value
|
|
- timestamp
|
|
- note/catatan if available
|