Refonte du créateur de badges et nombre de badges par bénévole
Créateur de badges refait d'après la maquette : champs sur le recto et le verso (BadgeField.face, verso placé en miroir dans le PDF pour le recto-verso), fond de zone, réduction automatique du texte, photo ovale, initiales sans photo, nom sur deux lignes (migration 0026) ; éditeur en trois colonnes (champs, aperçu recto/verso avec de vrais bénévoles, inspecteur), formats prédéfinis, annuler, flèches, zoom, repères de découpe, dépôt d'image sur l'aperçu, contrôle de tous les badges avant génération. Nombre de badges par bénévole (Volunteer.badge_count, 1 par défaut, migration 0027) : champ sur la fiche, autant d'exemplaires sur les planches, total affiché à la génération, colonne dans l'export Excel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
1a23881e81
commit
ced0855d47
@@ -0,0 +1,62 @@
|
||||
"""Éditeur de badges v2 (verso, fond de zone, auto-ajustement, photo ovale)
|
||||
|
||||
Revision ID: 0026_badge_editor_v2
|
||||
Revises: 0025_badge_field_text
|
||||
Create Date: 2026-10-27
|
||||
|
||||
`badge_field.face` : face du badge (`FRONT`/`BACK`) — les champs existants
|
||||
deviennent des champs du recto. La contrainte d'unicité passe de
|
||||
(`edition_id`, `field_type`) à (`edition_id`, `face`, `field_type`) : un même
|
||||
champ peut figurer sur les deux faces. `bg_color` (fond de la zone,
|
||||
transparent si `NULL`), `auto_fit` (réduction automatique du texte) et
|
||||
`photo_shape` (`RECT`/`OVAL`, champ `PHOTO`).
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
revision: str = "0026_badge_editor_v2"
|
||||
down_revision: str | None = "0025_badge_field_text"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
_FACE = sa.Enum("FRONT", "BACK", name="badgeface", native_enum=False)
|
||||
_PHOTO_SHAPE = sa.Enum("RECT", "OVAL", name="badgephotoshape", native_enum=False)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"badge_field",
|
||||
sa.Column("face", _FACE, server_default="FRONT", nullable=False),
|
||||
)
|
||||
op.add_column("badge_field", sa.Column("bg_color", sa.String(), nullable=True))
|
||||
op.add_column(
|
||||
"badge_field",
|
||||
sa.Column("auto_fit", sa.Boolean(), server_default="false", nullable=False),
|
||||
)
|
||||
op.add_column(
|
||||
"badge_field",
|
||||
sa.Column("photo_shape", _PHOTO_SHAPE, server_default="RECT", nullable=False),
|
||||
)
|
||||
op.drop_constraint("uq_badge_field_edition_type", "badge_field", type_="unique")
|
||||
op.create_unique_constraint(
|
||||
"uq_badge_field_edition_face_type",
|
||||
"badge_field",
|
||||
["edition_id", "face", "field_type"],
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# Le verso n'existait pas : ses champs sont perdus (sinon l'ancienne
|
||||
# contrainte d'unicité échouerait sur un champ présent sur les deux faces).
|
||||
op.execute("DELETE FROM badge_field WHERE face = 'BACK'")
|
||||
op.drop_constraint("uq_badge_field_edition_face_type", "badge_field", type_="unique")
|
||||
op.create_unique_constraint(
|
||||
"uq_badge_field_edition_type", "badge_field", ["edition_id", "field_type"]
|
||||
)
|
||||
op.drop_column("badge_field", "photo_shape")
|
||||
op.drop_column("badge_field", "auto_fit")
|
||||
op.drop_column("badge_field", "bg_color")
|
||||
op.drop_column("badge_field", "face")
|
||||
@@ -0,0 +1,35 @@
|
||||
"""Nombre de badges par bénévole
|
||||
|
||||
Revision ID: 0027_volunteer_badge_count
|
||||
Revises: 0026_badge_editor_v2
|
||||
Create Date: 2026-10-27
|
||||
|
||||
`volunteer.badge_count` : nombre d'exemplaires de son badge imprimés sur les
|
||||
planches (`POST .../badges/generate`), 1 par défaut — les bénévoles existants
|
||||
gardent un seul badge.
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
revision: str = "0027_volunteer_badge_count"
|
||||
down_revision: str | None = "0026_badge_editor_v2"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"volunteer",
|
||||
sa.Column("badge_count", sa.Integer(), nullable=False, server_default="1"),
|
||||
)
|
||||
op.create_check_constraint(
|
||||
"ck_volunteer_badge_count_positive", "volunteer", "badge_count >= 1"
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_constraint("ck_volunteer_badge_count_positive", "volunteer", type_="check")
|
||||
op.drop_column("volunteer", "badge_count")
|
||||
Reference in New Issue
Block a user