Refonte du créateur de badges et nombre de badges par bénévole
ci-cd / build-backend (push) Successful in 30s
ci-cd / deploy (push) Successful in 13s
ci-cd / build-frontend (push) Successful in 22s

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:
AdamThomas
2026-10-27 19:20:42 +01:00
co-authored by Claude Opus 5.5
parent 1a23881e81
commit ced0855d47
28 changed files with 3738 additions and 803 deletions
+15 -2
View File
@@ -8,7 +8,9 @@ from pydantic import BaseModel, ConfigDict, Field
from app.models import (
AssignmentSource,
BadgeAlign,
BadgeFace,
BadgeFieldType,
BadgePhotoShape,
FeePaymentStatus,
FormFieldType,
PositionCategory,
@@ -76,6 +78,9 @@ class VolunteerUpdate(ApiModel):
companion_wish_note: str | None = None
# Texte libre du badge (champ `FREE_TEXT`), saisi par la coordination.
badge_text: str | None = None
# Exemplaires du badge sur les planches (1 à 100 ; garde-fou contre une
# faute de frappe qui imprimerait des centaines de pages).
badge_count: int | None = Field(default=None, ge=1, le=100)
self_declared_available: bool | None = None
willing_to_pay_fee: bool | None = None
@@ -94,6 +99,7 @@ class VolunteerRead(ApiModel):
has_photo: bool
companion_wish_note: str | None
badge_text: str | None
badge_count: int
self_declared_available: bool
willing_to_pay_fee: bool
# Paiement de la cotisation via SumUp (voir CLAUDE.md § 2, `Volunteer`) —
@@ -346,6 +352,7 @@ class MatrixResponse(ApiModel):
# Badges (planches PDF) #
# --------------------------------------------------------------------------- #
class BadgeFieldIn(ApiModel):
face: BadgeFace = BadgeFace.FRONT
field_type: BadgeFieldType
x_mm: float
y_mm: float
@@ -357,11 +364,17 @@ class BadgeFieldIn(ApiModel):
color: str = "#000000"
# `FREE_TEXT` seulement (voir `BadgeField.text`), ignoré sinon.
text: str | None = None
# Fond de la zone (`#rrggbb`), `None` = transparent — voir `BadgeField`.
bg_color: str | None = None
auto_fit: bool = False
# `PHOTO` seulement, ignoré sinon.
photo_shape: BadgePhotoShape = BadgePhotoShape.RECT
class BadgeFieldsSet(ApiModel):
"""Remplace l'intégralité des champs du recto — au plus un par
`field_type` (décocher un champ dans l'éditeur retire sa ligne)."""
"""Remplace l'intégralité des champs du recto et du verso — au plus un
par (`face`, `field_type`) (décocher un champ dans l'éditeur retire sa
ligne)."""
fields: list[BadgeFieldIn] = Field(default_factory=list)