docs(crewing): rewrite design-page bodies to the reconciled model

Bring the Crewing design pages in line with Crewing-Implementation-Spec
(no longer just banners): leave is Manager-approved (MPO removed from
leave and the planner); interview waiver is an explicit Manager-approved
action with no auto path; only MPO/Manager raise requisitions (site staff
request relief cover, new RELIEF_REQUEST model + ReliefRequestStatus); the
Application pipeline is the 7-stage board (competency & references merged,
docs before salary, JOINING folded into onboard); SalaryStructure is
effective-dated (mid-assignment changes prorate); victualing is a separate
wage line; verify_site_records drops leave.

Updates state/sequence diagrams, the ER model + enums, the permission
matrix, the use-case diagram/catalogue, and the user-story backlog. Each
page's banner is reduced to a plain pointer to the spec.
Hardik 2026-06-22 11:59:08 +05:30
parent b9e5118693
commit bafb12cede
8 changed files with 207 additions and 145 deletions

@ -1,5 +1,9 @@
# Crewing Architecture # Crewing Architecture
> **Authoritative build spec:** [Crewing Implementation Spec](Crewing-Implementation-Spec)
> carries the full reconciled instructions (codebase changes, roles/nav matrices,
> screen spec). This page is the module/layer layout, aligned with that spec.
The Crewing Module is **not a new application** — it is a feature area inside the The Crewing Module is **not a new application** — it is a feature area inside the
existing Pelagia Portal. It adopts the same stack and the same patterns existing Pelagia Portal. It adopts the same stack and the same patterns
documented in [Architecture](Architecture); this page only describes what documented in [Architecture](Architecture); this page only describes what

