feat(mi-dia): gate de afluencia para apartar, pestana Afluencia en bitacora, cita cliente con fecha en calendario, filtros por desarrollo/origen corregidos, rangos salariales nuevos y soporte como acceso directo

This commit is contained in:
2026-09-25 10:23:24 +00:00
parent 8a5db114ec
commit 7f663208a0
19 changed files with 381 additions and 501 deletions

View File

@@ -1,5 +1,6 @@
import { randomUUID } from 'node:crypto'
import { AppError, NotFoundError } from '../utils/errors.js'
import { afluenciaCompleta } from '../config/vocabulario.js'
import { claveApartadoCreado } from './automatizaciones.service.js'
import { calcularClienteClave } from './recordatorio-vendedor.service.js'
import { prisma } from './prisma.js'
@@ -229,9 +230,10 @@ export class CrmLocalService {
opciones: { fecha?: string | undefined; usuarioId?: string | undefined; sombra?: boolean | undefined } = {},
): Promise<void> {
await this.filaLocal(itemId, board, opciones.usuarioId, opciones.sombra ?? false)
// Guardar fechaCita en datosJson para que la oportunidad la muestre en el calendario
// Guardar fechaCita en datosJson (oportunidad y apartado) para que la
// muestre Mi día y el calendario
const updateData: Record<string, unknown> = { etapa: label, pendienteSync: true }
if (opciones.fecha !== undefined && board === 'OPORTUNIDADES') {
if (opciones.fecha !== undefined && (board === 'OPORTUNIDADES' || board === 'APARTADO')) {
const existente = await prisma.leadCaptura.findUnique({ where: { leadId: itemId }, select: { datosJson: true } })
let datos: Record<string, unknown> = {}
if (existente?.datosJson) {
@@ -347,6 +349,11 @@ export class CrmLocalService {
!esIdLocal(oportunidadIdLocal),
)
// Regla de negocio: no se aparta sin la afluencia completa del cliente
if (!afluenciaCompleta(oportunidad.datosJson)) {
throw new AppError(400, 'Primero debes capturar la afluencia del cliente (botón Afluencia) antes de apartar')
}
const clave = claveApartadoCreado(oportunidadIdLocal)
const previo = await prisma.automatizacionState.findUnique({ where: { clave } })
if (previo !== null) {