feat(mi-dia): vendedores solo-app con cuenta Monday compartida

- Las listas personales de Mi día (leads, oportunidades, apartados) se
  calculan por captura local (LeadCaptura/Cliente + mapping
  LeadOportunidad) ADEMÁS de la columna people de Monday: la app ya es
  totalmente usable sin cuenta Monday
- Config MONDAY_VENDEDOR_COMPARTIDO_ID: cuando el usuario está ligado a
  la cuenta compartida, la columna people se ignora para 'lo mío' (si
  no, todos verían los leads de todos)
- scripts/vincular-vendedores-compartido.js: vincula todos los usuarios
  con rol vendedor a la cuenta Monday compartida
- Tests: 478 API, verde; verificado en vivo con usuario sin Monday
This commit is contained in:
2026-09-05 05:37:52 +00:00
parent b40b8d4627
commit af2fb10956
6 changed files with 171 additions and 24 deletions

View File

@@ -562,3 +562,65 @@ describe('clasificadores de estado', () => {
expect(esEstadoFinalApartado('Pago Apartado')).toBe(false)
})
})
describe('resumenMiDia — cuenta compartida / uso solo-app (sin Monday)', () => {
const COMPARTIDO = 999000111
it('sin vínculo Monday: ve lo que capturó en la app (registro local)', async () => {
const monday = mondayMock({
leads: [
lead({ id: 'l1' }), // capturado por mí (abajo)
lead({ id: 'l2' }), // no es mío
],
oportunidades: [oportunidad({ id: 'o1', updatedAt: '2026-08-28T10:00:00Z' })], // capturada por mí
})
const capturas = [
{ leadId: 'l1', nombreLead: 'Lead l1', telefono: null, createdAt: new Date('2026-08-27') },
{ leadId: 'o1', nombreLead: 'Lead o1', telefono: null, createdAt: new Date('2026-08-27') },
]
const r = await resumenMiDia(monday, sinMapeo, new Map(), capturas, [], AHORA)
expect(r.misLeads.map((l) => l.id)).toEqual(['o1', 'l1'])
expect(r.misOportunidades.items.map((o) => o.id)).toEqual(['o1'])
})
it('cuenta compartida: NO ve lo asignado a la cuenta compartida, solo su captura local', async () => {
const compartido: UsuarioMiDia = { nombre: 'Vendedor Piso', rol: 'vendedor', mondayUserId: COMPARTIDO }
const monday = mondayMock({
leads: [
lead({ id: 'l1', vendedorIds: [COMPARTIDO] }), // asignado a la cuenta compartida, capturado por otro
lead({ id: 'l2', vendedorIds: [COMPARTIDO] }), // asignado a la compartida, capturado por MÍ
],
})
const capturas = [{ leadId: 'l2', nombreLead: 'Lead l2', telefono: null, createdAt: new Date('2026-08-27') }]
const r = await resumenMiDia(monday, compartido, new Map(), capturas, [], AHORA, COMPARTIDO)
expect(r.misLeads.map((l) => l.id)).toEqual(['l2']) // l1 queda fuera
})
it('cuenta NO compartida: ve capturas + asignados (comportamiento de siempre)', async () => {
const monday = mondayMock({
leads: [
lead({ id: 'l1', vendedorIds: [MI_ID] }), // asignado a mí
lead({ id: 'l2', vendedorIds: [OTRO_ID] }), // capturado por mí (abajo)
lead({ id: 'l3', vendedorIds: [OTRO_ID] }), // ni asignado ni capturado
],
})
const capturas = [{ leadId: 'l2', nombreLead: 'Lead l2', telefono: null, createdAt: new Date('2026-08-27') }]
const r = await resumenMiDia(monday, vendedor, new Map(), capturas, [], AHORA, COMPARTIDO)
expect(r.misLeads.map((l) => l.id).sort()).toEqual(['l1', 'l2'])
})
it('mis apartados incluye los ligados a mis altas de cliente aunque el Vendedor sea la cuenta compartida', async () => {
const compartido: UsuarioMiDia = { nombre: 'Vendedor Piso', rol: 'vendedor', mondayUserId: COMPARTIDO }
const monday = mondayMock({
apartados: [
apartado({ id: 'p1', vendedorIds: [COMPARTIDO] }), // apartado de MI alta (abajo)
apartado({ id: 'p2', vendedorIds: [COMPARTIDO] }), // apartado de otro
],
})
const clientes = [
{ id: 'c1', nombreCompleto: 'Cliente p1', proyecto: 'SENDA', unidadCodigo: 'U-1', mondayApartadoId: 'p1', createdAt: new Date('2026-08-27') },
]
const r = await resumenMiDia(monday, compartido, new Map(), [], clientes, AHORA, COMPARTIDO)
expect(r.misApartados.map((a) => a.id)).toEqual(['p1'])
})
})