Files
2026-05-25 00:58:00 +02:00

76 lines
2.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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
"""
from alembic import op
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 (nur falls nicht vorhanden CREATE TYPE IF NOT EXISTS nicht überall unterstützt)
op.execute("""
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'assignment_mode') THEN
CREATE TYPE assignment_mode AS ENUM ('fza', 'payroll', 'both');
END IF;
END $$
""")
# Tabelle nur anlegen falls noch nicht vorhanden (idempotent)
op.execute("""
CREATE TABLE IF NOT EXISTS special_assignments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
date_from DATE NOT NULL,
date_to DATE NOT NULL,
factor NUMERIC(5,3) NOT NULL,
mode assignment_mode NOT NULL DEFAULT 'both',
label VARCHAR(100),
description TEXT,
CONSTRAINT ck_special_assignment_factor CHECK (factor > 0 AND factor <= 10),
CONSTRAINT ck_special_assignment_dates CHECK (date_from <= date_to)
)
""")
op.execute("CREATE INDEX IF NOT EXISTS ix_special_assignments_user_id ON special_assignments(user_id)")
op.execute("CREATE INDEX IF NOT EXISTS ix_special_assignments_company_id ON special_assignments(company_id)")
# Exclusion Constraint (nur falls noch nicht vorhanden)
op.execute("""
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'special_assignments_no_overlap'
) THEN
ALTER TABLE special_assignments
ADD CONSTRAINT special_assignments_no_overlap
EXCLUDE USING gist (
user_id WITH =,
daterange(date_from, date_to, '[]') WITH &&
);
END IF;
END $$
""")
def downgrade() -> None:
op.execute("DROP TABLE IF EXISTS special_assignments")
op.execute("DROP TYPE IF EXISTS assignment_mode")