diff --git a/panel.html b/panel.html index 383e9ec..cbed5cb 100644 --- a/panel.html +++ b/panel.html @@ -193,32 +193,49 @@ function processDashboard(scrapedList, activeList) { const todayStr = new Date().toISOString().split('T')[0]; - // 1. LIMPIAR DATOS - // Filtramos los archivados y los que ya están importados del Scraped (porque los importados ya vienen en activeList) - const trueScraped = scrapedList.filter(s => s.status !== 'archived' && s.status !== 'imported'); - const trueActive = activeList.filter(s => s.status !== 'archived'); - - // Unimos todo en una gran lista para los gráficos globales - const allServices = [...trueScraped, ...trueActive]; + // 1. FUSIÓN INTELIGENTE SIN DUPLICADOS (Usamos un Map basado en el ID) + const allServicesMap = new Map(); - // --- CÁLCULO DE KPIs --- + // Primero cargamos los servicios que vienen de la bandeja + scrapedList.forEach(s => { + if (s.status !== 'archived') { + allServicesMap.set(s.id, s); + } + }); + + // Luego sobrescribimos/agregamos con los de activos (que traen info más actualizada sobre el operario) + activeList.forEach(s => { + if (s.status !== 'archived') { + if (allServicesMap.has(s.id)) { + // Si ya existe, combinamos para no perder datos + allServicesMap.set(s.id, { ...allServicesMap.get(s.id), ...s }); + } else { + allServicesMap.set(s.id, s); + } + } + }); + + // Convertimos el mapa final en una lista pura y sin duplicados + const allServices = Array.from(allServicesMap.values()); + + // --- CÁLCULO DE KPIs CORRECTO --- - // 1. Total (La suma de los dos mundos) + // 1. Total (Sin duplicados) const totalActive = allServices.length; - // 2. Sin Asignar (Los de scraped que no están en rueda) - const unassignedCount = trueScraped.filter(s => s.automation_status !== 'in_progress').length; + // 2. Sin Asignar (Nadie asignado y no está buscando en la rueda) + const unassignedCount = allServices.filter(s => !s.assigned_name && s.automation_status !== 'in_progress').length; - // 3. En Rueda (Los de scraped buscando operario) - const queueCount = trueScraped.filter(s => s.automation_status === 'in_progress').length; + // 3. En Rueda (Nadie asignado pero SÍ está en la rueda) + const queueCount = allServices.filter(s => !s.assigned_name && s.automation_status === 'in_progress').length; - // 4. Asignados sin cita (Los activos que no tienen fecha agendada) - const pendingCount = trueActive.filter(s => !s.raw_data.scheduled_date || s.raw_data.scheduled_date === "").length; + // 4. Asignados sin cita (Tienen operario asignado pero no hay fecha) + const pendingCount = allServices.filter(s => s.assigned_name && (!s.raw_data.scheduled_date || s.raw_data.scheduled_date === "")).length; - // 5. Citas de hoy (Los activos con fecha de hoy) - const todayVisits = trueActive.filter(s => s.raw_data.scheduled_date === todayStr); + // 5. Citas de hoy (La fecha es hoy) + const todayVisits = allServices.filter(s => s.raw_data && s.raw_data.scheduled_date === todayStr); - // 6. Urgencias (Cualquiera que tenga la palabra URGENTE) + // 6. Urgencias (Cualquiera marcado como urgente) const urgentVisits = allServices.filter(s => { const raw = s.raw_data || {}; return raw['Urgente'] === 'Sí' || raw['Urgente'] === 'true' || raw['URGENTE'] === 'SI'; @@ -358,7 +375,7 @@ container.innerHTML = latest.map(s => { const name = s.raw_data['Nombre Cliente'] || s.raw_data['CLIENTE'] || "Nuevo Cliente"; - const isNew = s.status === 'pending'; + const isNew = !s.assigned_name && s.automation_status !== 'in_progress'; const icon = isNew ? '' : ''; return `