Files
geo/api/docs/TECHBOOK.md
Pierre 3443277d4a feat: Release version 3.1.4 - Mode terrain et génération PDF
 Nouvelles fonctionnalités:
- Ajout du mode terrain pour utilisation mobile hors connexion
- Génération automatique de reçus PDF avec template personnalisé
- Révision complète du système de cartes avec amélioration des performances

🔧 Améliorations techniques:
- Refactoring du module chat avec architecture simplifiée
- Optimisation du système de sécurité NIST SP 800-63B
- Amélioration de la gestion des secteurs géographiques
- Support UTF-8 étendu pour les noms d'utilisateurs

📱 Application mobile:
- Nouveau mode terrain dans user_field_mode_page
- Interface utilisateur adaptative pour conditions difficiles
- Synchronisation offline améliorée

🗺️ Cartographie:
- Optimisation des performances MapBox
- Meilleure gestion des tuiles hors ligne
- Amélioration de l'affichage des secteurs

📄 Documentation:
- Ajout guide Android (ANDROID-GUIDE.md)
- Documentation sécurité API (API-SECURITY.md)
- Guide module chat (CHAT_MODULE.md)

🐛 Corrections:
- Résolution des erreurs 400 lors de la création d'utilisateurs
- Correction de la validation des noms d'utilisateurs
- Fix des problèmes de synchronisation chat

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-19 19:38:03 +02:00

25 KiB
Executable File

Documentation Technique API RESTful PHP 8.3

Table des matières

  1. Structure du projet
  2. Configuration du serveur
  3. Flux d'une requête
  4. Architecture des composants
  5. Base de données
  6. Sécurité
  7. Gestion des mots de passe (NIST SP 800-63B)
  8. Endpoints API
  9. Changements récents

Structure du projet

/api/
├── docs/
│   └── TECHBOOK.md
├── src/
│   ├── Controllers/
│   │   └── UserController.php
│   ├── Core/
│   │   ├── Router.php
│   │   ├── Request.php
│   │   ├── Response.php
│   │   ├── Session.php
│   │   └── Database.php
│   └── Config/
│       └── config.php
├── index.php
└── .htaccess

Configuration du serveur

Prérequis

  • Debian 12
  • NGINX
  • PHP 8.3-FPM
  • MariaDB 10.11

Configuration NGINX

Le serveur NGINX est configuré pour rediriger toutes les requêtes vers le point d'entrée index.php de l'API.

Configuration PHP-FPM

PHP-FPM est configuré pour gérer les processus PHP avec des paramètres optimisés pour une API.

Flux d'une requête

Exemple détaillé du parcours d'une requête POST /api/users :

  1. Entrée de la requête

    • La requête arrive sur le serveur NGINX
    • NGINX redirige vers PHP-FPM via le socket unix
    • Le fichier .htaccess redirige vers index.php
  2. Initialisation (index.php)

    • Chargement des dépendances
    • Initialisation de la configuration
    • Démarrage de la session
    • Configuration des headers CORS
    • Initialisation du routeur
  3. Routage

    • Le Router analyse la méthode HTTP (POST)
    • Analyse de l'URI (/api/users)
    • Correspondance avec les routes enregistrées
    • Instanciation du Controller approprié
  4. Traitement (UserController)

    • Vérification de l'authentification
    • Récupération des données JSON
    • Validation des données reçues
    • Traitement métier
    • Interaction avec la base de données
    • Préparation de la réponse
  5. Réponse

    • Formatage de la réponse en JSON
    • Configuration des headers de réponse
    • Envoi au client

Architecture des composants

Core Components

Router

  • Gère le routage des requêtes
  • Associe les URLs aux Controllers
  • Gère les paramètres d'URL
  • Dispatch vers les méthodes appropriées

Request

  • Parse les données entrantes
  • Gère les différents types de contenu
  • Nettoie et valide les entrées
  • Fournit une interface unifiée pour accéder aux données

Response

  • Formate les réponses en JSON
  • Gère les codes HTTP
  • Configure les headers de réponse
  • Assure la cohérence des réponses

Session

  • Gère l'état des sessions
  • Stocke les données d'authentification
  • Vérifie les permissions
  • Sécurise les données de session

Database

  • Gère la connexion à MariaDB
  • Fournit une interface PDO
  • Gère le pool de connexions
  • Assure la sécurité des requêtes

Base de données

Structure des tables principales

