fix(flow): LeadCaptura para oportunidades y apartados en flujo Monday

- convertirLeadEndpoint: crea LeadCaptura OPORTUNIDADES al convertir lead
- escaneoOportunidades: crea LeadCaptura APARTADO al crear apartado
- Mi día: esMio para apartados incluye oportunidadId del usuario
- Flujo completo verificado: Lead → Contactado → Agendo → Aparto
This commit is contained in:
2026-09-07 19:55:56 +00:00
parent 9021733455
commit 586498c845
3 changed files with 43 additions and 1 deletions

View File

@@ -751,6 +751,25 @@ export async function convertirLeadEndpoint(req: Request, res: Response): Promis
}
try {
const { oportunidadId } = await convertirLead(mondayService, itemId, usuarioSub, body.fecha)
// Crear LeadCaptura local para la oportunidad (Mi día las necesita)
try {
const leadLocal = await prisma.leadCaptura.findFirst({ where: { leadId: itemId } })
await prisma.leadCaptura.upsert({
where: { leadId: oportunidadId },
update: { board: 'OPORTUNIDADES', etapa: 'Agendo Cita' },
create: {
leadId: oportunidadId,
board: 'OPORTUNIDADES',
etapa: 'Agendo Cita',
nombreLead: leadLocal?.nombreLead ?? '',
telefono: leadLocal?.telefono ?? null,
email: leadLocal?.email ?? null,
usuarioId: usuarioSub ?? 'sistema',
mondayItemId: oportunidadId,
pendienteSync: false,
},
})
} catch { /* best effort */ }
res.status(201).json({ leadId: itemId, oportunidadId, etapa: 'Agendo Cita' })
auditoria.registrar(usuarioSub ?? 'sistema', 'CONVERTIR_LEAD', 'lead', itemId)
} catch (err) {

View File

@@ -579,6 +579,25 @@ export class AutomatizacionesService {
})
await this.state.set(claveApartadoCreado(op.id), apartadoItemId)
resultado.apartadosCreados.push({ oportunidadId: op.id, nombre: op.nombre, apartadoItemId })
// Crear LeadCaptura local para el apartado (Mi día los necesita)
try {
// Buscar el usuarioId de la oportunidad original para vincular el apartado
const opLocal = await prisma.leadCaptura.findFirst({ where: { leadId: op.id } })
await prisma.leadCaptura.create({
data: {
leadId: apartadoItemId,
board: 'APARTADO',
etapa: 'Pago Apartado',
nombreLead: op.nombre,
telefono: op.telefono || null,
email: op.email || null,
usuarioId: opLocal?.usuarioId ?? 'sistema',
oportunidadId: op.id,
mondayItemId: apartadoItemId,
pendienteSync: false,
},
})
} catch (e) { console.error('[APARTADO-ERR]', e.message?.slice(0,150)) }
} catch (err) {
resultado.errores.push({ oportunidadId: op.id, mensaje: err instanceof Error ? err.message : String(err) })
}

View File

@@ -312,9 +312,13 @@ export async function resumenMiDia(
const apartadosDeMisClientes = new Set(
clientes.map((c) => c.mondayApartadoId).filter((id): id is string => id !== null),
)
// Set de oportunidades mías (por LeadCaptura o por vendedorIds)
const miosOportunidadesIds = new Set(
capturas.filter((c) => c.oportunidadId).map((c) => c.oportunidadId),
)
const miosApartados = apartados.filter(
(a) =>
(esMio(a.vendedorIds, a.id) || apartadosDeMisClientes.has(a.id)) && !esEstadoFinalApartado(a.estado),
(esMio(a.vendedorIds, a.id) || apartadosDeMisClientes.has(a.id) || miosOportunidadesIds.has(a.id)) && !esEstadoFinalApartado(a.estado),
)
const [cambiosLeads, cambiosOportunidades, cambiosApartados] = await Promise.all([