From 84d175e105ded3c4d0d0add1b24c5bd74e6b4bba Mon Sep 17 00:00:00 2001 From: Ben Mustapha Date: Wed, 10 Dec 2025 15:12:12 +0100 Subject: [PATCH 1/2] MAJ du mapping de l'entete --- .../MappingCDA_FHIR_Entete/ValueSetGender.fsh | 24 ---- input/pagecontent/mappingCDA-FHIR-entete.md | 112 +++++++++++++++++- sushi-config.yaml | 1 - 3 files changed, 106 insertions(+), 31 deletions(-) delete mode 100644 input/fsh/MappingCDA_FHIR_Entete/ValueSetGender.fsh diff --git a/input/fsh/MappingCDA_FHIR_Entete/ValueSetGender.fsh b/input/fsh/MappingCDA_FHIR_Entete/ValueSetGender.fsh deleted file mode 100644 index 797875963d..0000000000 --- a/input/fsh/MappingCDA_FHIR_Entete/ValueSetGender.fsh +++ /dev/null @@ -1,24 +0,0 @@ -Instance: mappingAdministrativeGender -InstanceOf: ConceptMap -Usage: #definition -Title: "Mapping ValueSet AdministrativeGender" -Description: "Mapping entre les codes du ValueSet FHIR AdministrativeGender et ceux du ValueSet JDV_J143-AdministrativeGender-CISIS établi par ce ConceptMap." - -* name = "Mapping ValueSet AdministrativeGender" -* status = #draft -* experimental = false - -* group[+].source = "http://hl7.org/fhir/administrative-gender" -* group[=].target = "https://mos.esante.gouv.fr/NOS/JDV_J143-AdministrativeGender-CISIS/FHIR/JDV-J143-AdministrativeGender-CISIS" - -* group[=].element[+].code = #male -* group[=].element[=].target.code = #M -* group[=].element[=].target.equivalence = #equivalent - -* group[=].element[+].code = #female -* group[=].element[=].target.code = #F -* group[=].element[=].target.equivalence = #equivalent - -* group[=].element[+].code = #unknown -* group[=].element[=].target.code = #UN -* group[=].element[=].target.equivalence = #equivalent \ No newline at end of file diff --git a/input/pagecontent/mappingCDA-FHIR-entete.md b/input/pagecontent/mappingCDA-FHIR-entete.md index 091e932145..21a6deb751 100644 --- a/input/pagecontent/mappingCDA-FHIR-entete.md +++ b/input/pagecontent/mappingCDA-FHIR-entete.md @@ -1,11 +1,13 @@ Liste des ConceptMap détaillant le mapping entre les éléments du modèle métier, du CDA et de FHIR. -### Éléments de 1ᵉʳ niveau +### Mapping entre les éléments de l'entête : Modèle métier / CDA / FHIR -{% sql { + + + + +{% sql { +"query": " +WITH AllGroups AS ( +-- Récupère tous les groupes de tous les ConceptMap +SELECT +r.id AS cm_id, +r.Web AS Web, +g.value AS group_json, +json_extract(g.value, '$.source') AS grp_source, +json_extract(g.value, '$.target') AS grp_target +FROM Resources r +JOIN json_each(r.json, '$.group') g +WHERE r.Type = 'ConceptMap' +), + +-- Classer chaque groupe en METIER / CDA / FHIR +ClassifiedGroups AS ( +SELECT +cm_id, +Web, +group_json, +grp_source, +grp_target, + +CASE +-- METIER +WHEN grp_source LIKE '%fr-lm%' THEN 'METIER' +-- CDA +WHEN grp_source LIKE '%cda%' OR grp_target LIKE '%cda%' OR grp_source LIKE '%fr-cda%' OR grp_target LIKE '%fr-cda%' THEN 'CDA' +-- FHIR + ELSE 'FHIR' +END AS grp_type +FROM AllGroups +), + +-- Extraire éléments + targets de chaque groupe classé +Elements AS ( +SELECT +cg.cm_id, +cg.Web, +cg.grp_type, +json_extract(e.value, '$.code') AS elem_code, +json_extract(t.value, '$.code') AS elem_target_code +FROM ClassifiedGroups cg +JOIN json_each(cg.group_json, '$.element') e +JOIN json_each(e.value, '$.target') t +), + +-- Construire tables temporaires METIER->CDA et CDA->FHIR +MetierToCDA AS ( +SELECT +cm_id, +Web, +elem_code AS Metier, +elem_target_code AS CDA +FROM Elements +WHERE grp_type = 'METIER' +), + +CDAtoFHIR AS ( +SELECT +cm_id, +elem_code AS CDA, +elem_target_code AS FHIR +FROM Elements +WHERE grp_type = 'CDA' +), + +-- join Metier->CDA with CDA->FHIR +FinalMapping AS ( +SELECT + m.Metier AS Metier, + m.CDA AS CDA, + cf.FHIR AS FHIR + FROM MetierToCDA m + LEFT JOIN CDAtoFHIR cf + ON m.cm_id = cf.cm_id + AND m.CDA = cf.CDA + ) + + SELECT + Metier, + CDA, + FHIR + FROM FinalMapping + ", + "class" : "lines", + "columns" : [ + { "title": "Modèle métier", "type": "markdown", "source": "Metier" }, + { "title": "CDA", "type": "markdown", "source": "CDA" }, + { "title": "FHIR", "type": "markdown", "source": "FHIR" } + ] + } %} + \ No newline at end of file diff --git a/sushi-config.yaml b/sushi-config.yaml index 78352a513d..1da019533b 100644 --- a/sushi-config.yaml +++ b/sushi-config.yaml @@ -446,7 +446,6 @@ groups: - mappingPersonneStructureRelatedEntityFHIR - mappingPersonneStructureAuteurFHIR - mappingSystemeFHIR - - mappingAdministrativeGender resources: Binary/BIO-CR-BIO-2024.01-Microbiologie-V1: From afd4e3ac5f8d4392260dc4ee1fe22b288dbe8b33 Mon Sep 17 00:00:00 2001 From: Ben Mustapha Date: Mon, 15 Dec 2025 10:03:06 +0100 Subject: [PATCH 2/2] =?UTF-8?q?Mise=20=C3=A0=20jour=20mapping=20entete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ModeleMetierCDAFHIR.fsh | 3 + .../MappingCDA_FHIR_Entete/PatientCDAFHIR.fsh | 2 +- input/pagecontent/mappingCDA-FHIR-entete.md | 205 +++++++++++------- 3 files changed, 135 insertions(+), 75 deletions(-) diff --git a/input/fsh/MappingCDA_FHIR_Entete/ModeleMetierCDAFHIR.fsh b/input/fsh/MappingCDA_FHIR_Entete/ModeleMetierCDAFHIR.fsh index 4862d6ee0a..292d212279 100644 --- a/input/fsh/MappingCDA_FHIR_Entete/ModeleMetierCDAFHIR.fsh +++ b/input/fsh/MappingCDA_FHIR_Entete/ModeleMetierCDAFHIR.fsh @@ -14,6 +14,9 @@ Description: """Ce ConceptMap présente trois groupes de mapping : // Groupe Mapping 1 : Modèle métier to CDA * group[+].source = "https://interop.esante.gouv.fr/ig/document/core/StructureDefinition/fr-lm-entete-document" * group[=].target = "https://interop.esante.gouv.fr/ig/document/core/StructureDefinition/fr-cda-clinical-document" +* group[=].element[+].code = #FRLMEnteteDocument +* group[=].element[=].target.code = #ClinicalDocument +* group[=].element[=].target.equivalence = #equivalent * group[=].element[+].code = #FRLMEnteteDocument.identifiantUniqueDocument * group[=].element[=].target.code = #ClinicalDocument.id * group[=].element[=].target.equivalence = #equivalent diff --git a/input/fsh/MappingCDA_FHIR_Entete/PatientCDAFHIR.fsh b/input/fsh/MappingCDA_FHIR_Entete/PatientCDAFHIR.fsh index 8986fc7212..6ec5ee7ced 100644 --- a/input/fsh/MappingCDA_FHIR_Entete/PatientCDAFHIR.fsh +++ b/input/fsh/MappingCDA_FHIR_Entete/PatientCDAFHIR.fsh @@ -32,7 +32,7 @@ Description: """Ce ConceptMap présente deux groupes de mapping : * group[=].element[=].target.code = #recordTarget.patientRole.patient.name.family * group[=].element[=].target.equivalence = #equivalent * group[=].element[+].code = #FRLMPatientUsager.personnePhysique.nomsPrenomsPatient.nom.nomNaissance -* group[=].element[=].target.code = #PrecordTarget.patientRole.patient.name.family@qualifier='BR' +* group[=].element[=].target.code = #recordTarget.patientRole.patient.name.family@qualifier='BR' * group[=].element[=].target.equivalence = #equivalent * group[=].element[+].code = #FRLMPatientUsager.personnePhysique.nomsPrenomsPatient.nom.nomUtilise * group[=].element[=].target.code = #recordTarget.patientRole.patient.name.family@qualifier='CL' diff --git a/input/pagecontent/mappingCDA-FHIR-entete.md b/input/pagecontent/mappingCDA-FHIR-entete.md index 21a6deb751..cc863c03e3 100644 --- a/input/pagecontent/mappingCDA-FHIR-entete.md +++ b/input/pagecontent/mappingCDA-FHIR-entete.md @@ -30,94 +30,151 @@ Liste des ConceptMap détaillant le mapping entre les éléments du modèle mét {% sql { "query": " WITH AllGroups AS ( --- Récupère tous les groupes de tous les ConceptMap -SELECT -r.id AS cm_id, -r.Web AS Web, -g.value AS group_json, -json_extract(g.value, '$.source') AS grp_source, -json_extract(g.value, '$.target') AS grp_target -FROM Resources r -JOIN json_each(r.json, '$.group') g -WHERE r.Type = 'ConceptMap' + -- Récupère tous les groupes de tous les ConceptMap et leur index + SELECT + r.id AS cm_id, + r.name AS Name, + r.Web AS Web, + g.key AS group_index, + g.value AS group_json, + json_extract(g.value, '$.source') AS grp_source, + json_extract(g.value, '$.target') AS grp_target + FROM Resources r + JOIN json_each(r.json, '$.group') g + WHERE r.Type = 'ConceptMap' ), --- Classer chaque groupe en METIER / CDA / FHIR ClassifiedGroups AS ( -SELECT -cm_id, -Web, -group_json, -grp_source, -grp_target, - -CASE --- METIER -WHEN grp_source LIKE '%fr-lm%' THEN 'METIER' --- CDA -WHEN grp_source LIKE '%cda%' OR grp_target LIKE '%cda%' OR grp_source LIKE '%fr-cda%' OR grp_target LIKE '%fr-cda%' THEN 'CDA' --- FHIR - ELSE 'FHIR' -END AS grp_type -FROM AllGroups + -- Classer chaque groupe en METIER / CDA / FHIR + SELECT + cm_id, + Name, + Web, + group_index, + group_json, + grp_source, + grp_target, + CASE + WHEN grp_source LIKE '%fr-lm%' THEN 'METIER' + WHEN grp_source LIKE '%cda%' + OR grp_target LIKE '%cda%' + OR grp_source LIKE '%fr-cda%' + OR grp_target LIKE '%fr-cda%' THEN 'CDA' + ELSE 'FHIR' + END AS grp_type + FROM AllGroups ), --- Extraire éléments + targets de chaque groupe classé Elements AS ( -SELECT -cg.cm_id, -cg.Web, -cg.grp_type, -json_extract(e.value, '$.code') AS elem_code, -json_extract(t.value, '$.code') AS elem_target_code -FROM ClassifiedGroups cg -JOIN json_each(cg.group_json, '$.element') e -JOIN json_each(e.value, '$.target') t + -- Extraire éléments + targets de chaque groupe classé + SELECT + cg.cm_id, + cg.Name, + cg.Web, + cg.group_index, + cg.grp_type, + e.key AS elem_index, + json_extract(e.value, '$.code') AS elem_code, + json_extract(t.value, '$.code') AS elem_target_code + FROM ClassifiedGroups cg + JOIN json_each(cg.group_json, '$.element') e + JOIN json_each(e.value, '$.target') t ), --- Construire tables temporaires METIER->CDA et CDA->FHIR MetierToCDA AS ( -SELECT -cm_id, -Web, -elem_code AS Metier, -elem_target_code AS CDA -FROM Elements -WHERE grp_type = 'METIER' + SELECT + cm_id, + Name, + Web, + group_index, + elem_index, + elem_code AS Metier, + elem_target_code AS CDA + FROM Elements + WHERE grp_type = 'METIER' ), CDAtoFHIR AS ( -SELECT -cm_id, -elem_code AS CDA, -elem_target_code AS FHIR -FROM Elements -WHERE grp_type = 'CDA' + SELECT + cm_id, + elem_index, + elem_code AS CDA, + elem_target_code AS FHIR + FROM Elements + WHERE grp_type = 'CDA' ), --- join Metier->CDA with CDA->FHIR FinalMapping AS ( -SELECT - m.Metier AS Metier, - m.CDA AS CDA, - cf.FHIR AS FHIR - FROM MetierToCDA m - LEFT JOIN CDAtoFHIR cf + -- Join Metier->CDA with CDA->FHIR + SELECT + m.Web, + m.Name, + m.group_index, + m.elem_index, + m.Metier, + m.CDA, + cf.FHIR + FROM MetierToCDA m + LEFT JOIN CDAtoFHIR cf ON m.cm_id = cf.cm_id AND m.CDA = cf.CDA - ) - - SELECT - Metier, - CDA, - FHIR - FROM FinalMapping - ", - "class" : "lines", - "columns" : [ - { "title": "Modèle métier", "type": "markdown", "source": "Metier" }, - { "title": "CDA", "type": "markdown", "source": "CDA" }, - { "title": "FHIR", "type": "markdown", "source": "FHIR" } - ] - } %} - \ No newline at end of file +) + +SELECT + CASE + WHEN Metier NOT LIKE '%.%' THEN + '**' || Metier || '**' + + WHEN (LENGTH(Metier) - LENGTH(REPLACE(Metier, '.', ''))) > 2 THEN + -- position du 1er point + substr(Metier, 1, + instr(Metier, '.') + + instr(substr(Metier, instr(Metier, '.') + 1), '.') + ) + || '\n' || + -- texte après le 2ème point + substr( + Metier, + instr(Metier, '.') + + instr(substr(Metier, instr(Metier, '.') + 1), '.') + 1 + ) + ELSE Metier +END AS Metier, + CASE + WHEN CDA NOT LIKE '%.%' THEN + '**' || CDA || '**' + + WHEN (LENGTH(CDA) - LENGTH(REPLACE(CDA, '.', ''))) > 2 THEN + -- position du 1er point + substr(CDA, 1, + instr(CDA, '.') + + instr(substr(CDA, instr(CDA, '.') + 1), '.') + ) + || '\n' || + -- texte après le 2ème point + substr( + CDA, + instr(CDA, '.') + + instr(substr(CDA, instr(CDA, '.') + 1), '.') + 1 + ) + ELSE CDA + END AS CDA, + CASE + WHEN FHIR NOT LIKE '%.%' THEN '**' || FHIR || '**' + ELSE FHIR + END AS FHIR, + Name AS \"Titre du profil\", + Web +FROM FinalMapping +ORDER BY + Name, + group_index, + elem_index +", +"class" : "lines", +"columns" : [ + { "title": "Modèle métier", "type": "markdown", "source": "Metier" }, + { "title": "CDA", "type": "markdown", "source": "CDA" }, + { "title": "FHIR", "type": "markdown", "source": "FHIR" } +] +} %}