ADR-007: Intégration complète S3 pour les rapports et photos

Date: 2026-02-01
Statut: Proposé
Décideurs: Équipe ObeeSmart
Contexte technique: ObeeSmart v5.1.0 → v6.0


Contexte

ObeeSmart dispose actuellement d'une intégration S3 partielle (v5.1.0) pour le stockage des photos. Cependant, cette intégration présente plusieurs lacunes qui impactent l'expérience utilisateur et la valeur métier des rapports :

État actuel (v5.1.0)

Composant État Détails
PhotoService ✅ Fonctionnel Upload, miniatures, EXIF, URLs signées
Stockage photos S3 ✅ Fonctionnel Chemin: {entity_type}s/{user_id}/{entity_id}/{uuid}.ext
ReportStorageService ⚠️ Partiel Upload PDF vers S3, mais pas de gestion photos
Photos dans PDFs ❌ Absent Code préparé (drawPhotoGrid) mais jamais appelé
Preview PDF inline ❌ Absent Téléchargement direct uniquement
Gestion erreurs S3 ⚠️ Insuffisant Pas de retry, pas de fallback

Problèmes identifiés

  1. Valeur métier réduite : Les rapports PDF ne contiennent pas les photos des visites, traitements et récoltes, réduisant leur utilité documentaire et légale.

  2. Ergonomie limitée :

    • Pas de prévisualisation PDF avant téléchargement
    • URLs signées expirent silencieusement (erreur 403)
    • Pas de galerie photos intégrée aux rapports web
  3. Robustesse insuffisante :

    • Rapport reste en status=generating si S3 échoue
    • Fichiers temporaires non nettoyés
    • Pas de fallback local
  4. Fonctionnalités manquantes :

    • Pas de statistiques d'utilisation S3
    • Pas de nettoyage automatique des anciens rapports
    • Pas d'export groupé avec photos

Décision

Objectif principal

Transformer le système de rapports en une solution documentaire complète où :

  • Les rapports PDF incluent automatiquement les photos pertinentes de la période
  • Les utilisateurs peuvent prévisualiser avant de télécharger
  • Le stockage S3 est robuste avec retry et fallback
  • L'expérience utilisateur est fluide et professionnelle

Architecture cible

┌─────────────────────────────────────────────────────────────────┐
│                    GÉNÉRATION RAPPORT v6.0                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  1. COLLECTE DONNÉES                                             │
│     ├── Ruches, Visites, Récoltes, Traitements, Alertes         │
│     └── Photos (NEW) ← Photo.findAll({period, entity_types})    │
│                                                                  │
│  2. PRÉPARATION PHOTOS                                           │
│     ├── Sélection (max 20 photos pertinentes)                   │
│     ├── Téléchargement miniatures S3 → buffers                  │
│     └── Tri par date/entité                                      │
│                                                                  │
│  3. GÉNÉRATION PDF                                               │
│     ├── Sections existantes (KPIs, tableaux, graphiques)        │
│     └── Section "Galerie Photos" (NEW)                          │
│         ├── Grille 3 colonnes                                   │
│         ├── Légendes (date, entité, caption)                    │
│         └── Pagination automatique                              │
│                                                                  │
│  4. UPLOAD S3 + FALLBACK                                         │
│     ├── Retry (3 tentatives, backoff exponentiel)               │
│     ├── Fallback local si échec                                 │
│     └── Mise à jour status Report                               │
│                                                                  │
│  5. ACCÈS UTILISATEUR                                            │
│     ├── Preview inline (PDF.js ou iframe)                       │
│     ├── Téléchargement direct                                   │
│     └── Partage (token, expiration)                             │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Composants modifiés

Fichier Modifications
helpers/reports-export-premium.js Collecte photos, passage au Python
helpers/generate_report_premium.py Section galerie photos avec ReportLab
helpers/export-service.js Activation drawPhotoGrid(), récupération buffers S3
services/ReportStorageService.js Retry logic, fallback local, statistiques
services/PhotoService.js Méthode getPhotosForReport()
routes/reports.js Endpoint preview, stats stockage
views/beekeeper/report-detail.pug Preview inline, amélioration UX
views/beekeeper/reports.pug Indicateurs visuels, actions rapides

