5.0 KiB
Export Excel de l'inventaire bovin — Design Spec
Bouton sur la page /inventory qui télécharge un XLSX listant tous les bovins actuellement présents sur l'exploitation.
Contexte
Le métier veut un Excel exportable depuis l'écran inventaire. Ferme n'a aujourd'hui aucun outil d'export Excel (uniquement PDF via dompdf). On choisit phpoffice/phpspreadsheet côté serveur, en suivant le même pattern que la génération PDF actuelle (endpoint qui streame le fichier, front qui télécharge via blob).
Périmètre : tous les bovins actifs (exitedAt IS NULL), ordre birthDate ASC, ignore les filtres UI. Pas de modale de sélection (à voir si le métier en demande une plus tard).
Architecture
Backend
Dépendance : composer require phpoffice/phpspreadsheet
Nouveau resource : src/ApiResource/BovineInventoryExport.php
#[ApiResource]avec une seule opérationGet:uriTemplate: '/bovines/inventory-export'output: falseprovider: BovineInventoryExportProvider::classsecurity: "is_granted('ROLE_USER')"(cohérent avec la page/inventory)- OpenApi tag
Bovines
Nouveau provider : src/State/Bovin/BovineInventoryExportProvider.php
- Injecte
EntityManagerInterface - Query Doctrine :
WHERE exitedAt IS NULL ORDER BY birthDate ASC - Construit le
Spreadsheetavec PhpSpreadsheet - Retourne une
Symfony\Component\HttpFoundation\Responseavec :Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheetContent-Disposition: attachment; filename="inventaire_bovins_YYYY-MM-DD.xlsx"- Body =
IOFactory::createWriter($spreadsheet, 'Xlsx')->save('php://output')capturé viaob_*
Frontend
Page : frontend/pages/inventory.vue
- Nouveau bouton "Exporter Excel" à droite du titre, à côté de "Rafraîchir"
- Style : même que "Rafraîchir" (bg-primary-500, h-[50px], icône
mdi:file-excel-outline) - Visible pour tout user authentifié (pas de gate admin)
- Au clic : appelle
useApi().getBlob('bovines/inventory-export'), crée un blob URL, déclenche un<a download>synthétique avec le filename retourné par le backend (lu depuis le headerContent-Disposition)
Génération XLSX — détails
Fichier :
- 1 seule feuille
Inventaire - Filename :
inventaire_bovins_YYYY-MM-DD.xlsx(date du jour serveur)
En-têtes (ligne 1) :
- 9 colonnes dans l'ordre :
N° National,N° Travail,Sexe,Né le,Age (mois),Race,Bâtiment,Case,Entrée le - Style : gras, fond
#f1f5f9(slate-100), bordure noire fine, alignement centré - Auto-filter activé sur la plage des en-têtes (Excel ajoute les boutons de filtre natifs)
- Freeze pane : ligne 2 figée
Lignes de données (à partir de la ligne 2) :
- Ordre
birthDate ASC(plus vieux en haut, NULL à la fin viaNULLS LASTnatif Postgres) - Largeurs de colonnes :
- N° National : 18
- N° Travail : 12
- Sexe : 10
- Né le : 12
- Age : 12
- Race : 12
- Bâtiment : 30
- Case : 8
- Entrée le : 12
Mapping des valeurs :
- Sexe :
M→Mâle,F→Femelle, autre / null → vide - Né le, Entrée le : format
JJ/MM/AAAA, vide si null - Age : entier (mois), vide si null
- Bâtiment, Case : valeurs nestées via
bovine.buildingCase.building.labeletbovine.buildingCase.caseNumber, vide si null
Couleurs des lignes (basées sur ageMonths, mêmes seuils que l'UI) :
| Tranche | Hex | Tailwind |
|---|---|---|
| 24+ mois | #ddd6fe |
violet-200 |
| 22-24 mois | #fecaca |
red-200 |
| 20-22 mois | #fed7aa |
orange-200 |
| < 20 mois ou NULL | #ffffff |
blanc |
Le fond est appliqué sur toute la ligne (9 cellules).
Flux d'erreur
- Exception PhpSpreadsheet (création buffer) → propage en 500 standard API Platform
- Pas d'utilisateur (token expiré) → 401 standard via la sécurité
Performance
- 936 lignes × 9 colonnes : génération en mémoire < 1s, fichier < 100 KB
- Pas de pagination, pas de streaming row-by-row (overkill pour ce volume)
Tests
Optionnel ce lot : test PHPUnit du provider qui vérifie que :
- Status 200
- Content-Type XLSX
- Header
Content-Disposition: attachment; filename=...xlsx - Body non vide
Mock simple de l'
EntityManagerInterfacepour retourner 2 bovins fictifs.
À faire en follow-up si on veut couvrir.
Verification manuelle
make composer-install(après avoir ajouté la dep)- Recharger
/inventory - Clic sur le bouton "Exporter Excel"
- Vérifier le téléchargement : nom de fichier =
inventaire_bovins_2026-04-24.xlsx - Ouvrir dans Excel/LibreOffice :
- 9 colonnes attendues
- En-tête figé en scrollant
- Auto-filter natif Excel
- Lignes colorées selon âge (violet/rouge/orange)
- Tri par date de naissance croissante
Critères d'acceptation
- L'export contient 100 % des bovins actifs (count =
SELECT COUNT(*) FROM bovine WHERE exited_at IS NULL) - Le filename inclut la date du jour
- Les couleurs correspondent aux seuils d'âge
- L'ordre matche l'UI (
birthDate ASC) - Pas de régression sur les autres endpoints
/api/bovines