Update Crewing Design Document

shad0w 2026-06-21 20:19:21 +00:00
parent 24dc4c62c1
commit 9bcc43f460

@ -1,164 +1,171 @@
# Crewing Design Document # Crewing Design Document
> 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) ·
> [Use Cases](Crewing-Use-Cases) · [Roles & Permissions](Crewing-Roles-and-Permissions) · > [Use Cases](Crewing-Use-Cases) · [Roles & Permissions](Crewing-Roles-and-Permissions) ·
> [User Stories](Crewing-User-Stories) > [User Stories](Crewing-User-Stories)
## 1. Purpose & scope ## 1. Purpose & scope
The Crewing Module digitises Pelagia's **manning process**: keeping every The Crewing Module digitises Pelagia's **manning process**: keeping every
dredger and site crewed with competent, documented, paid people, and recording dredger and site crewed with competent, documented, paid people, and recording
the full lifecycle of each crew member. the full lifecycle of each crew member.
**In scope** **In scope**
1. Vacancy detection & **requisitions**. 1. Vacancy detection & **requisitions**.
2. **Recruitment pipeline** (shortlist → vetting → proposal → interview → 2. **Recruitment pipeline** (shortlist → vetting → proposal → interview →
selection) for ex-hands and new candidates. selection) for ex-hands and new candidates.
3. **Onboarding** and the automatic processes it kicks off. 3. **Onboarding** and the automatic processes it kicks off.
4. **Crew records**: documents, bank, EPF, next-of-kin, emergency contact, 4. **Crew records**: documents, bank, EPF, next-of-kin, emergency contact,
contract, PPE. contract, PPE.
5. **Site HR**: leave planner, attendance. 5. **Site HR**: leave planner, attendance.
6. **Appraisal** (PM → MPO → Manager). 6. **Appraisal** (PM → MPO → Manager).
7. **Sign-off** and experience accrual. 7. **Sign-off** and experience accrual.
8. **Wage report** generation for Accounts. 8. **Wage report** generation for Accounts.
**Out of scope (v1)** — actual salary disbursement / banking integration (we **Out of scope (v1)** — actual salary disbursement / banking integration (we
produce the report; Accounts pays), payslip generation, statutory return filing, produce the report; Accounts pays), payslip generation, statutory return filing,
training-course delivery, and seafarer-document issuance (we store and verify, training-course delivery, and seafarer-document issuance (we store and verify,
we don't issue). we don't issue).
## 2. Actors ## 2. Actors
| Actor | Real-world role | Maps to PPMS role | | Actor | Real-world role | Maps to PPMS role |
|---|---|---| |---|---|---|
| **Site staff** | PM / Assistant PM / Site In-charge on the dredger | new `SITE_STAFF` role (proposed) | | **Site staff** | PM / Assistant PM / Site In-charge on the dredger | new `SITE_STAFF` role (proposed) |
| **MPO** | Manning / Personnel Officer in the office | existing `MANNING` role | | **MPO** | Manning / Personnel Officer in the office | existing `MANNING` role |
| **Accounts** | Finance team | existing `ACCOUNTS` role | | **Accounts** | Finance team | existing `ACCOUNTS` role |
| **Manager** | Department / crewing manager | existing `MANAGER` role | | **Manager** | Department / crewing manager | existing `MANAGER` role |
| **Candidate** | External applicant (ex-hand or new) | unauthenticated public form / lightweight `CANDIDATE` identity | | **Candidate** | External applicant (ex-hand or new) | unauthenticated public form |
| **Crew member** | Onboarded employee | data subject; not necessarily a portal login in v1 | | **Crew member** | Onboarded employee | data subject; not necessarily a portal login in v1 |
| Admin / Superuser / Auditor | as in PO module | existing roles | | Admin / Superuser / Auditor | as in PO module | existing roles |
See the on-vessel **rank hierarchy** (PM → … → Mess Boy) in See the on-vessel **rank hierarchy** (PM → … → Mess Boy) in
[Data Model § Rank](Crewing-Data-Model#rank-the-org-hierarchy). [Data Model § Rank](Crewing-Data-Model#rank-the-org-hierarchy).
## 3. Domain narrative ## 3. Domain narrative
### 3.1 A vacancy opens ### 3.1 A vacancy opens
A crew member goes on leave, finishes a contract (EOC), is terminated, is 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. otherwise site staff or the MPO raise it manually.
### 3.2 Sourcing candidates ### 3.2 Sourcing candidates
The MPO shortlists candidates for the rank. **Ex-hands are preferred** (people The MPO shortlists candidates for the rank. **Ex-hands are preferred** (people
who have sailed with Pelagia before — their record is already in the system). who have sailed with Pelagia before — their record is already in the system).
New candidates either **apply on the Pelagia site** (uploading a CV, which is New candidates either **apply on the Pelagia site** (uploading a CV, which is
**parsed** for age, vessel type, current/past rank and experience — with manual **parsed** for age, vessel type, current/past rank and experience — with manual
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 is evaluated against the rank's **minimum criteria**:
- **Competency** — qualifications for the rank. - **Competency** — qualifications for the rank.
- **Document verification** — seafarer documents present and valid. - **Document verification** — seafarer documents present and valid.
- **Experience***type of vessel*, *time in rank*, *total duration*. - **Experience***type of vessel*, *time in rank*, *total duration*.
- **Reference check** — previous-employer confirmation. - **Reference check** — previous-employer confirmation.
- **Salary agreement** — proposed structure accepted in principle. - **Salary agreement** — proposed structure accepted in principle.
The candidate is then **proposed** and (except for ex-hands, where it's The candidate is then **proposed** and (except for ex-hands, where it's
**optional**) **interviewed**. The outcome is **Selection** or **Rejection with **optional**) **interviewed**. The outcome is **Selection** or **Rejection with
remarks**. Every gate is recorded. 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
**contract letter** issued. Creating the **CrewAssignment** automatically starts: **contract letter** issued. Creating the **CrewAssignment** automatically starts:
- **salary** (the agreed structure becomes active), - **salary** (the agreed structure becomes active),
- **victualing** (food/messing allowance accrual), - **victualing** (food/messing allowance accrual),
- **attendance** capture, - **attendance** capture,
- **experience** accrual on this vessel/rank, - **experience** accrual on this vessel/rank,
- **PF** tracking (UAN/EPF), and - **PF** tracking (UAN/EPF), and
- the **PPE issue** checklist. - the **PPE issue** checklist.
The crew member receives an **Employee ID**. The crew member receives an **Employee ID**.
### 3.5 Life on site ### 3.5 Life on site
Site staff record **attendance** daily, **issue PPE** (with boiler-suit and shoe 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** through the site **leave planner** (which shows every crew for **leave** through the site **leave planner** (which shows every crew
member's contract span and leaves on one timeline). The PM raises **appraisals**; member's contract span and leaves on one timeline). The PM raises **appraisals**;
the **MPO verifies**, the **Manager approves**. the **MPO verifies**, the **Manager approves**.
### 3.6 Office verification ### 3.6 Office verification
The office is the source of truth for verified data. **The MPO verifies The office is the source of truth for verified data. **The MPO verifies
everything site staff enter, except attendance**; **bank details and EPF are everything site staff enter, except attendance**; **bank details and EPF are
verified by Accounts** (UAN/Aadhaar checked against EPFO). verified by Accounts** (UAN/Aadhaar checked against EPFO).
### 3.7 Sign-off & backfill ### 3.7 Sign-off & backfill
When a crew member signs off, the assignment closes, their **experience record When a crew member signs off, the assignment closes, their **experience record
is updated** with the completed tour, and a **backfill Requisition** is raised is updated** with the completed tour, and a **backfill Requisition** is raised
automatically — closing the loop back to §3.1. automatically — closing the loop back to §3.1.
### 3.8 Payroll feed ### 3.8 Payroll feed
At month end a **Wage Report** is generated per site: At month end a **Wage Report** is generated per site:
`crew × salary × days-attended (+ victualing)`. It is reviewed, **approved by the `crew × salary × days-attended (+ victualing)`. It is reviewed, **approved by the
Manager**, and **sent to Accounts** for disbursement. Manager**, and **sent to Accounts** for disbursement.
## 4. Salient features & design decisions ## 4. Salient features & design decisions
| # | Decision | Rationale | | # | Decision | Rationale |
|---|---|---| |---|---|---|
| D1 | **Two coupled state machines**`Requisition` (the vacancy) and `Application` (a candidate's progress against a requisition). | The requisition is "is this seat filled?"; the application is the per-candidate gated pipeline. Many applications per requisition; exactly one ends in onboarding. | | D1 | **Two coupled state machines**`Requisition` (the vacancy) and `Application` (a candidate's progress against a requisition). | The requisition is "is this seat filled?"; the application is the per-candidate gated pipeline. Many applications per requisition; exactly one ends in onboarding. |
| D2 | **Unified `CrewMember`** record with a `status` (PROSPECT → CANDIDATE → EMPLOYEE → EX_HAND). | "Ex-hand preferred" only works if a candidate and an ex-employee are the same record; experience carries forward automatically. | | D2 | **Unified `CrewMember`** record with a `status` (PROSPECT → CANDIDATE → EMPLOYEE → EX_HAND). | "Ex-hand preferred" only works if a candidate and an ex-employee are the same record; experience carries forward automatically. |
| D3 | **Onboarding is a side-effecting transition**, exactly like PO approval increments inventory. | Single source of truth: salary/victualing/attendance/experience/PF/PPE all start from one event, recorded as one `CrewAction`. | | D3 | **Onboarding is a side-effecting transition**, exactly like PO approval increments inventory. | Single source of truth: salary/victualing/attendance/experience/PF/PPE all start from one event, recorded as one `CrewAction`. |
| D4 | **Verification is a field-level state**, not a separate workflow. Each verifiable record carries `verificationStatus + verifiedBy`. Routing: site-entered → MPO; bank/EPF → Accounts. | Mirrors "view-only / upload / verify" split from the notebook; keeps the office as the trust boundary. | | D4 | **Verification is a field-level state**, not a separate workflow. Each verifiable record carries `verificationStatus + verifiedBy`. Routing: site-entered → MPO; bank/EPF → Accounts. | Mirrors "view-only / upload / verify" split from the notebook; keeps the office as the trust boundary. |
| D5 | **Sensitive fields are masked & gated.** Salary on the contract letter, full bank account number, and Aadhaar/PAN are restricted; site staff get *view-only-except-salary* on contracts and *view-only* bank. | Matches the explicit notebook rules and basic PII hygiene. | | D5 | **Sensitive fields are masked & gated.** Salary on the contract letter, full bank account number, and Aadhaar/PAN are restricted; site staff get *view-only-except-salary* on contracts and *view-only* bank. | Matches the explicit notebook rules and basic PII hygiene. |
| D6 | **Rank is reference data with a self-hierarchy** (3+ levels), mirroring the `Account` accounting-code hierarchy. | Drives requisition criteria, document requirements (e.g. licence for drivers), and the org chart. | | D6 | **Rank is reference data with a self-hierarchy** (3+ levels), mirroring the `Account` accounting-code hierarchy. | Drives requisition criteria, document requirements (e.g. licence for drivers), and the org chart. |
| D7 | **Document requirements are rank-driven.** A `RankDocRequirement` defines which seafarer docs a rank must hold. | "Seafarer docs (based on role)"; driving licence only for drivers. | | D7 | **Document requirements are rank-driven.** A `RankDocRequirement` defines which seafarer docs a rank must hold. | "Seafarer docs (based on role)"; driving licence only for drivers. |
| D8 | **Wage report is a generated artefact**, not live-computed on the Accounts screen. | Auditable monthly snapshot; mirrors PO export/report pattern. | | D8 | **Wage report is a generated artefact**, not live-computed on the Accounts screen. | Auditable monthly snapshot; mirrors PO export/report pattern. |
| D9 | **Reuse `Vessel`/`Site` as the cost centre** so crew cost is attributable on the same axis as PO spend. | Single cost-centre vocabulary across the portal. | | D9 | **Reuse `Vessel`/`Site` as the cost centre** so crew cost is attributable on the same axis as PO spend. | Single cost-centre vocabulary across the portal. |
| D10 | **CV parsing is best-effort with manual fallback.** Extraction populates a draft; a human confirms. | Never block intake on a parser; keep the office in control. | | D10 | **CV parsing is best-effort with manual fallback.** Extraction populates a draft; a human confirms. | Never block intake on a parser; keep the office in control. |
## 5. Non-functional requirements ## 5. Non-functional requirements
- **Auditability** — every lifecycle transition and verification writes a - **Auditability** — every lifecycle transition and verification writes a
`CrewAction` row (actor, type, note, metadata), like `POAction`. `CrewAction` row (actor, type, note, metadata), like `POAction`.
- **Privacy** — bank/EPF/identity documents are PII: stored via the same - **Privacy** — bank/EPF/identity documents are PII: stored via the same
signed-URL [file storage](File-Storage); account numbers and identity numbers signed-URL [file storage](File-Storage); account numbers and identity numbers
stored masked/encrypted; access gated by permission. stored masked/encrypted; access gated by permission.
- **Consistency** — all mutations are Server Actions calling `requirePermission` - **Consistency** — all mutations are Server Actions calling `requirePermission`
then the relevant state-machine guard; **no mutation REST endpoints**. then the relevant state-machine guard; **no mutation REST endpoints**.
- **Notifications** — declarative per-transition email/in-app side-effects via - **Notifications** — declarative per-transition email/in-app side-effects via
`lib/notifier.ts` (e.g. requisition raised → MPO; proposal → Manager; `lib/notifier.ts` (e.g. requisition raised → MPO; proposal → Manager;
appraisal verified → Manager; wage report ready → Accounts). appraisal verified → Manager; wage report ready → Accounts).
- **Document expiry** — documents with `expiryDate` surface upcoming-expiry - **Document expiry** — documents with `expiryDate` surface upcoming-expiry
warnings (medical fitness, passport, CDC, STCW). warnings (medical fitness, passport, CDC, STCW).
## 6. Assumptions ## 6. Assumptions
1. PM/APM/Site In-charge get a dedicated `SITE_STAFF` role rather than reusing 1. PM/APM/Site In-charge get a dedicated `SITE_STAFF` role rather than reusing
`TECHNICAL`. (Confirm in review — see Open Questions.) `TECHNICAL`. (Confirm in review — see Open Questions.)
2. Crew members are **data subjects**, not portal logins, in v1. A future phase 2. Crew members are **data subjects**, not portal logins, in v1. A future phase
may give crew a self-service login. may give crew a self-service login.
3. **EPFO** UAN/Aadhaar verification is a manual/assisted step in v1 (record the 3. **EPFO** UAN/Aadhaar verification is a manual/assisted step in v1 (record the
result); a programmatic check can follow the GstService precedent. result); a programmatic check can follow the GstService precedent.
4. "Victualing" is a per-day messing allowance, configurable per rank/vessel. 4. "Victualing" is a per-day messing allowance, configurable per rank/vessel.
5. One **active** assignment per crew member at a time. 5. One **active** assignment per crew member at a time.
## 7. Open questions ## 7. Open questions
| # | Question | | # | Question |
|---|---| |---|---|
| Q1 | New role `SITE_STAFF`, or extend `TECHNICAL`/`MANNING`? | | Q1 | New role `SITE_STAFF`, or extend `TECHNICAL`/`MANNING`? |
| Q2 | Does the candidate self-apply form live inside the portal (public route) or on the marketing site posting to an API? | | A1 | New role `SITE_STAFF_*` for the site heirarchy, MPO is "MANNING" |
| Q3 | EPFO verification — assisted-manual now, or build an EPFO proxy microservice like GstService? | | Q2 | Does the candidate self-apply form live inside the portal (public route) or on the marketing site posting to an API? |
| Q4 | Should salary structures be versioned per assignment (raises mid-contract) in v1, or single-structure-per-assignment? | | A2 | Lives at the static site pelagiamarine.com |
| Q5 | Is victualing part of the wage report total, or a separate accrual line? | | Q3 | EPFO verification — assisted-manual now, or build an EPFO proxy microservice like GstService? |
| Q6 | Do we need crew self-service (view own docs/payslip) in v1 or v2? | | A3 | EPFO proxy microservice like GstService would be better |
| Q7 | Attendance granularity — daily present/absent only, or shift/hours? | | Q4 | Should salary structures be versioned per assignment (raises mid-contract) in v1, or single-structure-per-assignment? |
| A4 | It is possible for the salary and entire contract to be changed mid assignment and salary must be calculated accordingly (days x amt 1 + days x amt 2) |
See the requirement backlog in [Crewing User Stories](Crewing-User-Stories). | Q5 | Is victualing part of the wage report total, or a separate accrual line? |
| A5 | separate accrual line? |
| Q6 | Do we need crew self-service (view own docs/payslip) in v1 or v2? |
| A6 | No, only PM APM Site-incharge users needed from site, they will generate slips for other site crew members |
| Q7 | Attendance granularity — daily present/absent only, or shift/hours? |
| A7 | Shift/hours + overtime? |
See the requirement backlog in [Crewing User Stories](Crewing-User-Stories).