"""Add planned_day_exclusion: one date the planner may not place leave on. Removing a single day out of a planner-placed period used to be impossible: the wish still said "a full week", so the next `POST /api/plan/sync` simply re-derived the day. This table is where "not this one date" is written down, per (workspace, child, parent, date). Deliberately a table of its own rather than a row in `day_override`: that one answers a *calendar* question ("is this a working day for this workspace?") and is workspace-wide, this one answers a *planning* question ("may a leave day be placed here?") and is per parent. See `app/entities/planned_day_exclusion.py`. A plain `CREATE TABLE` suffices — nothing existing changes, and there is nothing to backfill: before this migration no exclusion could be expressed, so the correct history is "none". Must stay byte-for-byte equivalent to the `planned_day_exclusion` table in `app/db/connection.py`'s `_FULL_SCHEMA` — `tests/integration/test_schema_parity.py` asserts exactly that. Revision ID: 005 Revises: 004 Create Date: 2026-09-19 """ from __future__ import annotations from alembic import op revision: str = "005" down_revision: str | None = "004" branch_labels: str | None = None depends_on: str | None = None def upgrade() -> None: op.execute( """ CREATE TABLE IF NOT EXISTS planned_day_exclusion ( id TEXT PRIMARY KEY, workspace_id TEXT NOT NULL, child_id TEXT NOT NULL, parent_personal_data_uuid TEXT NOT NULL, date DATE NOT NULL, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL, UNIQUE(workspace_id, child_id, parent_personal_data_uuid, date), FOREIGN KEY (workspace_id) REFERENCES workspace(id) ON DELETE CASCADE, FOREIGN KEY (child_id) REFERENCES child(id) ON DELETE CASCADE, FOREIGN KEY (parent_personal_data_uuid) REFERENCES personal_data(uuid) ON DELETE CASCADE ) """ ) op.execute( """ CREATE INDEX IF NOT EXISTS idx_planned_day_exclusion_workspace ON planned_day_exclusion (workspace_id) """ ) def downgrade() -> None: op.execute("DROP INDEX IF EXISTS idx_planned_day_exclusion_workspace") op.execute("DROP TABLE IF EXISTS planned_day_exclusion")