Configuracion para guardar en base de datos
This commit is contained in:
@@ -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() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 } });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user