feat(apartado): ficha completa en Monday + estado visible en la app

- El alta (directa y progresiva) llena el Apartado con telefono, correo,
  curp, Precio Final, Enganche, Fecha Compra, Vendedor (el capturista
  con Monday vinculado) y Forma de Pago; el path webhook/cron hereda
  contacto, precio y asesor de la oportunidad.
- Bidireccional: Mis clientes en /hoy muestra el estado actual del
  Apartado leyendolo de Monday (si lo mueven en Monday, la app lo
  refleja en el siguiente refresh).
- getApartados con la correccion value-null al leer Estado.
- Test del mapa de Tipo propuesta del cotizador (los 502 del log eran
  de un proceso previo al fix 4f31d1c; queda cubierto).
This commit is contained in:
2026-09-04 07:34:57 +00:00
parent d81797c610
commit 42cfe937cf
13 changed files with 428 additions and 12 deletions

View File

@@ -181,14 +181,55 @@ async function moverLeadAApartoSiAplica(body: Record<string, unknown>): Promise<
}
}
/** Item en el tablero Apartado (pipeline Enkontrol); solo si hay valor de venta */
/** Label del dropdown "Forma de Pago" (tablero Apartado) a partir del enum del formato de alta */
const FORMA_PAGO_LABEL: Record<string, string> = {
INFONAVIT: 'Infonavit',
APOYO_INFONAVIT: 'Apoyo Infonavit',
COFINAVIT: 'Cofinavit',
SEGUNDO_CREDITO: 'Segundo crédito',
CONTADO: 'Contado',
FOVISSSTE: 'Fovissste',
COFI_FOVISSSTE: 'Cofi-Fovissste',
BANCARIO: 'Bancario',
}
/**
* Label de "Forma de Pago" a partir de viviendaCredito.tiposCredito (arreglo
* del wizard; se toma el PRIMERO reconocido — la columna del board es de una
* sola forma de pago). undefined si no hay ninguno reconocible.
*/
export function formaPagoLabel(tiposCredito: unknown): string | undefined {
if (!Array.isArray(tiposCredito)) return undefined
for (const t of tiposCredito) {
const label = FORMA_PAGO_LABEL[String(t).trim().toUpperCase()]
if (label !== undefined) return label
}
return undefined
}
/** Item en el tablero Apartado (pipeline Enkontrol) con la ficha completa; solo si hay valor de venta */
async function crearApartadoSiAplica(
dg: { nombreCompleto: string },
vc: { ubicacion?: string | undefined; valorVenta?: string | number | undefined; enganche?: string | number | undefined },
dg: { nombreCompleto: string; celular?: string | undefined; email?: string | undefined; curp?: string | undefined },
vc: {
ubicacion?: string | undefined
valorVenta?: string | number | undefined
enganche?: string | number | undefined
tiposCredito?: unknown
},
capturadoPorId: string | null,
): Promise<string | null> {
const valorVenta = aNumero(vc.valorVenta)
if (valorVenta <= 0) return null
const enganche = aNumero(vc.enganche)
// Vendedor del apartado: el usuario Monday vinculado de quien capturó el alta
let vendedorId: number | undefined
if (capturadoPorId !== null) {
const capturista = await prisma.usuario.findUnique({
where: { id: capturadoPorId },
select: { mondayUserId: true },
})
vendedorId = capturista?.mondayUserId ?? undefined
}
return mondayService.crearApartado({
clienteNombre: dg.nombreCompleto,
unidadCodigo: vc.ubicacion ?? '',
@@ -196,6 +237,14 @@ async function crearApartadoSiAplica(
fechaApartado: hoyMas(0),
fechaLimite: hoyMas(15),
estadoLabel: 'Pago Apartado', // primer paso del pipeline Enkontrol
telefono: dg.celular,
email: dg.email,
curp: dg.curp,
precioFinal: valorVenta,
enganche: enganche > 0 ? enganche : undefined,
fechaCompra: hoyMas(0),
vendedorId,
formaPagoLabel: formaPagoLabel(vc.tiposCredito),
})
}
@@ -241,7 +290,7 @@ export async function crearCliente(req: Request, res: Response): Promise<void> {
...{ actividadEconomicaLabel: actividadEconomicaLabel(body.empleo?.tipoEmpleo) },
})
mondayApartadoId = await crearApartadoSiAplica(dg, vc)
mondayApartadoId = await crearApartadoSiAplica(dg, vc, req.usuarioToken?.sub ?? null)
await prisma.cliente.update({
where: { id: cliente.id },
@@ -444,7 +493,8 @@ export async function completarProgreso(req: Request, res: Response): Promise<vo
}
if (mondayApartadoId === null) {
mondayApartadoId = await crearApartadoSiAplica(dg, vc)
// El capturista original del alta progresiva es quien queda como Vendedor
mondayApartadoId = await crearApartadoSiAplica(dg, vc, cliente.capturadoPorId)
}
await prisma.cliente.update({