From 50e6eca7dad1c4f710afb48b4d7cb7ab18b6e1f4 Mon Sep 17 00:00:00 2001 From: Consult AS Technology Date: Sun, 6 Sep 2026 08:26:03 +0000 Subject: [PATCH] fix(mi-dia): dedup capturas que ya aparecen en leads/oportunidades Cuando un lead se crea con Monday activo, aparece tanto en el tablero Monday (misLeads) como en LeadCaptura (misCapturas). Filtrar de 'misCapturas' los items cuyo leadId ya existe en misLeads/misOportunidades para evitar el duplicado visual que reportan los vendedores. 597 tests verdes. --- api-gateway/src/services/mi-dia-local.test.ts | 2 +- .../src/services/mi-dia.service.test.ts | 29 ++++--------------- api-gateway/src/services/mi-dia.service.ts | 19 ++++++++++-- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/api-gateway/src/services/mi-dia-local.test.ts b/api-gateway/src/services/mi-dia-local.test.ts index 62c055c..6737441 100644 --- a/api-gateway/src/services/mi-dia-local.test.ts +++ b/api-gateway/src/services/mi-dia-local.test.ts @@ -70,7 +70,7 @@ describe('resumenMiDiaLocal (Monday caído)', () => { expect(r.misOportunidades.items.map((o) => o.id)).toEqual(['loc_o1']) expect(r.misOportunidades.items[0]).toMatchObject({ etapa: 'Afluencia', desarrollo: 'SENDA', modeloInteres: '1R' }) expect(r.misApartados.map((a) => a.id)).toEqual(['loc_a1']) - expect(r.misCapturas).toHaveLength(6) + expect(r.misCapturas).toHaveLength(4) // loc_l1 y loc_o1 se excluyen (ya en misLeads/misOportunidades) // Lo que no existe en local va vacío/cero sin romper el front expect(r.misActividadesHoy).toEqual([]) expect(r.apartadosPorVencer).toEqual([]) diff --git a/api-gateway/src/services/mi-dia.service.test.ts b/api-gateway/src/services/mi-dia.service.test.ts index c94d618..cd68061 100644 --- a/api-gateway/src/services/mi-dia.service.test.ts +++ b/api-gateway/src/services/mi-dia.service.test.ts @@ -372,7 +372,7 @@ describe('resumenMiDia (GET /api/mi-dia/resumen)', () => { } }) - it('mis capturas: enriquecidas con la etapa/origen actual de la oportunidad en Monday', async () => { + it('mis capturas: items en misLeads/misOportunidades no se duplican en misCapturas', async () => { const monday = mondayMock({ oportunidades: [oportunidad({ id: '100', nombre: 'Ana López', etapa: 'Contactado', origen: 'WhatsApp', asesorIds: [OTRO_ID] })], }) @@ -380,20 +380,11 @@ describe('resumenMiDia (GET /api/mi-dia/resumen)', () => { { leadId: '100', nombreLead: 'Ana López', telefono: '6641112233', createdAt: new Date('2026-08-27T09:00:00Z') }, ] const r = await resumenMiDia(monday, vendedor, new Map(), capturas, [], AHORA) - // Aunque la afluencia quedó asignada a OTRO por round-robin, la captura es mía - expect(r.misCapturas).toEqual([ - { - leadId: '100', - nombre: 'Ana López', - telefono: '6641112233', - estado: 'Contactado', - origen: 'WhatsApp', - capturadoEn: '2026-08-27T09:00:00.000Z', - }, - ]) + // La captura ya aparece en misLeads (via esMio → idsCapturados), asi que no se duplica + expect(r.misCapturas).toEqual([]) }) - it('mis capturas: capturas rápidas cruzan contra el tablero Leads por id', async () => { + it('mis capturas: captura rapida no se duplica si ya esta en misLeads', async () => { const monday = mondayMock({ leads: [lead({ id: 'lead-9', nombre: 'Pepe Rápido', estado: 'Contactado', origen: 'Web', vendedorIds: [OTRO_ID] })], }) @@ -401,16 +392,8 @@ describe('resumenMiDia (GET /api/mi-dia/resumen)', () => { { leadId: 'lead-9', nombreLead: 'Pepe Rápido', telefono: '4771112233', createdAt: new Date('2026-08-27T09:00:00Z') }, ] const r = await resumenMiDia(monday, vendedor, new Map(), capturas, [], AHORA) - expect(r.misCapturas).toEqual([ - { - leadId: 'lead-9', - nombre: 'Pepe Rápido', - telefono: '4771112233', - estado: 'Contactado', - origen: 'Web', - capturadoEn: '2026-08-27T09:00:00.000Z', - }, - ]) + // La captura ya aparece en misLeads (via esMio → idsCapturados), asi que no se duplica + expect(r.misCapturas).toEqual([]) }) it('mis capturas: si el item ya no existe en ningún tablero, estado y origen van vacíos', async () => { diff --git a/api-gateway/src/services/mi-dia.service.ts b/api-gateway/src/services/mi-dia.service.ts index 94c570e..9920f05 100644 --- a/api-gateway/src/services/mi-dia.service.ts +++ b/api-gateway/src/services/mi-dia.service.ts @@ -400,6 +400,14 @@ export async function resumenMiDia( } }) .sort((a, b) => b.capturadoEn.localeCompare(a.capturadoEn)) + // Excluir de "Mis capturas" los que ya aparecen en "Mis leads" o "Mis + // oportunidades" para no duplicar visualmente cuando el lead existe en + // Monday Y tambien en LeadCaptura (caso creacion con Monday activo). + const idsEnOtrosTabs = new Set([ + ...misLeads.map((l) => l.id), + ...mios.map((o) => o.id), + ]) + const misCapturasSinDuplicados = misCapturas.filter((c) => !idsEnOtrosTabs.has(c.leadId)) // "Mis clientes" es local + cruce con Monday: el alta en progreso lleva // proyecto '', el alta completada lleva el proyecto lleno. estadoApartado @@ -457,7 +465,7 @@ export async function resumenMiDia( generadoEn: ahora.toISOString(), sinMapeoMonday: sinMapeo, misLeads, - misCapturas, + misCapturas: misCapturasSinDuplicados, misClientes, misActividadesHoy, apartadosPorVencer, @@ -661,6 +669,13 @@ export function resumenMiDiaLocal( pendienteSync: c.pendienteSync, })) .sort((a, b) => b.capturadoEn.localeCompare(a.capturadoEn)) + // Excluir de "Mis capturas" los que ya aparecen en "Mis leads" u "Mis + // oportunidades" para no duplicar visualmente. + const idsEnOtrosTabsLocal = new Set([ + ...misLeads.map((l) => l.id), + ...itemsOportunidades.map((o) => o.id), + ]) + const misCapturasSinDuplicadosLocal = misCapturas.filter((c) => !idsEnOtrosTabsLocal.has(c.leadId)) const etapaApartadoPorId = new Map(apartadosLocales.map((a) => [a.leadId, a.etapa])) const misClientes: ClienteMiDia[] = clientes @@ -680,7 +695,7 @@ export function resumenMiDiaLocal( generadoEn: ahora.toISOString(), sinMapeoMonday: usuario.mondayUserId === null, misLeads, - misCapturas, + misCapturas: misCapturasSinDuplicadosLocal, misClientes, misActividadesHoy: [], // no hay tabla local de actividades apartadosPorVencer: [], // los apartados locales aún no guardan fecha límite