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
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user