From 2fcd41596e93f4ea612780ed5d339bf21d0d206e Mon Sep 17 00:00:00 2001 From: Hardik Date: Mon, 22 Jun 2026 05:13:22 +0530 Subject: [PATCH] docs(crewing): fix leave-planner inconsistencies - Leave is applied by the Site in-charge on behalf of crew (crew are not portal users), not self-service. - Attendance is visible to site staff + Manager only; the MPO has no attendance access. Drop MPO from record_attendance and (consequently) generate_wage_report; add a view_attendance permission. - A leave clash (approved leaves overlapping below a rank's required strength) auto-raises a LEAVE requisition; documented across module, design decisions, data model, workflows (new sequence), use cases, user stories, roles matrix and the architecture diagram. --- Crewing-Architecture.md | 1 + Crewing-Data-Model.md | 15 ++++++++--- Crewing-Design-Document.md | 24 ++++++++++++----- Crewing-Module.md | 12 ++++----- Crewing-Roles-and-Permissions.md | 24 ++++++++++++----- Crewing-Use-Cases.md | 15 ++++++++--- Crewing-User-Stories.md | 28 ++++++++++++++++---- Crewing-Workflows.md | 45 +++++++++++++++++++++++++++++--- 8 files changed, 130 insertions(+), 34 deletions(-) diff --git a/Crewing-Architecture.md b/Crewing-Architecture.md index 8780522..872097c 100644 --- a/Crewing-Architecture.md +++ b/Crewing-Architecture.md @@ -113,6 +113,7 @@ flowchart TB PPE --> A5 --> DB PLAN --> A6 ATT --> A6 --> DB + A6 -.leave clash.-> SM1 APPR --> A7 --> SM4 --> DB PAY --> A8 --> WR --> DB PAY --> H3 diff --git a/Crewing-Data-Model.md b/Crewing-Data-Model.md index 37d487a..1aa1fe7 100644 --- a/Crewing-Data-Model.md +++ b/Crewing-Data-Model.md @@ -210,7 +210,7 @@ erDiagram string assignmentId FK date date enum status "AttendanceStatus" - string recordedById FK + string recordedById FK "site staff; visible to site + Manager, not MPO" } LEAVE_REQUEST { string id PK @@ -219,7 +219,7 @@ erDiagram date fromDate date toDate enum status "LeaveStatus" - string appliedById FK + string appliedById FK "Site in-charge (applies for crew)" } PPE_ISSUE { string id PK @@ -327,8 +327,15 @@ erDiagram appends an `EXPERIENCE_RECORD`, and triggers a backfill requisition. - **Verification is a field** — `verificationStatus + verifiedById` on documents, bank and EPF. Routing rule (from the notebook): site-entered data → - **MPO**; bank + EPF → **Accounts**; attendance is operational (no separate - verify gate). + **MPO**; bank + EPF → **Accounts**. **Attendance** is operational: no verify + gate, and it is **visible only to site staff and the Manager — the MPO has no + attendance access** (the Manager reviews it for the wage report). +- **Leave** (`LEAVE_REQUEST`) is **applied by the Site in-charge for a crew + member** (`appliedById` = site staff, `assignmentId` = the crew member) and + **decided by the MPO**. An approved leave that **clashes** — overlaps others for + the same rank below its required strength — auto-raises a `Requisition` + (`reason = LEAVE`, `autoRaised`, system-raised), mirroring the sign-off backfill + on `CrewAssignment`. - **`SalaryStructure`** holds `basic`, `victualingPerDay`, and a JSON `allowances`; approved by a Manager. Salary is the restricted field on the contract letter for site staff. diff --git a/Crewing-Design-Document.md b/Crewing-Design-Document.md index be3d889..5c2e8da 100644 --- a/Crewing-Design-Document.md +++ b/Crewing-Design-Document.md @@ -51,7 +51,9 @@ 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 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; -otherwise site staff or the MPO raise it manually. +otherwise site staff or the MPO raise it manually. A **leave clash** — when +approved leaves overlap so a rank drops below its required strength on a +vessel/site — likewise **auto-raises a Requisition** (reason `LEAVE`). ### 3.2 Sourcing candidates The MPO shortlists candidates for the rank. **Ex-hands are preferred** (people @@ -89,14 +91,19 @@ The crew member receives an **Employee ID**. ### 3.5 Life on site Site staff record **attendance** daily, **issue PPE** (with boiler-suit and shoe sizes), maintain **documents/bank/EPF/next-of-kin/emergency contact**, and apply -for **leave** through the site **leave planner** (which shows every crew -member's contract span and leaves on one timeline). The PM raises **appraisals**; -the **MPO verifies**, the **Manager approves**. +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 +subjects, not portal users, so the **Site in-charge applies leave for them**). If +an approved leave **clashes** with another for the same rank, the planner +auto-raises a backfill **Requisition**. The PM raises **appraisals**; the **MPO +verifies**, the **Manager approves**. ### 3.6 Office verification The office is the source of truth for verified data. **The MPO verifies -everything site staff enter, except attendance**; **bank details and EPF are -verified by Accounts** (UAN/Aadhaar checked against EPFO). +everything site staff enter, except attendance** — which the **MPO cannot see at +all**; attendance is an operational record reviewed by the **Manager** (it feeds +the wage report). **Bank details and EPF are verified by Accounts** (UAN/Aadhaar +checked against EPFO). ### 3.7 Sign-off & backfill When a crew member signs off, the assignment closes, their **experience record @@ -122,6 +129,8 @@ Manager**, and **sent to Accounts** for disbursement. | 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. | | 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. | +| D11 | **A leave clash auto-raises a Requisition.** When approved leaves overlap so a rank falls below its required strength, the system raises a `LEAVE`-reason requisition automatically (same path as the sign-off backfill). | Overlapping leave was the planner's main blind spot; auto-raising keeps cover proactive instead of reactive. | +| D12 | **Attendance is Manager-only at the office.** Site staff record it; the **Manager** reviews it; the **MPO has no attendance access**. | The MPO's remit is recruitment + record verification (docs/PPE/leave/NoK); attendance is an operational/payroll input the Manager owns. | ## 5. Non-functional requirements @@ -148,6 +157,9 @@ Manager**, and **sent to Accounts** for disbursement. result); a programmatic check can follow the GstService precedent. 4. "Victualing" is a per-day messing allowance, configurable per rank/vessel. 5. One **active** assignment per crew member at a time. +6. Each rank has a **required strength** per vessel/site (default 1). A *leave + clash* = approved leaves overlapping such that active crew for that rank would + fall below that strength; this is what triggers the auto-requisition (D11). ## 7. Open questions diff --git a/Crewing-Module.md b/Crewing-Module.md index 65fc775..44f65b8 100644 --- a/Crewing-Module.md +++ b/Crewing-Module.md @@ -16,9 +16,9 @@ for email/in-app events. Today crewing lives in notebooks, WhatsApp, and spreadsheets (the source notes for this design were literally two notebook pages). The pain points it removes: -- **Vacancies are reactive and untracked.** A sign-off or leave creates a gap - that nobody formally owns until a vessel is short-handed. → Auto-raised - **Requisitions** on sign-off / end-of-contract. +- **Vacancies are reactive and untracked.** A sign-off or a leave clash creates a + gap that nobody formally owns until a vessel is short-handed. → Auto-raised + **Requisitions** on sign-off / end-of-contract and on a leave clash. - **Candidate vetting is ad-hoc.** Competency, document, reference and salary checks happen over chat with no record of who cleared what. → A gated **Candidate Pipeline** with an event log. @@ -32,17 +32,17 @@ for this design were literally two notebook pages). The pain points it removes: | Area | Capability | |---|---| -| **Requisitions** | Auto- 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. | | **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. | | **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). | | **PPE issue register** | Boiler-suit & shoe sizes plus issue tracking for the full PPE kit. | -| **Leave & attendance** | Site-level leave planner (contracts + leaves on one timeline) and daily attendance capture. | +| **Leave & attendance** | Site-level leave planner — the **Site in-charge applies leave on behalf of crew**, and an overlapping **leave clash auto-raises a requisition**. Daily attendance is captured on site and reviewed by the **Manager** (the MPO has no attendance access). | | **Appraisal** | PM raises → MPO verifies → Manager approves. | | **Sign-off** | Updates experience, closes the assignment, and auto-raises the backfill requisition. | | **Wage report** | Monthly, per site: crew × salary × days attended (+ victualing), generated and sent to Accounts. | -| **Verification** | Office sign-off: MPO verifies everything except attendance; bank + EPF verified by Accounts. | +| **Verification** | Office sign-off: MPO verifies everything except attendance (which the MPO cannot see — it is the Manager's to review); bank + EPF verified by Accounts. | ## How it fits PPMS diff --git a/Crewing-Roles-and-Permissions.md b/Crewing-Roles-and-Permissions.md index 7f67576..4c183eb 100644 --- a/Crewing-Roles-and-Permissions.md +++ b/Crewing-Roles-and-Permissions.md @@ -9,10 +9,10 @@ relevant state machine adds the status+role gate on top. | Crewing actor | PPMS role | Notes | |---|---|---| -| PM / APM / Site In-charge | **`SITE_STAFF`** (new, proposed) | apply-only leave, attendance, PPE issue, doc upload, view-only contract (except salary) & bank | -| MPO | **`MANNING`** (existing — "crew-management staff") | recruitment + verifies all site data except bank/EPF | +| PM / APM / Site In-charge | **`SITE_STAFF`** (new, proposed) | apply-only leave **(on behalf of crew)**, attendance, PPE issue, doc upload, view-only contract (except salary) & bank | +| MPO | **`MANNING`** (existing — "crew-management staff") | recruitment + verifies all site data except bank/EPF; **no attendance access** | | Accounts | **`ACCOUNTS`** | verifies bank + EPF; consumes wage report | -| Manager | **`MANAGER`** | approves salary structures, candidate list, appraisals, wage reports | +| Manager | **`MANAGER`** | approves salary structures, candidate list, appraisals, wage reports; **reviews attendance** | | Superuser | **`SUPERUSER`** | combined authority across crewing actions | | Auditor | **`AUDITOR`** | read-only across crewing | | Admin | **`ADMIN`** | manages ranks & doc requirements | @@ -44,13 +44,14 @@ relevant state machine adds the status+role gate on top. | `issue_ppe` | ✓ | ✓ | | ✓ | ✓ | | | | `apply_leave` | ✓ | ✓ | | ✓ | ✓ | | | | `decide_leave` | | ✓ | | ✓ | ✓ | | | -| `record_attendance` | ✓ | ✓ | | ✓ | ✓ | | | +| `record_attendance` | ✓ | | | | ✓ | | | +| `view_attendance` ³ | ✓ | | | ✓ | ✓ | ✓ | | | `verify_site_records` (docs/PPE/leave/NoK) | | ✓ | | ✓ | ✓ | | | | `verify_bank_epf` | | | ✓ | ✓ | ✓ | | | | `raise_appraisal` | ✓ | | | ✓ | ✓ | | | | `verify_appraisal` | | ✓ | | ✓ | ✓ | | | | `approve_appraisal` | | | | ✓ | ✓ | | | -| `generate_wage_report` | | ✓ | | ✓ | ✓ | | | +| `generate_wage_report` ⁴ | | | | ✓ | ✓ | | | | `approve_wage_report` | | | | ✓ | ✓ | | | | `view_wage_report` | | | ✓ | ✓ | ✓ | ✓ | ✓ | | `manage_ranks` | | | | ✓ | | | ✓ | @@ -58,6 +59,10 @@ relevant state machine adds the status+role gate on top. ¹ Site staff get crew records for **their own site only**, with contract **view-only-except-salary** and bank **view-only**. ² Accounts see bank/EPF and the wage report, not the full HR record. +³ **Attendance is deliberately not visible to the MPO** (or Accounts). Site staff +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 +month-end job) — **not** the MPO, who has no attendance access. ## 3. Field-level restrictions (PII) @@ -76,7 +81,14 @@ Enforced in Server Components/Actions on top of the permission map: **Manager-approved** and a contract letter is attached. - **Bank and EPF** records can only be set `VERIFIED` by **Accounts** (UAN/Aadhaar EPFO check); everything else site staff enter is verified by **MPO**. -- **Attendance** has no verification gate (operational record). +- **Attendance** has no verification gate (operational record). It is **recorded by + 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). +- **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 + clashes** — overlaps another for the same rank below its required strength — + **auto-raises a `LEAVE`-reason requisition** (system-raised, same backfill path + as sign-off). - 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`. - Only **one ACTIVE assignment** per crew member; sign-off is required before a diff --git a/Crewing-Use-Cases.md b/Crewing-Use-Cases.md index 7363d4e..e5b0ef2 100644 --- a/Crewing-Use-Cases.md +++ b/Crewing-Use-Cases.md @@ -18,6 +18,7 @@ flowchart LR subgraph Requisition U1(["Raise requisition"]) U2(["Sign off crew → auto-requisition"]) + U2b(["Leave clash → auto-requisition (system)"]) U3(["Cancel requisition"]) end subgraph Recruitment @@ -57,7 +58,7 @@ flowchart LR SS --- U1 & U2 & U12 & U13 & U14 & U15 & U16 & U19 CAND --- U4 - MPO --- U5 & U6 & U7 & U8 & U9 & U11 & U17 & U20 + MPO --- U5 & U6 & U7 & U8 & U9 & U11 & U17 & U20 & U2b MGR --- U3 & U9 & U10 & U11 & U21 & U22 & U23 & U24 ACC --- U18 & U24 ADM --- U25 @@ -78,9 +79,9 @@ flowchart LR | UC-09 | Select / reject with remarks | MPO / Manager | interview done / waived | `SELECTED` or `REJECTED` + remarks | | 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-12 | Apply for leave | Site staff | active assignment | `LeaveRequest(APPLIED)` | +| 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-14 | Record attendance | Site staff | active assignment | daily `Attendance` rows | +| 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-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) | @@ -92,6 +93,7 @@ flowchart LR | UC-23 | Approve wage report | Manager | report generated | `MANAGER_APPROVED` → `SENT_TO_ACCOUNTS` | | UC-24 | View / export wage report | Accounts / Manager | report sent | XLSX/PDF export for disbursement | | UC-25 | Manage ranks & doc requirements | Admin | — | rank hierarchy + per-rank required documents | +| UC-26 | Auto-requisition on leave clash | System | approved leaves overlap below a rank's required strength | `Requisition(OPEN, reason=LEAVE, autoRaised)`; MPO notified | ## 3. Notable extensions / alternates @@ -105,3 +107,10 @@ flowchart LR for the site to correct. - **UC-22 alt** — attendance gaps flagged before generation; report can be regenerated until approved. +- **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). +- **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 + generated by the Manager / month-end job, not the MPO). +- **UC-26** — a leave clash (overlapping approved leaves below a rank's required + strength) auto-raises a `LEAVE` requisition; same backfill path as UC-02. diff --git a/Crewing-User-Stories.md b/Crewing-User-Stories.md index e78f057..ea669d1 100644 --- a/Crewing-User-Stories.md +++ b/Crewing-User-Stories.md @@ -35,6 +35,16 @@ withdrawn vacancies don't clutter the pipeline. - AC1: only non-`FILLED` requisitions can be cancelled. - AC2: reason is required and audited. +**A5 — Auto-requisition on leave clash** +As the **system**, I want a requisition raised automatically when an approved +leave clashes (a rank drops below its required strength on a vessel/site), so that +the cover gap is owned immediately. +- AC1: approving a leave that overlaps others for the same rank below required + strength creates a `Requisition(OPEN, reason=LEAVE, autoRaised)`. +- AC2: the MPO is notified (email + in-app) and the clash is highlighted on the + planner. +- AC3: a `CrewAction(REQUISITION_RAISED)` is written. + --- ## Epic B — Candidate intake @@ -194,23 +204,29 @@ As **site staff**, I want to record PPE returns, so that the register is current As **site staff / MPO / Manager**, I want a planner showing every crew member's contract span and leaves on one timeline, so that I can plan cover. - AC1: timeline per site with contract bars + leave bars. -- AC2: overlapping absences for the same rank are highlighted. +- AC2: overlapping absences for the same rank are highlighted (a clash below + required strength auto-raises a requisition — see **A5**). -**G2 — Apply for leave** -As **site staff**, I want to apply for leave (apply-only), so that the office can -approve it. -- AC1: I cannot self-approve; status starts `APPLIED`. +**G2 — Apply for leave (for a crew member)** +As the **Site in-charge**, I want to apply for leave **on behalf of a crew member** +(apply-only; crew are not portal users), so that the office can approve it. +- AC1: I select the crew member's assignment, dates and type; status starts `APPLIED`. +- AC2: site staff cannot self-approve (no `decide_leave`). **G3 — Decide leave** As an **MPO**, I want to approve/reject leave with a note, so that the planner stays accurate. - 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 + the overlap), a backfill requisition is auto-raised — see **A5**. **G4 — Record attendance** As **site staff**, I want to record daily attendance, so that wages can be computed. - AC1: one row per assignment per day; statuses present/absent/half/leave/sign-off. - AC2: no verification gate (operational). +- AC3: attendance is visible to **site staff and the Manager only** — the **MPO + has no attendance access**. --- @@ -238,6 +254,8 @@ As a **Manager**, I want to approve a verified appraisal, so that it's final. As an **MPO**, I want a queue of pending site records (documents, PPE, leave, next-of-kin), so that I can verify everything except attendance. - AC1: verify sets `VERIFIED` + me as `verifiedBy`; reject returns with remarks. +- AC2: **attendance never appears in this queue** — the MPO has no attendance + access (it is the Manager's to review). **I2 — Accounts bank/EPF verification** As **Accounts**, I want to verify bank details and EPF (UAN/Aadhaar vs EPFO), so diff --git a/Crewing-Workflows.md b/Crewing-Workflows.md index b8c8932..028a1d2 100644 --- a/Crewing-Workflows.md +++ b/Crewing-Workflows.md @@ -9,11 +9,12 @@ tables**, and **sequence diagrams** for the end-to-end flows. ## 1. Requisition lifecycle -The vacancy. Raised automatically on sign-off / end-of-contract, or manually. +The vacancy. Raised automatically on sign-off / end-of-contract or on a **leave +clash**, or manually. ```mermaid stateDiagram-v2 - [*] --> OPEN : raise (auto on sign-off / manual) + [*] --> OPEN : raise (auto on sign-off / leave clash / manual) OPEN --> SHORTLISTING : add candidates SHORTLISTING --> PROPOSING : a candidate clears vetting PROPOSING --> INTERVIEWING : interview scheduled @@ -29,7 +30,7 @@ stateDiagram-v2 | From | Action | To | Roles | Side-effect | |---|---|---|---|---| -| — | `raise` | OPEN | system (sign-off) / SITE_STAFF / MANNING | email MPO | +| — | `raise` | OPEN | system (sign-off **or leave clash**) / SITE_STAFF / MANNING | email MPO | | OPEN | `start_shortlist` | SHORTLISTING | MANNING | — | | SHORTLISTING | `propose` | PROPOSING | MANNING | email Manager | | PROPOSING | `schedule_interview` | INTERVIEWING | MANNING | email candidate | @@ -93,6 +94,40 @@ stateDiagram-v2 `sign-off` closes the tour, appends an `EXPERIENCE_RECORD`, and **auto-raises a backfill Requisition** for the same rank/vessel. +### 3.1 Leave & the clash backfill + +Leave is **applied by the Site in-charge on behalf of a crew member** +(`LeaveRequest(APPLIED)`) and **decided by the MPO** (`APPROVED` / `REJECTED`). +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: +if the approved leaves would drop the rank **below its required strength**, it +**auto-raises a backfill `Requisition`** (reason `LEAVE`, `autoRaised`) — the same +mechanism as the sign-off backfill, surfaced on the planner where the clash is +highlighted. (Attendance, by contrast, is recorded on site and reviewed by the +**Manager**; the **MPO has no attendance access**.) + +```mermaid +sequenceDiagram + actor SIC as Site in-charge + participant SYS as App / state machines + actor MPO + participant DB as PostgreSQL + participant N as Notifier + + SIC->>SYS: apply leave for crew member (dates) + SYS->>DB: LeaveRequest (APPLIED) + MPO->>SYS: approve leave + SYS->>DB: LeaveRequest APPROVED; assignment ON_LEAVE + SYS->>SYS: check rank cover over the leave window + alt clash — rank below required strength + SYS->>DB: create Requisition (reason=LEAVE, autoRaised, OPEN) + SYS->>N: notify MPO "vacancy (leave clash): on " + N-->>MPO: email + bell + else covered + Note over SYS: no requisition needed + end +``` + --- ## 4. Appraisal lifecycle @@ -245,7 +280,9 @@ sequenceDiagram ``` Site staff see contract letters **view-only except salary** and bank details -**view-only**; salary and full account numbers are gated. +**view-only**; salary and full account numbers are gated. **Attendance** is +entered on site and **reviewed by the Manager only — the MPO has no attendance +access**; it has no verification gate. ---