fix(admin): reasignar mueve toda la cadena del cliente (lead+oportunidad+apartado) y sus actividades pendientes; 404 si el id no existe
This commit is contained in:
@@ -532,6 +532,62 @@ export class CrmLocalService {
|
||||
.slice(0, 15)
|
||||
.map(({ orden: _orden, ...resto }) => resto)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reasignación en cadena (solo admin): mueve el registro y TODA su cadena
|
||||
* al nuevo vendedor. Un cliente puede tener hasta 3 filas (lead →
|
||||
* oportunidad → apartado) y cada una tiene su propio leadId; reasignar sólo
|
||||
* la fila tocada dejaba al cliente "partido" entre dos vendedores (el lead
|
||||
* con uno y la oportunidad/apartado con el otro). También pasan las
|
||||
* actividades PENDIENTES (calendario); las completadas quedan como
|
||||
* historial del vendedor original. Devuelve cuántas filas se movieron.
|
||||
*/
|
||||
async reasignarCadena(itemId: string, usuarioId: string): Promise<number> {
|
||||
const origen = await prisma.leadCaptura.findUnique({ where: { leadId: itemId } })
|
||||
if (!origen) throw new NotFoundError('Lead no encontrado')
|
||||
|
||||
const ids = new Set<string>([itemId])
|
||||
let oportunidadId: string | null = null
|
||||
if (origen.board === 'LEADS') {
|
||||
oportunidadId = origen.oportunidadId
|
||||
} else if (origen.board === 'OPORTUNIDADES') {
|
||||
oportunidadId = itemId
|
||||
} else if (origen.board === 'APARTADO') {
|
||||
// Cadena inversa: el estado 'apartado-creado:{O}' apunta a este apartado
|
||||
const estado = await prisma.automatizacionState.findFirst({
|
||||
where: { clave: { startsWith: 'apartado-creado:' }, valor: itemId },
|
||||
})
|
||||
oportunidadId = estado?.clave.slice('apartado-creado:'.length) ?? null
|
||||
}
|
||||
|
||||
if (oportunidadId !== null) {
|
||||
ids.add(oportunidadId)
|
||||
// El lead origen (tabla LEADS) apunta a la oportunidad con su columna
|
||||
const lead = await prisma.leadCaptura.findFirst({
|
||||
where: { board: 'LEADS', oportunidadId },
|
||||
select: { leadId: true },
|
||||
})
|
||||
if (lead) ids.add(lead.leadId)
|
||||
// El apartado cuelga de la oportunidad por la clave de automatización
|
||||
const apartado = await prisma.automatizacionState.findUnique({
|
||||
where: { clave: claveApartadoCreado(oportunidadId) },
|
||||
})
|
||||
if (apartado) ids.add(apartado.valor)
|
||||
}
|
||||
|
||||
const listaIds = [...ids]
|
||||
const resultados = await prisma.$transaction([
|
||||
prisma.leadCaptura.updateMany({
|
||||
where: { leadId: { in: listaIds } },
|
||||
data: { usuarioId },
|
||||
}),
|
||||
prisma.recordatorioVendedor.updateMany({
|
||||
where: { leadId: { in: listaIds }, completado: false },
|
||||
data: { usuarioId },
|
||||
}),
|
||||
])
|
||||
return resultados[0].count
|
||||
}
|
||||
}
|
||||
|
||||
/** Singleton usado por los controllers (los tests instancian el suyo o mockean prisma) */
|
||||
|
||||
Reference in New Issue
Block a user