import type { Request, Response } from 'express' import { mondayService } from '../services/monday.service.js' import { detalleContacto, claveTelefono } from '../services/contactos-detalle.service.js' import { prisma } from '../services/prisma.js' import { NotFoundError } from '../utils/errors.js' /** * GET /api/contactos (Bearer) → contactos del tablero Contactos de Monday * (nombre, teléfono, email, estado), lo más reciente primero, máx 100. */ export async function listarContactosEndpoint(_req: Request, res: Response): Promise { res.json(await mondayService.getContactos()) } /** * GET /api/contactos/:id/detalle (Bearer) → ficha completa del contacto: * todas sus columnas, la propiedad comprada/en proceso (apartado relacionado), * quién atiende cada item relacionado (leads, oportunidades, apartados) y el * historial completo de atención (activity log de Monday + capturas locales). */ export async function detalleContactoEndpoint(req: Request, res: Response): Promise { const contactoId = String(req.params['id']) const contacto = await mondayService.getContactoDetalle(contactoId) if (contacto === null) throw new NotFoundError('Contacto no encontrado') // Nombres para "atendidoPor"/historial: usuarios del ecosistema + workspace const mapeados = await prisma.usuario.findMany({ where: { mondayUserId: { not: null }, activo: true }, select: { nombre: true, mondayUserId: true }, }) const nombresPorMondayId = new Map( mapeados.filter((m) => m.mondayUserId !== null).map((m) => [m.mondayUserId!, m.nombre]), ) try { for (const u of await mondayService.getUsuariosWorkspace()) { if (!nombresPorMondayId.has(u.id)) nombresPorMondayId.set(u.id, u.nombre) } } catch (err) { // eslint-disable-next-line no-console console.error('No se pudieron listar los usuarios del workspace de Monday:', err) } // Registro local: capturas con el mismo teléfono (Monday no guarda quién // capturó) y la ficha de cliente ligada a este contacto (o por celular). // LeadCaptura/Cliente no tienen relación Prisma a Usuario: se resuelve a mano. const clave = claveTelefono(contacto['Teléfono'] ?? '') const capturasTodas = await prisma.leadCaptura.findMany({ where: { telefono: { not: null } }, orderBy: { createdAt: 'desc' }, }) const capturasCrudas = capturasTodas.filter((c) => c.telefono !== null && clave !== '' && claveTelefono(c.telefono) === clave) const clienteCrudo = await prisma.cliente.findFirst({ where: { OR: [ { mondayContactoId: contactoId }, ...(clave !== '' ? [{ celular: { contains: clave } }] : []), ], }, include: { _count: { select: { documentos: true } } }, orderBy: { createdAt: 'desc' }, }) // Nombres de capturistas (ids locales → nombre para mostrar) const idsUsuarios = [ ...new Set([ ...capturasCrudas.map((c) => c.usuarioId), ...(clienteCrudo?.capturadoPorId ? [clienteCrudo.capturadoPorId] : []), ]), ] const usuariosLocal = idsUsuarios.length ? await prisma.usuario.findMany({ where: { id: { in: idsUsuarios } }, select: { id: true, nombre: true } }) : [] const nombreLocal = new Map(usuariosLocal.map((u) => [u.id, u.nombre])) const capturas = capturasCrudas.map((c) => ({ leadId: c.leadId, nombreLead: c.nombreLead, createdAt: c.createdAt, usuario: nombreLocal.has(c.usuarioId) ? { nombre: nombreLocal.get(c.usuarioId)! } : null, })) const clienteLocal = clienteCrudo ? { ...clienteCrudo, capturadoPor: clienteCrudo.capturadoPorId && nombreLocal.has(clienteCrudo.capturadoPorId) ? { nombre: nombreLocal.get(clienteCrudo.capturadoPorId)! } : null, } : null res.json(await detalleContacto(mondayService, contactoId, nombresPorMondayId, capturas, clienteLocal)) }