import { getInvoicePeriodDate, matchesInvoicePeriod } from "./invoicePeriod"; export type AnalyticsInvoice = { invoiceDate?: Date | string | number | null; createdAt?: Date | string | number | null; isSubscription?: number | null; status?: string | null; supplierName?: string | null; totalAmount?: number | string | null; }; export type AnnualInvoiceSummary = { year: number; bapCount: number; bapAmount: number; subscriptionCount: number; subscriptionAmount: number; totalAmount: number; }; export type SupplierBudgetSummary = { supplierName: string; subscriptionCount: number; subscriptionAmount: number; nonSubscriptionCount: number; nonSubscriptionAmount: number; totalAmount: number; }; function getAmount(value: AnalyticsInvoice["totalAmount"]): number { const amount = Number(value); return Number.isFinite(amount) ? amount : 0; } /** * Agrège les factures finalisées par année métier. « BAP » désigne ici les * factures hors abonnement, éligibles au circuit BAP, validées ou non. */ export function buildAnnualInvoiceSummary(invoices: AnalyticsInvoice[]): AnnualInvoiceSummary[] { const summaryByYear = new Map(); for (const invoice of invoices) { if (invoice.status !== "completed") continue; const date = getInvoicePeriodDate(invoice); if (!date) continue; const year = date.getFullYear(); const current = summaryByYear.get(year) ?? { year, bapCount: 0, bapAmount: 0, subscriptionCount: 0, subscriptionAmount: 0, totalAmount: 0, }; const amount = getAmount(invoice.totalAmount); if (invoice.isSubscription === 1) { current.subscriptionCount += 1; current.subscriptionAmount += amount; } else { current.bapCount += 1; current.bapAmount += amount; } current.totalAmount += amount; summaryByYear.set(year, current); } return Array.from(summaryByYear.values()).sort((a, b) => b.year - a.year); } /** Agrège le budget réellement facturé par fournisseur sur la période choisie. */ export function buildSupplierBudgetSummary( invoices: AnalyticsInvoice[], year: string, month: string, ): SupplierBudgetSummary[] { const summaryBySupplier = new Map(); for (const invoice of invoices) { if (invoice.status !== "completed" || !matchesInvoicePeriod(invoice, year, month)) continue; const supplierName = invoice.supplierName?.trim() || "Fournisseur inconnu"; const current = summaryBySupplier.get(supplierName) ?? { supplierName, subscriptionCount: 0, subscriptionAmount: 0, nonSubscriptionCount: 0, nonSubscriptionAmount: 0, totalAmount: 0, }; const amount = getAmount(invoice.totalAmount); if (invoice.isSubscription === 1) { current.subscriptionCount += 1; current.subscriptionAmount += amount; } else { current.nonSubscriptionCount += 1; current.nonSubscriptionAmount += amount; } current.totalAmount += amount; summaryBySupplier.set(supplierName, current); } return Array.from(summaryBySupplier.values()).sort((a, b) => b.totalAmount - a.totalAmount || a.supplierName.localeCompare(b.supplierName, "fr"), ); }