From 1ab38bc2a72b1bbccf891ceddbf13c5093cf1484 Mon Sep 17 00:00:00 2001 From: bach Date: Sat, 5 Sep 2026 10:40:01 +0200 Subject: [PATCH] =?UTF-8?q?Highlight=20versements=20not=20(fully)=20backed?= =?UTF-8?q?=20by=20their=20entr=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For "versement freelance" rows specifically: an amber outline plus a badge when the versement either isn't linked to any entrée client at all ("Non liée"), or is linked but reconciliationByEntree still shows a residual on that entrée ("Reste à verser" / "Sur-versé", with the amount in the tooltip). The residual belongs to the entrée as a whole, not to any one sortie -- when several versements share an entrée, each shows the same aggregate figure, since there's no way to attribute the shortfall to one specific payment. No highlight when the linked entrée isn't in the currently loaded window (can't tell either way -- same accepted trade-off as reconciliationByEntree itself). Verified: filtering to "Versement freelance" shows 21 of 25 loaded rows flagged (17 unlinked, 4 with a reste-à-verser residual), the remaining 4 fully-reconciled rows correctly unflagged, and the amber outline resolves correctly in dark mode. --- .../custom/figli_compta_ledger/css/home.css | 20 +++++++++++++ .../custom/figli_compta_ledger/js/home.js | 29 +++++++++++++++++++ .../templates/figli-compta-home.html.twig | 8 ++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/web/modules/custom/figli_compta_ledger/css/home.css b/web/modules/custom/figli_compta_ledger/css/home.css index 13e080c..bb78955 100644 --- a/web/modules/custom/figli_compta_ledger/css/home.css +++ b/web/modules/custom/figli_compta_ledger/css/home.css @@ -9,6 +9,7 @@ --figli-border: #dcdee2; --figli-error: #c9312b; --figli-positive: #1a7f37; + --figli-warning: #d97a0a; --figli-col-hover: rgba(15, 23, 42, 0.05); font-family: Inter, -apple-system, sans-serif; @@ -24,6 +25,7 @@ html.gin--dark-mode #figli-home-app { --figli-border: #3d3e42; --figli-error: #ff6b6b; --figli-positive: #4ade80; + --figli-warning: #f0a94e; --figli-col-hover: rgba(255, 255, 255, 0.07); } @@ -187,6 +189,24 @@ html.gin--dark-mode #figli-home-app { border-right: 1px solid var(--figli-error); } +/* Versement freelance not (fully) backed by its entrée: same thin-outline + treatment as an error row, but amber -- it's not the ligne itself + that's inconsistent (répartition still matches montant HT), it's the + entrée/sortie relationship that isn't settled yet. Doesn't stack with + figli-error-row's red in practice (different conditions), but scoped + to :not() just in case a row is somehow both, so one outline wins + rather than the borders visually competing. */ +#figli-home-app tr.figli-versement-warning-row:not(.figli-error-row) td { + border-top: 1px solid var(--figli-warning); + border-bottom: 1px solid var(--figli-warning); +} +#figli-home-app tr.figli-versement-warning-row:not(.figli-error-row) td:first-child { + border-left: 1px solid var(--figli-warning); +} +#figli-home-app tr.figli-versement-warning-row:not(.figli-error-row) td:last-child { + border-right: 1px solid var(--figli-warning); +} + #figli-home-app td.figli-ecart { color: var(--figli-error); font-weight: 700; diff --git a/web/modules/custom/figli_compta_ledger/js/home.js b/web/modules/custom/figli_compta_ledger/js/home.js index 8861882..785b6d6 100644 --- a/web/modules/custom/figli_compta_ledger/js/home.js +++ b/web/modules/custom/figli_compta_ledger/js/home.js @@ -383,6 +383,35 @@ 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 it pays out against: either not linked at all, + // or linked but reconciliationByEntree still shows a residual on + // that entrée. The residual belongs to the entrée as a whole, not + // to any one sortie -- when several versements share an entrée, + // each shows the same aggregate residual, since there's no way to + // say which specific one is "the" shortfall. Null (no highlight) + // when the linked entrée isn't in the currently loaded window -- + // same accepted trade-off as reconciliationByEntree itself. + versementStatus(item) { + if (item.type !== 'versement') return null; + if (!item.entreeLieeId) { + return { kind: 'non-liee', detail: 'Aucune entrée client liée.' }; + } + const recon = this.reconciliationByEntree.get(item.entreeLieeId); + if (!recon) return null; + if (recon.resteAVerser > 0.01) { + return { kind: 'reste', detail: 'Reste à verser sur l’entrée liée : ' + this.formatEur(recon.resteAVerser) }; + } + if (recon.surVerse > 0.01) { + return { kind: 'sur-verse', detail: 'Sur-versé sur l’entrée liée : ' + this.formatEur(recon.surVerse) }; + } + return null; + }, + versementStatusLabel(kind) { + if (kind === 'non-liee') return 'Non liée'; + if (kind === 'reste') return 'Reste à verser'; + return 'Sur-versé'; + }, // jj/mm/aa -- shorter than the API's ISO yyyy-mm-dd, saves column // width in a table already packed with 8 compte columns. formatDate(iso) { 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 999161e..3b8758b 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 @@ -101,7 +101,7 @@ {{ item.label }} ({{ item.count }} lignes) - +