Narratif généré : StructureMap CdaFrMDEToBundle #xD; map "https://interop.esante.gouv.fr/ig/fhir/mappingcdafhir/StructureMap/CdaFrMDEToBundle" = "CdaFrMDEToBundle"#xD; #xD; // Mapping CSE-MDE vers FHIR Bundle - Contexte Français#xD; #xD; uses "http://hl7.org/cda/stds/core/StructureDefinition/ClinicalDocument" alias ClinicalDocument as source#xD; uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias Bundle as target#xD; uses "http://hl7.org/fhir/StructureDefinition/Composition" alias Composition as target#xD; uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target#xD; uses "http://hl7.org/fhir/StructureDefinition/Observation" alias Observation as target#xD; #xD; imports "https://interop.esante.gouv.fr/ig/fhir/mappingcdafhir/StructureMap/CdaToFHIRTypes"#xD; imports "https://interop.esante.gouv.fr/ig/fhir/mappingcdafhir/StructureMap/CdaToBundle"#xD; imports "https://interop.esante.gouv.fr/ig/fhir/mappingcdafhir/StructureMap/CdaFrToBundle"#xD; #xD; // Entry point#xD; group CdaFrMDEToBundle(source cda : ClinicalDocument, target bundle : Bundle) {#xD; cda -> bundle.entry as e, e.resource = create('Composition') as composition, composition.id = uuid() as uuid, e.fullUrl = append('urn:uuid:', uuid), bundle.entry as e2, e2.resource = create('Patient') as patient, patient.id = uuid() as uuid2, e2.fullUrl = append('urn:uuid:', uuid2) then CdaFrMDEMapping(cda, patient, composition, bundle) "main";#xD; }#xD; #xD; // Main mapping group#xD; group CdaFrMDEMapping(source cda : ClinicalDocument, target patient : Patient, target composition : Composition, target bundle : Bundle) {#xD; // Bundle metadata#xD; cda -> bundle.id = uuid() "bundleId";#xD; cda.id as cdaId -> bundle.identifier as identifier then {#xD; cdaId.root as root where cdaId.extension.exists() -> identifier.system = translate(root, '#oid2uri', 'uri') "system";#xD; cdaId.extension as extension -> identifier.value = extension "value";#xD; cdaId.root as root where cdaId.extension.empty() -> identifier.system = 'urn:ietf:rfc:3986' "systemOid";#xD; cdaId.root as root where cdaId.extension.empty() -> identifier.value = append('urn:oid:', root) "valueOid";#xD; } "bundleIdentifier";#xD; cda -> bundle.type = 'document' "bundleType";#xD; cda.effectiveTime as effectiveTime -> bundle.timestamp = create('instant') as timestamp then TSInstant(effectiveTime, timestamp) "bundleTimestamp";#xD; // Composition using CdaToBundle function (includes patient mapping)#xD; cda -> composition then ClinicalDocumentComposition(cda, composition, patient, bundle) "composition";#xD; // Add gender mapping after ClinicalDocumentComposition (which calls ClinicalDocumentPatientRole)#xD; cda.recordTarget as recordTarget then {#xD; recordTarget.patientRole as patientRole then {#xD; patientRole.patient as cdaPatient then {#xD; cdaPatient.administrativeGenderCode as gender then MapGender(gender, patient) "patientGender";#xD; } "cdaPatient";#xD; };#xD; } "recordTargetGender";#xD; // Process sections with observations#xD; cda.component as cdaComp then {#xD; cdaComp.structuredBody as body then {#xD; body.component as bodyComp then {#xD; bodyComp.section as section then {#xD; // Create composition section#xD; section -> composition.section as compSection then {#xD; section.title as sectionTitle -> compSection.title = (sectionTitle.xmlText) "sectionTitle";#xD; section.code as sectionCode -> compSection.code = create('CodeableConcept') as cc then CDCodeableConcept(sectionCode, cc) "sectionCode";#xD; section.text as sectionText -> compSection.text = sectionText "sectionText";#xD; // Process observations in organizers#xD; section.entry as entry then {#xD; entry.organizer as organizer then {#xD; organizer.component as orgComp then {#xD; orgComp.observation as obs then {#xD; obs -> bundle.entry as obsEntry, obsEntry.resource = create('Observation') as observation, observation.id = uuid() as obsUuid, obsEntry.fullUrl = append('urn:uuid:', obsUuid), compSection.entry = create('Reference') as obsRef, obsRef.reference = append('urn:uuid:', obsUuid) then ProcessObservation(cda, obs, observation, patient, composition) "processObs";#xD; };#xD; } "orgComponent";#xD; };#xD; };#xD; } "compSection";#xD; };#xD; } "bodyComponent";#xD; };#xD; } "cdaComponent";#xD; }#xD; #xD; // Process individual observation using CdaToFHIRTypes functions#xD; group ProcessObservation(source cda : ClinicalDocument, source obs, target observation : Observation, target patient : Patient, target composition : Composition) {#xD; // Meta profile - ANS profiles based on LOINC code#xD; obs.code as obsCode where code = '29463-7' -> observation.meta = create('Meta') as meta then {#xD; obsCode -> meta.profile = 'https://interop.esante.gouv.fr/ig/fhir/mesures/StructureDefinition/mesures-fr-observation-body-weight' "profileWeight";#xD; } "metaWeight";#xD; obs.code as obsCode where code = '8302-2' -> observation.meta = create('Meta') as meta then {#xD; obsCode -> meta.profile = 'https://interop.esante.gouv.fr/ig/fhir/mesures/StructureDefinition/mesures-fr-observation-bodyheight' "profileHeight";#xD; } "metaHeight";#xD; obs.code as obsCode where code = '8287-5' -> observation.meta = create('Meta') as meta then {#xD; obsCode -> meta.profile = 'https://interop.esante.gouv.fr/ig/fhir/mesures/StructureDefinition/mesures-observation-head-circumference' "profileHeadCirc";#xD; } "metaHeadCirc";#xD; // Status - map CDA "completed" to FHIR "final"#xD; obs.statusCode as statusCode where code = 'completed' -> observation.status = 'final' "statusCompleted";#xD; obs.statusCode as statusCode where code != 'completed' -> observation.status = create('code') as status then CSCode(statusCode, status) "statusOther";#xD; // Category - vital-signs for all observations in CSE-MDE#xD; obs -> observation.category = create('CodeableConcept') as category then {#xD; obs -> category.coding = create('Coding') as coding then {#xD; obs -> coding.system = 'http://terminology.hl7.org/CodeSystem/observation-category' "system";#xD; obs -> coding.code = 'vital-signs' "code";#xD; } "coding";#xD; } "category";#xD; // Code using CDCodeableConcept from CdaToFHIRTypes#xD; obs.code as code -> observation.code = create('CodeableConcept') as cc then CDCodeableConcept(code, cc) "obsCode";#xD; // EffectiveDateTime - use effectiveTime from observation#xD; obs.effectiveTime as effectiveTime -> observation.effective = create('dateTime') as dt then TSDateTime(effectiveTime, dt) "effectiveDateTime";#xD; // Value as Quantity using PQQuantity from CdaToFHIRTypes#xD; obs.value as value -> observation.value = create('Quantity') as qty then PQQuantity(value, qty) "obsValue";#xD; // Subject reference#xD; obs -> observation.subject = create('Reference') as ref, ref.reference = ('urn:uuid:' + %patient.id) "obsSubject";#xD; }#xD; #xD; // Map CDA v3 administrative gender to FHIR gender#xD; group MapGender(source src, target patient : Patient) {#xD; src where code = 'M' -> patient.gender = 'male' "genderMale";#xD; src where code = 'F' -> patient.gender = 'female' "genderFemale";#xD; src where code = 'UN' -> patient.gender = 'other' "genderOther";#xD; src where code = 'UNK' -> patient.gender = 'unknown' "genderUnknown";#xD; }#xD; #xD;
Mapping CSE-MDE vers FHIR Bundle - Contexte Français
Agence du Numérique en Santé (ANS) - 2-10 Rue d'Oradour-sur-Glane, 75015 Paris
Process individual observation using CdaToFHIRTypes functions
Map CDA v3 administrative gender to FHIR gender