From e595f5e5695287fbd3e3e625ea7e1fcffaf56636 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Fri, 17 Jul 2026 15:42:56 -0500 Subject: [PATCH] fix: add db() to ingest_paciente; get_examenes_rips and recepcion updates Co-Authored-By: Claude Sonnet 4.6 --- api/lab/get_examenes_rips.php | 121 ++++++++++++++---- api/lab/ingest_paciente.php | 4 + .../20260716_rips_examenes_pendientes.sql | 12 ++ modules/turnero/views/recepcion.php | 30 ++++- 4 files changed, 138 insertions(+), 29 deletions(-) create mode 100644 migrations/20260716_rips_examenes_pendientes.sql diff --git a/api/lab/get_examenes_rips.php b/api/lab/get_examenes_rips.php index f089086..361ba3c 100644 --- a/api/lab/get_examenes_rips.php +++ b/api/lab/get_examenes_rips.php @@ -10,29 +10,52 @@ requireMethod('GET'); $cedula = trim($_GET['cedula'] ?? ''); if (!$cedula) jsonError('cedula requerida', 400); -$ripsUrl = defined('RIPS_MANAGER_URL') ? rtrim(RIPS_MANAGER_URL, '/') : ''; -if (!$ripsUrl) jsonError('RIPS_MANAGER_URL no configurado en el servidor', 503); +// ── 1. Buscar en cache local (exámenes enviados por el scheduler de RIPS) ───── +$examenes = []; +$fuenteCache = false; -// Llamada server-to-server al RIPS Manager -$url = $ripsUrl . '/pacientes/examenes?cedula=' . urlencode($cedula); -$ctx = stream_context_create([ - 'http' => [ - 'method' => 'GET', - 'header' => 'X-Lab-Key: ' . LAB_SYNC_KEY . "\r\n", - 'timeout' => 8, - 'ignore_errors' => true, - ], -]); +$cacheRow = db()->prepare( + "SELECT datos, recepcion_id, hora_recepcion + FROM rips_examenes_pendientes + WHERE numero_documento = ? + AND DATE(created_at) = CURDATE() + AND created_at >= NOW() - INTERVAL 30 MINUTE + ORDER BY created_at DESC + LIMIT 1" +); +$cacheRow->execute([$cedula]); +$cache = $cacheRow->fetch(PDO::FETCH_ASSOC); -$resp = @file_get_contents($url, false, $ctx); -if ($resp === false) jsonError('No se pudo conectar con RIPS Manager', 503); - -$data = json_decode($resp, true); -if (!($data['ok'] ?? false)) { - jsonError($data['error'] ?? 'Error en RIPS Manager', 502); +if ($cache) { + $examenes = json_decode($cache['datos'], true) ?: []; + $fuenteCache = true; } -$examenes = $data['examenes'] ?? []; +// ── 2. Si no hay cache, consultar RIPS Manager ──────────────────────────────── +if (!$examenes) { + $ripsUrl = defined('RIPS_MANAGER_URL') ? rtrim(RIPS_MANAGER_URL, '/') : ''; + if (!$ripsUrl) jsonError('RIPS_MANAGER_URL no configurado en el servidor', 503); + + $url = $ripsUrl . '/pacientes/examenes?cedula=' . urlencode($cedula); + $ctx = stream_context_create([ + 'http' => [ + 'method' => 'GET', + 'header' => 'X-Lab-Key: ' . LAB_SYNC_KEY . "\r\n", + 'timeout' => 8, + 'ignore_errors' => true, + ], + ]); + + $resp = @file_get_contents($url, false, $ctx); + if ($resp === false) jsonError('No se pudo conectar con RIPS Manager', 503); + + $data = json_decode($resp, true); + if (!($data['ok'] ?? false)) { + jsonError($data['error'] ?? 'Error en RIPS Manager', 502); + } + + $examenes = $data['examenes'] ?? []; +} if (!$examenes) { jsonOk(['encontrados' => [], 'no_mapeados' => [], 'total_rips' => 0]); } @@ -72,10 +95,60 @@ if ($codigos) { } $meta = $examenes[0] ?? []; + +// ── Médico ordenante ────────────────────────────────────────────────────────── +$medicoObj = null; +$docidmedico = trim($meta['medico_docidmedico'] ?? ''); +if ($docidmedico) { + $stm = db()->prepare( + "SELECT id, codigo, CONCAT(nombres, ' ', apellidos) AS nombre_completo, cod_especialidad + FROM medicos WHERE docidmedico = ? LIMIT 1" + ); + $stm->execute([$docidmedico]); + $row = $stm->fetch(PDO::FETCH_ASSOC); + if ($row) { + $medicoObj = [ + 'id' => (int)$row['id'], + 'codigo' => $row['codigo'], + 'nombre' => $row['nombre_completo'], + 'especialidad' => $row['cod_especialidad'] ?? '', + ]; + } +} + +// ── Empresa / EPS ───────────────────────────────────────────────────────────── +$empresaObj = null; +$nitEmpresa = trim($meta['nit_empresa'] ?? ''); +if ($nitEmpresa) { + $stm = db()->prepare( + "SELECT e.nit, e.nombre, e.razon_social, e.tarifa_id, + ti.nombre AS tarifa_nombre, e.descuento_pct, + e.tipo_usuario, e.req_autoriza, e.activa + FROM lab_empresas e + LEFT JOIN lab_tarifas_id ti ON ti.id = e.tarifa_id + WHERE e.nit = ? AND e.activa = 1 + LIMIT 1" + ); + $stm->execute([$nitEmpresa]); + $row = $stm->fetch(PDO::FETCH_ASSOC); + if ($row) { + $empresaObj = $row; + $empresaObj['activa'] = (bool)$empresaObj['activa']; + $empresaObj['req_autoriza'] = (bool)$empresaObj['req_autoriza']; + $empresaObj['descuento_pct'] = (float)$empresaObj['descuento_pct']; + } +} + jsonOk([ - 'encontrados' => $encontrados, - 'no_mapeados' => $no_mapeados, - 'total_rips' => count($examenes), - 'recepcion_id' => $meta['recepcion_id'] ?? null, - 'hora' => $meta['hora'] ?? null, + 'encontrados' => $encontrados, + 'no_mapeados' => $no_mapeados, + 'total_rips' => count($examenes), + 'recepcion_id' => $meta['recepcion_id'] ?? null, + 'hora' => $meta['hora'] ?? null, + 'fuente' => $fuenteCache ? 'cache' : 'rips', + 'diagnostico_cod' => $meta['diagnostico_cod'] ?? null, + 'diagnostico_nombre' => $meta['diagnostico_nombre'] ?? null, + 'medico' => $medicoObj, + 'empresa' => $empresaObj, + 'valor_total' => isset($meta['valor_total']) ? (float)$meta['valor_total'] : null, ]); diff --git a/api/lab/ingest_paciente.php b/api/lab/ingest_paciente.php index 83904ad..dbc1c04 100644 --- a/api/lab/ingest_paciente.php +++ b/api/lab/ingest_paciente.php @@ -136,6 +136,10 @@ if (!in_array($modo, ['insertar', 'upsert'], true)) { $examenesRaw = $data['examenes'] ?? null; $examenesGuardados = 0; +function db(): \PDO { + return Database::getInstance()->getConnection(); +} + function guardarExamenesPendientes(string $doc, array $examenes): int { if (!$examenes || !$doc) return 0; $pdo = db(); diff --git a/migrations/20260716_rips_examenes_pendientes.sql b/migrations/20260716_rips_examenes_pendientes.sql new file mode 100644 index 0000000..3dc6395 --- /dev/null +++ b/migrations/20260716_rips_examenes_pendientes.sql @@ -0,0 +1,12 @@ +-- Cache de exámenes enviados desde RIPS Manager junto con la ingesta de pacientes. +-- Se usa en get_examenes_rips.php para evitar el round-trip a RIPS cuando ya vienen precargados. +CREATE TABLE IF NOT EXISTS rips_examenes_pendientes ( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + numero_documento VARCHAR(30) NOT NULL, + datos JSON NOT NULL, + recepcion_id INT DEFAULT NULL, + hora_recepcion VARCHAR(20) DEFAULT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + INDEX idx_doc (numero_documento), + INDEX idx_created (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/modules/turnero/views/recepcion.php b/modules/turnero/views/recepcion.php index 5f3341e..71dea93 100644 --- a/modules/turnero/views/recepcion.php +++ b/modules/turnero/views/recepcion.php @@ -1633,8 +1633,6 @@ async function consultarExamenesRips(cedula) { if (!d.ok || !d.encontrados?.length) return; _ripsData = d; const hora = d.hora ? ' (' + String(d.hora).slice(0, 5) + ')' : ''; - document.getElementById('banner-rips-txt').textContent = - `${d.encontrados.length} examen(es) de RIPS${hora} — ¿Cargar?`; const warn = document.getElementById('banner-rips-warn'); if (d.no_mapeados?.length) { warn.textContent = `⚠ Sin mapeo: ${d.no_mapeados.join(', ')}`; @@ -1642,14 +1640,36 @@ async function consultarExamenesRips(cedula) { } else { warn.classList.add('d-none'); } - document.getElementById('banner-rips').classList.remove('d-none'); + // Si los exámenes vienen del cache local (enviados por RIPS scheduler) se cargan + // automáticamente. Si vienen del pull en vivo se muestra el banner para confirmación. + if (d.fuente === 'cache') { + await cargarExamenesRips(); + } else { + document.getElementById('banner-rips-txt').textContent = + `${d.encontrados.length} examen(es) de RIPS${hora} — ¿Cargar?`; + document.getElementById('banner-rips').classList.remove('d-none'); + } } catch (_) {} } -function cargarExamenesRips() { +async function cargarExamenesRips() { if (!_ripsData?.encontrados?.length || !examTS) return; _ripsData.encontrados.forEach(e => examTS.addItem(String(e.exam_tipo_id), true)); - recalcularPrecios(); + if (_ripsData.diagnostico_cod) { + document.getElementById('inp-diag').value = _ripsData.diagnostico_cod; + } + if (_ripsData.medico) { + const m = _ripsData.medico; + seleccionarMedico(m.id, m.codigo, m.nombre, m.especialidad || ''); + } + if (_ripsData.empresa) { + await seleccionarEmpresa(_ripsData.empresa); + } else { + recalcularPrecios(); + } + if (_ripsData.valor_total > 0) { + document.getElementById('inp-total').value = Math.round(_ripsData.valor_total); + } descartarRips(); }