ecarts de 0.01€ visible dans le tableau

This commit is contained in:
2026-09-09 21:42:17 +02:00
parent 5eca3804bf
commit 6e1c421e5b
3 changed files with 25 additions and 6 deletions
@@ -445,7 +445,12 @@
parCompte, parCompte,
somme, somme,
ecart, ecart,
hasError: Math.abs(ecart) > 0.01, // Visible écart = non-zero to the centime (a 0.01 mismatch is
// savable -- the blocking threshold stays at 0.01 server-side --
// but must still be shown; mirrors LedgerRowsController's
// hasError). 0.005 guards against float representation of
// stored centimes.
hasError: Math.abs(ecart) > 0.005,
linkable: LINKABLE_TYPES.includes(attrs.field_type_ligne), linkable: LINKABLE_TYPES.includes(attrs.field_type_ligne),
entreeLieeIds: entreeLieeNodes.map((n) => n.id), entreeLieeIds: entreeLieeNodes.map((n) => n.id),
entreeLieeLabels: entreeLieeNodes.map((n) => n.attributes.title || n.id), entreeLieeLabels: entreeLieeNodes.map((n) => n.attributes.title || n.id),
@@ -154,8 +154,10 @@
* remainder is negative; * remainder is negative;
* - triggers: row added/removed (Paragraphs AJAX re-render -> * - triggers: row added/removed (Paragraphs AJAX re-render ->
* behavior attach), HT change, manual amount edit; * behavior attach), HT change, manual amount edit;
* - live "Réparti / Écart" line under the widget, mirroring the * - live "Réparti / Écart" line in the widget's title cell: green when
* server's round(HT somme, 2) and its 0.01 tolerance. * the écart is zero to the centime, red otherwise (a 0.01 écart is
* savable -- blocking stays at 0.01 server-side -- but is shown,
* same as /lignes does).
* *
* "Manual vs assist" detection rests on a DOM property: assigning * "Manual vs assist" detection rests on a DOM property: assigning
* input.value programmatically fires no event, only a real user edit * input.value programmatically fires no event, only a real user edit
@@ -338,8 +340,14 @@
row.querySelector('.figli-repartition-ecart-sum').textContent = 'Réparti : ' + eur(somme); row.querySelector('.figli-repartition-ecart-sum').textContent = 'Réparti : ' + eur(somme);
var val = row.querySelector('.figli-repartition-ecart-val'); var val = row.querySelector('.figli-repartition-ecart-val');
val.textContent = isNaN(ecart) ? 'Écart : —' : 'Écart : ' + eur(ecart); val.textContent = isNaN(ecart) ? 'Écart : —' : 'Écart : ' + eur(ecart);
row.classList.toggle('is-ok', !isNaN(ecart) && Math.abs(ecart) <= 0.01); // Green only when the écart is zero to the centime: a 0.01
row.classList.toggle('is-ko', !isNaN(ecart) && Math.abs(ecart) > 0.01); // mismatch is still savable (the server's blocking threshold
// stays at 0.01) but it IS an écart -- signaled here in red,
// exactly as /lignes now displays it (LedgerRowsController's
// hasError). 0.005 guards against float representations of
// centime values.
row.classList.toggle('is-ok', !isNaN(ecart) && Math.abs(ecart) <= 0.005);
row.classList.toggle('is-ko', !isNaN(ecart) && Math.abs(ecart) > 0.005);
} }
// One delegated listener on the form (survives every Paragraphs // One delegated listener on the form (survives every Paragraphs
@@ -172,7 +172,13 @@ class LedgerRowsController extends ControllerBase {
'parCompte' => (object) $parCompte, 'parCompte' => (object) $parCompte,
'somme' => $somme, 'somme' => $somme,
'ecart' => $ecart, 'ecart' => $ecart,
'hasError' => abs($ecart) > 0.01, // "Écart visible" == non-zero to the centime. The presave/validation
// BLOCKING threshold stays at > 0.01 (tolerated rounding noise is
// savable), but a 0.01 écart is still a real mismatch and must be
// shown in the table -- at > 0.01 here it displayed nothing at all.
// 0.005 (not 0.0) keeps float representations of stored centimes
// from misclassifying.
'hasError' => abs($ecart) > 0.005,
'linkable' => in_array($type, self::LINKABLE_TYPES, TRUE), 'linkable' => in_array($type, self::LINKABLE_TYPES, TRUE),
'entreeLieeIds' => array_map(fn ($n) => $n->uuid(), $entreeLieeNodes), 'entreeLieeIds' => array_map(fn ($n) => $n->uuid(), $entreeLieeNodes),
'entreeLieeLabels' => array_map(fn ($n) => $n->getTitle() ?: $n->uuid(), $entreeLieeNodes), 'entreeLieeLabels' => array_map(fn ($n) => $n->getTitle() ?: $n->uuid(), $entreeLieeNodes),