diff --git a/servicios2.html b/servicios2.html
index f1beb8d..4e6101b 100644
--- a/servicios2.html
+++ b/servicios2.html
@@ -27,6 +27,7 @@
.border-col-2 { border-left-color: #f59e0b; } /* Ambar: Sin Cita */
.border-col-3 { border-left-color: #3b82f6; } /* Azul: Pendiente Inicio */
.border-col-4 { border-left-color: #10b981; } /* Verde: Trabajando */
+ .border-col-5 { border-left-color: #a855f7; } /* Morado: Incidencias */
/* Estilos base para formularios y modales */
.input-modern { @apply w-full bg-slate-50 border border-slate-200 px-4 py-3 rounded-xl text-sm font-semibold text-slate-700 outline-none transition-all focus:border-blue-500 focus:bg-white focus:ring-2 focus:ring-blue-100; }
@@ -89,46 +90,46 @@
-
+
@@ -588,15 +589,50 @@
return res.length > 5 ? res.charAt(0).toUpperCase() + res.slice(1) : texto;
}
+ // =====================================
+ // MOTOR KANBAN E INTELIGENCIA DE ESTADOS
// =====================================
- // MOTOR KANBAN
- // =====================================
+
+ function getServiceStateInfo(s) {
+ const raw = s.raw_data || {};
+ const dbStat = raw.status_operativo;
+
+ if (!s.assigned_name && (s.automation_status === 'in_progress' || s.automation_status === 'failed')) {
+ return { id: 'bolsa', name: s.automation_status === 'in_progress' ? 'Buscando Operario' : 'Fallo en Bolsa', color: s.automation_status === 'in_progress' ? 'amber' : 'red', is_final: false };
+ }
+
+ if (!s.assigned_name && (!dbStat || dbStat === 'sin_asignar')) {
+ return systemStatuses.find(st => st.name.toLowerCase().includes('pendiente de asignar')) || systemStatuses[0] || {id: 'sin_asignar', name: 'Sin Asignar', color: 'gray'};
+ }
+
+ const foundById = systemStatuses.find(st => String(st.id) === String(dbStat));
+ if (foundById) return foundById;
+
+ if (s.assigned_name && (!raw.scheduled_date || raw.scheduled_date === "")) {
+ const asignado = systemStatuses.find(st => st.name.toLowerCase() === 'asignado');
+ const esperando = systemStatuses.find(st => st.name.toLowerCase().includes('esperando'));
+ if (dbStat === 'esperando_cliente' && esperando) return esperando;
+ if (asignado) return asignado;
+ }
+
+ const stLower = String(dbStat).toLowerCase();
+ if (stLower === 'citado' || (s.assigned_name && raw.scheduled_date && !dbStat)) {
+ const citado = systemStatuses.find(st => st.name.toLowerCase().includes('citado'));
+ if(citado) return citado;
+ }
+ if (stLower === 'de_camino') return systemStatuses.find(st => st.name.toLowerCase().includes('camino')) || {name: 'De Camino', color: 'blue'};
+ if (stLower === 'trabajando') return systemStatuses.find(st => st.name.toLowerCase().includes('trabajando')) || {name: 'Trabajando', color: 'emerald'};
+ if (stLower === 'incidencia') return systemStatuses.find(st => st.name.toLowerCase().includes('incidencia')) || {name: 'Incidencia', color: 'purple'};
+
+ return { id: 'unknown', name: 'Desconocido', color: 'gray', is_final: false };
+ }
+
function renderKanban() {
const searchTerm = document.getElementById('searchFilter').value.toLowerCase();
const selectedOp = document.getElementById('opFilter').value;
const weekValue = document.getElementById('weekFilter').value;
- const cols = { unassigned: [], unscheduled: [], pending_start: [], working: [] };
+ const cols = { c1: [], c2: [], c3: [], c4: [], c5: [] };
localData.forEach(s => {
if (s.status === 'archived' || s.provider === 'SYSTEM_BLOCK') return;
@@ -618,40 +654,46 @@
if (!raw.scheduled_date || !isDateInWeekString(raw.scheduled_date, weekValue)) return;
}
- const dbStat = raw.status_operativo;
- const statusObj = systemStatuses.find(st => String(st.id) === String(dbStat));
- const stName = (statusObj?.name || "").toLowerCase();
+ // INTELIGENCIA DE ESTADOS
+ const stateInfo = getServiceStateInfo(s);
+ s._stateInfo = stateInfo; // Guardamos para la tarjeta
+ const stName = (stateInfo.name || "").toLowerCase();
- // Filtro de Estado (Pastillas superiores)
- if (activeStatusFilter !== "ALL" && String(statusObj?.id) !== activeStatusFilter) return;
+ // Filtro de Pastillas
+ if (activeStatusFilter !== "ALL" && String(stateInfo.id) !== activeStatusFilter) return;
- // Si está finalizado o anulado, NO SE MUESTRA en el tablero Kanban
- if (statusObj?.is_final || stName.includes('finaliza') || stName.includes('anulad') || stName.includes('terminad')) return;
+ // Ocultar finalizados
+ if (stateInfo.is_final || stName.includes('finaliza') || stName.includes('anulad') || stName.includes('terminad')) return;
const isWorking = stName.includes('trabaja') || stName.includes('camino');
const hasDate = raw.scheduled_date && raw.scheduled_date.trim() !== "";
+ const isIncident = stName.includes('incidencia') || stName.includes('pausa') || stName.includes('espera');
- // REPARTO KANBAN INTELIGENTE
+ // REPARTO KANBAN INTELIGENTE (5 COLUMNAS)
if (!s.assigned_to) {
- cols.unassigned.push(s);
+ cols.c1.push(s);
+ } else if (isIncident) {
+ cols.c5.push(s);
} else if (!hasDate) {
- cols.unscheduled.push(s);
+ cols.c2.push(s);
} else if (!isWorking) {
- cols.pending_start.push(s);
+ cols.c3.push(s);
} else {
- cols.working.push(s);
+ cols.c4.push(s);
}
});
- document.getElementById('count-unassigned').innerText = cols.unassigned.length;
- document.getElementById('count-unscheduled').innerText = cols.unscheduled.length;
- document.getElementById('count-pending-start').innerText = cols.pending_start.length;
- document.getElementById('count-working').innerText = cols.working.length;
+ document.getElementById('count-c1').innerText = cols.c1.length;
+ document.getElementById('count-c2').innerText = cols.c2.length;
+ document.getElementById('count-c3').innerText = cols.c3.length;
+ document.getElementById('count-c4').innerText = cols.c4.length;
+ document.getElementById('count-c5').innerText = cols.c5.length;
- document.getElementById('col-unassigned').innerHTML = cols.unassigned.map(s => buildCard(s, 1)).join('');
- document.getElementById('col-unscheduled').innerHTML = cols.unscheduled.map(s => buildCard(s, 2)).join('');
- document.getElementById('col-pending-start').innerHTML = cols.pending_start.map(s => buildCard(s, 3)).join('');
- document.getElementById('col-working').innerHTML = cols.working.map(s => buildCard(s, 4)).join('');
+ document.getElementById('col-1').innerHTML = cols.c1.map(s => buildCard(s, 1)).join('');
+ document.getElementById('col-2').innerHTML = cols.c2.map(s => buildCard(s, 2)).join('');
+ document.getElementById('col-3').innerHTML = cols.c3.map(s => buildCard(s, 3)).join('');
+ document.getElementById('col-4').innerHTML = cols.c4.map(s => buildCard(s, 4)).join('');
+ document.getElementById('col-5').innerHTML = cols.c5.map(s => buildCard(s, 5)).join('');
lucide.createIcons();
}
@@ -674,10 +716,9 @@
if (hasLock) alerts += `
`;
if (hasEyes) alerts += `
`;
- // Identificar el estado exacto actual para ponerle color a la etiqueta
- const dbStat = raw.status_operativo;
- const statusObj = systemStatuses.find(st => String(st.id) === String(dbStat)) || systemStatuses[0];
- const cMap = colorDict[statusObj?.color] || colorDict['gray'];
+ // Identificar el estado exacto actual leyendo la IA guardada
+ const stateInfo = s._stateInfo || {name: 'Desconocido', color: 'gray'};
+ const cMap = colorDict[stateInfo.color] || colorDict['gray'];
// Pie de tarjeta dinámico
let bottomInfo = '';