"""Sondervertretungs-Faktoren: special_assignments Tabelle Revision ID: 0029 Revises: 0028 Create Date: 2026-05-25 Neue Tabelle special_assignments: - user_id + company_id (ForeignKeys mit CASCADE) - date_from / date_to - factor NUMERIC(5,3) – Multiplikator (z.B. 1.5) - mode ENUM(fza|payroll|both) - label / description (optional) - Overlap-Check per Constraint (date_from <= date_to) + App-seitige Prüfung """ import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql revision = "0029" down_revision = "0028" branch_labels = None depends_on = None def upgrade() -> None: op.execute("CREATE EXTENSION IF NOT EXISTS btree_gist") # Enum erzeugen op.execute("CREATE TYPE assignment_mode AS ENUM ('fza', 'payroll', 'both')") op.create_table( "special_assignments", sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text("gen_random_uuid()")), sa.Column("user_id", postgresql.UUID(as_uuid=True), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True), sa.Column("company_id", postgresql.UUID(as_uuid=True), sa.ForeignKey("companies.id", ondelete="CASCADE"), nullable=False, index=True), sa.Column("date_from", sa.Date, nullable=False), sa.Column("date_to", sa.Date, nullable=False), sa.Column("factor", sa.Numeric(5, 3), nullable=False), sa.Column("mode", sa.Enum("fza", "payroll", "both", name="assignment_mode", create_type=False), nullable=False, server_default="both"), sa.Column("label", sa.String(100), nullable=True), sa.Column("description", sa.Text, nullable=True), sa.CheckConstraint("factor > 0 AND factor <= 10", name="ck_special_assignment_factor"), sa.CheckConstraint("date_from <= date_to", name="ck_special_assignment_dates"), ) # Exclusion Constraint: kein überlappender Zeitraum pro User op.execute( """ ALTER TABLE special_assignments ADD CONSTRAINT special_assignments_no_overlap EXCLUDE USING gist ( user_id WITH =, daterange(date_from, date_to, '[]') WITH && ) """ ) def downgrade() -> None: op.drop_table("special_assignments") op.execute("DROP TYPE IF EXISTS assignment_mode")