# Formule : corrections du calcul de composition et de la case « Formule normée »

## Calcul de composition — `app/Traits/composition_calcul_trait.php`

- **Division par zéro sur a/(a+c)** : `$aac` vaut 0 quand `$qteL` (ciment + addition) est nul.
- **Plafond de la norme (tableau NA.F.1)** :
  - le code colonne ciment et le code colonne addition sont calculés séparément. La colonne `t_norme_contrainte.<ciment><addition>_na` n'est lue que si les deux sont reconnus. Avant, un type d'addition inconnu produisait une colonne inexistante (ex. `cemI__na`) ;
  - formule, classe d'exposition et norme introuvables sont gérées : on n'accède plus à une propriété sur null ;
  - sans plafond applicable (type non géré, norme absente, valeur vide), la quantité d'addition retenue est `$qteF`, comme dans `formule_conformite_service`. Avant, si ni le ciment ni l'addition n'étaient reconnus, elle valait `$qteC` ;
  - un ratio maximum ≥ 1 n'est pas appliqué, pour éviter la division par zéro sur `1 - ratio`.

## Case « Formule normée pour la centrale » ne se décochait pas

Deux causes :

1. **Affichage** (`resources/views/formule/form.blade.php`, chargement du détail) : les cases étaient cochées avec `!!retour[key]`. La valeur `"0"` renvoyée sous forme de chaîne donne `true` en JavaScript, donc la case réapparaissait cochée. Remplacé par `retour[key] == 1`. Ce changement s'applique aussi aux autres cases du détail (modulée, STD…).
2. **Enregistrement** (`formule_controller::enregistrer`) : le détail était recherché par centrale seulement, sans variante. La lecture (`chercher_formule_detail`) filtre par variante. L'enregistrement pouvait donc modifier la ligne d'une autre variante. La recherche utilise maintenant la même variante (celle demandée, sinon la variante active). Une nouvelle ligne reçoit `formule_variant_id`.

3. **Cause principale — `has()` au lieu de `boolean()`** (`formule_controller::enregistrer`) : la vue envoie maintenant un `<input type="hidden" name="formule_normalisee" value="0">` avant la case (`value="1"`). Le champ est donc toujours présent dans la requête. Or le contrôleur faisait `$request->has('formule_normalisee') ? 1 : 0`, ce qui donnait toujours 1. Toutes les cases fusionnées dans `enregistrer` passent par `$request->boolean(...)`. Cette méthode lit la valeur : `"0"` donne 0, `"1"` ou `"on"` donne 1, et un champ absent donne 0. Cela corrige aussi les appels API qui envoient `0`/`false`.
   Vérifié par simulation de `enregistrer` en transaction annulée : `0` → 0, `1` → 1, `on` → 1.

## Remarque

Le PHP en ligne de commande (`php`) est en 7.4, alors que le projet utilise la syntaxe 8. Pour vérifier la syntaxe, utiliser le PHP 8 de `C:\wamp64\bin\php\php8*`.
