Compétences supprimées de bout en bout :
- tables `skill`, `volunteer_skill`, `shift_required_skill` ;
- `Volunteer.skill_codes`, `Shift.required_skill_codes`, colonne `skills`
de l'import, règle de validation `MISSING_REQUIRED_SKILL`, jeu de démo.
Disponibilités repensées : `Availability` passe de (`day_part_id`,
`status` tri-état) à une **fenêtre horaire libre** (`date`, `start_time`,
`end_time` ; `end <= start` ⇒ passe minuit), plusieurs par jour.
- Nouveaux endpoints `GET`/`PUT /editions/{id}/volunteers/{vid}/availability`
(PUT = remplacement complet, COORDINATION) et
`GET /editions/{id}/availability` (toute l'édition, pour la grille).
- `OUTSIDE_AVAILABILITY` (toujours WARNING) : compare le créneau à l'union
des fenêtres du bénévole ce jour-là ; renvoie `date` + `uncovered_minutes`.
`DayPart` ne sert plus qu'à la borne de « journée » du cumul 8 h.
- L'import ne gère plus les disponibilités (fenêtres saisies dans l'app) :
`values.py` supprimé, mapping réduit à nom/email/téléphone/commentaire.
Migration 0007 (recrée `availability`). `AvailabilityStatus` supprimé.
158 tests, `alembic check` et `ruff` au vert. Front à suivre.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM
156 lines
5.5 KiB
Python
156 lines
5.5 KiB
Python
"""Retrait des compétences ; disponibilités en fenêtres horaires libres
|
|
|
|
Revision ID: 0007_drop_skills_avail_windows
|
|
Revises: 0006_artist_and_volunteer_wishes
|
|
Create Date: 2026-09-10
|
|
|
|
- Suppression des tables `skill`, `volunteer_skill`, `shift_required_skill`.
|
|
- `availability` : on abandonne (`day_part_id`, `status`) au profit de
|
|
(`start_time`, `end_time`) — fenêtre horaire libre, plusieurs par jour.
|
|
La table est recréée (les anciennes lignes ne sont pas convertibles).
|
|
"""
|
|
|
|
from collections.abc import Sequence
|
|
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
|
|
revision: str = "0007_drop_skills_avail_windows"
|
|
down_revision: str | None = "0006_artist_and_volunteer_wishes"
|
|
branch_labels: str | Sequence[str] | None = None
|
|
depends_on: str | Sequence[str] | None = None
|
|
|
|
_STATUS = sa.Enum(
|
|
"AVAILABLE", "IF_NEEDED", "UNAVAILABLE",
|
|
name="availabilitystatus", native_enum=False,
|
|
)
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.drop_table("shift_required_skill")
|
|
op.drop_table("volunteer_skill")
|
|
op.drop_index("ix_skill_edition_id", table_name="skill")
|
|
op.drop_table("skill")
|
|
|
|
op.drop_table("availability")
|
|
op.create_table(
|
|
"availability",
|
|
sa.Column("created_at", sa.DateTime(), nullable=False),
|
|
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
|
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("start_time", sa.Time(), nullable=False),
|
|
sa.Column("end_time", sa.Time(), nullable=False),
|
|
sa.ForeignKeyConstraint(
|
|
["edition_id"], ["edition.id"], ondelete="CASCADE"
|
|
),
|
|
sa.ForeignKeyConstraint(
|
|
["volunteer_id"], ["volunteer.id"], ondelete="CASCADE"
|
|
),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
sa.UniqueConstraint(
|
|
"volunteer_id", "date", "start_time", "end_time",
|
|
name="uq_availability_window",
|
|
),
|
|
)
|
|
op.create_index(
|
|
op.f("ix_availability_edition_id"),
|
|
"availability",
|
|
["edition_id"],
|
|
unique=False,
|
|
)
|
|
op.create_index(
|
|
op.f("ix_availability_volunteer_id"),
|
|
"availability",
|
|
["volunteer_id"],
|
|
unique=False,
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index(op.f("ix_availability_volunteer_id"), table_name="availability")
|
|
op.drop_index(op.f("ix_availability_edition_id"), table_name="availability")
|
|
op.drop_table("availability")
|
|
op.create_table(
|
|
"availability",
|
|
sa.Column("created_at", sa.DateTime(), nullable=False),
|
|
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
|
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", _STATUS, nullable=False),
|
|
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(
|
|
op.f("ix_availability_edition_id"),
|
|
"availability", ["edition_id"], unique=False,
|
|
)
|
|
op.create_index(
|
|
op.f("ix_availability_volunteer_id"),
|
|
"availability", ["volunteer_id"], unique=False,
|
|
)
|
|
op.create_index(
|
|
op.f("ix_availability_day_part_id"),
|
|
"availability", ["day_part_id"], unique=False,
|
|
)
|
|
|
|
op.create_table(
|
|
"skill",
|
|
sa.Column("created_at", sa.DateTime(), nullable=False),
|
|
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
|
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.ForeignKeyConstraint(
|
|
["edition_id"], ["edition.id"], ondelete="CASCADE"
|
|
),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
sa.UniqueConstraint(
|
|
"edition_id", "code", name="uq_skill_edition_code"
|
|
),
|
|
)
|
|
op.create_index(
|
|
op.f("ix_skill_edition_id"), "skill", ["edition_id"], unique=False
|
|
)
|
|
op.create_table(
|
|
"volunteer_skill",
|
|
sa.Column("volunteer_id", sa.Uuid(), nullable=False),
|
|
sa.Column("skill_id", sa.Uuid(), nullable=False),
|
|
sa.ForeignKeyConstraint(
|
|
["skill_id"], ["skill.id"], ondelete="CASCADE"
|
|
),
|
|
sa.ForeignKeyConstraint(
|
|
["volunteer_id"], ["volunteer.id"], ondelete="CASCADE"
|
|
),
|
|
sa.PrimaryKeyConstraint("volunteer_id", "skill_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"),
|
|
)
|