Table users

  • encrypted_user_name : Identifiant de connexion chiffré (unique)
  • encrypted_email : Email chiffré (unique)
  • user_pass_hash : Hash du mot de passe
  • encrypted_name, encrypted_phone, encrypted_mobile : Données personnelles chiffrées
  • Autres champs : first_name, sect_name, fk_role, fk_entite, etc.

Table entites (Amicales)

  • chk_mdp_manuel (DEFAULT 0) : Gestion manuelle des mots de passe
  • chk_username_manuel (DEFAULT 0) : Gestion manuelle des identifiants
  • chk_stripe : Activation des paiements Stripe
  • Données chiffrées : encrypted_name, encrypted_email, encrypted_phone, etc.

Table medias

  • support : Type de support (entite, user, operation, passage)
  • support_id : ID de l'élément associé
  • file_category : Catégorie (logo, export, carte, etc.)
  • file_path : Chemin complet du fichier
  • processed_width/height : Dimensions après traitement
  • Utilisée pour stocker les logos des entités

Chiffrement des données

Toutes les données sensibles sont chiffrées avec AES-256-CBC :

  • Emails, noms, téléphones
  • Identifiants de connexion
  • Informations bancaires (IBAN, BIC)

Migration de base de données

Script SQL pour ajouter les nouveaux champs :

-- Ajout de la gestion manuelle des usernames
ALTER TABLE `entites` 
ADD COLUMN `chk_username_manuel` tinyint(1) unsigned NOT NULL DEFAULT 0 
COMMENT 'Gestion des usernames manuelle (1) ou automatique (0)' 
AFTER `chk_mdp_manuel`;

-- Index pour optimiser la vérification d'unicité
ALTER TABLE `users` 
ADD INDEX `idx_encrypted_user_name` (`encrypted_user_name`);

Sécurité

Mesures implémentées

  • Validation stricte des entrées
  • Protection contre les injections SQL (PDO)
  • Hachage sécurisé des mots de passe
  • Headers de sécurité HTTP
  • Gestion des CORS
  • Session sécurisée
  • Authentification requise
  • Chiffrement AES-256 des données sensibles
  • Envoi séparé des identifiants par email

Gestion des mots de passe (NIST SP 800-63B)

Vue d'ensemble

L'API implémente un système de gestion des mots de passe conforme aux recommandations NIST SP 800-63B, avec quelques adaptations spécifiques demandées par le client.

Service PasswordSecurityService

Le service PasswordSecurityService (src/Services/PasswordSecurityService.php) gère :

  • Validation des mots de passe selon NIST
  • Vérification contre les bases de données de mots de passe compromis (HIBP)
  • Génération de mots de passe sécurisés
  • Estimation de la force des mots de passe

Conformités NIST respectées

Recommandation NIST Notre Implémentation Status
Longueur minimale : 8 caractères MIN = 8 caractères CONFORME
Longueur maximale : 64 caractères minimum MAX = 64 caractères CONFORME
Accepter TOUS les caractères ASCII imprimables Aucune restriction sur les caractères CONFORME
Accepter les espaces Espaces acceptés (début, milieu, fin) CONFORME
Accepter Unicode (émojis, accents, etc.) Support UTF-8 avec mb_strlen() CONFORME
Vérifier contre les mots de passe compromis API Have I Been Pwned avec k-anonymity CONFORME
Pas d'obligation de composition Pas d'erreur si manque majuscules/chiffres/spéciaux CONFORME
Pas de changement périodique forcé Aucune expiration automatique CONFORME
Permettre les phrases de passe "Mon chat Félix a 3 ans!" accepté CONFORME

Déviations par choix du client

Recommandation NIST Notre Implémentation Raison
Email unique par compte Plusieurs comptes par email autorisés Demande client
Mot de passe ≠ identifiant Mot de passe = identifiant autorisé Demande client
Vérifier contexte utilisateur Pas de vérification nom/email dans mdp Demande client

Vérification contre les mots de passe compromis

Have I Been Pwned (HIBP) API

L'implémentation utilise l'API HIBP avec la technique k-anonymity pour préserver la confidentialité :

  1. Hash SHA-1 du mot de passe
  2. Envoi des 5 premiers caractères du hash à l'API
  3. Comparaison locale avec les suffixes retournés
  4. Aucun mot de passe en clair n'est transmis

Mode "Fail Open"

En cas d'erreur de l'API HIBP :

  • Le système laisse passer le mot de passe
  • Un avertissement est enregistré dans les logs
  • L'utilisateur n'est pas bloqué

Exemples de mots de passe

