# GESTFORM — Gestion des formulaires F3 (FNCE)

Application web (Express 5 + **MySQL** via `mysql2`, front HTML/CSS/JS sans build ni framework) pour gérer les formulaires F3 (Carte de Commerçant de Côte d'Ivoire) :
commandes, groupes organisés, bordereaux, talons (réception, capture d'images, saisie), tableaux de bord, export, utilisateurs. Interface et messages **en français**.
Version : `package.json > version` (incrémenter + entrée dans `CHANGELOG.md` à chaque livraison). Successeur de « Saisie des récépissés FNCE » (dossier `items`, SQLite, v1.0.4).

## Lancer / tester
* MySQL local de test : `..\mysql-local\demarrer-mysql.bat` (port 3307, base/utilisateur/mot de passe `gestfom`). Puis `node server.js` (http://localhost:3000).
* Configuration : variables d'environnement ou `.env` (voir `.env.example`, `lib/config.js`).
* `node outils/test-api.js` : test de bout en bout de l'API (serveur démarré ; **efface les données de test**, base locale seulement).
* Pas de suite de tests du front : vérifier à la main (ou Playwright + Edge), notamment sur mobile.

## Structure
* `server.js` : Express, sessions/cookies, connexion + code d'activation, utilisateurs, `/api/me`, `/api/listes`, branchement des modules.
* `lib/db.js` : pool MySQL (`q`, `un`, `tx`), création du schéma (`sql/schema.sql`, idempotent) et données de référence (`sql/seed.json`, généré par `outils/generer-seed.js` depuis les Excel du dossier `Donnees`).
* `lib/droits.js` : catalogue des droits + calcul des droits effectifs (groupe `GROUPE_DROIT` + droits propres `UTILISATEUR_DROIT` accordés/retirés ; le groupe `admin` a tout) + périmètre géographique `etendue()` (selon `GRP_Perimetre` du groupe : zone, dr, tout). `USER_Role` = code du groupe. `droit('module')` protège les routes ; `/api/me` envoie `droits` au front (attribut `data-droit` des menus/boutons).
* `lib/groupes.js` (BENEFICIAIRE, règle des homonymes, `groupeDeDr`), `commandes.js`, `bordereaux.js`, `talons.js` (réception, capture, saisie, liste, statistiques, export), `tableau.js` (DR + tableau de bord), `chargement.js` + `chargement-routes.js` (classeurs Excel), `images.js` (stockage chiffré), `valid.js`, `texte.js`, `listes.js`.
* `public/` : `app.js` (noyau : utilitaires, navigation, utilisateurs), un module par vue (`commandes.js`, `groupes.js`, `bordereaux.js`, `talons-*.js`, `tableau-bord.js`, `drs.js`, `chargement.js`) qui s'inscrit dans `FNCE.vues[nom]`. `views/app.html` : toutes les vues.
* `outils/` : `init-db`, `charger-f3`, `creer-admin`, `reinitialiser-test`, `test-api`, `generer-seed`.

## Modèle de données (fichier `gestion_formulaires_fnce.txt`)
* **BENEFICIAIRE** = groupe organisé : clé technique `Groupe_Code` (auto-incrément, suite de 9000001…) ; `BENE_Code` (2 chiffres du type + 5 chiffres) **nullable, unique** : vide pour un groupe créé par « Commande F3 », renseigné au chargement de ses formulaires (rattachement par nom + type + DR). `TBENE_Code` 21 = groupe de type DR (nom = celui de la DR), 31 = groupe.
* **FORMULAIRE** : clé `FORM_Numero` = code de paiement (10 chiffres) ; `Groupe_Code` (FK) + `BENE_Code` copié ; colonnes `FORM_AC*` (agent de collecte, colonnes `ac_*` des Excel) ; saisie du talon (`FORM_SaisiPar/Le`, champs `FORM_Recep*`, `FORM_Entreprise*`…) ; image (`FORM_Image*`) ; chargement (`FORM_ChargeLe`, `FORM_Source`). `TFORM_Code` = dernière lettre de `QPART_Code` (ex. `10500G`) ; un type inconnu (ex. `D`) est ajouté à TYPE_FORMULAIRE au chargement. Pas de table TARIFICATION : `QPART_Code` est une simple colonne.
* **Noms de tables en MAJUSCULES, toujours** (MySQL/Linux est sensible à la casse). Les dates sont lues en chaînes (`dateStrings`) ; les détails par montant sont du JSON dans des colonnes TEXT.
* Pour ajouter une colonne : l'ajouter dans `sql/schema.sql` **et** écrire un `ALTER TABLE` conditionnel dans `lib/db.js > initialiser` (le `CREATE TABLE IF NOT EXISTS` n'ajoute rien à une base existante).

## Règles à respecter
* Le front et l'API gardent les anciens noms JSON (`dr` = libellé de la DR, `groupe_id`, `agent_nom`, `detail`, `total`…) ; le mapping vers les colonnes se fait dans les `SELECT … AS …`.
* Sécurité : CSP sans script/style inline (tout dans `public/*.js` et `style.css`) ; toute requête qui modifie des données envoie `X-Requested-With: fnce` (anti-CSRF) ; texte affiché via DOM/`textContent`, jamais `innerHTML` ; requêtes SQL toujours paramétrées.
* Périmètre : tout accès à un formulaire / groupe / commande doit passer par `etendue()` ou `drAutorisee()` (un CZ/DR ne voit ni n'écrit hors de son périmètre ; hors périmètre = 404).
* Images : `lib/images.js` ; chemin `DATA_DIR/images/<DR>/<GROUPE>/<BENE_Code>_<FORM_Numero>.jpg`, contenu **chiffré AES-256-GCM** (clé `DATA_DIR/images.key`, ou variable `IMAGES_KEY`) ; servies uniquement par `/api/talons/:code/image` (droits + périmètre).
* Création du premier administrateur par le web : uniquement depuis localhost et jamais avec `TRUST_PROXY` (utiliser `outils/creer-admin.js`).
* Charte : vert `#00703a`, orange `#f05a00`, ambre `#f5a300`, bleu `#1558c0` pour les données imprimées (DR, code de paiement, redevance) ; le rouge est réservé aux erreurs et alertes.

## Bases locales
* `gestform_dev` : base de **développement / test** (copie de la base réelle du 2026-10-23), données dans `..\gestform-donnees-dev` ; c'est la base par défaut de `demarrer.bat` (port 3000). `test-api.js` et `reinitialiser-test.js` peuvent y tourner (ils effacent comptes et saisies).
* `gestform_reel` : base **définitive** (à déployer), données dans `..\gestform-donnees-reel`, `demarrer-reel.bat` (port 3001). `reinitialiser-test.js` refuse de s'y exécuter. Ne rien y tester.
* Outils : comptes `node outils/importer-comptes.js "classeur.xlsx" [--appliquer]` ; commandes `node outils/importer-commandes.js "classeur.xlsx" [--appliquer] [--utilisateur=...]` ; formulaires F3 : menu « Chargement F3 » ou `node outils/charger-f3.js [--sauf=...]` (la base visée = variable `DB_NAME`). L'ancienne base `gestfom` n'est plus utilisée.
