Logia de agente de Whatsapp

This commit is contained in:
unknown
2026-05-31 22:02:58 -04:00
parent aa7555b49d
commit ef78d9a14c
28 changed files with 12736 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, LessThan } from 'typeorm';
import { Lead, EstadoLead } from './lead.entity';
@Injectable()
export class LeadsService {
private readonly logger = new Logger(LeadsService.name);
constructor(
@InjectRepository(Lead)
private readonly leadRepo: Repository<Lead>,
) {}
/**
* Busca un lead por número de teléfono.
* Si no existe, lo crea con estado 'nuevo'.
*/
async findOrCreate(telefono: string): Promise<Lead> {
let lead = await this.leadRepo.findOne({ where: { telefono } });
if (!lead) {
lead = this.leadRepo.create({ telefono, estado_actual: 'nuevo' });
lead = await this.leadRepo.save(lead);
this.logger.log(`Lead nuevo creado: telefono=${telefono}, id=${lead.id}`);
}
return lead;
}
async findByTelefono(telefono: string): Promise<Lead | null> {
return this.leadRepo.findOne({ where: { telefono } });
}
async findById(id: number): Promise<Lead | null> {
return this.leadRepo.findOne({ where: { id } });
}
async findByEstado(estado: EstadoLead): Promise<Lead[]> {
return this.leadRepo.find({ where: { estado_actual: estado } });
}
async updateEstado(lead: Lead, estado: EstadoLead): Promise<Lead> {
lead.estado_actual = estado;
return this.leadRepo.save(lead);
}
/**
* Actualiza campos del lead según el estado actual del flujo.
* Solo actualiza los campos que se pasan en el partial.
*/
async updateDatos(leadId: number, datos: Partial<Lead>): Promise<Lead> {
await this.leadRepo.update(leadId, datos);
return this.leadRepo.findOne({ where: { id: leadId } });
}
async marcarViable(lead: Lead, viable: boolean): Promise<Lead> {
lead.viable = viable;
lead.estado_actual = viable ? 'completado' : 'no_viable';
return this.leadRepo.save(lead);
}
/**
* Marca como perdido cualquier lead en_proceso sin actividad en más de 48h.
*/
async marcarLeadsPerdidos(): Promise<void> {
const hace48h = new Date(Date.now() - 48 * 60 * 60 * 1000);
const leadsSinActividad = await this.leadRepo.find({
where: {
estado_actual: 'en_proceso',
updated_at: LessThan(hace48h),
},
});
for (const lead of leadsSinActividad) {
lead.estado_actual = 'perdido';
await this.leadRepo.save(lead);
this.logger.warn(
`Lead id=${lead.id} marcado como perdido por inactividad > 48h`,
);
}
}
async save(lead: Lead): Promise<Lead> {
return this.leadRepo.save(lead);
}
}