"""Schéma initial du domaine Revision ID: 0001_initial Revises: Create Date: 2026-09-09 """ from collections.abc import Sequence import sqlalchemy as sa from alembic import op revision: str = "0001_initial" down_revision: str | None = None branch_labels: str | Sequence[str] | None = None depends_on: str | Sequence[str] | None = None ROLE = sa.Enum("COORDINATOR", "LEAD", "VOLUNTEER", name="role", native_enum=False) AVAILABILITY_STATUS = sa.Enum( "AVAILABLE", "IF_NEEDED", "UNAVAILABLE", name="availabilitystatus", native_enum=False, ) ASSIGNMENT_STATUS = sa.Enum( "PROPOSED", "CONFIRMED", "DECLINED", "CANCELLED", name="assignmentstatus", native_enum=False, ) ASSIGNMENT_SOURCE = sa.Enum( "SOLVER", "MANUAL", name="assignmentsource", native_enum=False ) POSITION_CATEGORY = sa.Enum( "BAR", "TICKETING", "WELCOME", "PARKING", "CLEANING", "CATERING", "SETUP", "STAGE", "OTHER", name="positioncategory", native_enum=False, ) TSHIRT_SIZE = sa.Enum( "XS", "S", "M", "L", "XL", "XXL", "XXXL", name="tshirtsize", native_enum=False, ) def _timestamps() -> tuple[sa.Column, sa.Column]: return ( sa.Column("created_at", sa.DateTime(), nullable=False), sa.Column("updated_at", sa.DateTime(), nullable=False), ) def upgrade() -> None: op.create_table( "edition", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("year", sa.Integer(), nullable=False), sa.Column("name", sa.String(), nullable=True), sa.Column("start_date", sa.Date(), nullable=False), sa.Column("end_date", sa.Date(), nullable=False), sa.Column("retention_days", sa.Integer(), nullable=True), *_timestamps(), sa.PrimaryKeyConstraint("id"), ) op.create_index("ix_edition_year", "edition", ["year"]) op.create_table( "day_part", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("edition_id", sa.Uuid(), nullable=False), sa.Column("code", sa.String(), nullable=False), sa.Column("label", sa.String(), nullable=False), sa.Column("start_time", sa.Time(), nullable=False), sa.Column("end_time", sa.Time(), nullable=False), sa.Column("order", sa.Integer(), server_default="0", nullable=False), *_timestamps(), sa.ForeignKeyConstraint( ["edition_id"], ["edition.id"], ondelete="CASCADE" ), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint( "edition_id", "code", name="uq_day_part_edition_code" ), ) op.create_index("ix_day_part_edition_id", "day_part", ["edition_id"]) op.create_table( "skill", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("edition_id", sa.Uuid(), nullable=False), sa.Column("code", sa.String(), nullable=False), sa.Column("label", sa.String(), nullable=False), *_timestamps(), sa.ForeignKeyConstraint( ["edition_id"], ["edition.id"], ondelete="CASCADE" ), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("edition_id", "code", name="uq_skill_edition_code"), ) op.create_index("ix_skill_edition_id", "skill", ["edition_id"]) op.create_table( "volunteer", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("edition_id", sa.Uuid(), nullable=False), sa.Column("email", sa.String(), nullable=True), sa.Column("first_name", sa.String(), nullable=False), sa.Column("last_name", sa.String(), nullable=False), sa.Column("phone", sa.String(), nullable=True), sa.Column("tshirt_size", TSHIRT_SIZE, nullable=True), sa.Column("diet", sa.String(), nullable=True), sa.Column("comment", sa.String(), nullable=True), *_timestamps(), sa.ForeignKeyConstraint( ["edition_id"], ["edition.id"], ondelete="CASCADE" ), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint( "edition_id", "email", name="uq_volunteer_edition_email" ), ) op.create_index("ix_volunteer_edition_id", "volunteer", ["edition_id"]) op.create_index("ix_volunteer_email", "volunteer", ["email"]) op.create_table( "volunteer_skill", sa.Column("volunteer_id", sa.Uuid(), nullable=False), sa.Column("skill_id", sa.Uuid(), nullable=False), sa.ForeignKeyConstraint( ["volunteer_id"], ["volunteer.id"], ondelete="CASCADE" ), sa.ForeignKeyConstraint( ["skill_id"], ["skill.id"], ondelete="CASCADE" ), sa.PrimaryKeyConstraint("volunteer_id", "skill_id"), ) op.create_table( "account", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("edition_id", sa.Uuid(), nullable=False), sa.Column("email", sa.String(), nullable=False), sa.Column("role", ROLE, nullable=False), sa.Column("volunteer_id", sa.Uuid(), nullable=True), *_timestamps(), sa.ForeignKeyConstraint( ["edition_id"], ["edition.id"], ondelete="CASCADE" ), sa.ForeignKeyConstraint( ["volunteer_id"], ["volunteer.id"], ondelete="CASCADE" ), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint( "edition_id", "email", name="uq_account_edition_email" ), sa.UniqueConstraint("volunteer_id", name="uq_account_volunteer"), ) op.create_index("ix_account_edition_id", "account", ["edition_id"]) op.create_index("ix_account_email", "account", ["email"]) op.create_table( "magic_link_token", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("account_id", sa.Uuid(), nullable=False), sa.Column("token_hash", sa.String(), nullable=False), sa.Column("expires_at", sa.DateTime(), nullable=False), sa.Column("used_at", sa.DateTime(), nullable=True), *_timestamps(), sa.ForeignKeyConstraint( ["account_id"], ["account.id"], ondelete="CASCADE" ), sa.PrimaryKeyConstraint("id"), ) op.create_index( "ix_magic_link_token_account_id", "magic_link_token", ["account_id"] ) op.create_index( "ix_magic_link_token_token_hash", "magic_link_token", ["token_hash"], unique=True, ) op.create_table( "position", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("edition_id", sa.Uuid(), nullable=False), sa.Column("name", sa.String(), nullable=False), sa.Column("location", sa.String(), nullable=True), sa.Column("category", POSITION_CATEGORY, nullable=False), sa.Column("lead_account_id", sa.Uuid(), nullable=True), *_timestamps(), sa.ForeignKeyConstraint( ["edition_id"], ["edition.id"], ondelete="CASCADE" ), sa.ForeignKeyConstraint( ["lead_account_id"], ["account.id"], ondelete="SET NULL" ), sa.PrimaryKeyConstraint("id"), ) op.create_index("ix_position_edition_id", "position", ["edition_id"]) op.create_table( "shift", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("edition_id", sa.Uuid(), nullable=False), sa.Column("position_id", sa.Uuid(), nullable=False), sa.Column("starts_at", sa.DateTime(), nullable=False), sa.Column("ends_at", sa.DateTime(), nullable=False), sa.Column("min_staff", sa.Integer(), server_default="0", nullable=False), sa.Column( "ideal_staff", sa.Integer(), server_default="0", nullable=False ), *_timestamps(), sa.ForeignKeyConstraint( ["edition_id"], ["edition.id"], ondelete="CASCADE" ), sa.ForeignKeyConstraint( ["position_id"], ["position.id"], ondelete="CASCADE" ), sa.PrimaryKeyConstraint("id"), ) op.create_index("ix_shift_edition_id", "shift", ["edition_id"]) op.create_index("ix_shift_position_id", "shift", ["position_id"]) op.create_table( "shift_required_skill", sa.Column("shift_id", sa.Uuid(), nullable=False), sa.Column("skill_id", sa.Uuid(), nullable=False), sa.ForeignKeyConstraint( ["shift_id"], ["shift.id"], ondelete="CASCADE" ), sa.ForeignKeyConstraint( ["skill_id"], ["skill.id"], ondelete="CASCADE" ), sa.PrimaryKeyConstraint("shift_id", "skill_id"), ) op.create_table( "availability", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("edition_id", sa.Uuid(), nullable=False), sa.Column("volunteer_id", sa.Uuid(), nullable=False), sa.Column("date", sa.Date(), nullable=False), sa.Column("day_part_id", sa.Uuid(), nullable=False), sa.Column("status", AVAILABILITY_STATUS, nullable=False), *_timestamps(), sa.ForeignKeyConstraint( ["edition_id"], ["edition.id"], ondelete="CASCADE" ), sa.ForeignKeyConstraint( ["volunteer_id"], ["volunteer.id"], ondelete="CASCADE" ), sa.ForeignKeyConstraint( ["day_part_id"], ["day_part.id"], ondelete="CASCADE" ), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint( "volunteer_id", "date", "day_part_id", name="uq_availability_slot" ), ) op.create_index("ix_availability_edition_id", "availability", ["edition_id"]) op.create_index( "ix_availability_volunteer_id", "availability", ["volunteer_id"] ) op.create_index( "ix_availability_day_part_id", "availability", ["day_part_id"] ) op.create_table( "assignment", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("edition_id", sa.Uuid(), nullable=False), sa.Column("volunteer_id", sa.Uuid(), nullable=False), sa.Column("shift_id", sa.Uuid(), nullable=False), sa.Column( "status", ASSIGNMENT_STATUS, server_default="PROPOSED", nullable=False, ), sa.Column( "source", ASSIGNMENT_SOURCE, server_default="MANUAL", nullable=False, ), sa.Column( "locked", sa.Boolean(), server_default="false", nullable=False ), *_timestamps(), sa.ForeignKeyConstraint( ["edition_id"], ["edition.id"], ondelete="CASCADE" ), sa.ForeignKeyConstraint( ["volunteer_id"], ["volunteer.id"], ondelete="CASCADE" ), sa.ForeignKeyConstraint( ["shift_id"], ["shift.id"], ondelete="CASCADE" ), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint( "volunteer_id", "shift_id", name="uq_assignment_volunteer_shift" ), ) op.create_index("ix_assignment_edition_id", "assignment", ["edition_id"]) op.create_index( "ix_assignment_volunteer_id", "assignment", ["volunteer_id"] ) op.create_index("ix_assignment_shift_id", "assignment", ["shift_id"]) def downgrade() -> None: op.drop_table("assignment") op.drop_table("availability") op.drop_table("shift_required_skill") op.drop_table("shift") op.drop_table("position") op.drop_table("magic_link_token") op.drop_table("account") op.drop_table("volunteer_skill") op.drop_table("volunteer") op.drop_table("skill") op.drop_table("day_part") op.drop_table("edition")