# 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