Encadenar extractor de preferencias y aplicación de extras en el orquestador

This commit is contained in:
Carlos Narro
2026-05-31 16:19:21 +02:00
parent 11d78e4f69
commit ba61ff4b4d

View File

@@ -3,8 +3,10 @@ import { db } from '@/db';
import { leads, leadPipelineEventos } from '@/db/schema'; import { leads, leadPipelineEventos } from '@/db/schema';
import { getPricingConfigFor, getCatalogFor, getEnvioModeFor } from '@/db/pricing-queries'; import { getPricingConfigFor, getCatalogFor, getEnvioModeFor } from '@/db/pricing-queries';
import { computeBudget } from '@/budget'; import { computeBudget } from '@/budget';
import type { BudgetInputs } from '@/budget/types';
import type { Lead } from '@/db/schema'; import type { Lead } from '@/db/schema';
import { deterministicExtractor } from '@/lib/voice/extractor';
import { mergeIntoBudgetInputs, applyPreferences } from '@/lib/voice/apply';
import type { RawCallData } from '@/lib/voice/preferences';
// Render demo por tipo de reforma. No hay generación IA real en esta fase (keyless): // Render demo por tipo de reforma. No hay generación IA real en esta fase (keyless):
// reusamos los renders de muestra del directorio público. // reusamos los renders de muestra del directorio público.
@@ -84,21 +86,29 @@ export async function procesarLead(leadId: string): Promise<void> {
metadata: { simulado: true, renderUrl }, metadata: { simulado: true, renderUrl },
}); });
// Paso 6b: presupuesto calculado (REAL) con el catálogo del reformista // Paso 6b: presupuesto calculado (REAL) con catálogo + preferencias abstraídas
const [config, catalog] = await Promise.all([ const [config, catalog] = await Promise.all([
getPricingConfigFor(lead.tenantId), getPricingConfigFor(lead.tenantId),
getCatalogFor(lead.tenantId), getCatalogFor(lead.tenantId),
]); ]);
const inputs: BudgetInputs = {
const raw: RawCallData = {
tipoReforma: tipo, tipoReforma: tipo,
m2Suelo: lead.m2Suelo ?? null, m2Suelo: lead.m2Suelo ?? null,
alturaTecho: lead.alturaTecho ?? null, calidad: lead.calidadGlobal ?? null,
calidadGlobal: lead.calidadGlobal ?? 'media',
estructural: lead.estructural, estructural: lead.estructural,
provincia: lead.provincia ?? null, urgencia: lead.urgencia ?? null,
materialSelections: (lead.materialSelections as Record<string, string>) ?? {}, presupuestoTarget: lead.presupuestoTarget ?? null,
tasteText: lead.tasteText ?? '',
}; };
const result = computeBudget(inputs, config, catalog); const prefs = deterministicExtractor.extract(raw, catalog);
const inputs = mergeIntoBudgetInputs(prefs, {
tipoReforma: lead.tipoReforma,
m2Suelo: lead.m2Suelo ?? null,
alturaTecho: lead.alturaTecho ?? null,
provincia: lead.provincia ?? null,
});
const result = applyPreferences(computeBudget(inputs, config, catalog), prefs);
await db await db
.update(leads) .update(leads)
@@ -108,6 +118,7 @@ export async function procesarLead(leadId: string): Promise<void> {
renderUrl, renderUrl,
presupuestoEstimado: result.total, presupuestoEstimado: result.total,
desgloseSnapshot: { stage: 'presupuesto_generado', result }, desgloseSnapshot: { stage: 'presupuesto_generado', result },
preferencesSnapshot: prefs,
pipelineStage: 'presupuesto_generado', pipelineStage: 'presupuesto_generado',
updatedAt: new Date(), updatedAt: new Date(),
}) })