Configuracion para guardar en base de datos

This commit is contained in:
unknown
2026-06-02 23:11:46 -04:00
parent fc6a7044b0
commit e5c8956b64
3 changed files with 86 additions and 23 deletions

View File

@@ -332,14 +332,14 @@ Reglas para valor_extraido:
} }
const valoresPermitidos = this.leadsService.getValoresPermitidos(estado); const valoresPermitidos = this.leadsService.getValoresPermitidos(estado);
const valor = clasificacion.valor_extraido?.trim().toLowerCase(); const valor = this.normalizarTexto(clasificacion.valor_extraido ?? '');
if (!valor) { if (!valor) {
return { valido: false, valorNormalizado: null }; return { valido: false, valorNormalizado: null };
} }
const coincide = valoresPermitidos.some( const coincide = valoresPermitidos.some(
(v) => v === valor || valor.includes(v), (v) => v === valor || valor.includes(v) || v.includes(valor),
); );
if (!coincide) { if (!coincide) {
@@ -347,11 +347,21 @@ Reglas para valor_extraido:
} }
const valorNormalizado = const valorNormalizado =
valoresPermitidos.find((v) => v === valor || valor.includes(v)) ?? valor; valoresPermitidos.find(
(v) => v === valor || valor.includes(v) || v.includes(valor),
) ?? valor;
return { valido: true, valorNormalizado }; return { valido: true, valorNormalizado };
} }
private normalizarTexto(valor: string): string {
return valor
.trim()
.toLowerCase()
.normalize('NFD')
.replace(/\p{Diacritic}/gu, '');
}
private claveReintento(leadId: number, estado: string): string { private claveReintento(leadId: number, estado: string): string {
return `${leadId}:${estado}`; return `${leadId}:${estado}`;
} }
@@ -603,6 +613,11 @@ Devuelve SOLO el mensaje final listo para enviar, sin explicaciones ni JSON.
const campo = this.leadsService.getCampoParaEstado(estadoFlujo); const campo = this.leadsService.getCampoParaEstado(estadoFlujo);
if (campo) { if (campo) {
entidad = { [campo]: validacion.valorNormalizado }; entidad = { [campo]: validacion.valorNormalizado };
} else if (
estadoFlujo === 'apertura' &&
clasificacion.valor_extraido?.trim()
) {
entidad = { nombre: clasificacion.valor_extraido.trim() };
} }
} }

View File

