const createError = require('http-errors'); const config = require('../config'); const { getBusToken } = require('../utils/busAuth'); const { findPatient } = require('../services/patient'); const { findDocumentReferenceByPatient } = require('../services/documentReference'); const { DOCUMENT_TYPES } = require('../constants/documentTypes'); const NATIONAL_ID_SYSTEM = 'https://federador.msal.gob.ar/patient-id'; /** * Extracts the Federador national identifier from a Patient resource. */ function extractNationalIdentifier(patient) { const identifiers = Array.isArray(patient.identifier) ? patient.identifier : []; 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; } /** * ITI-67: Find Document References (MHD) * * GET /fhir/DocumentReference?subject=:localId * GET /fhir/DocumentReference?patient.identifier=:localId * GET /fhir/DocumentReference?subject=:localId&type=:type * * Flow: * 1. Fetch the Patient from the Bus by local ID to obtain the national identifier. * 2. Search DocumentReferences in the Bus by that national identifier * (opcionalmente filtrando por tipo de documento). * 3. Return the resulting Bundle. * * Required query parameter (one of): * subject — local Patient ID in the Bus. * patient.identifier — same semantics, alternate FHIR parameter name. * * Optional query parameter: * type — tipo de documento a buscar. Acepta las etiquetas conocidas * (IPS, MeOW, IT) o un token FHIR (`system|code`, ej: `http://loinc.org|60591-5`). * Si se omite, devuelve documentos de cualquier tipo. */ async function listDocumentReference(req, res, next) { try { const localPatientIdentifier = req.query.subject ?? req.query['patient.identifier']; if (!localPatientIdentifier) { throw createError(400, 'Missing required query parameter: subject or patient.identifier'); } const documentType = resolveDocumentType(req.query.type); const token = await getBusToken( config.bus.url, config.bus.jwtSecret, config.bus.issuer, [ config.bus.mpiScope, config.bus.documentRegistryScope ].join(',') ); // 1. Obtengo el identificador nacional del paciente en forma de referencia const patientSearchset = await findPatient(token, { identifier: localPatientIdentifier }); if (!patientSearchset) { throw createError(422, 'Could not resolve national identifier for the given patient'); } const patientNationalId = patientSearchset.entry[0].fullUrl // 2. Obtengo el listado de entradas del indice de atenciones asociadada al id de paciente // (y, si se pidió, al tipo de documento). const documentReferenceSearchset = await findDocumentReferenceByPatient(token, patientNationalId, documentType) res.status(200).json(documentReferenceSearchset); } catch (err) { next(err); } } module.exports = { listDocumentReference };