Show the drill-down's own totals in the footer, not the year's

Clicking an entrée's "N sorties liées" badge drills down to just that
entrée + its linked sorties (filterEntreeId) -- but the footer kept
showing the current year's totals throughout, which answers a
different question than the one this view exists for ("does this
entrée balance against what was paid out").

drilldownTotals() computes the same shape locally (montant_ht/ttc,
écart, par_compte) from the already-loaded drill-down rows -- no
server round-trip needed, unlike the per-year figures. footerTotals()
picks between it and currentYearTotals depending on whether
filterEntreeId is set, so the footer swaps automatically and reverts
the moment the drill-down is cleared.

Verified: montant_ht and every compte column match the drill-down's
two rows summed by hand exactly (to the cent), and closing the
drill-down correctly restores the normal per-year footer.
This commit is contained in:
2026-09-05 11:02:01 +02:00
parent 5a311b8439
commit 6bdf12b8fe
2 changed files with 47 additions and 6 deletions
@@ -336,6 +336,44 @@
return true;
});
},
// Footer totals while drilled down into one entrée + its linked
// sorties (see filteredRows' drill-down branch above): the whole
// point of this view is "does this entrée balance against what was
// paid out", so the footer should answer exactly that instead of
// the current year's totals -- and it can be computed locally
// (unlike the per-year figures, this handful of rows is already
// fully loaded), no server round-trip needed. Same shape as
// /lignes/api/totaux so the template can render either the same
// way.
drilldownTotals() {
if (!this.filterEntreeId) return null;
let montantHt = 0;
let montantTtc = 0;
let ecart = 0;
const parCompte = {};
for (const r of this.filteredRows) {
montantHt += r.montant_ht || 0;
montantTtc += r.montant_ttc || 0;
ecart += r.ecart || 0;
for (const [c, v] of Object.entries(r.parCompte)) {
parCompte[c] = (parCompte[c] || 0) + v;
}
}
const round = (v) => Math.round(v * 100) / 100;
return {
montant_ht: round(montantHt),
montant_ttc: round(montantTtc),
ecart: round(ecart),
par_compte: Object.fromEntries(Object.entries(parCompte).map(([c, v]) => [c, round(v)])),
};
},
// What the footer actually renders -- the drill-down's own totals
// while active, otherwise the current year's (see
// detectCurrentYear()/loadCurrentYearTotals()). Switches back
// automatically the moment filterEntreeId clears.
footerTotals() {
return this.filterEntreeId ? this.drilldownTotals : this.currentYearTotals;
},
groupedRows() {
const list = this.filteredRows;
if (this.groupBy === 'none') return list;
@@ -182,13 +182,16 @@
<td class="actions-col"></td>
<td class="actions-col"></td>
<td colspan="4">
Solde {{ currentYear || '…' }} (créditeur / débiteur)
<span v-if="currentYearLoading" class="figli-note">chargement…</span>
<template v-if="filterEntreeId">Solde entrée + sorties liées (créditeur / débiteur)</template>
<template v-else>
Solde {{ currentYear || '…' }} (créditeur / débiteur)
<span v-if="currentYearLoading" class="figli-note">chargement…</span>
</template>
</td>
<td class="amount">{{ currentYearTotals ? formatEur(currentYearTotals.montant_ht) : '' }}</td>
<td class="amount">{{ currentYearTotals ? formatEur(currentYearTotals.montant_ttc) : '' }}</td>
<td v-for="c in allComptes" :key="c" class="amount compte-col" :class="currentYearTotals ? soldeClass(currentYearTotals.par_compte[c]) : ''">{{ currentYearTotals && currentYearTotals.par_compte[c] !== undefined ? formatEur(currentYearTotals.par_compte[c]) : '' }}</td>
<td class="amount" :class="currentYearTotals ? soldeClass(currentYearTotals.ecart) : ''">{{ currentYearTotals ? formatEur(currentYearTotals.ecart) : '' }}</td>
<td class="amount">{{ footerTotals ? formatEur(footerTotals.montant_ht) : '' }}</td>
<td class="amount">{{ footerTotals ? formatEur(footerTotals.montant_ttc) : '' }}</td>
<td v-for="c in allComptes" :key="c" class="amount compte-col" :class="footerTotals ? soldeClass(footerTotals.par_compte[c]) : ''">{{ footerTotals && footerTotals.par_compte[c] !== undefined ? formatEur(footerTotals.par_compte[c]) : '' }}</td>
<td class="amount" :class="footerTotals ? soldeClass(footerTotals.ecart) : ''">{{ footerTotals ? formatEur(footerTotals.ecart) : '' }}</td>
</tr>
</tfoot>
</table>