Data Management with FHIR
0.1.0 - ci-build
Data Management with FHIR - Local Development build (v0.1.0) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions
| Official URL: https://interop.aphp.fr/ig/fhir/dm/StructureMap/CorePhysical2FHIR | Version: 0.1.0 | |||
| Draft as of 2025-10-23 | Computable Name: CorePhysical2FHIR | |||
Alignement de l''usage Core du modèle physique du DPI vers les ressources FHIR
map "https://interop.aphp.fr/ig/fhir/dm/StructureMap/CorePhysical2FHIR" = "CorePhysical2FHIR" // Alignement de l''usage Core du modèle physique du DPI vers les ressources FHIR uses "https://interop.aphp.fr/ig/fhir/dm/StructureDefinition/CoreDataSet" alias DataSet as source uses "https://interop.aphp.fr/ig/fhir/dm/StructureDefinition/CorePatient" alias PatientTable as source uses "https://interop.aphp.fr/ig/fhir/dm/StructureDefinition/CoreSejour" alias SejourTable as source uses "https://interop.aphp.fr/ig/fhir/dm/StructureDefinition/CoreBiology" alias BiologyTable as source uses "https://interop.aphp.fr/ig/fhir/dm/StructureDefinition/CoreClinical" alias ClinicalTable as source uses "https://interop.aphp.fr/ig/fhir/dm/StructureDefinition/CoreDiag" alias DiagTable as source uses "https://interop.aphp.fr/ig/fhir/dm/StructureDefinition/CoreActe" alias ActeTable as source uses "https://interop.aphp.fr/ig/fhir/dm/StructureDefinition/CoreAddress" alias AddressTable as source uses "https://interop.aphp.fr/ig/fhir/dm/StructureDefinition/CoreMedicationAdm" alias MedicationAdmTable as source uses "https://interop.aphp.fr/ig/fhir/dm/StructureDefinition/CoreMedicationPre" alias MedicationPreTable as source uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias FHIRBundle as target uses "http://hl7.org/fhir/StructureDefinition/Patient" alias FHIRPatient as target uses "http://hl7.org/fhir/StructureDefinition/Encounter" alias FHIREncounter as target uses "http://hl7.org/fhir/StructureDefinition/Observation" alias FHIRObservation as target uses "http://hl7.org/fhir/StructureDefinition/Meta" alias FHIRMeta as target uses "http://hl7.org/fhir/StructureDefinition/Procedure" alias FHIRProcedure as target uses "http://hl7.org/fhir/StructureDefinition/Condition" alias FHIRCondition as target group dataSet(source srcDataSet : DataSet, target tgtBundle : FHIRBundle) <<types>> { srcDataSet -> tgtBundle.id = uuid() "setId"; srcDataSet -> tgtBundle.type = 'transaction' "setType"; srcDataSet.patient as srcPatient -> tgtBundle.entry as tgtPatientEntry, tgtPatientEntry.resource = create('Patient') as newPatient then { srcPatient then patient(srcPatient, newPatient) "setPatient"; srcPatient then setEntryRequestAndFullUrl(newPatient, tgtPatientEntry) "setRequestAndFullUrl"; srcDataSet.address as srcAddress where patientNi.reference = ('PatientCore/' + %srcPatient.patientNi.toString()) then patientAddress(srcAddress, newPatient) "addPatientAddress"; srcDataSet.sejour as srcSejour where patientNi.reference = ('PatientCore/' + %srcPatient.patientNi.toString()) -> tgtBundle.entry as tgtEncounterEntry, tgtEncounterEntry.resource = create('Encounter') as newEncounter then { srcSejour then encounter(srcSejour, newPatient, newEncounter) "setEncounter"; srcSejour then setEntryRequestAndFullUrl(newEncounter, tgtEncounterEntry) "setRequestAndFullUrl"; srcDataSet.acte as srcActe where sejourNi.reference = ('SejourCore/' + %srcSejour.sejourNi.toString()) -> tgtBundle.entry as tgtProcedureEntry, tgtProcedureEntry.resource = create('Procedure') as newProcedure then { srcActe then procedure(srcActe, newPatient, newEncounter, newProcedure) "setProcedure"; srcActe then setEntryRequestAndFullUrl(newProcedure, tgtProcedureEntry) "setRequestAndFullUrl"; } "createProcedure"; srcDataSet.diag as srcDiag where sejourNi.reference = ('SejourCore/' + %srcSejour.sejourNi.toString()) -> tgtBundle.entry as tgtConditionEntry, tgtConditionEntry.resource = create('Condition') as newCondition then { srcDiag then condition(srcDiag, newPatient, newEncounter, newCondition) "setCondition"; srcDiag then setEntryRequestAndFullUrl(newCondition, tgtConditionEntry) "setRequestAndFullUrl"; } "createProcedure"; srcDataSet.biology as srcBiology where sejourNi.reference = ('SejourCore/' + %srcSejour.sejourNi.toString()) -> tgtBundle.entry as tgtBiologyEntry, tgtBiologyEntry.resource = create('Observation') as newObservation then { srcBiology then observationBiol(srcBiology, newPatient, newEncounter, newObservation) "setBiology"; srcBiology then setEntryRequestAndFullUrl(newObservation, tgtBiologyEntry) "setRequestAndFullUrl"; } "createObservation"; } "createEncounter"; } "createPatient"; } group patient(source srcPatient : PatientTable, target tgtPatient : FHIRPatient) { srcPatient -> tgtPatient.id = uuid() "setId"; srcPatient.patientNi as srcNi -> tgtPatient.meta as tgtMeta then setPatientMeta(srcNi, tgtMeta) "setMeta"; // copie la valeur du champ patientNi de la table Patient dans l'élément id de la ressource FHIR Patient srcPatient -> tgtPatient.name as tgtPatientName then setHumainName(srcPatient, tgtPatientName) "setHumainName"; srcPatient -> tgtPatient.identifier as tgtPatientIdentifier then setHumainNir(srcPatient, tgtPatientIdentifier) "setHumainNir"; srcPatient.gender as srcPatientGender -> tgtPatient.gender = translate(srcPatientGender, 'https://interop.aphp.fr/ig/fhir/dm/ConceptMap/DpiGender2Hl7Gender', 'code') "setGender"; // traduit la valeur du champ gender de la table Patient dans l'élément gender de la ressource FHIR Patient srcPatient.birthDate as srcPatientBirthDate -> tgtPatient.birthDate = srcPatientBirthDate "setBirthDate"; // copie la valeur du champ birthDate de la table Patient dans l'élément birthDate de la ressource FHIR Patient } group setPatientMeta(source srcNi, target tgtMeta : FHIRMeta) { srcNi -> tgtMeta.source = ('https://aphp.fr/fhir/Endpoint/dpi/PatientTable' + '/' + %srcNi.toString()) "setSource"; } group setHumainName(source srcPatient : PatientTable, target tgtPatientName) { srcPatient -> tgtPatientName.use = 'usual' "setUse"; // srcPatient -> tgtPatientName.text = (%srcPatient.firstName + ' ' + %srcPatient.name) "setText"; // srcPatient.name as srcPatientName -> tgtPatientName.family = srcPatientName "setName"; // srcPatient.firstName as srcPatientFirstName -> tgtPatientName.given = srcPatientFirstName "setFirstName"; // les trois lignes précédentes marchent dans matchbox mais génèrent une erreur au QA. La solution ci dessous marche dans matchbox et ne génère pas d'erreur au QA. srcPatient.name as srcPatientName -> tgtPatientName.family = srcPatientName then { srcPatient.firstName as srcPatientFirstName -> tgtPatientName.given = srcPatientFirstName, tgtPatientName.text = (%srcPatientFirstName + ' ' + %srcPatientName) "setFirstNameAndText"; } "setName"; } group setHumainNir(source srcPatient : PatientTable, target tgtPatientIdentifier) { srcPatient.nir as srcPatientNir -> tgtPatientIdentifier.use = 'official', tgtPatientIdentifier.type = cc('https://hl7.fr/ig/fhir/core/CodeSystem/fr-core-cs-v2-0203', 'INS-NIR'), tgtPatientIdentifier.system = 'urn:oid:1.2.250.1.213.1.4.8', tgtPatientIdentifier.value = srcPatientNir "setNir"; } group patientAddress(source srcAddress : AddressTable, target tgtPatient : FHIRPatient) { srcAddress -> tgtPatient.address = create('Address') as newAddress then { srcAddress.zipCode as srczip -> newAddress.postalCode = srczip "setZip"; srcAddress.city as srcCity -> newAddress.city = srcCity "setCity"; srcAddress.country as srcCountry -> newAddress.country = srcCountry "setCountry"; srcAddress.address as srcAddressText -> newAddress.text = srcAddressText "setText"; srcAddress where current = true -> newAddress.use = 'home' "setUseHome"; srcAddress where current = false -> newAddress.use = 'old' "setUseOld"; srcAddress where latitude.exists() or longitude.exists() -> newAddress.extension = create('Extension') as firstLevelExtension then { srcAddress -> firstLevelExtension.url = ('http://hl7.org/fhir/StructureDefinition/geolocation') then { srcAddress.latitude as srcLat -> firstLevelExtension.extension = create('Extension') as latExtension then { srcLat -> latExtension.url = ('latitude'), latExtension.value = srcLat "setLat"; } "setLatExt"; srcAddress.longitude as srcLong -> firstLevelExtension.extension = create('Extension') as longExtension then { srcLong -> longExtension.url = ('longitude'), longExtension.value = srcLong "setLong"; } "setLongExt"; } "setflext"; } "setCoordinatesExtension"; } "setAddress"; } group encounter(source srcSejour : SejourTable, source srcPatient : FHIRPatient, target tgtEncounter : FHIREncounter) { srcSejour -> tgtEncounter.id = uuid() "setId"; srcSejour.sejourNi as srcNi -> tgtEncounter.meta as tgtMeta then setEncounterMeta(srcNi, tgtMeta) "setMeta"; // copie la valeur du champ patientNi de la table Patient dans l'élément id de la ressource FHIR Patient srcSejour -> tgtEncounter.status = 'finished' "setStatus"; srcSejour.sejourType as srcSejourType -> tgtEncounter.class = translate(srcSejourType, 'https://interop.aphp.fr/ig/fhir/dm/ConceptMap/DpiEncounterType2SemanticLayerEncounterClass', 'Coding') "setEncounterClass"; srcPatient.id as patientId -> tgtEncounter.subject = create('Reference') as newSubject then setSubjectReference(patientId, newSubject) "setSubjectReference"; srcSejour.patientNi; // fk vers le patient à conserver pour la construction auto du périmètre final srcSejour -> tgtEncounter.period = create('Period') as newActualPeriod then { srcSejour.sejourStart as srcPeriodStart -> newActualPeriod.start = srcPeriodStart "setStart"; srcSejour.sejourEnd as srcPeriodEnd -> newActualPeriod.end = srcPeriodEnd "setEnd"; } "setPeriod"; } group setEncounterMeta(source srcNi, target tgtMeta : FHIRMeta) { srcNi -> tgtMeta.source = ('https://aphp.fr/fhir/Endpoint/dpi/SejourTable' + '/' + %srcNi.toString()) "setSource"; } group setSubjectReference(source srcPatientId, target newSubject) { srcPatientId -> newSubject.reference = ('Patient/' + %srcPatientId.toString()) "setReference"; } group procedure(source srcActe : ActeTable, source srcPatient : FHIRPatient, source srcEncounter : FHIREncounter, target tgtProcedure : FHIRProcedure) { srcActe -> tgtProcedure.id = uuid() "setId"; srcActe.acteNi as srcNi -> tgtProcedure.meta as tgtMeta then setProcedureMeta(srcNi, tgtMeta) "setMeta"; srcPatient.id as patientId -> tgtProcedure.subject = create('Reference') as newSubject then setSubjectReference(patientId, newSubject) "setSubjectReference"; srcEncounter.id as encounterId -> tgtProcedure.encounter = create('Reference') as newEncounter then setEncounterReference(encounterId, newEncounter) "setEncounterReference"; srcActe -> tgtProcedure.status = 'completed' "setStatus"; srcActe where dateStart.exists() or dateEnd.exists -> tgtProcedure.performed = create('Period') as tgtProcedurePeriod then { srcActe.dateStart as srcActeStart -> tgtProcedurePeriod.start = srcActeStart "setActeStart"; srcActe.dateEnd as srcActeEnd -> tgtProcedurePeriod.end = srcActeEnd "setActeEnd"; } "setDate"; srcActe.code as acteCode -> tgtProcedure.code = cc('https://smt.esante.gouv.fr/terminologie-ccam', acteCode) "setCode"; // C'est le code de la CCAM facturante } group setProcedureMeta(source srcNi, target tgtMeta : FHIRMeta) { srcNi -> tgtMeta.source = ('https://aphp.fr/fhir/Endpoint/dpi/ActeTable' + '/' + %srcNi.toString()) "setSource"; } group setEncounterReference(source srcEncounterId, target newEncounter) { srcEncounterId -> newEncounter.reference = ('Encounter/' + %srcEncounterId.toString()) "setReference"; } group condition(source srcDiag : DiagTable, source srcPatient : FHIRPatient, source srcEncounter : FHIREncounter, target tgtCondition : FHIRCondition) { srcDiag -> tgtCondition.id = uuid() "setId"; srcDiag.diagNi as srcNi -> tgtCondition.meta as tgtMeta then setConditionMeta(srcNi, tgtMeta) "setMeta"; srcPatient.id as patientId -> tgtCondition.subject = create('Reference') as newSubject then setSubjectReference(patientId, newSubject) "setSubjectReference"; srcEncounter.id as encounterId -> tgtCondition.encounter = create('Reference') as newEncounter then setEncounterReference(encounterId, newEncounter) "setEncounterReference"; srcDiag -> tgtCondition.verificationStatus = 'confirmed' "setVerificationStatus"; srcDiag -> tgtCondition.category = cc('http://terminology.hl7.org/CodeSystem/condition-category', 'encounter-diagnosis') "setCategory"; srcDiag.code as diagCode -> tgtCondition.code = cc('http://hl7.org/fhir/sid/icd-10', diagCode) "setCode"; } group setConditionMeta(source srcNi, target tgtMeta : FHIRMeta) { srcNi -> tgtMeta.source = ('https://aphp.fr/fhir/Endpoint/dpi/DiagTable' + '/' + %srcNi.toString()) "setSource"; } group observationBiol(source srcBiology : BiologyTable, source srcPatient : FHIRPatient, source srcEncounter : FHIREncounter, target tgtObservation : FHIRObservation) { srcBiology -> tgtObservation.id = uuid() "setId"; srcBiology.biologyNi as srcNi -> tgtObservation.meta as tgtMeta then setBiologyMeta(srcNi, tgtMeta) "setMeta"; srcPatient.id as patientId -> tgtObservation.subject = create('Reference') as newSubject then setSubjectReference(patientId, newSubject) "setSubjectReference"; srcEncounter.id as encounterId -> tgtObservation.encounter = create('Reference') as newEncounter then setEncounterReference(encounterId, newEncounter) "setEncounterReference"; srcBiology -> tgtObservation.status = 'final' "setStatus"; srcBiology -> tgtObservation.category = cc('http://terminology.hl7.org/CodeSystem/observation-category', 'vital-signs') "setCategory"; srcBiology.biologyDatePrel as biologyDatePrel -> tgtObservation.effective = biologyDatePrel "setDate"; srcBiology.biologyCode as biologyCode -> tgtObservation.code = cc('http://loinc.org', biologyCode) "setCode"; srcBiology.biologyValue -> tgtObservation.value = create('Quantity') as tgtObsQuantity then { srcBiology.biologyValue as biologyValue -> tgtObsQuantity.value = biologyValue "setValue"; srcBiology.biologyUnit as biologyUnit -> tgtObsQuantity.code = biologyUnit, tgtObsQuantity.unit = biologyUnit, tgtObsQuantity.system = 'http://unitsofmeasure.org' "setUnit"; } "setQuantity"; } group setBiologyMeta(source srcNi, target tgtMeta : FHIRMeta) { srcNi -> tgtMeta.source = ('https://aphp.fr/fhir/Endpoint/dpi/BiologyTable' + '/' + %srcNi.toString()) "setSource"; } group setEntryRequestAndFullUrl(source newRes, target tgtEntry) { newRes.id as newResId then { newResId -> tgtEntry.fullUrl = ('https://aphp.fr/' + %newRes.type().name + '/' + %newResId) "setFullUrl"; newResId -> tgtEntry.request as tgtEntryRequest, tgtEntryRequest.method = 'POST', tgtEntryRequest.url = (%newRes.type().name + '/' + %newResId) "setRequest"; } "setResourceType"; }