Checkpoint: Budget réel confirmé en ordre décroissant de montant total ; graphique en barres annuel comparant les montants BAP et abonnements ajouté au tableau de bord.
All checks were successful
Validation applicative / TypeScript, tests et build (push) Successful in 3m19s
All checks were successful
Validation applicative / TypeScript, tests et build (push) Successful in 3m19s
This commit is contained in:
@@ -155,11 +155,26 @@ export default function Dashboard() {
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{stats?.annualSummary?.length ? (
|
||||
<div className="overflow-x-auto rounded-lg border">
|
||||
<table className="w-full min-w-[780px] text-sm">
|
||||
<thead className="bg-muted/60 text-left text-muted-foreground"><tr><th className="px-4 py-3 font-medium">Année</th><th className="px-4 py-3 text-right font-medium">Factures BAP</th><th className="px-4 py-3 text-right font-medium">Montant BAP</th><th className="px-4 py-3 text-right font-medium">Abonnements</th><th className="px-4 py-3 text-right font-medium">Montant abonnements</th><th className="px-4 py-3 text-right font-medium">Total annuel</th></tr></thead>
|
||||
<tbody>{stats.annualSummary.map((row) => <tr key={row.year} className="border-t hover:bg-muted/30"><td className="px-4 py-3 font-semibold">{row.year}</td><td className="px-4 py-3 text-right">{row.bapCount}</td><td className="px-4 py-3 text-right text-blue-700">{formatCurrency(row.bapAmount)}</td><td className="px-4 py-3 text-right">{row.subscriptionCount}</td><td className="px-4 py-3 text-right text-violet-700">{formatCurrency(row.subscriptionAmount)}</td><td className="px-4 py-3 text-right font-semibold text-emerald-700">{formatCurrency(row.totalAmount)}</td></tr>)}</tbody>
|
||||
</table>
|
||||
<div className="space-y-6">
|
||||
<div className="h-[300px] rounded-lg border bg-white p-4">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={[...stats.annualSummary].reverse()} margin={{ top: 8, right: 16, left: 12, bottom: 4 }}>
|
||||
<CartesianGrid strokeDasharray="3 3" vertical={false} />
|
||||
<XAxis dataKey="year" />
|
||||
<YAxis tickFormatter={(value) => new Intl.NumberFormat("fr-FR", { notation: "compact", maximumFractionDigits: 1 }).format(value)} />
|
||||
<Tooltip formatter={(value: number) => formatCurrency(Number(value))} labelFormatter={(year) => `Année ${year}`} />
|
||||
<Legend />
|
||||
<Bar dataKey="bapAmount" name="Montant BAP" fill="#2563eb" radius={[4, 4, 0, 0]} />
|
||||
<Bar dataKey="subscriptionAmount" name="Montant abonnements" fill="#7c3aed" radius={[4, 4, 0, 0]} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
<div className="overflow-x-auto rounded-lg border">
|
||||
<table className="w-full min-w-[780px] text-sm">
|
||||
<thead className="bg-muted/60 text-left text-muted-foreground"><tr><th className="px-4 py-3 font-medium">Année</th><th className="px-4 py-3 text-right font-medium">Factures BAP</th><th className="px-4 py-3 text-right font-medium">Montant BAP</th><th className="px-4 py-3 text-right font-medium">Abonnements</th><th className="px-4 py-3 text-right font-medium">Montant abonnements</th><th className="px-4 py-3 text-right font-medium">Total annuel</th></tr></thead>
|
||||
<tbody>{stats.annualSummary.map((row) => <tr key={row.year} className="border-t hover:bg-muted/30"><td className="px-4 py-3 font-semibold">{row.year}</td><td className="px-4 py-3 text-right">{row.bapCount}</td><td className="px-4 py-3 text-right text-blue-700">{formatCurrency(row.bapAmount)}</td><td className="px-4 py-3 text-right">{row.subscriptionCount}</td><td className="px-4 py-3 text-right text-violet-700">{formatCurrency(row.subscriptionAmount)}</td><td className="px-4 py-3 text-right font-semibold text-emerald-700">{formatCurrency(row.totalAmount)}</td></tr>)}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
) : <div className="py-8 text-center text-muted-foreground">Aucune facture finalisée avec une date disponible.</div>}
|
||||
</CardContent>
|
||||
|
||||
@@ -21,4 +21,13 @@ describe("agrégats de facturation", () => {
|
||||
{ supplierName: "SFR", subscriptionCount: 1, subscriptionAmount: 20, nonSubscriptionCount: 1, nonSubscriptionAmount: 100, totalAmount: 120 },
|
||||
]);
|
||||
});
|
||||
|
||||
it("classe le budget du fournisseur le plus facturé au moins facturé", () => {
|
||||
const rows = buildSupplierBudgetSummary([
|
||||
...invoices,
|
||||
{ invoiceDate: "2026-05-22", createdAt: "2026-05-22", status: "completed", isSubscription: 0, supplierName: "Orange", totalAmount: "300" },
|
||||
], "2026", "05");
|
||||
|
||||
expect(rows.map((row) => row.supplierName)).toEqual(["Orange", "SFR"]);
|
||||
});
|
||||
});
|
||||
|
||||
5
todo.md
5
todo.md
@@ -820,3 +820,8 @@
|
||||
- [x] Créer l’écran Budget réel à la fin du menu Facturation
|
||||
- [x] Afficher par fournisseur les montants Abonnement, Hors abonnement et le total
|
||||
- [x] Ajouter les tests et valider TypeScript, build et affichage en sandbox
|
||||
|
||||
## Améliorations Budget réel et tableau de bord
|
||||
- [x] Confirmer le tri décroissant par montant total dans le budget
|
||||
- [x] Ajouter un graphique annuel BAP versus abonnements au tableau de bord
|
||||
- [x] Ajouter les tests et valider TypeScript, build et rendu sandbox
|
||||
|
||||
Reference in New Issue
Block a user