import { db } from "@/db"; import { project_offers, offer_micros } from "@/db/schema"; import { eq } from "drizzle-orm"; export type ForecastMonth = { year: number; month: number; // 1-12 label: string; // "giu 2026" total: number; }; export async function getRevenueForecast12Months(): Promise { // Load all project offers with micro duration info const offers = await db .select({ start_date: project_offers.start_date, duration_months: offer_micros.duration_months, accepted_total: project_offers.accepted_total, }) .from(project_offers) .innerJoin(offer_micros, eq(project_offers.micro_id, offer_micros.id)); // Build 12-month bucket array starting from current month const now = new Date(); const buckets: ForecastMonth[] = Array.from({ length: 12 }, (_, i) => { const d = new Date(now.getFullYear(), now.getMonth() + i, 1); return { year: d.getFullYear(), month: d.getMonth() + 1, label: d.toLocaleDateString("it-IT", { month: "short", year: "numeric" }), total: 0, }; }); for (const offer of offers) { // Skip offers with no accepted_total — they contribute 0 to forecast if (!offer.accepted_total) continue; const total = parseFloat(String(offer.accepted_total)); if (isNaN(total) || total <= 0) continue; const perMonth = total / offer.duration_months; const start = new Date(offer.start_date); for (let m = 0; m < offer.duration_months; m++) { const offerMonth = new Date(start.getFullYear(), start.getMonth() + m, 1); const bucket = buckets.find( (b) => b.year === offerMonth.getFullYear() && b.month === offerMonth.getMonth() + 1 ); if (bucket) bucket.total += perMonth; } } // Round totals to 2 decimal places buckets.forEach((b) => { b.total = Math.round(b.total * 100) / 100; }); return buckets; }