Écran Statistiques : inscriptions, réponses, cotisations et besoins
ci-cd / build-backend (push) Successful in 33s
ci-cd / build-frontend (push) Successful in 19s
ci-cd / deploy (push) Successful in 12s

Nouvel onglet « Statistiques » (/statistiques, COORDINATION), alimenté
par GET /editions/{id}/stats (app/api/stats.py, recalculé à chaque appel,
aucune nouvelle entité) :
- inscriptions : total, 7 derniers jours, évolution cumulée par jour
- réponses : part des bénévoles ayant renseigné chaque information,
  artistes les plus demandés
- cotisations : en ligne / sur place / aucune, montants par type,
  mécénat, formulaires remplis sans paiement abouti
- besoins face aux bénévoles, par journée de festival : heures × personnes
  demandées vs disponibilités déclarées vs affectées ; par poste, places
  pourvues (plafonnées à l'effectif idéal de chaque créneau) et rapport
  vœux / place

Graphiques SVG maison (components/charts.tsx) avec infobulles au survol
et au clavier, vue tableau pour chacun, palette validée (daltonisme,
contraste), mise en page vérifiée sur ordinateur et mobile. Le mock
calcule les mêmes chiffres et étale les inscriptions du jeu de démo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AdamThomas
2026-10-04 19:40:46 +02:00
co-authored by Claude Opus 5.5
parent ff57bbd863
commit ee1f6ed72e
17 changed files with 1775 additions and 2 deletions
+21 -1
View File
@@ -194,6 +194,24 @@ les tables sauf les tables d'association.
`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).
- **Statistiques** (`GET /editions/{id}/stats`, COORDINATION,
`app/api/stats.py` ; écran `/statistiques`, `StatsPage.tsx`) : aucune
nouvelle entité, tout est recalculé à chaque appel. Inscriptions (total,
7 derniers jours, évolution cumulée par jour d'ajout `created_at`,
jours sans inscription inclus), réponses (part des bénévoles ayant
renseigné chaque information, artistes demandés), cotisations (mode de
paiement — même règle que `lib/fee.ts:feeMode` —, montants par type,
mécénat, `PendingFormSubmission` jamais payées), besoins face aux
bénévoles : par **journée de festival** (§ 3), heures × personnes
demandées (min/idéal) vs heures de disponibilité déclarées vs heures
affectées ; par poste, places min/idéales, places **pourvues plafonnées
créneau par créneau à l'effectif idéal** (`filled` — un sureffectif ne
compense jamais un trou ailleurs ; `assigned` garde le total brut) et
nombre de vœux. Graphiques en SVG maison (`components/charts.tsx`,
aucune bibliothèque), palette validée (daltonisme/contraste) sur le fond
`paper`, chaque graphique doublé d'une vue tableau. Le mock calcule les
mêmes chiffres (`buildStats`) et étale les dates d'inscription du jeu
de démo (`registeredAt`).
- **Export bénévoles** (Excel, `app/exporting/xlsx.py` + `GET
/editions/{id}/volunteers/export`, COORDINATION) : une ligne par
bénévole, mêmes champs que la fiche (coordonnées, vœux, cotisation,
@@ -398,6 +416,7 @@ Matrice appliquée par les endpoints :
| `badges` (config + génération) | ✔ | — | — |
| `position-sheets` (génération) | ✔ | — | — |
| `form` (config) | ✔ | — | — |
| `stats` | ✔ | — | — |
| `form/public`, `form/public/submit` | *(aucune authentification — voir § 2, `FormField`)* |||
**Authentification — deux systèmes selon le compte**, une même session JWT
@@ -721,7 +740,7 @@ l'étape 21.)*
│ │ │ # day_parts, imports, artists, volunteers,
│ │ │ # availability, positions, shifts,
│ │ │ # assignments, solver, matrix, notifications,
│ │ │ # badges, position_sheets, forms
│ │ │ # badges, position_sheets, forms, stats
│ │ ├── auth/ # mot de passe + lien magique + JWT + rôles
│ │ ├── email/ # SMTP (sender) + rendu texte (templates) et HTML (html.py) + logo (branding.py)
│ │ ├── importing/ # import CSV/Excel (parser, text, service)
@@ -863,6 +882,7 @@ Aucune dépendance locale requise hors Docker.
| 37 | Cerfa mécénat : nouveau modèle PDF, date du versement repositionnée, date de signature remplie (date du paiement), case « Virement, prélèvement, carte bancaire » cochée (paiement SumUp) ; message de confirmation du paiement annonçant l'email et le reçu fiscal | à valider |
| 38 | Créneaux de nuit : une heure de début avant le début de journée (premier créneau type) saisie sur la carte d'un jour désigne la nuit qui suit (00:00 le samedi ⇒ dimanche 00:00) ; écran « Postes & créneaux », feuilles de poste et chaînage du solveur regroupent par journée de festival, comme la grille et la validation | à valider |
| 39 | Mode de paiement de la cotisation visible partout (`lib/fee.ts:feeMode`, `app/exporting/xlsx.py:_payment_mode`) : en ligne (type, montant, statut, mécénat), sur place, ou rien — section « Cotisation » sur la fiche (case « Paiera sur place » modifiable à la main), colonne « Cotisation » dans la liste, colonne « Mode de paiement » dans l'export Excel | à valider |
| 40 | Écran Statistiques (`/statistiques`, COORDINATION, `GET /editions/{id}/stats`) : inscriptions (nombre, évolution cumulée), réponses au formulaire, artistes demandés, cotisations (en ligne / sur place / aucune, par type, mécénat, paiements jamais aboutis), besoins par journée de festival face aux disponibilités déclarées et aux affectations, places pourvues et vœux par poste — graphiques SVG maison avec infobulles et vues tableau | à valider |
**Reste hors périmètre** (modèle prêt à les accueillir) : SMS, constructeur
de formulaire, pointage sur site, IA. Frontend : squelette + 6 écrans +