138 lines
3.5 KiB
TypeScript
138 lines
3.5 KiB
TypeScript
import { Injectable, Logger } from '@nestjs/common';
|
|
import axios from 'axios';
|
|
|
|
export interface LeadState {
|
|
id: string;
|
|
nombre: string;
|
|
telefono: string;
|
|
botStep: string;
|
|
estadoWa: string;
|
|
espacio: string;
|
|
rangoM2: string;
|
|
estilo: string;
|
|
presupuestoDeclarado: string;
|
|
viable: boolean | null;
|
|
}
|
|
|
|
@Injectable()
|
|
export class ApiClient {
|
|
private readonly logger = new Logger(ApiClient.name);
|
|
private readonly baseUrl: string;
|
|
private readonly apiKey: string;
|
|
|
|
constructor() {
|
|
this.baseUrl = process.env.API_BASE_URL || 'http://localhost:3000';
|
|
this.apiKey = process.env.FUNNEL_API_KEY || '';
|
|
}
|
|
|
|
private get headers() {
|
|
return {
|
|
Authorization: `Bearer ${this.apiKey}`,
|
|
'Content-Type': 'application/json',
|
|
};
|
|
}
|
|
|
|
async getLead(leadId: string): Promise<LeadState | null> {
|
|
try {
|
|
const { data } = await axios.get(`${this.baseUrl}/api/leads/${leadId}`, {
|
|
headers: this.headers,
|
|
});
|
|
return data;
|
|
} catch (err: any) {
|
|
if (err.response?.status === 404) return null;
|
|
this.logger.error(`Error fetching lead ${leadId}: ${err.message}`);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async guardarConversacion(
|
|
leadId: string,
|
|
rol: 'user' | 'assistant' | 'system',
|
|
mensaje: string,
|
|
options?: { estadoWa?: string; botStep?: string; mediaType?: string; mediaUrl?: string; transcripcionAudio?: string },
|
|
): Promise<boolean> {
|
|
return this.post(`/api/leads/${leadId}/conversacion`, {
|
|
rol,
|
|
mensaje,
|
|
...options,
|
|
});
|
|
}
|
|
|
|
async actualizarPerfil(
|
|
leadId: string,
|
|
datos: Record<string, unknown>,
|
|
): Promise<boolean> {
|
|
return this.post(`/api/leads/${leadId}/perfil`, datos);
|
|
}
|
|
|
|
async obtenerHistorial(leadId: string): Promise<Array<{ role: string; content: string }>> {
|
|
try {
|
|
const { data } = await axios.get(
|
|
`${this.baseUrl}/api/leads/${leadId}/conversacion`,
|
|
{ headers: this.headers },
|
|
);
|
|
if (Array.isArray(data)) {
|
|
return data.map((m: any) => ({ role: m.rol || m.role, content: m.mensaje || m.content }));
|
|
}
|
|
return [];
|
|
} catch (err: any) {
|
|
if (err.response?.status === 404) return [];
|
|
this.logger.error(`Error fetching historial for ${leadId}: ${err.message}`);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
async calificarLead(
|
|
leadId: string,
|
|
score: number,
|
|
nivel: 'A' | 'B' | 'C' | 'D',
|
|
criterios?: Record<string, unknown>,
|
|
notasAgente?: string,
|
|
): Promise<boolean> {
|
|
return this.post(`/api/leads/${leadId}/calificacion`, {
|
|
score,
|
|
nivel,
|
|
criterios,
|
|
notasAgente,
|
|
});
|
|
}
|
|
|
|
async registrarIntento(
|
|
leadId: string,
|
|
canal: string,
|
|
numeroIntento: number,
|
|
resultado?: string,
|
|
completado?: boolean,
|
|
): Promise<boolean> {
|
|
return this.post(`/api/leads/${leadId}/intento`, {
|
|
canal,
|
|
numeroIntento,
|
|
resultado,
|
|
completado,
|
|
});
|
|
}
|
|
|
|
async enviarIngesta(
|
|
leadId: string,
|
|
items: Array<Record<string, unknown>>,
|
|
flags?: { perfilCompleto?: boolean; finalizar?: boolean },
|
|
): Promise<boolean> {
|
|
return this.post(`/api/leads/${leadId}/ingesta`, {
|
|
items,
|
|
...flags,
|
|
});
|
|
}
|
|
|
|
private async post(path: string, body: unknown): Promise<boolean> {
|
|
try {
|
|
const { status } = await axios.post(`${this.baseUrl}${path}`, body, {
|
|
headers: this.headers,
|
|
});
|
|
return status === 200;
|
|
} catch (err: any) {
|
|
this.logger.error(`POST ${path} error: ${err.response?.status} ${err.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
}
|