Les totaux du footer de /lignes suivent maintenant les filtres actifs
Remplace /lignes/api/totaux (LedgerStatsController::totauxAnnee(), toujours non filtré) par une agrégation côté client des lignes renvoyées par LedgerRowsController::index() (même endpoint que la fenêtre glissante) avec annee=<année visible> + les filtres actifs. Reste une requête serveur dédiée sur l'année entière (pas de LIMIT/range sur la requête Entity), donc le total ne dépend jamais de ce qui est effectivement chargé dans la fenêtre glissante à cet instant -- vérifié : 207 lignes non filtrées vs 13 avec le filtre "OVH", total du footer identique au calcul indépendant dans les deux cas. onFilterChanged() déclenche maintenant systématiquement loadCurrentYearTotals() (pas seulement quand detectCurrentYear() détecte un changement d'année) -- sinon changer un filtre en restant sur la même année laissait le footer afficher l'ancien total non filtré. totauxAnnee() et sa route sont supprimés (plus aucun appelant après ce changement, vérifié par recherche).
This commit is contained in:
@@ -305,10 +305,44 @@
|
||||
return json;
|
||||
}
|
||||
|
||||
async function fetchYearTotals(annee) {
|
||||
const res = await fetch('/lignes/api/totaux?annee=' + encodeURIComponent(annee), { headers: { Accept: 'application/json' } });
|
||||
if (!res.ok) throw new Error('/lignes/api/totaux a répondu ' + res.status);
|
||||
return res.json();
|
||||
// Sums the same fields LedgerRowsController::index() rows carry into
|
||||
// the {montant_ht, cotisation, montant_ttc, ecart, par_compte} shape
|
||||
// the footer template expects.
|
||||
function aggregateTotals(rows) {
|
||||
let montantHt = 0;
|
||||
let cotisation = 0;
|
||||
let montantTtc = 0;
|
||||
let ecart = 0;
|
||||
const parCompte = {};
|
||||
for (const r of rows) {
|
||||
montantHt += r.montant_ht || 0;
|
||||
cotisation += r.cotisation || 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),
|
||||
cotisation: round(cotisation),
|
||||
montant_ttc: round(montantTtc),
|
||||
ecart: round(ecart),
|
||||
par_compte: Object.fromEntries(Object.entries(parCompte).map(([c, v]) => [c, round(v)])),
|
||||
};
|
||||
}
|
||||
|
||||
// Per-année footer totals, filtered the same way the table itself is --
|
||||
// fetches every row for the year via the same server-side-filtered
|
||||
// endpoint the table window uses (fetchFilteredLignes), then sums them
|
||||
// client-side. Replaces the old /lignes/api/totaux (LedgerStatsController::
|
||||
// totauxAnnee(), always unfiltered) now that the footer needs to
|
||||
// reflect whatever's actually on screen, not the whole year regardless
|
||||
// of the active filters.
|
||||
async function fetchYearTotals(annee, filters) {
|
||||
const rows = await fetchFilteredLignes({ annee }, filters);
|
||||
return Object.assign({ annee }, aggregateTotals(rows));
|
||||
}
|
||||
|
||||
// URL hash (#compte=Maud,Bachir&type=versement,achat&annee=2023&ecarts=1&aller=2024)
|
||||
@@ -1471,8 +1505,17 @@
|
||||
// filter actually left too few rows to fill the viewport, wedging
|
||||
// every future filter change and scroll-triggered load right along
|
||||
// with it.
|
||||
//
|
||||
// loadCurrentYearTotals() is called unconditionally here (not just
|
||||
// left to detectCurrentYear()'s own trigger): that one only
|
||||
// re-fetches when the *visible year* changes, so a filter change
|
||||
// while staying on the same year would otherwise leave the footer
|
||||
// showing stale, pre-filter totals. Independent of the window
|
||||
// reload above (different endpoint call, no shared state), so no
|
||||
// need to chain it through the same queue.
|
||||
onFilterChanged() {
|
||||
this._queueWindowOp(() => this.reloadWindow()).then(() => this.ensureScrollable());
|
||||
this.loadCurrentYearTotals();
|
||||
this.syncHash();
|
||||
},
|
||||
// Keeps extending the window (both directions) as long as a filter
|
||||
@@ -1591,7 +1634,7 @@
|
||||
if (!this.currentYear) return;
|
||||
this.currentYearLoading = true;
|
||||
try {
|
||||
this.currentYearTotals = await fetchYearTotals(this.currentYear);
|
||||
this.currentYearTotals = await fetchYearTotals(this.currentYear, this.currentFilters());
|
||||
} catch (err) {
|
||||
this.currentYearTotals = null;
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user