Acceptés (conformes NIST)

  • monmotdepasse → Accepté (≥8 caractères, pas compromis)
  • 12345678 → Accepté SI pas dans HIBP
  • Mon chat s'appelle Félix! → Accepté (phrase de passe)
  • → Accepté si ≥8 espaces
  • 😀🎉🎈🎁🎂🍰🎊🎀 → Accepté (8 émojis)
  • jean.dupont → Accepté même si = username

Refusés

  • pass123 → Refusé (< 8 caractères)
  • password → Refusé (compromis dans HIBP)
  • 123456789 → Refusé (compromis dans HIBP)
  • Mot de passe > 64 caractères → Refusé

Force des mots de passe

Le système privilégie la LONGUEUR sur la complexité (conforme NIST) :

Longueur Force Score
< 8 car. Trop court 0-10
8-11 car. Acceptable 20-40
12-15 car. Bon 40-60
16-19 car. Fort 60-80
≥20 car. Très fort 80-100
Compromis Compromis ≤10

Génération automatique

Pour la génération automatique, le système reste strict pour garantir des mots de passe forts :

  • Longueur : 12-16 caractères
  • Contient : majuscules + minuscules + chiffres + spéciaux
  • Vérifié contre HIBP (10 tentatives max)
  • Exemple : Xk9#mP2$nL5!

Gestion des comptes multiples par email

Depuis janvier 2025, le système permet plusieurs comptes avec le même email :

Fonction lostPassword adaptée

  • Recherche TOUS les comptes avec l'email fourni
  • Génère UN SEUL mot de passe pour tous ces comptes
  • Met à jour TOUS les comptes en une requête
  • Envoie UN SEUL email avec la liste des usernames concernés

Exemple de comportement

Si 3 comptes partagent l'email contact@amicale.fr :

  • jean.dupont
  • marie.martin
  • paul.durand

L'email contiendra :

Bonjour,
Voici votre nouveau mot de passe pour les comptes : jean.dupont, marie.martin, paul.durand
Mot de passe : XyZ123!@#

Endpoints API dédiés aux mots de passe

Vérification de force (public)

POST /api/password/check
Content-Type: application/json

{
  "password": "monmotdepasse",
  "check_compromised": true
}

Réponse :

{
  "status": "success",
  "valid": false,
  "errors": [
    "Ce mot de passe a été trouvé 23 547 fois dans des fuites de données."
  ],
  "warnings": [
    "Suggestion : Évitez les séquences communes pour plus de sécurité"
  ],
  "strength": {
    "score": 20,
    "strength": "Faible",
    "feedback": ["Ce mot de passe a été compromis"],
    "length": 13,
    "diversity": 1
  },
  "compromised": {
    "compromised": true,
    "occurrences": 23547,
    "message": "Ce mot de passe a été trouvé 23 547 fois dans des fuites de données"
  }
}

Vérification de compromission uniquement (public)

POST /api/password/compromised
Content-Type: application/json

{
  "password": "monmotdepasse"
}

Génération automatique (authentifié)

GET /api/password/generate?length=14
Authorization: Bearer {session_id}

Réponse :

{
  "status": "success",
  "password": "Xk9#mP2$nL5!qR",
  "length": 14,
  "strength": {
    "score": 85,
    "strength": "Très fort",
    "feedback": []
  }
}

Configuration et sécurité

Paramètres de sécurité

  • Timeout API HIBP : 5 secondes
  • Cache : 15 minutes pour les vérifications répétées
  • Logging : Aucun mot de passe en clair dans les logs
  • K-anonymity : Seuls 5 caractères du hash SHA-1 envoyés

Points d'intégration

  • LoginController::register : Validation lors de l'inscription
  • LoginController::lostPassword : Génération sécurisée
  • UserController::createUser : Validation si mot de passe manuel
  • UserController::updateUser : Validation lors du changement
  • ApiService::generateSecurePassword : Génération avec vérification HIBP

Résumé

100% CONFORME NIST pour les aspects techniques
Adapté aux besoins du client (emails multiples, mdp=username)
Sécurité maximale avec vérification HIBP
Expérience utilisateur optimale (souple mais sécurisé)

Endpoints API

Routes Publiques vs Privées

L'API distingue deux types de routes :

Routes Publiques

  • POST /api/login
  • POST /api/register
  • GET /api/health

Routes Privées (Nécessitent une session authentifiée)

  • Toutes les autres routes

Authentification

L'authentification utilise le système de session PHP natif.

Login

POST /api/login
Content-Type: application/json

