Compare commits

...

2 Commits

Author SHA1 Message Date
Alejandro Gomez Auad
c5b0d1c480 Corregido el parametro type de ITI-67 para que sea un token FHIR real
Se saca el mapeo de etiquetas propias (IPS/MeOW/IT) a codigo LOINC:
'type' ahora se pasa tal cual al Bus como token FHIR (system|code),
consistente con la semantica estandar de busqueda por token en FHIR,
en vez de una convencion propia que solo este gateway entendia.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 16:52:08 +00:00
Alejandro Gomez Auad
7f8b603be6 Agregado ruteo nginx para las transformaciones de bundle ($ddcc/$dvc/$icvp2/$meow)
Las rutas GET /fhir/Bundle/:id/\$ddcc|\$dvc|\$icvp2|\$meow, implementadas en
bus-gateway/controllers/bundleSigner.js, no tenian ningun location que las
mandara a bus-gateway: caian todas al catch-all /fhir/ y terminaban en
hapi-fhir, que no las entiende. Se agrega un location por regex que las
matchea especificamente y las deja pasar a bus_gateway, sin afectar el
resto de rutas /fhir/Bundle/:id.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 16:50:47 +00:00
5 changed files with 31 additions and 22 deletions

View File

@ -20,7 +20,7 @@ El componente actúa exclusivamente como gateway: no contiene lógica de negocio
| ITI-65 | `POST` | `/fhir/MeOWDocument` | Provide Document Bundle (MeOW - Medication Overview): variante document. | | ITI-65 | `POST` | `/fhir/MeOWDocument` | Provide Document Bundle (MeOW - Medication Overview): variante document. |
| ITI-65 | `POST` | `/fhir/ITTransaction` | Provide Document Bundle (IT - Consultation Note / respuesta de interconsulta): variante transacción. | | ITI-65 | `POST` | `/fhir/ITTransaction` | Provide Document Bundle (IT - Consultation Note / respuesta de interconsulta): variante transacción. |
| ITI-65 | `POST` | `/fhir/ITDocument` | Provide Document Bundle (IT - Consultation Note): variante document. | | ITI-65 | `POST` | `/fhir/ITDocument` | Provide Document Bundle (IT - Consultation Note): variante document. |
| ITI-67 | `GET` | `/fhir/DocumentReference` | Find Document References: busca el paciente por ID local en el MPI para obtener su ID nacional y consulta los DocumentReferences en el Document Registry. Admite filtrar por tipo de documento con el parámetro opcional `type` (`IPS`, `MeOW`, `IT`, o un token FHIR `system\|code`). | | ITI-67 | `GET` | `/fhir/DocumentReference` | Find Document References: busca el paciente por ID local en el MPI para obtener su ID nacional y consulta los DocumentReferences en el Document Registry. Admite filtrar por tipo de documento con el parámetro opcional `type`, un token FHIR `system\|code` (ej. `http://loinc.org\|60591-5` para IPS, `http://loinc.org\|56445-0` para MeOW, `http://loinc.org\|57133-1` para IT). |
| ITI-78 | `GET` | `/fhir/Patient` | Patient Demographics Query: búsqueda de pacientes en el MPI. | | ITI-78 | `GET` | `/fhir/Patient` | Patient Demographics Query: búsqueda de pacientes en el MPI. |
| ITI-78 | `GET` | `/fhir/Patient/:id` | Patient Demographics Query: obtención de un paciente por ID en el MPI. | | ITI-78 | `GET` | `/fhir/Patient/:id` | Patient Demographics Query: obtención de un paciente por ID en el MPI. |
| ITI-104 | `POST` | `/fhir/Patient` | Patient Identity Feed: alta de paciente en el MPI. | | ITI-104 | `POST` | `/fhir/Patient` | Patient Identity Feed: alta de paciente en el MPI. |

View File

