Guía de Implementación de Homologación Regional (PH4H) de Costa Rica
0.1.0 - ci-build
Guía de Implementación de Homologación Regional (PH4H) de Costa Rica - Versión en desarrollo (v0.1.0): no se debe usar en producción. Es un borrador en discusión en las mesas de trabajo de la Iniciativa HL7® Costa Rica y cambia sin aviso. Vea el ciclo de vida de las guías.
| Estado de las normas de la página: Informative |
$transform en un servidorEsta página explica cómo se aplican los mapas de la guía: quién los ejecuta, qué necesita el motor, cómo se invoca cada transformación y qué se comprueba antes y después. Los ejemplos usan los recursos de prueba de la guía, que se pueden descargar y reproducir.
El nodo nacional de PH4H (el componente del HIE que intercambia con los demás países) toma un recurso FHIR R5 de los registros nacionales y, antes de enviarlo, lo transforma en el perfil FHIR R4 que espera RACSEL o IPS. La transformación no se programa en el nodo: se ejecuta con los StructureMap de esta guía mediante la operación estándar StructureMap/$transform, en un motor de mapeo que la implemente. Cualquier otro sistema del país que necesite producir los perfiles regionales puede usar los mismos mapas.
Los mapas solo cubren el envío (R5 a R4). Los mapas de recepción (R4 a R5) quedan previstos para cuando haga falta recibir información para la continuidad de la atención.
| Recurso de Costa Rica (R5) | StructureMap | Perfil de destino (R4) |
|---|---|---|
| Paciente | CRPatientToLACPatient |
LACPatient (RACSEL) |
| Organización | CROrganizationToLACOrganization |
LACOrganization (RACSEL) |
| Profesional de salud | CRPractitionerToIPS |
Practitioner-uv-ips (IPS) |
| Rol del profesional | CRPractitionerRoleToIPS |
PractitionerRole-uv-ips (IPS) |
Los cuatro mapas importan CRComun, que no se invoca directamente: reúne los grupos que transforman los tipos de datos (identificador, referencia, concepto, nombre, contacto, dirección y periodo).
Para cada recurso que sale del país, el nodo nacional sigue estos pasos:
StructureMap/$transform, en un motor que corre en R5 y tiene cargadas las dependencias de la sección siguiente.meta.profile, con el paquete de RACSEL (que trae IPS). La salida de cada mapa de esta guía valida con 0 errores sobre los ejemplos publicados.transform, el recurso nacional como origen y el StructureMap como política) y enviar el recurso R4.| Qué | De dónde | Para qué |
|---|---|---|
Los cinco StructureMap de esta guía |
package.tgz (JSON) o los archivos .fml de input/maps del paquete de pruebas |
Son las transformaciones |
ConceptMap cr-sistema-identificador-oid y cr-sistema-identificador-tipo |
Esta guía | URI de los sistemas de identificación → OID del país y tipo HL7 v2-0203 |
ConceptMap cr-pais-alfa3-alfa2 y cr-profesion-salud-isco08 |
IG terminológica de Costa Rica (R5) | País alfa-3 → alfa-2 y profesión → ISCO-08 |
Estructuras de origen y destino con URL de versión: http://hl7.org/fhir/5.0/StructureDefinition/<recurso> y http://hl7.org/fhir/4.0/StructureDefinition/<recurso> |
Se generan desde los paquetes hl7.fhir.r5.core y hl7.fhir.r4.core (el script de pruebas muestra cómo) |
Son las que declaran los mapas, como los mapas oficiales de HL7 entre versiones |
Perfiles de destino: racsel.org#0.2.1 (incluye IPS y el núcleo R4) |
Registro de paquetes FHIR | Validar la salida |
El motor debe correr en R5, la versión de la entrada. Un motor R4 lee el recurso R5 como si fuera R4 y descarta en silencio lo que R4 no tiene (por ejemplo, PractitionerRole.contact o la estructura de Practitioner.communication). Los ConceptMap de esta guía están en R4 porque la guía se publica en R4; para un motor R5 se convierten (equivalence → relationship), como hace el script de pruebas.
El validador de HL7 incluye el motor de mapeo. Con los mapas en input/maps, los ConceptMap R5 en conceptmaps/ y las estructuras con URL de versión en xver/:
java -jar validator_cli.jar transform https://hl7.or.cr/fhir/ph4h/StructureMap/CRPatientToLACPatient \
paciente-r5.json -version 5.0 \
-ig xver -ig conceptmaps \
-ig input/maps/CRComun.fml -ig input/maps/CRPatientToLACPatient.fml \
-output paciente-r4.json
Entrada: el paciente de ejemplo en R5, con cédula, pasaporte y expediente local (fragmento):
{
"resourceType": "Patient",
"identifier": [
{ "use": "official",
"type": { "coding": [ { "system": "https://hl7.or.cr/fhir/terminology/CodeSystem/cr-tipo-identificacion", "code": "pasaporte" },
{ "system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "PPN" } ] },
"system": "https://hl7.or.cr/fhir/sid/pasaporte/CRI", "value": "119870123" },
{ "use": "usual",
"type": { "coding": [ { "system": "https://hl7.or.cr/fhir/terminology/CodeSystem/cr-tipo-identificacion", "code": "expediente-local" } ] },
"system": "https://hl7.or.cr/fhir/sid/expediente/cj-3101123456", "value": "2026-004512" }
],
"address": [ { "city": "101", "district": "10101", "state": "1", "country": "CRI" } ]
}
Salida: un Patient R4 que cumple LACPatient. El pasaporte va primero con el OID del país y solo el tipo v2-0203; el expediente local no viaja; el país pasa a alfa-2:
{
"resourceType": "Patient",
"meta": { "profile": [ "http://racsel.org/StructureDefinition/LACPatient" ] },
"identifier": [
{ "use": "official",
"type": { "coding": [ { "system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "PPN" } ] },
"system": "urn:oid:2.16.188", "value": "119870123" }
],
"address": [ { "city": "101", "district": "10101", "state": "1", "country": "CR" } ]
}
$transform en un servidorEs la forma en que el nodo nacional invoca los mapas en producción. Con un servidor que implemente la operación y corra en R5 (por ejemplo, Matchbox):
Cargar los mapas. Matchbox acepta el FML directamente:
POST [base]/StructureMap
Content-Type: text/fhir-mapping
<contenido de input/maps/CRComun.fml>
Repetir con cada mapa (CRComun primero, porque los demás lo importan). Los ConceptMap y las estructuras con URL de versión se cargan como recursos normales (PUT [base]/ConceptMap/<id>, PUT [base]/StructureDefinition/<id>).
Transformar. El recurso R5 va en el cuerpo y el mapa en el parámetro source:
POST [base]/StructureMap/$transform?source=https://hl7.or.cr/fhir/ph4h/StructureMap/CRPatientToLACPatient
Content-Type: application/fhir+json
Accept: application/fhir+json
{ "resourceType": "Patient", "id": "ejemplo-cr", ... }
La respuesta es el Patient R4 del ejemplo anterior.
Son condiciones de PH4H que el mapa no puede resolver, así que el nodo nacional las comprueba antes de transformar, con una expresión FHIRPath sobre el recurso R5:
| Recurso | Regla | FHIRPath (debe ser true) |
|---|---|---|
| Paciente | LACPatient exige el pasaporte; un paciente sin pasaporte no se envía |
identifier.where(use = 'official' and type.coding.exists(system = 'https://hl7.or.cr/fhir/terminology/CodeSystem/cr-tipo-identificacion' and code = 'pasaporte')).exists() |
| Organización | LACOrganization exige la dirección con país; viene del contacto general (sin purpose) |
contact.where(purpose.exists().not()).address.country.exists() |
Lo que no pasa a R4 no es una regla de envío sino una pérdida documentada: la autorización de salud de la organización, el programa de la CCSS y el identificador del rol, y la marca de idioma preferido del profesional. Se listan en la sección 8 de cada modelo lógico de la IG core.
Cada salida declara su perfil en meta.profile; se valida con el paquete de RACSEL, que trae IPS:
java -jar validator_cli.jar paciente-r4.json -version 4.0.1 -ig racsel.org#0.2.1
Advertencias que se aceptan: falta de narrativa (dom-6), los tipos de identificador NI, LN, XX y FI fuera del ValueSet identifier-type de R4 (es extensible) y los CodeSystem de Costa Rica que el validador R4 no encuentra.
Además de los cambios comunes (OID, tipo v2-0203, país alfa-2), cada mapa resuelve lo propio de su recurso. Los ejemplos de salida muestran el resultado completo.
Profesional de salud. El código de colegiado pierde el colegio, que iba en el system de la URI; el mapa lo repone en assigner.display según el sufijo de la URI (.../colegiado/cmc → Colegio de Médicos y Cirujanos de Costa Rica):
{ "use": "official",
"type": { "coding": [ { "system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "LN" } ] },
"system": "urn:oid:2.16.188", "value": "12345",
"assigner": { "display": "Colegio de Médicos y Cirujanos de Costa Rica" } }
Rol del profesional. La profesión conserva el código de Costa Rica y agrega el de ISCO-08, que recomienda IPS; el programa de la CCSS no se envía. Las referencias lógicas (por identificador) reciben el tipo v2-0203, porque con el OID del país el system ya no distingue el tipo:
{ "code": [ { "coding": [
{ "system": "https://hl7.or.cr/fhir/terminology/CodeSystem/cr-profesion-salud", "code": "medicina" },
{ "system": "urn:oid:2.16.840.1.113883.2.9.6.2.7", "code": "221" } ] } ],
"practitioner": { "identifier": {
"type": { "coding": [ { "system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "LN" } ] },
"system": "urn:oid:2.16.188", "value": "12345" },
"display": "Dra. Ana Mora Rojas" } }
Organización. El contacto general de R5 (contact sin purpose) pasa a telecom y address del recurso, como en R4; la autorización de salud (qualification) no existe en R4 y no se envía.
Un mapa nuevo (otro recurso, o la recepción R4 a R5) sigue la misma estructura: declara el origen y el destino con URL de versión, importa CRComun y reutiliza sus grupos. Los mapas de esta guía se escriben con estas convenciones, para que se lean sin conocer el recurso de memoria:
fechaNacimiento, codigoColegiado), nunca una letra ni una abreviatura. Los parámetros de todos los grupos se llaman origen y destino, y la variable del elemento de destino agrega el sufijo Destino.CRComun, con el nombre del tipo en español (Identificador, Direccion); un grupo por recurso en cada mapa, con el nombre del mapa."pasaporte", "contactoGeneral"), porque el motor lo escribe en el registro de la transformación.translate() sobre un ConceptMap, no con valores fijos en el mapa.group CRPatientToLACPatient(source origen : Patient, target destino : PatientR4) {
origen.birthDate as fechaNacimiento -> destino.birthDate = fechaNacimiento "nacimiento";
origen.address as direccion -> destino.address as direccionDestino then Direccion(direccion, direccionDestino) "direccion";
}
Cada mapa nuevo trae su ejemplo R5 de entrada en input/pruebas/entrada y la salida R4 esperada en input/examples, y se agrega a los casos del script de pruebas.
Las pruebas de los mapas se pueden reproducir con el paquete pruebas-mapas.zip. Trae el script de pruebas, los mapas en FML, los ejemplos R5 de entrada, las salidas R4 esperadas y los ConceptMap de esta guía y de la terminológica, con la misma estructura de carpetas que el repositorio de la guía. Su archivo LEEME.md indica los requisitos: Java, jq, el validador de HL7 y los paquetes del núcleo R5 y R4 y de RACSEL en la caché de paquetes.
scripts/probar-mapas.sh transforma cada ejemplo de entrada R5 (input/pruebas/entrada) con el validador de HL7, compara la salida con el ejemplo esperado (input/examples) y valida todas las salidas contra el perfil de su meta.profile. Genera las estructuras con URL de versión desde los paquetes del núcleo R5 y R4, y toma los ConceptMap de la IG terminológica de la carpeta terminologia del paquete (en el repositorio, de la IG terminológica compilada con SUSHI). Con --actualizar copia cada salida sobre su ejemplo esperado, para revisar el diff antes de hacer commit.
El IG Publisher valida los ejemplos de salida contra RACSEL e IPS, pero todavía no resuelve las estructuras con URL de versión, porque HL7 no ha publicado en el registro de paquetes sus estructuras entre versiones (hl7.fhir.uv.xver). Por eso el control de calidad de la guía reporta errores en los StructureMap (estructura no encontrada y, en cadena, contextos de destino desconocidos): se aceptan y se documentan hasta que ese paquete exista. Los mapas se verifican con el script.