@@ -116,8 +116,11 @@ export class LeadsService {
} }
async updateEstado(lead: Lead, estado: EstadoLead | string): Promise<Lead> { async updateEstado(lead: Lead, estado: EstadoLead | string): Promise<Lead> {
lead.estado_actual = estado as EstadoLead; await this.leadRepo.update(lead.id, {
return this.leadRepo.save(lead); estado_actual: estado as EstadoLead,
});
this.logger.log(`Lead id=${lead.id} estado_actual=${estado}`);
return this.leadRepo.findOne({ where: { id: lead.id } });
} }
/** /**
@@ -125,14 +128,62 @@ export class LeadsService {
* Solo actualiza los campos que se pasan en el partial. * Solo actualiza los campos que se pasan en el partial.
*/ */
async updateDatos(leadId: number, datos: Partial<Lead>): Promise<Lead> { async updateDatos(leadId: number, datos: Partial<Lead>): Promise<Lead> {
const campos = Object.keys(datos).filter(
(k) => datos[k as keyof Lead] !== undefined,
);
if (campos.length === 0) {
return this.leadRepo.findOne({ where: { id: leadId } });
}
await this.leadRepo.update(leadId, datos); await this.leadRepo.update(leadId, datos);
this.logger.log(
`Lead id=${leadId} datos guardados: ${JSON.stringify(datos)}`,
);
return this.leadRepo.findOne({ where: { id: leadId } }); return this.leadRepo.findOne({ where: { id: leadId } });
} }
async marcarViable(lead: Lead, viable: boolean): Promise<Lead> { async marcarViable(lead: Lead, viable: boolean): Promise<Lead> {
lead.viable = viable; const estado = viable ? 'completado' : 'no_viable';
lead.estado_actual = viable ? 'completado' : 'no_viable'; await this.leadRepo.update(lead.id, { viable, estado_actual: estado });
return this.leadRepo.save(lead); this.logger.log(`Lead id=${lead.id} viable=${viable}, estado=${estado}`);
return this.leadRepo.findOne({ where: { id: lead.id } });
}
/**
* Persiste datos del lead y cambio de estado en una sola operacion.
*/
async persistirTurno(
leadId: number,
datos: Partial<Lead>,
options?: { nuevoEstado?: string; viable?: boolean },
): Promise<Lead> {
const patch: Partial<Lead> = { ...datos };
if (options?.nuevoEstado === 'fin_viable') {
patch.viable = true;
patch.estado_actual = 'completado';
} else if (options?.nuevoEstado === 'fin_no_viable') {
patch.viable = false;
patch.estado_actual = 'no_viable';
} else if (options?.nuevoEstado) {
patch.estado_actual = options.nuevoEstado as EstadoLead;
} else if (options?.viable !== undefined && options?.viable !== null) {
patch.viable = options.viable;
patch.estado_actual = options.viable ? 'completado' : 'no_viable';
}
const campos = Object.keys(patch).filter(
(k) => patch[k as keyof Lead] !== undefined,
);
if (campos.length === 0) {
return this.leadRepo.findOne({ where: { id: leadId } });
}
await this.leadRepo.update(leadId, patch);
this.logger.log(
`Lead id=${leadId} persistido: ${JSON.stringify(patch)}`,
);
return this.leadRepo.findOne({ where: { id: leadId } });
} }
/** /**

View File

@@ -190,7 +190,7 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy {
const telefono = jid.split("@")[0]; const telefono = jid.split("@")[0];
try { try {
const lead = await this.leadsService.findOrCreate(telefono); let lead = await this.leadsService.findOrCreate(telefono);
if (ESTADOS_TERMINALES.includes(lead.estado_actual)) { if (ESTADOS_TERMINALES.includes(lead.estado_actual)) {
this.logger.log( this.logger.log(
@@ -299,21 +299,18 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy {
this.logger.log(`LUISA [${telefono}]: ${respuesta}`); this.logger.log(`LUISA [${telefono}]: ${respuesta}`);
if (entidad && Object.keys(entidad).length > 0) { if (
await this.leadsService.updateDatos(lead.id, entidad); (entidad && Object.keys(entidad).length > 0) ||
} nuevoEstado ||
(viable !== undefined && viable !== null)
if (nuevoEstado === "fin_viable" || nuevoEstado === "fin_no_viable") { ) {
await this.leadsService.marcarViable( lead = await this.leadsService.persistirTurno(lead.id, entidad ?? {}, {
lead, nuevoEstado,
nuevoEstado === "fin_viable", viable,
});
this.logger.log(
`Lead id=${lead.id} en DB — estado=${lead.estado_actual}, espacio=${lead.espacio ?? "-"}, rango_m2=${lead.rango_m2 ?? "-"}, estilo=${lead.estilo ?? "-"}, urgencia=${lead.urgencia ?? "-"}, presupuesto=${lead.presupuesto_declarado ?? "-"}`,
); );
this.logger.log(`Lead id=${lead.id} finalizado como ${nuevoEstado}`);
} else if (nuevoEstado) {
await this.leadsService.updateEstado(lead, nuevoEstado);
this.logger.log(`Lead id=${lead.id} avanzado a estado=${nuevoEstado}`);
} else if (viable !== undefined && viable !== null) {
await this.leadsService.marcarViable(lead, viable);
} }
await this.conversacionService.guardarMensaje( await this.conversacionService.guardarMensaje(