Étape 22 : feuilles de poste (PDF), complément des badges

Une page par poste et par jour, listant les créneaux avec les bénévoles
affectés et leur téléphone — à imprimer et afficher sur place. Aucune
nouvelle entité : dérivé de Position/Shift/Assignment/Volunteer
existants (contrairement aux badges, pas de personnalisation à
configurer). Un créneau à besoin 0/0 sans affectation n'apparaît pas.

Backend : app/sheets/pdf.py (ReportLab, Platypus — SimpleDocTemplate/
Table plutôt que le canvas bas niveau des badges, plus adapté à un
rapport texte multi-pages), POST /editions/{id}/position-sheets/generate
(COORDINATION, {position_ids?} — absent = tous les postes).

Frontend : bouton « Feuilles de poste » dans la grille des besoins,
respecte le filtre de catégorie déjà actif à l'écran.

Vérifié : pytest (284 passés), ruff, alembic check, tsc --noEmit,
eslint, vite build, smoke (flux de bout en bout en mode démonstration)
— tous verts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
AdamThomas
2026-09-21 21:27:01 +02:00
co-authored by Claude Sonnet 5
parent 111d1e5c4b
commit 40127a2252
17 changed files with 561 additions and 4 deletions
+13 -1
View File
@@ -175,6 +175,15 @@ les tables sauf les tables d'association.
pour rien : juste ReportLab) : pages recto personnalisées suivies, planche
par planche, de la page de verso correspondante (même image répétée à
chaque emplacement) — impression recto-verso classique.
- **Feuilles de poste** (PDF, `app/sheets/pdf.py` + `app/api/position_sheets.py`) :
aucune nouvelle entité — dérivées de `Position`/`Shift`/`Assignment`/
`Volunteer` existants. Complément des badges (un badge identifie un
bénévole ; une feuille identifie un poste pour la journée) : une page par
poste et par jour, listant les créneaux du jour avec les bénévoles
affectés et leur téléphone, pour affichage sur place.
`POST /editions/{id}/position-sheets/generate` (COORDINATION,
`{position_ids?}` — absent = tous) ; un créneau à besoin 0/0 sans aucune
affectation n'apparaît pas (rien à imprimer).
- **`FormTemplate`** : configuration du formulaire public d'inscription
d'une édition (une ligne, créée à la demande). `is_open` coupe les
nouvelles soumissions sans effacer la configuration.
@@ -233,6 +242,7 @@ Matrice appliquée par les endpoints :
| `availability` lecture / écriture | ✔ / ✔ | ✔ / — | la sienne / — |
| `matrix`, `import`, `accounts` | ✔ / ✔ / ✔ | ✔ / — / — | — |
| `badges` (config + génération) | ✔ | — | — |
| `position-sheets` (génération) | ✔ | — | — |
| `form` (config) | ✔ | — | — |
| `form/public`, `form/public/submit` | *(aucune authentification — voir § 2, `FormField`)* |||
@@ -485,7 +495,7 @@ l'étape 21.)*
│ │ │ # day_parts, imports, artists, volunteers,
│ │ │ # availability, positions, shifts,
│ │ │ # assignments, solver, matrix, notifications,
│ │ │ # badges, forms
│ │ │ # badges, position_sheets, forms
│ │ ├── auth/ # mot de passe + lien magique + JWT + rôles
│ │ ├── email/ # SMTP (sender) + rendu des emails (templates)
│ │ ├── importing/ # import CSV/Excel (parser, text, service)
@@ -493,6 +503,7 @@ l'étape 21.)*
│ │ ├── validation/ # moteur pur (models, engine) + loader (base)
│ │ ├── solver/ # suggestions OR-Tools (models, engine, loader)
│ │ ├── badges/ # génération PDF des planches (pdf.py, ReportLab)
│ │ ├── sheets/ # génération PDF des feuilles de poste (pdf.py)
│ │ ├── forms/ # hCaptcha (captcha.py) — voir api/forms.py
│ │ ├── bootstrap.py # instance vierge : édition + 1er compte
│ │ ├── seed.py # jeu de démonstration (python -m app.seed)
@@ -605,6 +616,7 @@ Aucune dépendance locale requise hors Docker.
| 19 | Revue de sécurité avant ouverture au public : refus de démarrer en production avec un `JWT_SECRET` par défaut/vide/court, avertissement si `EMAIL_ENABLED=false` en production, en-têtes de sécurité (nginx + Caddy), pas de jeton dans les logs d'accès du frontend, limiteur de tentatives sur `/auth/login` et `/auth/magic-link` | à valider |
| 20 | Planches de badges bénévoles (PDF) : recto personnalisable (fond + champs nom/poste(s)/catégorie/rôle, éditeur glisser-déposer), verso fixe (même image pour tous), écran « Badges » dédié (`/badges`, COORDINATION) | à valider |
| 21 | Formulaire public d'inscription (`/inscription`, sans authentification) : champs activables par la coordination (email, téléphone, vœux de poste — max 2, vœux d'artiste — un par soir, vœu de compagnon en texte libre, disponibilité/cotisation déclaratives, photo, commentaire), captcha hCaptcha, ouverture/fermeture, lien à partager, écran de configuration dédié (`/inscriptions`, COORDINATION) — les bénévoles créés rejoignent directement la liste | à valider |
| 22 | Feuilles de poste (PDF, complément des badges) : une page par poste et par jour avec les créneaux, les bénévoles affectés et leur téléphone — bouton depuis la grille des besoins (COORDINATION) ; photo du bénévole affichée sur son écran et sur l'écran référent (en face du nom de chaque membre de l'équipe) | à valider |
**Reste hors périmètre** (modèle prêt à les accueillir) : SMS, constructeur
de formulaire, pointage sur site, IA. Frontend : squelette + 6 écrans +