{
    "email": "user@example.com",
    "password": "SecurePassword123"
}

Réponse réussie :

{
  "message": "Connecté avec succès",
  "user": {
    "id": 123,
    "email": "user@example.com"
  }
}

Notes importantes :

  • Un cookie de session PHP sécurisé est automatiquement créé
  • Le cookie est httpOnly, secure et SameSite=Strict
  • L'ID de session est régénéré à chaque login réussi

Logout

POST /api/logout

Réponse réussie :

{
  "message": "Déconnecté avec succès"
}

Sécurité des Sessions

La configuration des sessions inclut :

  • Sessions PHP natives sécurisées

  • Protection contre la fixation de session

  • Cookies httpOnly (protection XSS)

  • Mode strict pour les cookies

  • Validation côté serveur à chaque requête

  • use_strict_mode = 1

  • cookie_httponly = 1

  • cookie_secure = 1

  • cookie_samesite = Strict

  • Régénération de l'ID de session après login

  • Destruction complète de la session au logout

Users

Création d'utilisateur

La création d'utilisateur s'adapte aux paramètres de l'entité (amicale) :

POST /api/users
Content-Type: application/json
Authorization: Bearer {session_id}

{
    "email": "john@example.com",
    "name": "John Doe",
    "first_name": "John",
    "role": 1,
    "fk_entite": 5,
    "username": "j.doe38",  // Requis si chk_username_manuel=1 pour l'entité
    "password": "SecurePass123",  // Requis si chk_mdp_manuel=1 pour l'entité
    "phone": "0476123456",
    "mobile": "0612345678",
    "sect_name": "Secteur A",
    "date_naissance": "1990-01-15",
    "date_embauche": "2020-03-01"
}

Comportement selon les paramètres de l'entité :

chk_username_manuel chk_mdp_manuel Comportement
0 0 Username et password générés automatiquement
0 1 Username généré, password requis dans le payload
1 0 Username requis dans le payload, password généré
1 1 Username et password requis dans le payload

Validation du username (si manuel) :

  • Format : 10-30 caractères
  • Commence par une lettre
  • Caractères autorisés : a-z, 0-9, ., -, _
  • Doit être unique dans toute la base

Réponse réussie :

{
  "status": "success",
  "message": "Utilisateur créé avec succès",
  "id": 123,
  "username": "j.doe38",  // Toujours retourné
  "password": "xY7#mK9@pL2"  // Retourné seulement si généré automatiquement
}

Envoi d'emails :

  • Email 1 : Identifiant de connexion (toujours envoyé)
  • Email 2 : Mot de passe (toujours envoyé, 1 seconde après le premier)

Codes de statut :

  • 201: Création réussie
  • 400: Données invalides ou username/password manquant si requis
  • 401: Non authentifié
  • 403: Accès non autorisé (rôle insuffisant)
  • 409: Email ou username déjà utilisé
  • 500: Erreur serveur

Vérification de disponibilité du username

POST /api/users/check-username
Content-Type: application/json
Authorization: Bearer {session_id}

{
    "username": "j.doe38"
}

Réponse si disponible :

{
  "status": "success",
  "available": true,
  "message": "Nom d'utilisateur disponible",
  "username": "j.doe38"
}

Réponse si déjà pris :

{
  "status": "success",
  "available": false,
  "message": "Ce nom d'utilisateur est déjà utilisé",
  "suggestions": ["j.doe38_42", "j.doe381234", "j.doe3825"]
}

Autres endpoints

  • GET /api/users
  • GET /api/users/{id}
  • PUT /api/users/{id}
  • DELETE /api/users/{id}
  • POST /api/users/{id}/reset-password

Entités (Amicales)

Upload du logo d'une entité

POST /api/entites/{id}/logo
Content-Type: multipart/form-data
Authorization: Bearer {session_id}

Body:
  logo: File (image/png, image/jpeg, image/jpg)

