fix(apartados): el apartado se crea al momento de dar Apartó

El endpoint POST /oportunidades/:id/etapa en 'Aparto' ahora garantiza la
creación del apartado antes de responder (asegurarApartado con reintentos:
Monday tarda ~1s en propagar la etapa). Antes dependía del webhook y Mis
apartados recargaba antes de que existiera. El webhook y el cron quedan
como red de seguridad para cambios hechos directo en Monday (dedup
compartido, idempotente).
This commit is contained in:
2026-09-05 01:21:18 +00:00
parent dc5e99ad98
commit b40b8d4627
3 changed files with 87 additions and 0 deletions

View File

@@ -704,3 +704,56 @@ describe('AutomatizacionesService.escaneoOportunidades', () => {
expect(state.mapa.get('apartado-creado:10')).toBeUndefined() // sin dedup: se reintenta en la próxima pasada
})
})
describe('AutomatizacionesService.asegurarApartado (botón Aparto de Mi día)', () => {
it('dedup: si ya existe el apartado, lo devuelve sin tocar Monday', async () => {
const monday = mondayMock([], [oportunidad('10', { etapa: 'Aparto' })])
const state = stateEnMemoria()
state.mapa.set('apartado-creado:10', 'apt-viejo')
const svc = crearServicio(monday, state)
const r = await svc.asegurarApartado('10', 3, 0)
expect(r).toBe('apt-viejo')
expect(monday.apartados).toEqual([])
})
it('crea el apartado en la primera pasada si la etapa ya se ve', async () => {
const monday = mondayMock([], [oportunidad('10', { etapa: 'Aparto' })])
const svc = crearServicio(monday, stateEnMemoria())
const r = await svc.asegurarApartado('10', 3, 0)
expect(r).toBe('apt-1')
expect(monday.apartados).toHaveLength(1)
})
it('reintenta cuando Monday aún no propaga la etapa (read-after-write)', async () => {
// La oportunidad se lee en 'Afluencia' en la primera pasada y en 'Aparto'
// en la segunda (así se comporta Monday ~1s después del cambio)
const op = oportunidad('10', { etapa: 'Afluencia' })
const oportunidades = [op]
const monday = mondayMock([], oportunidades)
const svc = crearServicio(monday, stateEnMemoria())
const original = monday.getOportunidades.bind(monday)
let llamadas = 0
monday.getOportunidades = async () => {
llamadas++
if (llamadas >= 2) op.etapa = 'Aparto'
return original()
}
const r = await svc.asegurarApartado('10', 3, 0)
expect(r).toBe('apt-1')
expect(llamadas).toBeGreaterThanOrEqual(2)
expect(monday.apartados).toHaveLength(1)
})
it('agota los reintentos y devuelve null si nunca se ve en Aparto', async () => {
const monday = mondayMock([], [oportunidad('10', { etapa: 'Cotizador' })])
const svc = crearServicio(monday, stateEnMemoria())
const r = await svc.asegurarApartado('10', 2, 0)
expect(r).toBeNull()
expect(monday.apartados).toEqual([])
})
})