Skip to content

Employee monthly schedules ​

Monthly work schedules drive working_days per employee per month. That count feeds attendance KPIs and other scorecard logic (see Where schedules are used).


Collections ​

CollectionPurpose
tbl_scorecard_configDay codes document _id: schedule-day-codes (field codes[])
tbl_employee_schedulesOne document per employee per month

Schedule document id: {employee_id}:{YYYY}-{MM}

Fields:

FieldDescription
employee_id, year, monthIdentity
working_daysCached count of days whose code_id maps to is_working_day: true
days[]Per calendar day: day, code_id, time_ranges[]

Legacy documents may still store code (abbreviation) on a day; the API migrates to code_id on read when possible.


Day codes (catalog) ​

Each catalog row has:

FieldDescription
idStable ID (employee cells reference this, not the abbreviation)
codeShort label on the grid (e.g. WD, OFF)
descriptionLong label
is_working_dayWhen true, the day counts toward working_days (attendance KPI)
is_task_delivery_dayWhen true, the day is a task-delivery workday (BSC quantity KPI + scorecard grid). Defaults to is_working_day when omitted on legacy rows. VL and SL default to is_task_delivery_day: true but is_working_day: false.
sort_orderConfig UI ordering

Empty cells (no code_id) are non-working and have no times.

Configured at Scorecard → Configurations → Schedule Day Codes.


Time ranges ​

Optional shift times per day (time_ranges[]):

FieldDescription
start_minutesMinutes from midnight (0 = 12:00 AM)
end_minutesExclusive end (e.g. 5:00 AM → 300)
  • Up to 8 non-overlapping ranges per day.
  • Same-day shift: end_minutes > start_minutes (e.g. 8:00 AM–5:00 PM).
  • Overnight shift: end_minutes <= start_minutes — end is the next morning, exclusive (e.g. 8:00 PM–5:00 AM → start_minutes=1200, end_minutes=300). Legacy data may still use two segments (0–300 and 1200–1440); the UI merges those for display.

Default weekday template ​

Used for auto-fill and Apply weekday template:

DayCodeTimes
Mon–FriWD8:00 PM – 5:00 AM (single overnight range)
Sat–SunOFF(none)

Defined in api/app/services/schedule_time_ranges.py (default_weekday_time_ranges()).


Employees in the grid ​

  • Active employees (status: true), regardless of bsc_status.
  • Grid includes employee name, department, cluster (primary department), and WD (working-day count).
  • Default scope: departments of the signed-in user.
  • Level 3+: scope=all or department_ids (comma-separated) to widen the list.

Auto-fill ​

When loading the month grid for the current month or next month (one month ahead):

  • Any active employee without a saved schedule gets the weekday template above.
  • Existing saved schedules are never overwritten by auto-fill.

Manual bulk actions (level 3+, audit-logged):

ActionBehavior
Copy from last monthCopies prior month day-by-day; weekday template if prior month missing
Apply weekday templateOverwrites the whole month for filtered employees

Who can edit ​

AccessEdit which months
Any authenticatedView all months
Level 3–4Any month that is not dashboard-finalized
Level 5Any month, including finalized (should re-generate the final report after corrections)
Level 1–2View only

A month locks for levels 3–4 when the BSC dashboard month report status is final. Past draft months stay editable. Reopen on the BSC dashboard unlocks schedules again. Saves and bulk actions return HTTP 409 while locked.

See Fiscal cycles & locks.


Working days for attendance ​

text
resolve_working_days_for_employee(db, employee_id, year, month) → int
  1. Saved schedule in tbl_employee_schedules → working_days on that document (recomputed on save from day codes).
  2. Else → Mon–Fri count in the calendar month (weekdays_in_calendar_month).

HTTP: GET /v1/scorecard/employee-schedules/working-days/{employee_id}?year=&month=

Attendance KPI formula (when working_days is used):

text
(working_days − violation_count) / working_days × 100

See also BSC metrics.


Where schedules are used ​

ConsumerNotes
Working-days APIGET .../working-days/{employee_id} — per-employee resolved count
BSC attendance KPIsresolve_working_days_for_employee in bsc_employee_compute
Task delivery calendaris_task_delivery_day on day codes; task_delivery/workdays.py
Task delivery scorecard gridDay code abbreviations; pending/missing highlights — Fiscal cycles § Task delivery
Dashboard / analyticsNot in the product yet — Roadmap

API ​

MethodPathWho
GET/v1/scorecard/schedule-day-codesAuthenticated
PUT/v1/scorecard/schedule-day-codesLevel ≥ 3
GET/v1/scorecard/employee-schedules/month?year=&month=&search=&scope=&department_ids=Authenticated (auto-fill on load; default scope=my)
PUT/v1/scorecard/employee-schedules/monthLevel ≥ 3 (409 if dashboard month is final, unless level 5)
POST/v1/scorecard/employee-schedules/month/copy-from-previousLevel ≥ 3
POST/v1/scorecard/employee-schedules/month/apply-templateLevel ≥ 3
GET/v1/scorecard/employee-schedules/{employee_id}/{year}/{month}Authenticated
GET/v1/scorecard/employee-schedules/working-days/{employee_id}?year=&month=Authenticated

Audit logging ​

Creates/updates write to tbl_logs with resources employee_schedule and schedule_day_codes (same pattern as SBS/ATW entries).


UI ​

RouteDescription
/organization/schedulesMonthly grid: frozen identity columns, scrollable days, filters, bulk actions, save month
/organizationChart + list (schedules are a separate nav link) — see Organization
Scorecard → Configurations → Schedule Day CodesCode catalog

Grid behavior (summary):

  • Sort default: employee → department → cluster; column headers toggle primary sort.
  • Today column: US Eastern (America/New_York) date; header highlight only.
  • Day headers: May 27 + weekday line; weekend headers use opaque styling.
  • Status line: Showing N employees · May 2026 · {active filter summary}.

Key frontend files:

  • web/src/pages/OrganizationSchedulesPage.tsx
  • web/src/pages/organization_components/EmployeeSchedulesPanel.tsx
  • web/src/pages/organization_components/scheduleFilterUtils.ts
  • web/src/pages/organization_components/scheduleTimeUtils.ts

Key backend files:

  • api/app/services/employee_schedules.py
  • api/app/services/schedule_day_codes.py
  • api/app/services/schedule_time_ranges.py
  • api/app/services/employee_schedule_policy.py

Not in v1 ​

  • CSV import/export for schedules
  • Schedule data on Organization chart/list pages (schedules are only on /organization/schedules)
  • Pagination (acceptable for <200 employees per filter today)
  • Auto-migrating legacy two-segment overnight rows to one range on save (optional future)