(igual que el ingest). * * Parámetros: * desde Y-m-d opcional (por defecto: hoy) * hasta Y-m-d opcional (por defecto: igual a desde) * documento string opcional — solo ese paciente * * Respuesta: * { ok, desde, hasta, total, turnos: [ { fecha, turno, estado_turno, * numero_documento, paciente, examenes: [cod_legacy…], * muestras: [ { tipo, nombre_tipo, estado, motivo_rechazo, * recibida_at, recibida_por } ] } ] } * * Solo lectura: no crea, no modifica, no borra. */ ob_start(); require_once __DIR__ . '/../../config/config.php'; header('Content-Type: application/json; charset=utf-8'); function salir(array $r, int $code = 200): void { ob_clean(); http_response_code($code); echo json_encode($r, JSON_UNESCAPED_UNICODE); exit; } if ($_SERVER['REQUEST_METHOD'] !== 'GET') { salir(['ok' => false, 'error' => 'Método no permitido'], 405); } // ── Autenticación por API key, idéntica al ingest ──────────────────────── $keyHeader = $_SERVER['HTTP_X_LAB_KEY'] ?? $_SERVER['HTTP_X_LAB_SYNC_KEY'] ?? ''; if (!defined('LAB_SYNC_KEY') || !$keyHeader || !hash_equals(LAB_SYNC_KEY, $keyHeader)) { salir(['ok' => false, 'error' => 'No autorizado'], 401); } // ── Parámetros ─────────────────────────────────────────────────────────── $hoy = date('Y-m-d'); $desde = $_GET['desde'] ?? $hoy; $hasta = $_GET['hasta'] ?? $desde; if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $desde)) $desde = $hoy; if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $hasta)) $hasta = $desde; if ($desde > $hasta) [$desde, $hasta] = [$hasta, $desde]; // Tope de 31 días por consulta: es un endpoint de sincronización, no de archivo if ((strtotime($hasta) - strtotime($desde)) > 31 * 86400) { salir(['ok' => false, 'error' => 'Rango máximo: 31 días'], 400); } $documento = trim($_GET['documento'] ?? ''); $pdo = Database::getInstance()->getConnection(); // ── Turnos del rango con paciente y solicitud ──────────────────────────── $where = "DATE(t.creado_at) BETWEEN :desde AND :hasta AND ts.id IS NOT NULL"; $binds = ['desde' => $desde, 'hasta' => $hasta]; if ($documento !== '') { $where .= " AND p.numero_documento = :doc"; $binds['doc'] = $documento; } $stmt = $pdo->prepare( "SELECT t.id AS turno_id, t.codigo AS turno, t.estado AS estado_turno, DATE(t.creado_at) AS fecha, ts.id AS solicitud_id, p.numero_documento, p.nombre_completo AS paciente FROM turnero_turnos t JOIN turnero_solicitudes ts ON ts.turno_id = t.id LEFT JOIN lab_pacientes p ON p.id = ts.paciente_id WHERE {$where} ORDER BY t.creado_at" ); $stmt->execute($binds); $turnos = $stmt->fetchAll(PDO::FETCH_ASSOC); if (!$turnos) { salir(['ok' => true, 'desde' => $desde, 'hasta' => $hasta, 'total' => 0, 'turnos' => []]); } $solIds = array_column($turnos, 'solicitud_id'); $ph = implode(',', array_fill(0, count($solIds), '?')); // ── Muestras de esas solicitudes, con nombre del tipo y quién recibió ──── $stmtM = $pdo->prepare( "SELECT m.solicitud_id, m.tipo_muestra AS tipo, m.estado, m.motivo_rechazo, m.recibida_at, u.full_name AS recibida_por, tm.nombre AS nombre_tipo FROM turnero_muestras m LEFT JOIN admin_users u ON u.id = m.recibida_por LEFT JOIN lab_tipos_muestra tm ON tm.codigo COLLATE utf8mb4_unicode_ci = m.tipo_muestra COLLATE utf8mb4_unicode_ci WHERE m.solicitud_id IN ({$ph})" ); $stmtM->execute($solIds); $muestrasPorSol = []; foreach ($stmtM->fetchAll(PDO::FETCH_ASSOC) as $m) { $sid = (int) $m['solicitud_id']; unset($m['solicitud_id']); $muestrasPorSol[$sid][] = $m; } // ── Exámenes (códigos legacy, que son los que el Data Lab entiende) ────── $stmtE = $pdo->prepare( "SELECT i.solicitud_id, COALESCE(NULLIF(et.codigo_legacy,''), et.codigo) AS cod FROM turnero_examen_items i JOIN exam_tipos et ON et.id = i.exam_tipo_id WHERE i.solicitud_id IN ({$ph})" ); $stmtE->execute($solIds); $examenesPorSol = []; foreach ($stmtE->fetchAll(PDO::FETCH_ASSOC) as $e) { $examenesPorSol[(int) $e['solicitud_id']][] = $e['cod']; } $salida = []; foreach ($turnos as $t) { $sid = (int) $t['solicitud_id']; $salida[] = [ 'fecha' => $t['fecha'], 'turno' => $t['turno'], 'estado_turno' => $t['estado_turno'], 'numero_documento' => $t['numero_documento'], 'paciente' => $t['paciente'], 'examenes' => $examenesPorSol[$sid] ?? [], 'muestras' => $muestrasPorSol[$sid] ?? [], ]; } salir(['ok' => true, 'desde' => $desde, 'hasta' => $hasta, 'total' => count($salida), 'turnos' => $salida]);