"""Absence comments + cancellation-request status (agent-11 PR1) Revision ID: 0035 Revises: 0034 Create Date: 2026-06-23 - Neuer Enum-Wert AbsenceStatus.CANCELLATION_REQUESTED (Mitarbeiter-Stornoantrag für genehmigte Anträge → Manager genehmigt/lehnt ab) - Neue Tabelle absence_comments (Kommentar-Thread + System-Kommentare bei Statuswechsel) mit company_id-Spalte → reguläre company_id-RLS-Policy (analog 0024). """ from alembic import op from sqlalchemy import text revision = "0035" down_revision = "0034" branch_labels = None depends_on = None _BYPASS = "COALESCE(current_setting('app.bypass_rls', true), 'off') = 'on'" _CID = "company_id = NULLIF(current_setting('app.company_id', true), '')::uuid" _USING = f"({_BYPASS} OR {_CID})" def _exec(sql: str) -> None: op.execute(text(sql)) def upgrade() -> None: # 1) Enum-Wert ergänzen (idempotent) _exec("ALTER TYPE absencestatus ADD VALUE IF NOT EXISTS 'cancellation_requested'") # 2) Tabelle anlegen _exec(""" CREATE TABLE IF NOT EXISTS absence_comments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), absence_id UUID NOT NULL REFERENCES absences(id) ON DELETE CASCADE, company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE, author_id UUID REFERENCES users(id) ON DELETE SET NULL, body TEXT NOT NULL, is_system BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ) """) _exec("CREATE INDEX IF NOT EXISTS ix_absence_comments_absence_id ON absence_comments(absence_id)") _exec("CREATE INDEX IF NOT EXISTS ix_absence_comments_company_id ON absence_comments(company_id)") # 3) RLS (company_id-gefenced, analog 0024) _exec("ALTER TABLE absence_comments ENABLE ROW LEVEL SECURITY") _exec("ALTER TABLE absence_comments FORCE ROW LEVEL SECURITY") for cmd in ("select", "insert", "update", "delete"): _exec(f"DROP POLICY IF EXISTS rls_absence_comments_{cmd} ON absence_comments") _exec(f"CREATE POLICY rls_absence_comments_select ON absence_comments FOR SELECT USING {_USING}") _exec(f"CREATE POLICY rls_absence_comments_insert ON absence_comments FOR INSERT WITH CHECK {_USING}") _exec(f"CREATE POLICY rls_absence_comments_update ON absence_comments FOR UPDATE USING {_USING} WITH CHECK {_USING}") _exec(f"CREATE POLICY rls_absence_comments_delete ON absence_comments FOR DELETE USING {_USING}") def downgrade() -> None: # Enum-Wert kann in PostgreSQL nicht entfernt werden – Tabelle wird gedroppt. _exec("DROP TABLE IF EXISTS absence_comments")