From d0a42dba33d83810f01975d857fbbf10d6865f6c Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Thu, 9 Jul 2026 14:05:39 -0500 Subject: [PATCH] feat: auto-load RIPS exams when patient is selected in recepcion When a patient with a cedula is selected, the system queries RIPS Manager for exams registered in the last 5 minutes. A green banner shows the count with a "Cargar" button that pre-fills TomSelect. Unmapped exam codes shown as a warning. Banner clears on deselect/reset. - config.php: RIPS_MANAGER_URL constant from env var - api/lab/get_examenes_rips.php: proxy + codigo_legacy mapper - recepcion.php: banner HTML + consultarExamenesRips/cargarExamenesRips JS Co-Authored-By: Claude Sonnet 4.6 --- api/lab/get_examenes_rips.php | 81 +++++++++++++++++++++++++++++ config/config.php | 4 ++ modules/turnero/views/recepcion.php | 62 ++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 api/lab/get_examenes_rips.php diff --git a/api/lab/get_examenes_rips.php b/api/lab/get_examenes_rips.php new file mode 100644 index 0000000..f089086 --- /dev/null +++ b/api/lab/get_examenes_rips.php @@ -0,0 +1,81 @@ + [ + '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]); +} + +// Mapear COD_EXAMEN → exam_tipos por codigo_legacy +$codigos = array_values(array_unique(array_filter( + array_map(fn($e) => trim($e['cod_examen'] ?? ''), $examenes) +))); + +$encontrados = []; +$no_mapeados = []; + +if ($codigos) { + $ph = implode(',', array_fill(0, count($codigos), '?')); + $stmt = db()->prepare( + "SELECT id AS exam_tipo_id, codigo, nombre, codigo_legacy + FROM exam_tipos + WHERE codigo_legacy IN ($ph) AND activo = 1" + ); + $stmt->execute($codigos); + $mapa = []; + foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) { + $mapa[trim($r['codigo_legacy'])] = $r; + } + foreach ($codigos as $cod) { + if (isset($mapa[$cod])) { + $encontrados[] = [ + 'exam_tipo_id' => (int)$mapa[$cod]['exam_tipo_id'], + 'codigo' => $mapa[$cod]['codigo'], + 'nombre' => $mapa[$cod]['nombre'], + 'cod_rips' => $cod, + ]; + } else { + $no_mapeados[] = $cod; + } + } +} + +$meta = $examenes[0] ?? []; +jsonOk([ + 'encontrados' => $encontrados, + 'no_mapeados' => $no_mapeados, + 'total_rips' => count($examenes), + 'recepcion_id' => $meta['recepcion_id'] ?? null, + 'hora' => $meta['hora'] ?? null, +]); diff --git a/config/config.php b/config/config.php index ce1b00d..26d5c98 100644 --- a/config/config.php +++ b/config/config.php @@ -406,6 +406,10 @@ if (!defined('MIGRATION_TOKEN')) { if (!defined('LAB_SYNC_KEY')) { define('LAB_SYNC_KEY', getenv('LAB_SYNC_KEY') ?: 'rips-lab-sync-2026'); } +// URL base del RIPS Manager (para consultas server-to-server) +if (!defined('RIPS_MANAGER_URL')) { + define('RIPS_MANAGER_URL', getenv('RIPS_MANAGER_URL') ?: ''); +} define('TIMEZONE', 'America/Bogota'); // Información del desarrollador diff --git a/modules/turnero/views/recepcion.php b/modules/turnero/views/recepcion.php index 5344749..1c06812 100644 --- a/modules/turnero/views/recepcion.php +++ b/modules/turnero/views/recepcion.php @@ -625,6 +625,24 @@ document.addEventListener('DOMContentLoaded', function() { + + +
Exámenes solicitados
@@ -1437,6 +1455,48 @@ function seleccionarPaciente(pac) { // Precargar en background (usuario decide si abre) _historialPacienteCargado = false; _historialPacienteId = pac.id; + + // Consultar exámenes recientes en RIPS (últimos 5 min) + const cedula = (pac.numero_documento || pac.documento || '').toString().trim(); + if (cedula) consultarExamenesRips(cedula); +} + +// ── Exámenes desde RIPS ─────────────────────────────────────── +let _ripsData = null; + +async function consultarExamenesRips(cedula) { + _ripsData = null; + document.getElementById('banner-rips').classList.add('d-none'); + if (!cedula) return; + try { + const r = await fetch(`${BASE_WA}api/lab/get_examenes_rips.php?cedula=${encodeURIComponent(cedula)}`); + const d = await r.json(); + 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(', ')}`; + warn.classList.remove('d-none'); + } else { + warn.classList.add('d-none'); + } + document.getElementById('banner-rips').classList.remove('d-none'); + } catch (_) {} +} + +function cargarExamenesRips() { + if (!_ripsData?.encontrados?.length || !examTS) return; + _ripsData.encontrados.forEach(e => examTS.addItem(String(e.exam_tipo_id), true)); + recalcularPrecios(); + descartarRips(); +} + +function descartarRips() { + _ripsData = null; + document.getElementById('banner-rips').classList.add('d-none'); } function togglePagoCombinado() { @@ -1463,6 +1523,7 @@ function resetPagoCombinado() { function desvincularPaciente() { pacienteActivo = null; _historialPacienteId = null; + descartarRips(); _historialPacienteCargado = false; document.getElementById('bloque-pac-no-vinculado').classList.remove('d-none'); document.getElementById('bloque-pac-seleccionado').classList.add('d-none'); @@ -2037,6 +2098,7 @@ function resetCheckboxes() { if (examTS) { examTS.clear(); examTS.enable(); } document.getElementById('wrap-examenes').classList.remove('disabled'); document.getElementById('bloque-medico').style.display = ''; + descartarRips(); document.getElementById('sel-pago').value = ''; document.getElementById('inp-total').value = ''; document.getElementById('inp-obs').value = '';