medOS ultra

Staff Schedule System

Overview + TOR mapping for the staff scheduling system, the existing-frontend audit and ultimate design.

4 min read diagramsUpdated 2026-04-29docs/architecture/staff-schedule-system/00-overview.md

Why this document exists

medOS-ultra already has a partially built staff scheduling system spread across:

  • web/packages/scheduling-kit/ (frontend) — calendar UI, shift templates, leave worklist
  • services/foundation/ (backend) — staffScheduleManagement, workTimeSetting, leaveRequest
  • services/administration/ (backend) — appointment, holiday, device, doctorRoom, corporateEmployees
  • infrastructure/medbase/ (Supabase) — schedule_business_hours only; no shift/roster tables yet
  • web/src/containers/conference/ + core-kit/conference/separate conference scheduling system

The TOR (sections 2.2.2.1 – 2.2.2.18) requires a single integrated module that covers shift planning, resource booking, leave, swaps, appointment integration, and reporting. The existing pieces don’t meet the TOR alone — there are 5 critical gaps (resource booking integration, shift swap workflow, hour-cap tracking, RBAC enforcement at DB layer, audit log scoped to schedule events).

This documentation set is the blueprint to close those gaps.

Document set

File Topic
00-overview.md This file — TOR mapping, gap analysis, glossary
01-existing-frontend.md Existing staff-schedule miniapps, routes, key components
02-conference-system.md Conference scheduling — separate architecture, why, integration points
03-backend-apis.md Foundation + Administration service modules, REST endpoints, schemas
04-database-schema.md Supabase tables (existing + gaps), MongoDB collections, RLS
05-ultimate-design.md Target architecture: unified scheduler, user profile, resource booking, RBAC
06-uat-flows-implementation.md All 4 UAT flows mapped to concrete implementation steps

TOR coverage matrix

Status legend: ✅ implemented · 🟡 partial · ❌ missing

TOR § Requirement Status Where
2.2.2.1 Schedule CRUD with location, equipment, conditions, notes 🟡 staffScheduleManagement has CRUD; equipment binding is not enforced
2.2.2.2 Schedule staff in advance StaffScheduleManagement.date arbitrary future date
2.2.2.3 Shift cycles (เวรเช้า/บ่าย/ดึก) WorkTimeSetting.item[]
2.2.2.4 Manpower targets per slot 🟡 WorkTimeSetting.item.patientAmount exists; no per-shift headcount target table
2.2.2.5 Annual + ad-hoc holidays Holiday entity (administration service)
2.2.2.6 Edit by authorized role only 🟡 App-layer guard in NestJS controllers; no DB-level RLS on schedule rows
2.2.2.7 Shift swap with approval workflow No swap entity, no approval action
2.2.2.8 Replace assigned staff in pre-set schedules 🟡 Doable via PUT /staffScheduleManagements/:id but no swap-aware audit
2.2.2.9 Leave management LeaveRequest + updateTreatmentPlanAndStatus approval action
2.2.2.10 Bind to appointment system 🟡 scheduleCheck + eventScheduleCheck validate availability; no quota deduction loop
2.2.2.11 Show staff DB + contact 🟡 corporateEmployees exists; not wired to schedule UI directory
2.2.2.12 Reports (monthly schedule, hours, room utilization, daily/monthly headcount) No report endpoints, no print views
2.2.2.13 Live monthly hours summary (during & after planning) WorkTimeSetting has caps; no actual-vs-target rollup view
2.2.2.14 Cross-department visibility (find free slots) 🟡 Possible via getAllByStaffId but no aggregated cross-dept view
2.2.2.15 Manage locations (building/dept/room) + per-location shift cycles 🟡 room/department entities exist; room controller is a stub
2.2.2.16 Per-person monthly hour cap 🟡 WorkTimeSetting.hourHigh/otHourHigh static; no enforcement at create time
2.2.2.17 (TOR section likely covers training/certification — verify with user) Out of scope for this doc unless TOR text supplied
2.2.2.18 Mark hours as regular vs OT 🟡 WorkTimeSetting.isOt flag exists; not surfaced per-shift-row in staffScheduleManagement.item

The 5 critical gaps

  1. Resource booking — rooms and equipment are first-class entities (room, device) but not linked to staffScheduleManagement. UAT Flow 1 fails: nothing prevents two doctors from booking the same Ultrasound at 09:00.
  2. Shift swap workflow — UAT Flow 2 fails: there is no ShiftSwapRequest entity, no notification fan-out, no auto-swap on approve, no audit log entry.
  3. Appointment quota loop — UAT Flow 3 partial: scheduleCheck exists but no atomic decrement of patientAmount when an appointment is created against a shift slot.
  4. Leave → schedule sync — UAT Flow 4 partial: LeaveRequest approval doesn’t tag the staffScheduleManagement rows or block downstream appointments on that day.
  5. Audit trail scoped to schedule eventsfhir_audit_log exists in Supabase but is patient-scoped; schedule edits (who created/swapped/cancelled) have no dedicated immutable log surfaced in the admin UI.

Glossary

Term Meaning
Shift / กะ Named time block (เวรเช้า 08-16, เวรบ่าย 16-24, เวรดึก 00-08) defined in WorkTimeSetting.item[]
Schedule entry A single staff-on-a-shift-on-a-date row in StaffScheduleManagement
Roster The aggregated view of all schedule entries per dept per month
Manpower target Required min staff count per shift per dept per day
Hour cap Per-person monthly ceiling (regular + OT)
Conference Tumor-board / case-review event; uses leave_request.leaveType='conference', NOT shift tables
Resource Physical asset — room, equipment, vehicle — that a shift may consume
Ask Anything