Sin turno activo
Haga clic en de un turno para llamarlo, o use "Llamar siguiente"getConnection(); $_dispRow = null; // 1. Chequeo por token de navegador (cookie) $_devToken = trim($_COOKIE['turnero_token'] ?? ''); if ($_devToken) { $_s = $_dispPdo->prepare( "SELECT td.lugar_id, td.nombre, tl.tipo FROM turnero_dispositivos td JOIN turnero_lugares tl ON tl.id = td.lugar_id WHERE td.token = ? AND td.activo = 1 LIMIT 1" ); $_s->execute([$_devToken]); $_dispRow = $_s->fetch(PDO::FETCH_ASSOC) ?: null; } // 2. Fallback por IP if (!$_dispRow) { $_clientIp = trim(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'] ?? '')[0]); $_s = $_dispPdo->prepare( "SELECT td.lugar_id, td.nombre, tl.tipo FROM turnero_dispositivos td JOIN turnero_lugares tl ON tl.id = td.lugar_id WHERE td.ip = ? AND td.token IS NULL AND td.activo = 1 LIMIT 1" ); $_s->execute([$_clientIp]); $_dispRow = $_s->fetch(PDO::FETCH_ASSOC) ?: null; } if ($_dispRow) { $_SESSION['turnero_dispositivo'] = $_dispRow; $_forzado = (int)$_dispRow['lugar_id']; if ($_dispRow['tipo'] !== 'recepcion') { header('Location: ' . BASE_URL . 'erp.php?m=turnero&v=lugar&lugar_id=' . $_forzado); exit; } if ((int)($_GET['desk_id'] ?? 0) !== $_forzado) { header('Location: ' . BASE_URL . 'erp.php?m=turnero&v=recepcion&desk_id=' . $_forzado); exit; } $_recepForzado = $_forzado; } } catch (\Throwable $_) {} // Restricción a nivel de usuario (turnero_lugar_id en admin_users) if (!$_recepForzado) { $_userDesk = (int)($_SESSION['admin_user']['turnero_lugar_id'] ?? 0); if ($_userDesk) { if ((int)($_GET['desk_id'] ?? 0) !== $_userDesk) { header('Location: ' . BASE_URL . 'erp.php?m=turnero&v=recepcion&desk_id=' . $_userDesk); exit; } $_recepForzado = $_userDesk; } } // Cargar catálogos para la ficha try { $pdo = Database::getInstance()->getConnection(); $lugarRecepcion = $pdo->query( "SELECT id, nombre FROM turnero_lugares WHERE tipo='recepcion' AND activo=1 ORDER BY sort_order LIMIT 1" )->fetch(PDO::FETCH_ASSOC); // Destinos agrupados: un representante por grupo_id, individuales si grupo_id=NULL $lugaresDestino = $pdo->query( "SELECT MIN(id) AS id, CASE WHEN grupo_id IS NOT NULL THEN 'Toma de Muestras' ELSE nombre END AS nombre, grupo_id FROM turnero_lugares WHERE tipo='muestras' AND activo=1 GROUP BY COALESCE(grupo_id, id) ORDER BY MIN(sort_order)" )->fetchAll(PDO::FETCH_ASSOC); $lugarMuestras = $lugaresDestino[0] ?? null; $examenes = $pdo->query( "SELECT et.id, et.codigo, et.nombre, et.categoria, et.cups, et.genero_permitido, IF(COUNT(etc.formulario_id) > 0, 1, 0) AS tiene_consentimiento FROM exam_tipos et LEFT JOIN exam_tipo_consentimientos etc ON etc.exam_tipo_id = et.id WHERE et.activo = 1 GROUP BY et.id ORDER BY et.categoria, et.nombre" )->fetchAll(PDO::FETCH_ASSOC); // Agrupar exámenes por categoría $examenesAgrupados = []; foreach ($examenes as $ex) { $cat = $ex['categoria'] ?: 'General'; $examenesAgrupados[$cat][] = $ex; } // Escritorio de recepción (vía ?desk_id=X) $deskId = (int)($_GET['desk_id'] ?? 0); $desk = null; $desksRecepcion = $pdo->query( "SELECT id, nombre FROM turnero_lugares WHERE tipo='recepcion' AND activo=1 ORDER BY sort_order" )->fetchAll(PDO::FETCH_ASSOC); if ($deskId) { foreach ($desksRecepcion as $d) { if ($d['id'] === $deskId) { $desk = $d; break; } } if (!$desk) { $deskId = 0; } } // Si solo hay un escritorio, asignarlo automáticamente if (!$deskId && count($desksRecepcion) === 1) { $desk = $desksRecepcion[0]; $deskId = (int)$desk['id']; } $prioridades = $pdo->query( "SELECT codigo, nombre, color FROM turnero_prioridades WHERE activo=1 ORDER BY orden_peso" )->fetchAll(PDO::FETCH_ASSOC); } catch (\Throwable $e) { $lugares = []; $examenesAgrupados = []; $deskId = 0; $desk = null; $lugarRecepcion = null; $lugarMuestras = null; $prioridades = []; } $deskNombre = $desk['nombre'] ?? null; // null = vista genérica $adminNombre = $_SESSION['admin_user']['full_name'] ?? $_SESSION['admin_user']['username'] ?? 'Operador'; ?>
Sin turno activo
Haga clic en de un turno para llamarlo, o use "Llamar siguiente"