@ -3,7 +3,6 @@ const config = require('../config');
const { getBusToken } = require('../utils/busAuth'); const { getBusToken } = require('../utils/busAuth');
const { findPatient } = require('../services/patient'); const { findPatient } = require('../services/patient');
const { findDocumentReferenceByPatient } = require('../services/documentReference'); const { findDocumentReferenceByPatient } = require('../services/documentReference');
const { DOCUMENT_TYPES } = require('../constants/documentTypes');
const NATIONAL_ID_SYSTEM = 'https://federador.msal.gob.ar/patient-id'; const NATIONAL_ID_SYSTEM = 'https://federador.msal.gob.ar/patient-id';
@ -15,20 +14,6 @@ function extractNationalIdentifier(patient) {
return identifiers.find(id => id.system === NATIONAL_ID_SYSTEM) || null; return identifiers.find(id => id.system === NATIONAL_ID_SYSTEM) || null;
} }
/**
* Resuelve el parámetro de búsqueda `type` a un token FHIR (`system|code`).
* Acepta tanto las etiquetas conocidas (IPS, MeOW, IT case-insensitive)
* como un token FHIR ya armado (`system|code` o `code`), que se pasa tal cual
* para no acoplar la búsqueda a los tipos de documento ya conocidos.
*/
function resolveDocumentType(rawType) {
if (!rawType) return undefined;
const knownType = Object.values(DOCUMENT_TYPES).find(
t => t.label.toLowerCase() === rawType.toLowerCase()
);
return knownType ? `${knownType.system}|${knownType.code}` : rawType;
}
/** /**
@ -49,9 +34,11 @@ function resolveDocumentType(rawType) {
* patient.identifier same semantics, alternate FHIR parameter name. * patient.identifier same semantics, alternate FHIR parameter name.
* *
* Optional query parameter: * Optional query parameter:
* type tipo de documento a buscar. Acepta las etiquetas conocidas * type token FHIR de DocumentReference.type (`system|code`, `|code` o `code`),
* (IPS, MeOW, IT) o un token FHIR (`system|code`, ej: `http://loinc.org|60591-5`). * ej: `http://loinc.org|60591-5` (IPS), `http://loinc.org|56445-0` (MeOW),
* Si se omite, devuelve documentos de cualquier tipo. * `http://loinc.org|57133-1` (IT). Se pasa tal cual al Bus, sin traducir
* alias propios, para no apartarse de la semántica estándar de búsqueda
* por token de FHIR. Si se omite, devuelve documentos de cualquier tipo.
*/ */
async function listDocumentReference(req, res, next) { async function listDocumentReference(req, res, next) {
try { try {
@ -59,7 +46,7 @@ async function listDocumentReference(req, res, next) {
if (!localPatientIdentifier) { if (!localPatientIdentifier) {
throw createError(400, 'Missing required query parameter: subject or patient.identifier'); throw createError(400, 'Missing required query parameter: subject or patient.identifier');
} }
const documentType = resolveDocumentType(req.query.type); const documentType = req.query.type;
const token = await getBusToken( const token = await getBusToken(
config.bus.url, config.bus.url,
config.bus.jwtSecret, config.bus.jwtSecret,

View File

@ -8,9 +8,9 @@ sequenceDiagram
participant IndiceNacion as Indice Documentos participant IndiceNacion as Indice Documentos
end end
participant NodoDominio2 as Nodo B participant NodoDominio2 as Nodo B
Note over HIS_A,FederadorNacion: Tipos soportados: IPS, MeOW, IT (parámetro opcional type) Note over HIS_A,FederadorNacion: Tipos soportados (LOINC): 60591-5 IPS, 56445-0 MeOW, 57133-1 IT (parámetro opcional type=system|code)
Note over HIS_A,FederadorNacion: 1. Busqueda y resolución de Identidad Note over HIS_A,FederadorNacion: 1. Busqueda y resolución de Identidad
HIS_A->>NodoDominio: ITI67: Solicita los documentos asociados al paciente por su identificador local, opcionalmente filtrando por tipo <br /> [GET /DocumentReference?patient.identifier=<ID_Local>&type=<IPS|MeOW|IT>] HIS_A->>NodoDominio: ITI67: Solicita los documentos asociados al paciente por su identificador local, opcionalmente filtrando por tipo <br /> [GET /DocumentReference?patient.identifier=<ID_Local>&type=<system|code>]
NodoDominio->>FederadorNacion: Busca el paciente por su identificador local <br /> [GET /Patient?identifier=<ID_Local>] NodoDominio->>FederadorNacion: Busca el paciente por su identificador local <br /> [GET /Patient?identifier=<ID_Local>]
FederadorNacion-->>NodoDominio: 200 OK (Patient Searchset) FederadorNacion-->>NodoDominio: 200 OK (Patient Searchset)
Note over NodoDominio,IndiceNacion: 2. Busqueda de Metadatos Note over NodoDominio,IndiceNacion: 2. Busqueda de Metadatos

View File

@ -96,6 +96,17 @@ http {
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
# Transformaciones de bundle (nodo nacional, via bus-gateway/bundleSigner):
# /fhir/Bundle/:id/$ddcc, $dvc, $icvp2, $meow
location ~ ^/fhir/Bundle/[^/]+/\$(ddcc|dvc|icvp2|meow)$ {
proxy_pass http://bus_gateway;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s;
}
# Resto de /fhir/* va a hapi-fhir # Resto de /fhir/* va a hapi-fhir
location /fhir/ { location /fhir/ {
proxy_pass http://hapi_fhir; proxy_pass http://hapi_fhir;

View File

@ -112,6 +112,17 @@ http {
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
# Transformaciones de bundle (nodo nacional, via bus-gateway/bundleSigner):
# /fhir/Bundle/:id/$ddcc, $dvc, $icvp2, $meow
location ~ ^/fhir/Bundle/[^/]+/\$(ddcc|dvc|icvp2|meow)$ {
proxy_pass http://bus_gateway;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s;
}
# Resto de /fhir/* va a hapi-fhir # Resto de /fhir/* va a hapi-fhir
location /fhir/ { location /fhir/ {
proxy_pass http://hapi_fhir; proxy_pass http://hapi_fhir;