Nouveaux composants

Fichier Rôle
services/ReportPhotoService.js Orchestration photos pour rapports
job/cleanup-old-reports.js Cron nettoyage S3 (rapports > 1 an)
public/js/pdf-preview.js Viewer PDF inline (PDF.js)

Alternatives considérées

Alternative 1 : Liens photos dans PDF (pas d'embed)

Description : Inclure des QR codes ou liens vers les photos S3 au lieu d'embarquer les images.

Avantages :

  • PDF plus léger
  • Pas de traitement images côté serveur

Inconvénients :

  • ❌ Nécessite connexion internet pour voir les photos
  • ❌ URLs signées expirent (rapport "cassé" après 1h)
  • ❌ Moins professionnel pour documentation légale

Décision : Rejeté - Les rapports doivent être autonomes et consultables hors-ligne.

Alternative 2 : Génération PDF côté client (jsPDF)

Description : Générer le PDF dans le navigateur avec jsPDF.

Avantages :

  • Moins de charge serveur
  • Preview instantané

Inconvénients :

  • ❌ Dépendant du navigateur/device
  • ❌ Qualité variable
  • ❌ Pas de stockage centralisé
  • ❌ Impossible de partager via lien

Décision : Rejeté - Besoin de rapports standardisés et partageables.

Alternative 3 : Service externe de génération PDF

Description : Utiliser un service comme DocRaptor, PDFShift ou Anvil.

Avantages :

  • Design avancé (CSS → PDF)
  • Moins de code à maintenir

Inconvénients :

  • ❌ Coût par génération
  • ❌ Dépendance externe
  • ❌ Données sensibles envoyées à un tiers
  • ❌ Latence réseau

Décision : Rejeté - Préférence pour solution auto-hébergée.


Conséquences

Positives

  1. Valeur documentaire accrue : Rapports complets avec preuves visuelles (visites, état des ruches, traitements).

  2. Conformité réglementaire : Documentation photographique pour traçabilité sanitaire.

  3. Expérience utilisateur améliorée :

    • Preview avant téléchargement
    • Galerie photos contextualisée
    • Partage simplifié
  4. Robustesse accrue :

    • Retry automatique
    • Fallback local
    • Nettoyage programmé
  5. Scalabilité : Architecture préparée pour augmentation du volume.

Négatives

  1. Complexité accrue : Plus de code à maintenir (photos dans PDF, preview, retry).

  2. Temps de génération : PDFs plus lourds (photos = 2-5 Mo vs 500 Ko).

  3. Stockage S3 : Augmentation espace utilisé (~3× avec photos).

  4. Dépendances : PDF.js pour preview (lib externe côté client).

Risques et mitigations

Risque Probabilité Impact Mitigation
PDFs trop volumineux Moyenne Moyen Limiter à 20 photos, utiliser miniatures 600px
Timeout génération Faible Élevé Génération async, notification quand prêt
S3 indisponible Faible Élevé Fallback local, retry 3×, alerting
Migration données existantes Moyenne Moyen Script migration progressif

Plan d'implémentation

Voir document détaillé : IMPLEMENTATION-s3-reports.md

Phases

Phase Durée estimée Livrable
Phase 1 : Photos dans PDFs 3-4 jours PDFs avec galerie photos
Phase 2 : Robustesse S3 2 jours Retry, fallback, logs
Phase 3 : Preview PDF 2 jours Viewer inline
Phase 4 : Ergonomie 2 jours UX améliorée, stats
Phase 5 : Maintenance 1 jour Cron nettoyage, monitoring

Total estimé : 10-12 jours de développement


Métriques de succès

Métrique Objectif Mesure
Photos dans rapports 100% des rapports avec photos Comptage photos_count > 0
Taux d'échec S3 < 1% Logs erreurs / total uploads
Temps génération PDF < 30s (avec photos) Monitoring durée
Adoption preview > 50% des consultations Analytics clics preview vs download
Satisfaction utilisateur Retours positifs Feedback qualitatif

Références


Historique

Date Version Auteur Changements
2026-02-01 1.0 Claude Création initiale