# HolidayCalendar

## Description

HolidayCalendar is a **named holiday calendar** — a stable master record identified by a machine-facing `key` (e.g. `JP_NATIONAL`, `US_CA`) and a human-facing `name` — that groups the dated `CompanyHoliday` facts belonging to it and that a `WorkRule` references for holiday classification. It makes the holiday calendar a first-class, scoped entity rather than a single global list: different regions, legal entities, or worker populations can each maintain their own set of holidays.

This resolves what the earlier design left as the Company scope seam (ADR-018, an open question in `CompanyHoliday`): scoping is now implemented structurally through HolidayCalendar rather than deferred. Each `CompanyHoliday` belongs to exactly one calendar via `calendarId`, so the same date can be a holiday in one calendar and an ordinary working day in another, enabling per-region/per-entity calendars and multi-country operation. Calculation classifies a worker's date as a holiday only through the calendar resolved from that worker's effective `WorkRule` (`WorkRule.holidayCalendarId`), never from a global lookup.

HolidayCalendar is master data (not effective-dated): the identity of a calendar — its `key` and `name` — is a stable classification, corrected in place if entered wrong rather than versioned. What varies over time (which dates are holidays) lives on the `CompanyHoliday` facts scoped to the calendar; which calendar applies to whom lives on the effective-dated `WorkRule`.

## Domain Model Definitions

### Model type

Standard

### Command Definitions

- createHolidayCalendar — register a new calendar with a stable `key` and `name`
- updateHolidayCalendar — correct a calendar's `key` or `name` in place
- deleteHolidayCalendar — remove a calendar only when no `CompanyHoliday` or `WorkRule` references it

### Query Definitions

- getHolidayCalendar — retrieve a single holiday calendar by id
- listHolidayCalendars — paginated list of all holiday calendars (PaginationInput / buildPaginatedResult conventions)

### Models

- HolidayCalendar

### Invariants

- `key` is a stable, unique, machine-facing identifier for the calendar; registering a second calendar with the same `key` is rejected
- `name` is a human-facing label; it carries no scoping or calculation semantics and may be renamed without side effects
- HolidayCalendar is master data, not effective-dated: it is corrected in place rather than superseded by a generation
- Each `CompanyHoliday` belongs to exactly one HolidayCalendar via `calendarId`; a `holidayDate` is unique per `(calendarId, holidayDate)`, so the same date may be a holiday in one calendar and a working day in another
- Holiday classification for a worker resolves the calendar from that worker's effective `WorkRule.holidayCalendarId`; a `WorkRule` with a null `holidayCalendarId` classifies no date as a holiday
- A calendar referenced by any `CompanyHoliday` or `WorkRule` is preserved (not deleted) so scoped holiday determination remains resolvable

### Relationships

- **Referenced by CompanyHoliday**: each `CompanyHoliday` belongs to one HolidayCalendar via `calendarId`; uniqueness of a holiday date is scoped to the calendar
- **Referenced by WorkRule**: `WorkRule.holidayCalendarId` (optional) selects the calendar used to classify a worker's dates as holidays; null means no calendar applies
- **Read by time-tracking calculation (cross-module, one-directional)**: the Reported → Calculated conversion classifies a date as a holiday only via the calendar resolved from the effective `WorkRule`, scoped by `calendarId` (ADR-014)
- **Read by scheduling (cross-module, one-directional)**: scheduling reads the scoped calendar to determine scheduled working-day status when building schedules and shifts (ADR-017)
