diff --git a/web/modules/custom/figli_compta_ledger/js/home.js b/web/modules/custom/figli_compta_ledger/js/home.js index 2665b99..7a17b77 100644 --- a/web/modules/custom/figli_compta_ledger/js/home.js +++ b/web/modules/custom/figli_compta_ledger/js/home.js @@ -508,22 +508,29 @@ const detail = relevant.map((compte) => compte + ' : ' + this.formatEur(ecarts[compte])).join(', '); return { detail, comptes: relevant.length }; }, - // Flags a "versement freelance" row that isn't (fully) backed by - // the entrée client(s) it pays out against: either not linked at - // all, or linked but its own compte(s) still show a residual - // against at least one of them. Deliberately scoped to just the - // compte(s) this versement's own répartition touches - // (reconciliationByEntree's parCompteResidual), not the entrée's - // overall resteAVerser/surVerse -- those can be driven entirely by - // a *different* compte tied to some other sortie linked to the - // same entrée, which says nothing about whether this versement's - // own répartition is settled. When linked to several entrées (see - // reconciliationByEntree's equal-split note), each entrée's - // residual for these compte(s) counts separately -- they're - // independent invoices, each with its own outstanding amount. - // Entrées outside the currently loaded window are skipped (same - // accepted trade-off as reconciliationByEntree itself); null only - // if none of them could be checked at all. + // Status badge for a "versement freelance" row -- always present + // when the row is a versement, specifically so a linked-but-settled + // versement still gets a badge to drill down through (it used to + // return null there, silently losing the only way to open the + // linked entrée's filtered view for versements with nothing wrong + // to report). "kind" distinguishes not-linked-at-all, a residual + // against at least one linked entrée, or linked-and-settled: + // - not linked at all + // - linked but its own compte(s) still show a residual against at + // least one linked entrée -- deliberately scoped to just the + // compte(s) this versement's own répartition touches + // (reconciliationByEntree's parCompteResidual), not the + // entrée's overall resteAVerser/surVerse, which can be driven + // entirely by a *different* compte tied to some other sortie + // linked to the same entrée and would say nothing about + // whether this versement's own répartition is settled. When + // linked to several entrées (see reconciliationByEntree's + // equal-split note), each entrée's residual for these compte(s) + // counts separately -- they're independent invoices, each with + // its own outstanding amount. + // - linked and settled (as far as the currently loaded window can + // tell -- a linked entrée outside it is silently skipped, same + // accepted trade-off as reconciliationByEntree itself) versementStatus(item) { if (item.type !== 'versement') return null; if (!item.entreeLieeIds.length) { @@ -531,30 +538,39 @@ } let resteAVerser = 0; let surVerse = 0; - let checked = 0; for (const entreeId of item.entreeLieeIds) { const recon = this.reconciliationByEntree.get(entreeId); if (!recon) continue; - checked++; for (const c of Object.keys(item.parCompte)) { const residual = recon.parCompteResidual[c] || 0; if (residual > 0.01) resteAVerser += residual; else if (residual < -0.01) surVerse += -residual; } } - if (!checked) return null; if (resteAVerser > 0.01) { return { kind: 'reste', detail: 'Reste à verser (comptes de cette ligne) : ' + this.formatEur(Math.round(resteAVerser * 100) / 100) }; } if (surVerse > 0.01) { return { kind: 'sur-verse', detail: 'Sur-versé (comptes de cette ligne) : ' + this.formatEur(Math.round(surVerse * 100) / 100) }; } - return null; + const n = item.entreeLieeIds.length; + return { kind: 'ok', detail: 'Lié à ' + n + ' entrée' + (n > 1 ? 's' : '') + ' client' + (n > 1 ? 's' : '') + '.' }; }, versementStatusLabel(kind) { if (kind === 'non-liee') return 'Non liée'; if (kind === 'reste') return 'Reste à verser'; - return 'Sur-versé'; + if (kind === 'sur-verse') return 'Sur-versé'; + return 'Lié'; + }, + // Only non-liee/sur-versé read as a hard anomaly (red); reste is + // its own softer amber; ok gets neither, falling back to the + // badge's default green -- same "all clear" green the entrée side + // already uses for a fully-settled "N sorties liées". + versementStatusClasses(kind) { + return { + 'is-anomalie': kind === 'non-liee' || kind === 'sur-verse', + 'is-reste': kind === 'reste', + }; }, // jj/mm/aa -- shorter than the API's ISO yyyy-mm-dd, saves column // width in a table already packed with 8 compte columns. diff --git a/web/modules/custom/figli_compta_ledger/templates/figli-compta-home.html.twig b/web/modules/custom/figli_compta_ledger/templates/figli-compta-home.html.twig index 1f15c6c..bbb21fb 100644 --- a/web/modules/custom/figli_compta_ledger/templates/figli-compta-home.html.twig +++ b/web/modules/custom/figli_compta_ledger/templates/figli-compta-home.html.twig @@ -161,10 +161,10 @@ ⚠ {{ versementStatusLabel(versementStatus(item).kind) }} + >{{ versementStatus(item).kind === 'ok' ? '' : '⚠ ' }}{{ versementStatusLabel(versementStatus(item).kind) }} {{ formatEur(item.montant_ht) }} {{ formatEur(item.montant_ttc) }}