Restrictions :

  • Réservé aux administrateurs d'amicale (fk_role == 2)
  • L'admin ne peut uploader que le logo de sa propre amicale
  • Un seul logo actif par entité (le nouveau remplace l'ancien)

Traitement de l'image :

  • Formats acceptés : PNG, JPG, JPEG
  • Redimensionnement automatique : 250x250px maximum (ratio conservé)
  • Résolution : 72 DPI (standard web)
  • Préservation de la transparence pour les PNG

Stockage :

  • Chemin : /uploads/entites/{id}/logo/logo_{id}_{timestamp}.{ext}
  • Enregistrement dans la table medias
  • Suppression automatique de l'ancien logo

Réponse réussie :

{
  "status": "success",
  "message": "Logo uploadé avec succès",
  "media_id": 42,
  "file_name": "logo_5_1234567890.jpg",
  "file_path": "/entites/5/logo/logo_5_1234567890.jpg",
  "dimensions": {
    "width": 250,
    "height": 180
  }
}

Récupération du logo d'une entité

GET /api/entites/{id}/logo
Authorization: Bearer {session_id}

Réponse :

{
  "status": "success",
  "logo": {
    "id": 42,
    "data_url": "data:image/png;base64,iVBORw0KGgoAAAANS...",
    "file_name": "logo_5_1234567890.png",
    "mime_type": "image/png",
    "width": 250,
    "height": 180,
    "size": 15234
  }
}

Note : Le logo est également inclus automatiquement dans la réponse du login si disponible.

Mise à jour d'une entité

PUT /api/entites/{id}
Content-Type: application/json
Authorization: Bearer {session_id}

{
    "name": "Amicale de Grenoble",
    "adresse1": "123 rue de la Caserne",
    "adresse2": "",
    "code_postal": "38000",
    "ville": "Grenoble",
    "phone": "0476123456",
    "mobile": "0612345678",
    "email": "contact@amicale38.fr",
    "chk_stripe": true,  // Activation paiement Stripe
    "chk_mdp_manuel": false,  // Génération auto des mots de passe
    "chk_username_manuel": false,  // Génération auto des usernames
    "chk_copie_mail_recu": true,
    "chk_accept_sms": false
}

Paramètres de gestion des membres :

Paramètre Type Description
chk_mdp_manuel boolean true: L'admin saisit les mots de passe
false: Génération automatique
chk_username_manuel boolean true: L'admin saisit les identifiants
false: Génération automatique
chk_stripe boolean Active/désactive les paiements Stripe

Note : Ces paramètres sont modifiables uniquement par les administrateurs (fk_role > 1).

Réponse du login avec paramètres entité

Lors du login, les paramètres de l'entité sont retournés dans le groupe amicale :

{
  "status": "success",
  "session_id": "abc123...",
  "session_expiry": "2025-01-09T15:30:00+00:00",
  "user": {
    "id": 9999980,
    "fk_entite": 5,
    "fk_role": 2,
    "fk_titre": null,
    "first_name": "Pierre",
    "sect_name": "",
    "date_naissance": "1990-01-15",  // Maintenant correctement récupéré
    "date_embauche": "2020-03-01",   // Maintenant correctement récupéré
    "username": "pv_admin",
    "name": "VALERY ADM",
    "phone": "0476123456",            // Maintenant correctement récupéré
    "mobile": "0612345678",           // Maintenant correctement récupéré
    "email": "contact@resalice.com"
  },
  "amicale": {
    "id": 5,
    "name": "Amicale de Grenoble",
    "chk_mdp_manuel": 0,
    "chk_username_manuel": 0,
    "chk_stripe": 1,
    "logo": {                         // Logo de l'entité (si disponible)
      "id": 42,
      "data_url": "data:image/png;base64,iVBORw0KGgoAAAANS...",
      "file_name": "logo_5_1234567890.png",
      "mime_type": "image/png",
      "width": 250,
      "height": 180
    }
    // ... autres champs
  }
}

Ces paramètres permettent à l'application Flutter d'adapter dynamiquement le formulaire de création de membre.

Intégration Frontend

Configuration des Requêtes

Toutes les requêtes API depuis le frontend doivent inclure :

fetch('/api/endpoint', {
  credentials: 'include', // Important pour les cookies de session
  // ... autres options
});

Gestion des Sessions

  • Les cookies de session sont automatiquement gérés par le navigateur
  • Pas besoin de stocker ou gérer des tokens manuellement
  • Redirection vers /login si session expirée (401)

Maintenance et Déploiement

Logs

  • Logs d'accès NGINX : /var/log/nginx/api-access.log
  • Logs d'erreur NGINX : /var/log/nginx/api-error.log
  • Logs PHP : /var/log/php/php-error.log

Déploiement

  1. Pull du repository
  2. Vérification des permissions
  3. Configuration de l'environnement
  4. Tests des endpoints
  5. Redémarrage des services

Surveillance

  • Monitoring des processus PHP-FPM
  • Surveillance de la base de données
  • Monitoring des performances
  • Alertes sur erreurs critiques

Changements récents

Version 3.0.7 (Août 2025)

1. Implémentation complète de la norme NIST SP 800-63B pour les mots de passe

  • Nouveau service : PasswordSecurityService pour la gestion sécurisée des mots de passe
  • Vérification HIBP : Intégration de l'API Have I Been Pwned avec k-anonymity
  • Validation souple : Suppression des obligations de composition (majuscules, chiffres, spéciaux)
  • Support Unicode : Acceptation de tous les caractères, incluant émojis et espaces
  • Nouveaux endpoints : /api/password/check, /api/password/compromised, /api/password/generate

2. Autorisation des emails multiples

  • Suppression de l'unicité : Un même email peut être utilisé pour plusieurs comptes
  • Adaptation de lostPassword : Mise à jour de tous les comptes partageant l'email
  • Un seul mot de passe : Tous les comptes avec le même email reçoivent le même nouveau mot de passe

3. Autorisation mot de passe = identifiant

  • Choix client : Permet d'avoir un mot de passe identique au nom d'utilisateur
  • Pas de vérification contextuelle : Aucune vérification nom/email dans le mot de passe

Version 3.0.6 (Août 2025)

1. Correction des rôles administrateurs

  • Avant : Les administrateurs d'amicale devaient avoir fk_role > 2
  • Après : Les administrateurs d'amicale ont fk_role > 1 (donc rôle 2 et plus)
  • Impact : Les champs chk_stripe, chk_mdp_manuel, chk_username_manuel sont maintenant modifiables par les admins d'amicale (rôle 2)

2. Envoi systématique des deux emails lors de la création d'utilisateur

  • Avant : Le 2ème email (mot de passe) n'était envoyé que si le mot de passe était généré automatiquement
  • Après : Les deux emails sont toujours envoyés lors de la création d'un membre
    • Email 1 : Identifiant (username)
    • Email 2 : Mot de passe (1 seconde après)
  • Raison : Le nouveau membre a toujours besoin des deux informations pour se connecter

3. Ajout des champs manquants dans la réponse du login

  • Champs ajoutés dans la requête SQL :
    • fk_titre
    • date_naissance
    • date_embauche
    • encrypted_phone
    • encrypted_mobile
  • Impact : Ces données sont maintenant correctement retournées dans l'objet user lors du login

4. Système de gestion des logos d'entité

  • Nouvelle fonctionnalité : Upload et gestion des logos pour les amicales
  • Routes ajoutées :
    • POST /api/entites/{id}/logo : Upload d'un nouveau logo
    • GET /api/entites/{id}/logo : Récupération du logo
  • Caractéristiques :
    • Réservé aux administrateurs d'amicale (fk_role == 2)
    • Un seul logo actif par entité
    • Redimensionnement automatique (250x250px max)
    • Format base64 dans les réponses JSON (compatible Flutter)
    • Logo inclus automatiquement dans la réponse du login

5. Amélioration de l'intégration Flutter

  • Format d'envoi des images : Base64 data URL pour compatibilité multiplateforme
  • Structure de réponse enrichie : Le logo est inclus dans l'objet amicale lors du login
  • Optimisation : Pas de requête HTTP supplémentaire nécessaire pour afficher le logo

Version 3.0.8 (Janvier 2025)

1. Système de génération automatique de reçus fiscaux pour les dons

  • Nouveau service : ReceiptService pour la génération automatique de reçus PDF
  • Déclencheurs automatiques :
    • Création d'un passage avec fk_type=1 (don) et email valide
    • Mise à jour d'un passage en don si nom_recu est vide/null
  • Caractéristiques techniques :
    • PDF ultra-légers (< 5KB) générés en format natif sans librairie externe
    • Support des caractères accentués avec conversion automatique
    • Stockage structuré : /uploads/entites/{entite_id}/recus/{operation_id}/
    • Enregistrement dans la table medias avec catégorie recu
  • Queue d'envoi email :
    • Envoi automatique par email avec pièce jointe PDF
    • Format MIME multipart pour compatibilité maximale
    • Gestion dans la table email_queue avec statut de suivi
  • Nouvelle route API :
    • GET /api/passages/{id}/receipt : Récupération du PDF d'un reçu
    • Retourne le PDF en base64 ou téléchargement direct selon Accept header
  • Champs base de données utilisés :
    • nom_recu : Nom du fichier PDF généré
    • date_creat_recu : Date de génération du reçu
    • date_sent_recu : Date d'envoi par email
    • chk_email_sent : Indicateur d'envoi réussi