Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

03 — User Journeys (Staff Module)

End-to-end journeys mapped to the exact API surface. All backend behavior cited from source; flows marked (proposed) for client-only decisions.

J1 — Create a staff member (Org Admin / HR)

Backend steps: POST /staff (staff.controller.ts:24) → duplicate guard (staff.service.ts:31-36) → create with status: ACTIVE, employmentType defaulting to full_time (staff.service.ts:37-43) → StaffCreated event (staff.service.ts:44-54in-app queue, event-queue-map.ts:34).

flowchart LR
    A[Admin opens Staff list] --> B[Taps FAB Add staff]
    B --> C[Create Staff form]
    C -->|user selected from Users list| D[POST /api/v1/staff]
    D --> E{employeeNumber unique?}
    E -- no --> F[409 DUPLICATE_RESOURCE<br/>inline error on employeeNumber]
    F --> C
    E -- yes --> G[201 + staff record<br/>status=active default]
    G --> H[StaffCreated event<br/>in-app notification]
    H --> I[Snackbar 'Staff created'<br/>navigate to detail]
  • Form fields: userId (required picker), employeeNumber (required), departmentId, designationId, employmentType, joiningDate, salaryGrade (create-staff.dto.ts:5-38).
  • status is not settable at creation (staff.service.ts:39).
  • Haptic: lightImpact on success (00-shared/08 §3).

J2 — Manage departments (Org Admin / HR)

Backend steps: POST /departments duplicate-name guard (department.service.ts:22-30); list via GET /departments (department.controller.ts:29); update PATCH /departments/:id; delete DELETE /departments/:id (soft). No events emitted by the catalog services (department.service.ts:19-20).

flowchart TD
    A[Departments list] --> B[FAB Add department]
    B --> C[POST /api/v1/departments<br/>name required, code?, headId?]
    C --> D{name duplicates?}
    D -- yes --> E[409 inline error]
    E --> C
    D -- no --> F[201 department<br/>status=active]
    F --> G[Row appears in list]
    A --> H[Row menu: Edit / Deactivate]
    H --> I[PATCH /api/v1/departments/:id<br/>name, code, headId, status]
    H --> J[DELETE /api/v1/departments/:id]
    J --> K[404 if already deleted]
    K --> L[Removed from list<br/>no member-count check OQ-4]
  • headId picker sources staff (department.schema.ts:15-16); a soft-deleted head renders as unlinked ((proposed) — backend stores the bare ref).
  • Dept→staff counts and "reassign members before deleting" are not enforced server-side — see OQ-4; the client must present the risk in the confirm dialog.

J3 — Manage designations (Org Admin / HR)

Backend steps: POST /designations duplicate-name guard (designation.service.ts:25-28); level is IsInt (designation.dto.ts:14-17); optional departmentId (designation.schema.ts:9-10).

flowchart LR
    A[Designations list] --> B[FAB Add designation]
    B --> C[POST /api/v1/designations<br/>name required, level?, departmentId?]
    C --> D{name duplicates?}
    D -- yes --> E[409 inline error]
    D -- no --> F[201 designation<br/>level default 0, status active]
    F --> G[List, sorted by level<br/>client-side proposed]
    A --> H[Edit: PATCH /api/v1/designations/:id]
    H --> I[Update name/level/dept/status]
    A --> J[Delete: DELETE /api/v1/designations/:id]
  • level defaults to 0 (designation.schema.ts:15-16); sort-by-level is (proposed) — the API returns insertion order (designation.service.ts:41-50).

J4 — Edit a staff profile (HR)

Backend steps: PATCH /staff/:id (staff.controller.ts:33) → existence check 404 (staff.service.ts:79) → $set + version++ (base.repository.ts:57-66) → StaffUpdated with changed keys (staff.service.ts:82-90).

flowchart LR
    A[Staff detail] --> B[Edit button]
    B --> C[Edit form prefilled from GET /staff/:id]
    C --> D[PATCH /api/v1/staff/:id]
    D --> E{exists?}
    E -- no --> F[404 RESOURCE_NOT_FOUND]
    F --> G[Empty-state 'not found']
    E -- yes --> H[200 updated record]
    H --> I[StaffUpdated → audit-write]
    I --> J[Snackbar 'Saved'<br/>detail refreshes]
  • All fields optional on update (update-staff.dto.ts:5-42) — send only changed fields; changes list is the audit delta (staff.service.ts:88).
  • status may be set here — this is the sanctioned way to move a member to on_leave/inactive/terminated (update-staff.dto.ts:35-38).

J5 — Deactivate a staff member (HR / Org Admin)

Backend steps: DELETE /staff/:id (staff.controller.ts:36) → soft delete sets isDeleted + deletedAt + deletedBy and bumps version (base.repository.ts:68-74) → 404 when already deleted (staff.service.ts:94-95) → StaffDeleted audit event (staff.service.ts:96-103).

flowchart LR
    A[Staff detail or row menu] --> B[Deactivate]
    B --> C{Confirm dialog<br/>'This removes the staff member from all lists'}
    C -- cancel --> A
    C -- confirm --> D[DELETE /api/v1/staff/:id]
    D --> E{found & active?}
    E -- no --> F[404 RESOURCE_NOT_FOUND]
    E -- yes --> G[200 empty data<br/>StaffDeleted → audit-write]
    G --> H[Navigate back to list<br/>row gone; snackbar]
  • No restore path exists (no un-delete endpoint) — the dialog must say so (base.repository.ts:68-74; OQ-8 for a future restore).
  • The list refetches because soft-deleted rows are excluded from every query (base.repository.ts:20-30).

J6 — Browse the staff directory (read-only (proposed))

GET /staff?page=&limit= (staff.controller.ts:27) — no server-side q/sort for staff (staff.service.ts:64-76, OQ-2). Journey: open Staff → list loads → pull-to-refresh → infinite scroll / page controls → tap row → detail with tabs. Status badges map 1:1 to StaffStatus (staff.schema.ts:7-12).