@ -1,10 +1,8 @@
# Crewing Data Model # Crewing Data Model
> **Reconciled:** [Crewing Implementation Spec](Crewing-Implementation-Spec) is the > **Authoritative build spec:** [Crewing Implementation Spec](Crewing-Implementation-Spec)
> authoritative build instruction set. Where this page differs, follow the spec — > carries the full reconciled instructions (codebase changes, roles/nav matrices,
> notably the **7-stage `ApplicationStage`**, **effective-dated `SalaryStructure`** > screen spec). This page is the detailed schema, aligned with that spec.
> (mid-assignment changes), the new **`RELIEF_REQUEST`** model, and **leave decided
> by the Manager**.
**Proposed source of truth:** `App/prisma/schema.prisma` (new models). Mirrors **Proposed source of truth:** `App/prisma/schema.prisma` (new models). Mirrors
the conventions on [Data Model](Data-Model): monetary values are `Decimal`, the conventions on [Data Model](Data-Model): monetary values are `Decimal`,
@ -20,9 +18,12 @@ enum RequisitionStatus { OPEN SHORTLISTING PROPOSING INTERVIEWING SELECTED
// candidate progress against a requisition (the gated pipeline) // candidate progress against a requisition (the gated pipeline)
enum CandidateType { EX_HAND NEW } enum CandidateType { EX_HAND NEW }
enum ApplicationStage { enum ApplicationStage {
SHORTLISTED COMPETENCY_CHECK DOC_VERIFICATION REFERENCE_CHECK SHORTLISTED COMPETENCY_AND_REFERENCES DOC_VERIFICATION SALARY_AGREEMENT
SALARY_AGREEMENT PROPOSED INTERVIEW SELECTED REJECTED JOINING ONBOARDED PROPOSED INTERVIEW SELECTED REJECTED ONBOARDED
} }
// the 7 board stages are SHORTLISTED → COMPETENCY_AND_REFERENCES → DOC_VERIFICATION
// → SALARY_AGREEMENT → PROPOSED → INTERVIEW → SELECTED; ONBOARDED is the terminal
// system state, REJECTED the branch. Joining formalities fold into the onboard action.
// the person's overall status // the person's overall status
enum CrewStatus { PROSPECT CANDIDATE EMPLOYEE EX_HAND BLACKLISTED } enum CrewStatus { PROSPECT CANDIDATE EMPLOYEE EX_HAND BLACKLISTED }
@ -33,7 +34,8 @@ enum AssignmentStatus { ACTIVE ON_LEAVE SIGNED_OFF }
// site HR // site HR
enum AttendanceStatus { PRESENT ABSENT HALF_DAY ON_LEAVE SIGN_OFF } enum AttendanceStatus { PRESENT ABSENT HALF_DAY ON_LEAVE SIGN_OFF }
enum LeaveType { ANNUAL MEDICAL EMERGENCY UNPAID OTHER } enum LeaveType { ANNUAL MEDICAL EMERGENCY UNPAID OTHER }
enum LeaveStatus { APPLIED APPROVED REJECTED CANCELLED } enum LeaveStatus { APPLIED APPROVED REJECTED CANCELLED } // decided by the Manager
enum ReliefRequestStatus { OPEN CONVERTED DISMISSED } // site-staff gap flag → office converts
// PPE kit // PPE kit
enum PpeItem { enum PpeItem {
@ -142,7 +144,7 @@ erDiagram
APPLICATION ||--o{ APPLICATION_GATE : evaluated_by APPLICATION ||--o{ APPLICATION_GATE : evaluated_by
APPLICATION ||--o{ REFERENCE_CHECK : has APPLICATION ||--o{ REFERENCE_CHECK : has
CREW_ASSIGNMENT ||--o| SALARY_STRUCTURE : paid_by CREW_ASSIGNMENT ||--o{ SALARY_STRUCTURE : paid_by
CREW_ASSIGNMENT ||--o| CONTRACT_LETTER : documented_by CREW_ASSIGNMENT ||--o| CONTRACT_LETTER : documented_by
CREW_ASSIGNMENT ||--o{ ATTENDANCE : records CREW_ASSIGNMENT ||--o{ ATTENDANCE : records
CREW_ASSIGNMENT ||--o{ LEAVE_REQUEST : has CREW_ASSIGNMENT ||--o{ LEAVE_REQUEST : has
@ -190,7 +192,7 @@ erDiagram
APPLICATION_GATE { APPLICATION_GATE {
string id PK string id PK
string applicationId FK string applicationId FK
string gate "competency|document|experience|reference|salary|interview" string gate "competency_reference|document|experience|salary|interview"
enum result "PENDING|VERIFIED|REJECTED" enum result "PENDING|VERIFIED|REJECTED"
string note string note
string decidedById FK string decidedById FK
@ -208,10 +210,13 @@ erDiagram
SALARY_STRUCTURE { SALARY_STRUCTURE {
string id PK string id PK
string assignmentId FK string assignmentId FK
enum rateBasis "MONTHLY|DAILY (the other is derived)"
decimal basic decimal basic
decimal victualingPerDay decimal victualingPerDay
json allowances json allowances
string currency string currency
date effectiveFrom "effective-dated: many per assignment"
date effectiveTo "null = current"
string approvedById FK "Manager" string approvedById FK "Manager"
} }
CONTRACT_LETTER { CONTRACT_LETTER {
@ -235,6 +240,16 @@ erDiagram
date toDate date toDate
enum status "LeaveStatus" enum status "LeaveStatus"
string appliedById FK "Site in-charge (applies for crew)" string appliedById FK "Site in-charge (applies for crew)"
string decidedById FK "Manager (approves/rejects)"
}
RELIEF_REQUEST {
string id PK
string vesselId FK
string rankId FK
string reason
enum status "ReliefRequestStatus"
string requestedById FK "site staff (flags a foreseen gap)"
string requisitionId FK "set when the office converts it"
} }
PPE_ISSUE { PPE_ISSUE {
string id PK string id PK
@ -334,9 +349,10 @@ erDiagram
what makes "ex-hand preferred" cheap — their experience and documents are what makes "ex-hand preferred" cheap — their experience and documents are
already on file. `employeeId` is assigned at onboarding. already on file. `employeeId` is assigned at onboarding.
- **`Application` vs `Requisition`** — one requisition, many applications; - **`Application` vs `Requisition`** — one requisition, many applications;
`APPLICATION_GATE` rows are the audit of each vetting gate (the columns in `APPLICATION_GATE` rows are the audit of each vetting gate (competency &
notebook page 2: competency, document, experience, reference, salary, references, document, experience, salary, interview — competency and reference
interview). `interviewWaived` is set true for ex-hands. are one gate). `interviewWaived` is set true **only after a Manager-approved
waiver** for a returning ex-hand — never automatically.
- **`CrewAssignment`** is a single tour of duty. Onboarding creates it and - **`CrewAssignment`** is a single tour of duty. Onboarding creates it and
flips the requisition to `FILLED`. Sign-off sets `signOffDate`/`SIGNED_OFF`, flips the requisition to `FILLED`. Sign-off sets `signOffDate`/`SIGNED_OFF`,
appends an `EXPERIENCE_RECORD`, and triggers a backfill requisition. appends an `EXPERIENCE_RECORD`, and triggers a backfill requisition.
@ -347,16 +363,23 @@ erDiagram
attendance access** (the Manager reviews it for the wage report). attendance access** (the Manager reviews it for the wage report).
- **Leave** (`LEAVE_REQUEST`) is **applied by the Site in-charge for a crew - **Leave** (`LEAVE_REQUEST`) is **applied by the Site in-charge for a crew
member** (`appliedById` = site staff, `assignmentId` = the crew member) and member** (`appliedById` = site staff, `assignmentId` = the crew member) and
**decided by the MPO**. An approved leave that **clashes** — overlaps others for **decided by the Manager** (`decidedById`) — the **MPO has no leave role**. An
the same rank below its required strength — auto-raises a `Requisition` approved leave that **clashes** — overlaps others for the same rank below its
(`reason = LEAVE`, `autoRaised`, system-raised), mirroring the sign-off backfill required strength — auto-raises a `Requisition` (`reason = LEAVE`, `autoRaised`,
on `CrewAssignment`. system-raised), mirroring the sign-off backfill on `CrewAssignment`.
- **`SalaryStructure`** holds `basic`, `victualingPerDay`, and a JSON - **`RELIEF_REQUEST`** is the site-staff channel for flagging a foreseen cover gap
`allowances`; approved by a Manager. Salary is the restricted field on the (site staff do **not** raise requisitions). The office reviews it and **converts**
contract letter for site staff. it into a `Requisition` (`requisitionId` set, status `CONVERTED`).
- **`WageReport` / `WageLine`** are the generated monthly artefact: - **`SalaryStructure`** holds a `rateBasis` (MONTHLY or DAILY, the other derived),
`lineTotal = daysAttended × dailyRate + victualing`; the report `basic`, `victualingPerDay`, and a JSON `allowances`; approved by a Manager. It
`totalAmount` is the sum. Exportable to XLSX/PDF like a PO. is **effective-dated** (`effectiveFrom`/`effectiveTo`) so the salary or contract
can change mid-assignment — many structures per assignment. Salary is the
restricted field on the contract letter for site staff.
- **`WageReport` / `WageLine`** are the generated monthly artefact. A line
**prorates across the effective-dated structures** that overlap the month
(`days×rate₁ + days×rate₂`); **victualing is a separate accrual line**, not
rolled into base pay. The report `totalAmount` is the sum. Exportable to
XLSX/PDF like a PO.
- **PPE as inventory** — when the inventory flag is on, a `PPE_ISSUE` can also - **PPE as inventory** — when the inventory flag is on, a `PPE_ISSUE` can also
decrement `ItemInventory` at the site (optional integration). decrement `ItemInventory` at the site (optional integration).

@ -1,11 +1,8 @@
# Crewing Design Document # Crewing Design Document
> **Reconciled:** [Crewing Implementation Spec](Crewing-Implementation-Spec) is the > **Authoritative build spec:** [Crewing Implementation Spec](Crewing-Implementation-Spec)
> authoritative build instruction set. Where this page differs, follow the spec — > carries the full reconciled instructions (codebase changes, final roles/nav
> notably: **leave is Manager-approved** (not MPO); the **interview waiver is an > matrices, screen spec). This page is the design rationale, aligned with that spec.
> explicit Manager-approved action** (never automatic); **only MPO/Manager raise
> requisitions** (site staff *request relief cover*); the recruitment board has
> **7 stages**; the **MPO has no attendance access**.
> Companion pages: [Architecture](Crewing-Architecture) · > Companion pages: [Architecture](Crewing-Architecture) ·
> [Data Model](Crewing-Data-Model) · [Workflows](Crewing-Workflows) · > [Data Model](Crewing-Data-Model) · [Workflows](Crewing-Workflows) ·
@ -61,7 +58,8 @@ A crew member goes on leave, finishes a contract (EOC), is terminated, is
signed off on medical grounds, or leaves for another reason. Any of these signed off on medical grounds, or leaves for another reason. Any of these
creates a **gap** for a specific **rank** on a specific **vessel/site**. On a creates a **gap** for a specific **rank** on a specific **vessel/site**. On a
*scheduled sign-off* the gap (and its **Requisition**) is raised automatically; *scheduled sign-off* the gap (and its **Requisition**) is raised automatically;
otherwise site staff or the MPO raise it manually. A **leave clash** — when otherwise the **MPO or Manager** raise it manually (site staff instead **request
relief cover**, which the office converts into a requisition). A **leave clash** — when
approved leaves overlap so a rank drops below its required strength on a approved leaves overlap so a rank drops below its required strength on a
vessel/site — likewise **auto-raises a Requisition** (reason `LEAVE`). vessel/site — likewise **auto-raises a Requisition** (reason `LEAVE`).
@ -73,17 +71,23 @@ New candidates either **apply on the Pelagia site** (uploading a CV, which is
entry as fallback) or are **uploaded manually** by the MPO. entry as fallback) or are **uploaded manually** by the MPO.
### 3.3 Vetting (gated) ### 3.3 Vetting (gated)
Each shortlisted candidate is evaluated against the rank's **minimum criteria**: Each shortlisted candidate moves through a **7-stage** gated pipeline, evaluated
against the rank's **minimum criteria**:
- **Competency** — qualifications for the rank. 1. **Competency & references** — qualifications for the rank plus previous-employer
- **Document verification** — seafarer documents present and valid. confirmation (one stage).
- **Experience***type of vessel*, *time in rank*, *total duration*. 2. **Document verification** — seafarer documents present and valid.
- **Reference check** — previous-employer confirmation. 3. **Salary agreement** — proposed structure accepted in principle (Manager
- **Salary agreement** — proposed structure accepted in principle. approves the structure).
4. **Proposal** — terms put to the candidate.
5. **Interview****everyone is interviewed**; for a returning ex-hand the
interview may be **waived only with explicit Manager approval** (never
automatic).
6. **Selection** — all gates cleared and Manager-approved.
The candidate is then **proposed** and (except for ex-hands, where it's Experience (*type of vessel*, *time in rank*, *total duration*) is checked as part
**optional**) **interviewed**. The outcome is **Selection** or **Rejection with of competency/document review. The outcome of any gate is **pass** or **Rejection
remarks**. Every gate is recorded. with remarks**; every gate is recorded.
### 3.4 Onboarding ### 3.4 Onboarding
On selection: **joining formalities** run — salary is confirmed and a On selection: **joining formalities** run — salary is confirmed and a
@ -103,9 +107,9 @@ Site staff record **attendance** daily, **issue PPE** (with boiler-suit and shoe
sizes), maintain **documents/bank/EPF/next-of-kin/emergency contact**, and apply sizes), maintain **documents/bank/EPF/next-of-kin/emergency contact**, and apply
for **leave on behalf of crew members** through the site **leave planner** (which for **leave on behalf of crew members** through the site **leave planner** (which
shows every crew member's contract span and leaves on one timeline; crew are data shows every crew member's contract span and leaves on one timeline; crew are data
subjects, not portal users, so the **Site in-charge applies leave for them**). If subjects, not portal users, so the **Site in-charge applies leave for them** and
an approved leave **clashes** with another for the same rank, the planner the **Manager approves** it). If an approved leave **clashes** with another for the
auto-raises a backfill **Requisition**. The PM raises **appraisals**; the **MPO same rank, the planner auto-raises a backfill **Requisition**. The PM raises **appraisals**; the **MPO
verifies**, the **Manager approves**. verifies**, the **Manager approves**.
### 3.6 Office verification ### 3.6 Office verification

@ -1,12 +1,9 @@
# Crewing Module # Crewing Module
> **Reconciled:** [Crewing Implementation Spec](Crewing-Implementation-Spec) is the > **Authoritative build spec:** [Crewing Implementation Spec](Crewing-Implementation-Spec)
> authoritative build instruction set (it reconciles this design page with the > carries the full reconciled instructions — codebase changes, the final
> design handoff). Where they differ, follow the spec — notably: **leave is > roles/permission and navigation matrices, and the detailed screen spec. This
> Manager-approved** (not MPO); the **interview waiver is an explicit > page is the design overview, aligned with that spec.
> Manager-approved action** (never automatic); **only MPO/Manager raise
> requisitions** (site staff *request relief cover*); the recruitment board has
> **7 stages**; the **MPO has no attendance access**.
The **Crewing Module** (a.k.a. *Manning*) extends Pelagia Portal (PPMS) from a The **Crewing Module** (a.k.a. *Manning*) extends Pelagia Portal (PPMS) from a
purchasing system into a crew lifecycle system. It manages the people who run purchasing system into a crew lifecycle system. It manages the people who run
@ -41,7 +38,7 @@ for this design were literally two notebook pages). The pain points it removes:
| Area | Capability | | Area | Capability |
|---|---| |---|---|
| **Requisitions** | Auto-raised (on sign-off / end-of-contract, or when a **leave clash** leaves a rank short) or manually-raised vacancy for a rank on a vessel/site; reason (leave / end-of-contract / termination / medical / other). | | **Requisitions** | Auto-raised (on sign-off / end-of-contract, or when a **leave clash** leaves a rank short) or manually-raised vacancy for a rank on a vessel/site; reason (leave / end-of-contract / termination / medical / other). |
| **Candidate pipeline** | Shortlist (ex-hand preferred) → competency → document verification → reference check → salary agreement → proposal → interview (optional for ex-hands) → selection / rejection with remarks. | | **Candidate pipeline** | A 7-stage gated board: shortlist (ex-hand preferred) → competency & references → document verification → salary agreement → proposal → interview → selection / rejection with remarks. Everyone is interviewed; for returning ex-hands the interview can be **waived only with Manager approval**. |
| **CV intake** | Self-apply on the Pelagia site or MPO upload; CV parsed for age, vessel type, rank and experience, with manual fallback. | | **CV intake** | Self-apply on the Pelagia site or MPO upload; CV parsed for age, vessel type, rank and experience, with manual fallback. |
| **Onboarding** | One selection event starts salary, victualing, attendance, experience accrual, PF tracking and the PPE issue checklist. | | **Onboarding** | One selection event starts salary, victualing, attendance, experience accrual, PF tracking and the PPE issue checklist. |
| **Crew records** | Bank details, EPF/UAN, next of kin, emergency contact, contract letter, and role-based seafarer documents (STCW, Aadhaar, PAN, Passport, CDC, COC, photo, licence, medical fitness). | | **Crew records** | Bank details, EPF/UAN, next of kin, emergency contact, contract letter, and role-based seafarer documents (STCW, Aadhaar, PAN, Passport, CDC, COC, photo, licence, medical fitness). |

@ -1,11 +1,9 @@
# Crewing Roles and Permissions # Crewing Roles and Permissions
> **Reconciled:** the authoritative permission matrix is in > **Authoritative build spec:** the same matrix appears in
> [Crewing Implementation Spec § 6](Crewing-Implementation-Spec#6-roles--permissions-final-matrix). > [Crewing Implementation Spec § 6](Crewing-Implementation-Spec#6-roles--permissions-final-matrix),
> It corrects this page: **`decide_leave` → Manager only** (not MPO); `apply_leave` > alongside the codebase wiring. This page is the detailed rationale, aligned with
> → Site staff + Manager; **leave removed** from `verify_site_records`; > that spec.
> `raise_requisition` is **MPO/Manager only** (site staff get `request_relief_cover`);
> and new `request/approve_interview_waiver` + `record_interview_result` permissions.
Crewing extends the existing `lib/permissions.ts` map (see Crewing extends the existing `lib/permissions.ts` map (see
[Roles and Permissions](Roles-and-Permissions)) with crewing permissions. Every [Roles and Permissions](Roles-and-Permissions)) with crewing permissions. Every
@ -16,10 +14,10 @@ relevant state machine adds the status+role gate on top.
| Crewing actor | PPMS role | Notes | | Crewing actor | PPMS role | Notes |
|---|---|---| |---|---|---|
| PM / APM / Site In-charge **(the only on-site logins)** | **`SITE_STAFF`** (new, proposed) | apply-only leave **(on behalf of crew)**, attendance, PPE issue, doc upload, view-only contract (except salary) & bank | | PM / APM / Site In-charge **(the only on-site logins)** | **`SITE_STAFF`** (new, proposed) | apply-only leave **(on behalf of crew)**, attendance, PPE issue, doc upload, view-only contract (except salary) & bank; **requests relief cover** (does not raise requisitions) |
| MPO | **`MANNING`** (existing — "crew-management staff") | recruitment + verifies all site data except bank/EPF; **no attendance access** | | MPO | **`MANNING`** (existing — "crew-management staff") | recruitment + verifies site data (docs/PPE/NoK), **except** bank/EPF (Accounts) and leave (Manager); **no leave and no attendance access** |
| Accounts | **`ACCOUNTS`** | verifies bank + EPF; consumes wage report | | Accounts | **`ACCOUNTS`** | verifies bank + EPF; consumes wage report |
| Manager | **`MANAGER`** | approves salary structures, candidate list, appraisals, wage reports; **reviews attendance** | | Manager | **`MANAGER`** | approves salary structures, candidate selection, interview waivers, **leave**, appraisals, wage reports; **reviews attendance** |
| Superuser | **`SUPERUSER`** | combined authority across crewing actions | | Superuser | **`SUPERUSER`** | combined authority across crewing actions |
| Auditor | **`AUDITOR`** | read-only across crewing | | Auditor | **`AUDITOR`** | read-only across crewing |
| Admin | **`ADMIN`** | manages ranks & doc requirements | | Admin | **`ADMIN`** | manages ranks & doc requirements |
@ -44,25 +42,29 @@ relevant state machine adds the status+role gate on top.
| Permission | SITE | MAN | ACC | MGR | SU | AUD | ADM | | Permission | SITE | MAN | ACC | MGR | SU | AUD | ADM |
|---|:--:|:--:|:--:|:--:|:--:|:--:|:--:| |---|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
| `raise_requisition` | ✓ | ✓ | | ✓ | ✓ | | | | `raise_requisition` ⁵ | | ✓ | | ✓ | ✓ | | |
| `request_relief_cover` ⁵ | ✓ | | | | ✓ | | |
| `convert_relief_to_requisition` | | ✓ | | ✓ | ✓ | | |
| `cancel_requisition` | | ✓ | | ✓ | ✓ | | | | `cancel_requisition` | | ✓ | | ✓ | ✓ | | |
| `view_requisitions` | ✓ | ✓ | | ✓ | ✓ | ✓ | ✓ | | `view_requisitions` | | ✓ | | ✓ | ✓ | ✓ | ✓ |
| `manage_candidates` (shortlist/vetting) | | ✓ | | ✓ | ✓ | | | | `manage_candidates` (shortlist/vetting) | | ✓ | | ✓ | ✓ | | |
| `record_reference_check` | | ✓ | | ✓ | ✓ | | | | `record_reference_check` | | ✓ | | ✓ | ✓ | | |
| `propose_interview` | | ✓ | | ✓ | ✓ | | | | `record_interview_result` | | ✓ | | ✓ | ✓ | | |
| `request_interview_waiver` ⁶ | | ✓ | | | ✓ | | |
| `approve_interview_waiver` ⁶ | | | | ✓ | ✓ | | |
| `approve_salary_structure` | | | | ✓ | ✓ | | | | `approve_salary_structure` | | | | ✓ | ✓ | | |
| `select_candidate` | | ✓ | | ✓ | ✓ | | | | `select_candidate` (final approval) | | | | ✓ | ✓ | | |
| `onboard_crew` | | ✓ | | ✓ | ✓ | | | | `onboard_crew` | | ✓ | | ✓ | ✓ | | |
| `sign_off_crew` | ✓ | ✓ | | ✓ | ✓ | | | | `sign_off_crew` | ✓ | ✓ | | ✓ | ✓ | | |
| `view_crew_records` | ✓¹ | ✓ | ✓² | ✓ | ✓ | ✓ | ✓ | | `view_crew_records` | ✓¹ | ✓ | ✓² | ✓ | ✓ | ✓ | ✓ |
| `upload_crew_records` (docs/NoK/emergency/EPF) | ✓ | ✓ | | ✓ | ✓ | | | | `upload_crew_records` (docs/NoK/emergency/EPF) | ✓ | ✓ | | ✓ | ✓ | | |
| `issue_ppe` | ✓ | ✓ | | ✓ | ✓ | | | | `issue_ppe` | ✓ | ✓ | | ✓ | ✓ | | |
| `apply_leave` | ✓ | | | ✓ | ✓ | | | | `apply_leave` | ✓ | | | ✓ | ✓ | | |
| `decide_leave` | | | | ✓ | ✓ | | | | `decide_leave` | | | | ✓ | ✓ | | |
| `record_attendance` | ✓ | | | | ✓ | | | | `record_attendance` | ✓ | | | | ✓ | | |
| `view_attendance` ³ | ✓ | | | ✓ | ✓ | ✓ | | | `view_attendance` ³ | ✓ | | | ✓ | ✓ | ✓ | |
| `verify_site_records` (docs/PPE/leave/NoK) | | ✓ | | ✓ | ✓ | | | | `verify_site_records` (docs/PPE/NoK) | | ✓ | | ✓ | ✓ | | |
| `verify_bank_epf` | | | ✓ | | ✓ | | | | `verify_bank_epf` | | | ✓ | | ✓ | | |
| `raise_appraisal` | ✓ | | | ✓ | ✓ | | | | `raise_appraisal` | ✓ | | | ✓ | ✓ | | |
| `verify_appraisal` | | ✓ | | ✓ | ✓ | | | | `verify_appraisal` | | ✓ | | ✓ | ✓ | | |
| `approve_appraisal` | | | | ✓ | ✓ | | | | `approve_appraisal` | | | | ✓ | ✓ | | |
@ -78,6 +80,14 @@ relevant state machine adds the status+role gate on top.
record it; the **Manager** reviews it (it feeds the wage report). record it; the **Manager** reviews it (it feeds the wage report).
⁴ The wage report reads attendance, so it is generated by the **Manager** (or the ⁴ The wage report reads attendance, so it is generated by the **Manager** (or the
month-end job) — **not** the MPO, who has no attendance access. month-end job) — **not** the MPO, who has no attendance access.
**Site staff do not raise requisitions.** They flag a gap with
`request_relief_cover`; the office (MPO/Manager) reviews it and converts it into a
requisition.
⁶ Everyone is interviewed. For a returning ex-hand the MPO may
`request_interview_waiver`; only a **Manager** can `approve_interview_waiver`
(never automatic).
**Leave is decided by the Manager**, not the MPO. Site staff apply on behalf of
crew; the MPO has no role in leave.
## 3. Field-level restrictions (PII) ## 3. Field-level restrictions (PII)
@ -100,10 +110,16 @@ Enforced in Server Components/Actions on top of the permission map:
site staff and visible only to site staff and the Manager** — the **MPO cannot site staff and visible only to site staff and the Manager** — the **MPO cannot
see attendance**; the Manager reviews it (it feeds the wage report). see attendance**; the Manager reviews it (it feeds the wage report).
- **Leave is applied by the Site in-charge on behalf of crew** (crew are not portal - **Leave is applied by the Site in-charge on behalf of crew** (crew are not portal
users); the **MPO decides** (approves/rejects) leave. An **approved leave that users); the **Manager decides** (approves/rejects) leave — the **MPO has no leave
clashes** — overlaps another for the same rank below its required strength — role**. An **approved leave that clashes** — overlaps another for the same rank
**auto-raises a `LEAVE`-reason requisition** (system-raised, same backfill path below its required strength — **auto-raises a `LEAVE`-reason requisition**
as sign-off). (system-raised, same backfill path as sign-off).
- **Site staff do not raise requisitions.** A foreseen gap is flagged with
`request_relief_cover`; the office converts the relief request into a
requisition.
- **Everyone is interviewed**; an ex-hand interview is **waived only with Manager
approval** (`request_interview_waiver` by MPO → `approve_interview_waiver` by
Manager).
- An **appraisal** must be `MPO_VERIFIED` before a Manager can approve it. - An **appraisal** must be `MPO_VERIFIED` before a Manager can approve it.
- A **wage report** must be `MANAGER_APPROVED` before it is `SENT_TO_ACCOUNTS`. - A **wage report** must be `MANAGER_APPROVED` before it is `SENT_TO_ACCOUNTS`.
- Only **one ACTIVE assignment** per crew member; sign-off is required before a - Only **one ACTIVE assignment** per crew member; sign-off is required before a

@ -1,10 +1,8 @@
# Crewing Use Cases # Crewing Use Cases
> **Reconciled:** [Crewing Implementation Spec](Crewing-Implementation-Spec) is the > **Authoritative build spec:** [Crewing Implementation Spec](Crewing-Implementation-Spec)
> authoritative build instruction set. Where this page differs, follow the spec — > carries the full reconciled instructions (codebase changes, roles/nav matrices,
> notably: **leave is decided by the Manager** (UC-12); the **interview waiver is an > screen spec). This page is the actor/use-case catalogue, aligned with that spec.
> explicit Manager-approved action** (UC-08); and **only MPO/Manager raise
> requisitions** (site staff *request relief cover*, UC-01).
Actors and the use cases each can perform. The diagram uses a flowchart to Actors and the use cases each can perform. The diagram uses a flowchart to
approximate UML use-case notation (Mermaid has no native use-case diagram); approximate UML use-case notation (Mermaid has no native use-case diagram);
@ -23,6 +21,7 @@ flowchart LR
subgraph Requisition subgraph Requisition
U1(["Raise requisition"]) U1(["Raise requisition"])
U1b(["Request relief cover"])
U2(["Sign off crew → auto-requisition"]) U2(["Sign off crew → auto-requisition"])
U2b(["Leave clash → auto-requisition (system)"]) U2b(["Leave clash → auto-requisition (system)"])
U3(["Cancel requisition"]) U3(["Cancel requisition"])
@ -39,13 +38,14 @@ flowchart LR
end end
subgraph SiteHR["Site HR"] subgraph SiteHR["Site HR"]
U12(["Apply for leave"]) U12(["Apply for leave"])
U12b(["Approve leave (Manager)"])
U13(["View leave planner"]) U13(["View leave planner"])
U14(["Record attendance"]) U14(["Record attendance"])
U15(["Issue PPE (sizes)"]) U15(["Issue PPE (sizes)"])
U16(["Upload documents / EPF / NoK"]) U16(["Upload documents / EPF / NoK"])
end end
subgraph Verify["Office verification"] subgraph Verify["Office verification"]
U17(["Verify docs / PPE / leave"]) U17(["Verify docs / PPE / NoK"])
U18(["Verify bank & EPF"]) U18(["Verify bank & EPF"])
end end
subgraph Appraisal subgraph Appraisal
@ -62,10 +62,10 @@ flowchart LR
U25(["Manage ranks & doc requirements"]) U25(["Manage ranks & doc requirements"])
end end
SS --- U1 & U2 & U12 & U13 & U14 & U15 & U16 & U19 SS --- U1b & U2 & U12 & U13 & U14 & U15 & U16 & U19
CAND --- U4 CAND --- U4
MPO --- U5 & U6 & U7 & U8 & U9 & U11 & U17 & U20 & U2b MPO --- U1 & U5 & U6 & U7 & U8 & U9 & U11 & U17 & U20 & U2b
MGR --- U3 & U9 & U10 & U11 & U21 & U22 & U23 & U24 MGR --- U1 & U3 & U9 & U10 & U11 & U12b & U13 & U21 & U22 & U23 & U24
ACC --- U18 & U24 ACC --- U18 & U24
ADM --- U25 ADM --- U25
``` ```
@ -78,23 +78,25 @@ flowchart LR
| ID | Use case | Primary actor | Pre-condition | Main success outcome | | ID | Use case | Primary actor | Pre-condition | Main success outcome |
|---|---|---|---|---| |---|---|---|---|---|
| UC-01 | Raise requisition | Site staff / MPO | a rank is or will be vacant | `Requisition(OPEN)` created, MPO notified | | UC-01 | Raise requisition | MPO / Manager | a rank is or will be vacant | `Requisition(OPEN)` created, MPO notified |
| UC-01b | Request relief cover | Site staff | a foreseen cover gap | `ReliefRequest(OPEN)`; office converts it into a requisition |
| UC-02 | Auto-requisition on sign-off | System | crew member signed off | requisition raised automatically; experience updated | | UC-02 | Auto-requisition on sign-off | System | crew member signed off | requisition raised automatically; experience updated |
| UC-03 | Cancel requisition | Manager | requisition not yet filled | `CANCELLED` with reason | | UC-03 | Cancel requisition | Manager | requisition not yet filled | `CANCELLED` with reason |
| UC-04 | Apply with CV | Candidate | careers form reachable | `CrewMember(PROSPECT)` + application; CV parsed or manual | | UC-04 | Apply with CV | Candidate | careers form reachable | `CrewMember(PROSPECT)` + application; CV parsed or manual |
| UC-05 | Shortlist candidates | MPO | requisition `OPEN` | applications `SHORTLISTED`; ex-hands preferred | | UC-05 | Shortlist candidates | MPO | requisition `OPEN` | applications `SHORTLISTED`; ex-hands preferred |
| UC-06 | Run vetting gates | MPO | candidate shortlisted | competency/document/experience gates recorded | | UC-06 | Run vetting gates | MPO | candidate shortlisted | competency/document/experience gates recorded |
| UC-07 | Reference check | MPO | candidate in vetting | reference result recorded | | UC-07 | Reference check | MPO | candidate in vetting | reference result recorded |
| UC-08 | Propose & interview | MPO | gates cleared | proposal sent; interview recorded (waived for ex-hands) | | UC-08 | Propose & interview | MPO | gates cleared | proposal sent; interview result recorded — ex-hand interview waivable **only with Manager approval** |
| UC-09 | Select / reject with remarks | MPO / Manager | interview done / waived | `SELECTED` or `REJECTED` + remarks | | UC-09 | Select / reject with remarks | MPO records, **Manager approves** | interview done or Manager-approved waiver | `SELECTED` (Manager-approved) or `REJECTED` + remarks |
| UC-10 | Approve salary structure & candidate list | Manager | candidate proposed | salary structure approved | | UC-10 | Approve salary structure & candidate list | Manager | candidate proposed | salary structure approved |
| UC-11 | Onboard candidate | MPO / Manager | candidate selected | `CrewAssignment(ACTIVE)`; salary/victualing/attendance/experience/PF/PPE started; employeeId issued; requisition `FILLED` | | UC-11 | Onboard candidate | MPO / Manager | candidate selected | `CrewAssignment(ACTIVE)`; salary/victualing/attendance/experience/PF/PPE started; employeeId issued; requisition `FILLED` |
| UC-12 | Apply for leave (for a crew member) | Site in-charge | crew has active assignment | `LeaveRequest(APPLIED)` on the crew member's assignment | | UC-12 | Apply for leave (for a crew member) | Site in-charge | crew has active assignment | `LeaveRequest(APPLIED)` on the crew member's assignment |
| UC-13 | View leave planner | Site staff / MPO / Manager | — | timeline of contracts + leaves per site | | UC-12b | Approve / reject leave | Manager | leave applied | `APPROVED` → assignment `ON_LEAVE` (clash auto-raises a requisition); or `REJECTED` |
| UC-13 | View leave planner | Site staff / Manager | — | timeline of contracts + leaves per site (the MPO has no leave access) |
| UC-14 | Record attendance | Site staff | active assignment | daily `Attendance` rows (visible to site staff + Manager; **not** the MPO) | | UC-14 | Record attendance | Site staff | active assignment | daily `Attendance` rows (visible to site staff + Manager; **not** the MPO) |
| UC-15 | Issue PPE | Site staff | active assignment | `PpeIssue` with size (boiler suit/shoes) | | UC-15 | Issue PPE | Site staff | active assignment | `PpeIssue` with size (boiler suit/shoes) |
| UC-16 | Upload documents / EPF / next-of-kin / emergency | Site staff | crew exists | records created `PENDING` verification | | UC-16 | Upload documents / EPF / next-of-kin / emergency | Site staff | crew exists | records created `PENDING` verification |
| UC-17 | Verify docs / PPE / leave | MPO | pending records exist | `VERIFIED` (everything except attendance) | | UC-17 | Verify docs / PPE / NoK | MPO | pending records exist | `VERIFIED` (everything except attendance and leave) |
| UC-18 | Verify bank & EPF | Accounts | pending bank/EPF | `VERIFIED`; UAN/Aadhaar checked vs EPFO | | UC-18 | Verify bank & EPF | Accounts | pending bank/EPF | `VERIFIED`; UAN/Aadhaar checked vs EPFO |
| UC-19 | Raise appraisal | Site staff (PM) | active assignment | `Appraisal(SUBMITTED)` | | UC-19 | Raise appraisal | Site staff (PM) | active assignment | `Appraisal(SUBMITTED)` |
| UC-20 | Verify appraisal | MPO | appraisal submitted | `MPO_VERIFIED` | | UC-20 | Verify appraisal | MPO | appraisal submitted | `MPO_VERIFIED` |
@ -110,7 +112,8 @@ flowchart LR
- **UC-04 alt** — CV not parseable → manual field entry (never blocks intake). - **UC-04 alt** — CV not parseable → manual field entry (never blocks intake).
- **UC-06/07/09 alt** — any gate fails → `REJECTED` with remarks; application - **UC-06/07/09 alt** — any gate fails → `REJECTED` with remarks; application
ends, requisition stays open for other candidates. ends, requisition stays open for other candidates.
- **UC-08 alt** — ex-hand → interview waived (`interviewWaived = true`). - **UC-08 alt** — returning ex-hand → MPO requests an interview waiver; on
**Manager approval** `interviewWaived = true` (never automatic).
- **UC-11 alt** — joining formalities incomplete (no signed contract / unapproved - **UC-11 alt** — joining formalities incomplete (no signed contract / unapproved
salary) → onboarding blocked. salary) → onboarding blocked.
- **UC-16/17 alt** — verifier rejects a record → back to `PENDING` with remarks - **UC-16/17 alt** — verifier rejects a record → back to `PENDING` with remarks
@ -118,7 +121,8 @@ flowchart LR
- **UC-22 alt** — attendance gaps flagged before generation; report can be - **UC-22 alt** — attendance gaps flagged before generation; report can be
regenerated until approved. regenerated until approved.
- **UC-12 note** — crew are data subjects, not portal users, so the **Site - **UC-12 note** — crew are data subjects, not portal users, so the **Site
in-charge applies leave on their behalf** (apply-only; the MPO decides it). in-charge applies leave on their behalf** (apply-only; the **Manager decides it**
— the MPO has no leave role).
- **UC-14 note** — attendance is recorded by site staff and **reviewed by the - **UC-14 note** — attendance is recorded by site staff and **reviewed by the
Manager**; the **MPO has no attendance access** (so the wage report, UC-22, is Manager**; the **MPO has no attendance access** (so the wage report, UC-22, is
generated by the Manager / month-end job, not the MPO). generated by the Manager / month-end job, not the MPO).

@ -1,10 +1,8 @@
# Crewing User Stories # Crewing User Stories
> **Reconciled:** [Crewing Implementation Spec § 10](Crewing-Implementation-Spec#10-user-stories) > **Authoritative build spec:** [Crewing Implementation Spec](Crewing-Implementation-Spec)
> carries the authoritative reconciliations to this backlog — notably **A2** > carries the full reconciled instructions (codebase changes, roles/nav matrices,
> (site staff *request relief cover*; only MPO/Manager raise requisitions), > screen spec). This page is the requirement backlog, aligned with that spec.
> **G3** (the **Manager** decides leave), **C7/C8** (interview waiver is an explicit
> Manager-approved action), and **G4/I1** (the **MPO has no attendance access**).
Backlog for the Crewing Module, grouped into epics. Format: Backlog for the Crewing Module, grouped into epics. Format:
*As a `<role>`, I want `<capability>`, so that `<value>`* + acceptance criteria *As a `<role>`, I want `<capability>`, so that `<value>`* + acceptance criteria
@ -24,11 +22,18 @@ signs off, so that no vacancy goes untracked.
- AC4: a `CrewAction(REQUISITION_RAISED)` is written. - AC4: a `CrewAction(REQUISITION_RAISED)` is written.
**A2 — Manual requisition** **A2 — Manual requisition**
As **site staff / MPO**, I want to raise a requisition manually (e.g. planned As an **MPO / Manager**, I want to raise a requisition manually (e.g. planned
leave), so that I can pre-empt a gap. leave), so that I can pre-empt a gap.
- AC1: I select vessel, rank, reason, needed-by date, and min-experience criteria. - AC1: I select vessel, rank, reason, needed-by date, and min-experience criteria.
- AC2: the requisition appears in the MPO shortlist queue. - AC2: the requisition appears in the MPO shortlist queue.
**A2b — Request relief cover (site staff)**
As **site staff**, I want to flag a foreseen cover gap (I cannot raise
requisitions myself), so that the office can act on it.
- AC1: I submit a relief request (vessel, rank, reason, note) → `ReliefRequest(OPEN)`.
- AC2: it appears in the office "Relief requests from sites" list; the MPO/Manager
**convert** it into a requisition (status `CONVERTED`).
**A3 — Requisition list & detail** **A3 — Requisition list & detail**
As an **MPO/Manager**, I want a filterable list of requisitions by As an **MPO/Manager**, I want a filterable list of requisitions by
vessel/rank/status, so that I can prioritise sourcing. vessel/rank/status, so that I can prioritise sourcing.
@ -114,16 +119,21 @@ allowances), so that the proposal has terms.
- AC1: structure captured; visible only to office roles (not site staff). - AC1: structure captured; visible only to office roles (not site staff).
**C7 — Proposal & interview** **C7 — Proposal & interview**
As an **MPO**, I want to propose to the candidate and record an interview, so As an **MPO**, I want to propose to the candidate and record an interview result,
that selection is informed. so that selection is informed.
- AC1: new candidates require an interview record. - AC1: **everyone is interviewed** by default; the MPO records the result.
- AC2: ex-hands can have the interview **waived** (`interviewWaived`). - AC2: for a returning ex-hand the interview is **waived only with Manager
approval** — the MPO requests the waiver (`request_interview_waiver`), a
**Manager** approves it (`approve_interview_waiver`), then `interviewWaived` is
set. There is no automatic waiver.
**C8 — Selection / rejection with remarks** **C8 — Selection / rejection with remarks**
As an **MPO/Manager**, I want to select or reject with remarks, so that the As an **MPO** (records) and **Manager** (approves), I want to select or reject
decision and its reason are on record. with remarks, so that the decision and its reason are on record.
- AC1: rejection requires remarks. - AC1: rejection requires remarks.
- AC2: selection requires all prior gates cleared. - AC2: selection requires all prior gates cleared.
- AC3: **selection is Manager-approved** — the MPO records the interview result;
the Manager approves the salary structure and the selection.
**C9 — Pipeline board** **C9 — Pipeline board**
As an **MPO**, I want a board showing each candidate's stage per requisition, so As an **MPO**, I want a board showing each candidate's stage per requisition, so
@ -207,8 +217,9 @@ As **site staff**, I want to record PPE returns, so that the register is current
## Epic G — Leave & attendance ## Epic G — Leave & attendance
**G1 — Site leave planner** **G1 — Site leave planner**
As **site staff / MPO / Manager**, I want a planner showing every crew member's As **site staff / Manager**, I want a planner showing every crew member's
contract span and leaves on one timeline, so that I can plan cover. contract span and leaves on one timeline, so that I can plan cover. (The MPO has
no leave access.)
- AC1: timeline per site with contract bars + leave bars. - AC1: timeline per site with contract bars + leave bars.
- AC2: overlapping absences for the same rank are highlighted (a clash below - AC2: overlapping absences for the same rank are highlighted (a clash below
required strength auto-raises a requisition — see **A5**). required strength auto-raises a requisition — see **A5**).
@ -220,8 +231,8 @@ As the **Site in-charge**, I want to apply for leave **on behalf of a crew membe
- AC2: site staff cannot self-approve (no `decide_leave`). - AC2: site staff cannot self-approve (no `decide_leave`).
**G3 — Decide leave** **G3 — Decide leave**
As an **MPO**, I want to approve/reject leave with a note, so that the planner As a **Manager**, I want to approve/reject leave with a note, so that the planner
stays accurate. stays accurate (the **MPO has no leave role**).
- AC1: approval moves the assignment to `ON_LEAVE` for the period. - AC1: approval moves the assignment to `ON_LEAVE` for the period.
- AC2: if the approval creates a clash (the rank falls below required strength for - AC2: if the approval creates a clash (the rank falls below required strength for
the overlap), a backfill requisition is auto-raised — see **A5**. the overlap), a backfill requisition is auto-raised — see **A5**.

@ -1,10 +1,9 @@
# Crewing Workflows # Crewing Workflows
> **Reconciled:** [Crewing Implementation Spec](Crewing-Implementation-Spec) is the > **Authoritative build spec:** [Crewing Implementation Spec](Crewing-Implementation-Spec)
> authoritative build instruction set. Where this page differs, follow the spec — > carries the full reconciled instructions (codebase wiring, roles/nav matrices,
> notably: **leave is decided by the Manager** (not MPO); ex-hands pass through > screen spec). This page holds the detailed state/sequence diagrams, aligned with
> **Interview** unless a **Manager-approved waiver** is granted (no automatic > that spec.
> waiver path); and the Application pipeline has the reconciled **7 stages**.
Every crewing lifecycle is enforced by a single state-machine module (the Every crewing lifecycle is enforced by a single state-machine module (the
`po-state-machine.ts` pattern) and recorded as `CrewAction` audit rows. This `po-state-machine.ts` pattern) and recorded as `CrewAction` audit rows. This
@ -24,8 +23,7 @@ stateDiagram-v2
OPEN --> SHORTLISTING : add candidates OPEN --> SHORTLISTING : add candidates
SHORTLISTING --> PROPOSING : a candidate clears vetting SHORTLISTING --> PROPOSING : a candidate clears vetting
PROPOSING --> INTERVIEWING : interview scheduled PROPOSING --> INTERVIEWING : interview scheduled
PROPOSING --> SELECTED : ex-hand, interview waived INTERVIEWING --> SELECTED : candidate selected (or Manager-approved waiver)
INTERVIEWING --> SELECTED : candidate selected
INTERVIEWING --> SHORTLISTING : all rejected, re-source INTERVIEWING --> SHORTLISTING : all rejected, re-source
SELECTED --> FILLED : onboarded (assignment created) SELECTED --> FILLED : onboarded (assignment created)
OPEN --> CANCELLED : vacancy withdrawn OPEN --> CANCELLED : vacancy withdrawn
@ -36,40 +34,43 @@ stateDiagram-v2
| From | Action | To | Roles | Side-effect | | From | Action | To | Roles | Side-effect |
|---|---|---|---|---| |---|---|---|---|---|
| — | `raise` | OPEN | system (sign-off **or leave clash**) / SITE_STAFF / MANNING | email MPO | | — | `raise` | OPEN | system (sign-off **or leave clash**) / MANNING / MANAGER | email MPO |
| OPEN | `start_shortlist` | SHORTLISTING | MANNING | — | | OPEN | `start_shortlist` | SHORTLISTING | MANNING | — |
| SHORTLISTING | `propose` | PROPOSING | MANNING | email Manager | | SHORTLISTING | `propose` | PROPOSING | MANNING | email Manager |
| PROPOSING | `schedule_interview` | INTERVIEWING | MANNING | email candidate | | PROPOSING | `schedule_interview` | INTERVIEWING | MANNING | email candidate |
| PROPOSING | `select` (ex-hand) | SELECTED | MANNING, MANAGER | email candidate | | INTERVIEWING | `select` | SELECTED | MANAGER | email candidate |
| INTERVIEWING | `select` | SELECTED | MANNING, MANAGER | email candidate |
| INTERVIEWING | `reject_all` | SHORTLISTING | MANNING | — | | INTERVIEWING | `reject_all` | SHORTLISTING | MANNING | — |
| SELECTED | `onboard` | FILLED | MANNING, MANAGER | **onboarding side-effects** | | SELECTED | `onboard` | FILLED | MANNING, MANAGER | **onboarding side-effects** |
| OPEN/SHORTLISTING | `cancel` | CANCELLED | MANAGER | — | | OPEN/SHORTLISTING | `cancel` | CANCELLED | MANNING, MANAGER | — |
Site staff do **not** raise requisitions — they **request relief cover**, which
the office converts into a requisition. Selection is **Manager-approved** (the MPO
records the interview result; the Manager approves the salary structure and the
selection). For a returning ex-hand the interview may be **waived only with Manager
approval** — there is no automatic waiver path.
--- ---
## 2. Candidate pipeline (Application) ## 2. Candidate pipeline (Application)
The per-candidate gated vetting from notebook page 2. Many applications run per The per-candidate gated vetting from notebook page 2, as a **7-stage board**.
requisition; one ends in `ONBOARDED`. **Ex-hands skip the interview** (optional). Many applications run per requisition; one ends in `ONBOARDED`. **Everyone is
Any gate can end in **rejection with remarks**. interviewed**; for a returning ex-hand the interview is **waived only with Manager
approval** (`interviewWaived` is set after approval). Any gate can end in
**rejection with remarks**.
```mermaid ```mermaid
stateDiagram-v2 stateDiagram-v2
[*] --> SHORTLISTED [*] --> SHORTLISTED
SHORTLISTED --> COMPETENCY_CHECK SHORTLISTED --> COMPETENCY_AND_REFERENCES
COMPETENCY_CHECK --> DOC_VERIFICATION : pass COMPETENCY_AND_REFERENCES --> DOC_VERIFICATION : pass
DOC_VERIFICATION --> REFERENCE_CHECK : pass DOC_VERIFICATION --> SALARY_AGREEMENT : pass
REFERENCE_CHECK --> SALARY_AGREEMENT : pass SALARY_AGREEMENT --> PROPOSED : agreed (Manager approves structure)
SALARY_AGREEMENT --> PROPOSED : agreed PROPOSED --> INTERVIEW : proposal accepted
PROPOSED --> INTERVIEW : new candidate INTERVIEW --> SELECTED : pass / Manager-approved waiver
PROPOSED --> SELECTED : ex-hand (interview waived) SELECTED --> ONBOARDED : onboard (joining formalities, Manager-approved)
INTERVIEW --> SELECTED : pass COMPETENCY_AND_REFERENCES --> REJECTED : fail (remarks)
SELECTED --> JOINING : joining formalities
JOINING --> ONBOARDED : contract + salary confirmed
COMPETENCY_CHECK --> REJECTED : fail (remarks)
DOC_VERIFICATION --> REJECTED : fail (remarks) DOC_VERIFICATION --> REJECTED : fail (remarks)
REFERENCE_CHECK --> REJECTED : fail (remarks)
SALARY_AGREEMENT --> REJECTED : not agreed SALARY_AGREEMENT --> REJECTED : not agreed
INTERVIEW --> REJECTED : fail (remarks) INTERVIEW --> REJECTED : fail (remarks)
ONBOARDED --> [*] ONBOARDED --> [*]
@ -103,8 +104,9 @@ backfill Requisition** for the same rank/vessel.
### 3.1 Leave & the clash backfill ### 3.1 Leave & the clash backfill
Leave is **applied by the Site in-charge on behalf of a crew member** Leave is **applied by the Site in-charge on behalf of a crew member**
(`LeaveRequest(APPLIED)`) and **decided by the MPO** (`APPROVED` / `REJECTED`). (`LeaveRequest(APPLIED)`) and **decided by the Manager** (`APPROVED` / `REJECTED`)
An approval moves the assignment to `ON_LEAVE` for the period. On approval the — the **MPO has no role in leave**. An approval moves the assignment to `ON_LEAVE`
for the period. On approval the
state machine checks the rank's cover on that vessel/site over the leave window: state machine checks the rank's cover on that vessel/site over the leave window:
if the approved leaves would drop the rank **below its required strength**, it if the approved leaves would drop the rank **below its required strength**, it
**auto-raises a backfill `Requisition`** (reason `LEAVE`, `autoRaised`) — the same **auto-raises a backfill `Requisition`** (reason `LEAVE`, `autoRaised`) — the same
@ -116,13 +118,14 @@ highlighted. (Attendance, by contrast, is recorded on site and reviewed by the
sequenceDiagram sequenceDiagram
actor SIC as Site in-charge actor SIC as Site in-charge
participant SYS as App / state machines participant SYS as App / state machines
actor MPO actor MGR as Manager
participant DB as PostgreSQL participant DB as PostgreSQL
participant N as Notifier participant N as Notifier
actor MPO
SIC->>SYS: apply leave for crew member (dates) SIC->>SYS: apply leave for crew member (dates)
SYS->>DB: LeaveRequest (APPLIED) SYS->>DB: LeaveRequest (APPLIED)
MPO->>SYS: approve leave MGR->>SYS: approve leave
SYS->>DB: LeaveRequest APPROVED; assignment ON_LEAVE SYS->>DB: LeaveRequest APPROVED; assignment ON_LEAVE
SYS->>SYS: check rank cover over the leave window SYS->>SYS: check rank cover over the leave window
alt clash — rank below required strength alt clash — rank below required strength
@ -234,20 +237,20 @@ sequenceDiagram
actor C as Candidate actor C as Candidate
participant DB as PostgreSQL participant DB as PostgreSQL
MPO->>SYS: competency check MPO->>SYS: competency & references check
SYS->>DB: gate(competency)=VERIFIED SYS->>DB: gate(competency_reference)=VERIFIED
MPO->>SYS: document verification MPO->>SYS: document verification
SYS->>DB: gate(document)=VERIFIED SYS->>DB: gate(document)=VERIFIED
MPO->>SYS: reference check
SYS->>DB: gate(reference)=VERIFIED
MPO->>SYS: salary agreement (propose structure) MPO->>SYS: salary agreement (propose structure)
SYS->>DB: gate(salary)=VERIFIED, proposedSalary SYS->>DB: gate(salary)=PROPOSED, proposedSalary
MPO->>C: proposal MPO->>C: proposal
alt new candidate alt interview held (everyone by default)
MPO->>SYS: schedule + record interview MPO->>SYS: schedule + record interview result
SYS->>DB: gate(interview)=VERIFIED SYS->>DB: gate(interview)=VERIFIED
else ex-hand else returning ex-hand, waiver requested
Note over MPO,SYS: interview waived MPO->>MGR: request interview waiver
MGR->>SYS: approve waiver
SYS->>DB: gate(interview)=WAIVED (Manager-approved)
end end
MGR->>SYS: approve salary structure + select MGR->>SYS: approve salary structure + select
SYS->>DB: application SELECTED SYS->>DB: application SELECTED
@ -271,10 +274,10 @@ sequenceDiagram
actor MPO actor MPO
actor ACC as Accounts actor ACC as Accounts
SS->>SYS: upload documents / PPE issue / leave / next-of-kin / EPF SS->>SYS: upload documents / PPE issue / next-of-kin / EPF
SYS->>DB: records (verificationStatus=PENDING) SYS->>DB: records (verificationStatus=PENDING)
par MPO verifies (all except attendance) par MPO verifies (all except attendance and leave)
MPO->>SYS: verify document / PPE / leave / NoK MPO->>SYS: verify document / PPE / NoK
SYS->>DB: VERIFIED (verifiedById=MPO) SYS->>DB: VERIFIED (verifiedById=MPO)
and Accounts verifies bank + EPF and Accounts verifies bank + EPF
ACC->>SYS: verify bank detail ACC->>SYS: verify bank detail