feat: resume l'annee civile sur l'accueil
L'accueil ne decrivait qu'un document : les quatre tuiles lisaient le dernier compte rendu importe, sans rien dire de ce que contient la base. Il resume desormais une annee civile, avec un selecteur des annees presentes. L'annee par defaut est celle du dernier compte rendu et non l'annee en cours : la fenetre etait calee sur `date.today()`, si bien que sans import depuis quelques mois l'ecran se serait vide alors que la base est pleine. Ce que les tuiles annoncent : - recettes facturees, report exclu, avec l'encaisse et le recouvrement ; - depenses, debit et credits recus ; - net reverse, rapproche des soldes annonces par les comptes rendus ; - restant du, date, car un stock ne se cumule pas d'un mois sur l'autre. Le net reverse vaut « encaisse - debit + credit », et cette egalite tombe au centime sur le solde extrait du PDF pour avril, mai et juin 2026. Elle s'ecarte de 288,52 EUR en fevrier et de 1 188,03 EUR en mars, les deux mois dont l'extraction a par ailleurs des defauts. L'ecart est donc affiche et jamais lisse : c'est le seul controle de bout en bout dont on dispose sur la qualite d'une extraction. Les regles vivent dans services/tresorerie.py, a cote de celles des revenus. Le lot compte est celui qui a ete facture dans l'annee : la table `lots` retient deux ecritures par lot (« 0001 » et « 01 »), sequelle de la normalisation des numeros, et en annoncerait 40 la ou il y en a 20. Le graphique passe du vert et rouge au bleu et ambre : sous deuteranopie, green-400 et red-400 ne se separent qu'a un delta E de 7,9, sous le seuil de 8. La paire retenue tient a 30,2. `/recent-revenus` disparait — c'etait le dernier agregat a compter les lignes de report — et `/immeubles-shortcuts` est borne a la meme annee que le reste de l'ecran, deux perimetres sur un ecran donnant deux montants sans que rien ne les distingue. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
56
frontend/src/utils/format.js
Normal file
56
frontend/src/utils/format.js
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Mises en forme partagées des montants et des dates.
|
||||
*
|
||||
* Chaque composant redéfinissait son `formatAmount`, avec des variantes
|
||||
* d'arrondi et de séparateur : deux écrans pouvaient écrire différemment le
|
||||
* même euro. Les nouveaux affichages passent par ici.
|
||||
*/
|
||||
|
||||
const EUROS = new Intl.NumberFormat('fr-FR', {
|
||||
style: 'currency',
|
||||
currency: 'EUR',
|
||||
maximumFractionDigits: 0
|
||||
})
|
||||
|
||||
const EUROS_PRECIS = new Intl.NumberFormat('fr-FR', {
|
||||
style: 'currency',
|
||||
currency: 'EUR'
|
||||
})
|
||||
|
||||
const MOIS_COURTS = [
|
||||
'janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin',
|
||||
'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'
|
||||
]
|
||||
|
||||
/** Montant arrondi à l'euro, pour les chiffres qu'on lit d'un coup d'œil. */
|
||||
export function formatMontant(valeur) {
|
||||
if (valeur == null) return '—'
|
||||
return EUROS.format(valeur)
|
||||
}
|
||||
|
||||
/** Montant au centime, pour les écarts et les rapprochements. */
|
||||
export function formatMontantPrecis(valeur) {
|
||||
if (valeur == null) return '—'
|
||||
return EUROS_PRECIS.format(valeur)
|
||||
}
|
||||
|
||||
/** Montant signé, le « + » explicite pour ce qui revient au propriétaire. */
|
||||
export function formatEcart(valeur) {
|
||||
if (valeur == null) return '—'
|
||||
const signe = valeur > 0 ? '+' : ''
|
||||
return `${signe}${EUROS_PRECIS.format(valeur)}`
|
||||
}
|
||||
|
||||
/** "2026-06-22" → "22/06/2026" */
|
||||
export function formatDate(chaine) {
|
||||
if (!chaine) return '—'
|
||||
const [annee, mois, jour] = chaine.split('-')
|
||||
return `${jour}/${mois}/${annee}`
|
||||
}
|
||||
|
||||
/** "2026-06" → "juin" (l'année est portée par le titre de la période) */
|
||||
export function formatMois(chaine) {
|
||||
if (!chaine) return ''
|
||||
const [, mois] = chaine.split('-')
|
||||
return MOIS_COURTS[parseInt(mois, 10) - 1] ?? chaine
|
||||
}
|
||||
Reference in New Issue
Block a user