import { inArray, eq } from "drizzle-orm"; import { db } from "@/db"; import { offer_tier_services, services, offer_micro_services, offer_services, } from "@/db/schema"; /** * "Valore dell'offerta" calcolato: la somma dei prezzi dei servizi collegati a * un tier (micro). * * Due sorgenti, nell'ordine: `offer_tier_services` → `services` (catalogo * Phase 12) e, per i tier che non hanno righe lì, il legacy * `offer_micro_services` → `offer_services`. * * Vive in un modulo neutro perché lo leggono **due** lati: il portale cliente * (`client-view.ts`, dove è il fallback quando l'admin non ha messo un * override) e l'area admin (`admin-queries.ts`, dove serve a mostrare quale * cifra si sta sostituendo). Duplicarlo significherebbe farli divergere. * * Legge solo prezzi: nomi e descrizioni dei servizi non servono a nessuno dei * due chiamanti, e client-view non deve proiettare più di quanto renderizza. * * @returns Map micro_id → totale con 2 decimali. I micro senza servizi non * compaiono nella mappa (il chiamante decide se è "0" o "assente"). */ export async function getComputedOfferValues( microIds: string[] ): Promise> { const out = new Map(); if (microIds.length === 0) return out; const sum = (prices: Array) => prices.reduce((acc, p) => acc + (parseFloat(p ?? "0") || 0), 0).toFixed(2); // Sorgente primaria: catalogo unificato. const tierRows = await db .select({ tier_id: offer_tier_services.tier_id, unit_price: services.unit_price, }) .from(offer_tier_services) .innerJoin(services, eq(offer_tier_services.service_id, services.id)) .where(inArray(offer_tier_services.tier_id, microIds)); const byTier = new Map>(); for (const row of tierRows) { const existing = byTier.get(row.tier_id) ?? []; existing.push(row.unit_price); byTier.set(row.tier_id, existing); } for (const [tierId, prices] of byTier) out.set(tierId, sum(prices)); // Fallback legacy solo per i micro rimasti scoperti. const needLegacy = microIds.filter((id) => !out.has(id)); if (needLegacy.length === 0) return out; const legacyRows = await db .select({ micro_id: offer_micro_services.micro_id, price: offer_services.price, }) .from(offer_micro_services) .innerJoin(offer_services, eq(offer_micro_services.service_id, offer_services.id)) .where(inArray(offer_micro_services.micro_id, needLegacy)); const byMicro = new Map>(); for (const row of legacyRows) { const existing = byMicro.get(row.micro_id) ?? []; existing.push(row.price); byMicro.set(row.micro_id, existing); } for (const [microId, prices] of byMicro) out.set(microId, sum(prices)); return out; }