From 78726283c68e57fa2845ab370c4afdd76b4a1795 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Tue, 7 Jan 2025 13:06:50 -0300 Subject: [PATCH] core: add some missing Encounter.class codes These codes were not handled, but now are: - OBSENC (v3) - I (v2 -> IMP) - P (v2 -> PRENC) Additionally, we verify the code system too now. --- .../core/core_templates/encounter.sql.jinja | 2 +- .../studies/core/fhir_mapping_tables.sql | 38 +++++++++++-------- .../core/reference_sql/builder_encounter.sql | 4 +- .../reference_sql/builder_prereq_tables.sql | 38 +++++++++++-------- tests/core/test_core_encounters.py | 25 ++++++++++++ 5 files changed, 75 insertions(+), 32 deletions(-) create mode 100644 tests/core/test_core_encounters.py diff --git a/cumulus_library/studies/core/core_templates/encounter.sql.jinja b/cumulus_library/studies/core/core_templates/encounter.sql.jinja index 389b646d..b5c4d401 100644 --- a/cumulus_library/studies/core/core_templates/encounter.sql.jinja +++ b/cumulus_library/studies/core/core_templates/encounter.sql.jinja @@ -135,6 +135,6 @@ SELECT DISTINCT concat('Encounter/', e.id) AS encounter_ref FROM temp_encounter AS e LEFT JOIN core__fhir_mapping_expected_act_encounter_code_v3 AS eac - ON e.class_code = eac.found + ON e.class_code = eac.found AND e.class_system = eac.found_system LEFT JOIN core__fhir_act_encounter_code_v3 AS ac ON eac.expected = ac.code INNER JOIN core__patient AS p ON e.subject_ref = p.subject_ref; diff --git a/cumulus_library/studies/core/fhir_mapping_tables.sql b/cumulus_library/studies/core/fhir_mapping_tables.sql index 2a040ac2..e3edd445 100644 --- a/cumulus_library/studies/core/fhir_mapping_tables.sql +++ b/cumulus_library/studies/core/fhir_mapping_tables.sql @@ -118,23 +118,31 @@ SELECT * FROM -- ############################################################ -- FHIR mapping of as found Encounter codes to the expected encounter code from --- http://hl7.org/fhir/STU3/v3/ActEncounterCode/vs.html +-- http://hl7.org/fhir/R4/v3/ActEncounterCode/vs.html CREATE TABLE core__fhir_mapping_expected_act_encounter_code_v3 AS SELECT * FROM ( VALUES - ('AMB', 'AMB'), - ('AMB', 'R'), - ('AMB', 'O'), - ('EMER', 'EMER'), - ('EMER', 'E'), - ('FLD', 'FLD'), - ('HH', 'HH'), - ('IMP', 'IMP'), - ('ACUTE', 'ACUTE'), - ('NONAC', 'NONAC'), - ('PRENC', 'PRENC'), - ('SS', 'SS'), - ('VR', 'VR') - ) AS t (expected, found); + -- http://hl7.org/fhir/R4/v3/ActEncounterCode/vs.html + -- This is the modern, expected class system. + ('AMB', 'AMB', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('EMER', 'EMER', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('FLD', 'FLD', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('HH', 'HH', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('IMP', 'IMP', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('ACUTE', 'ACUTE', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('NONAC', 'NONAC', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('OBSENC', 'OBSENC', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('PRENC', 'PRENC', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('SS', 'SS', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('VR', 'VR', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + -- http://terminology.hl7.org/CodeSystem/v2-0004 + -- This is an older class system, still in active use apparently (at BCH Cerner). + -- Unmapped codes: B (obstetrics), C (commercial), N (not applicable), U (unknown) + ('EMER', 'E', 'http://terminology.hl7.org/CodeSystem/v2-0004'), + ('IMP', 'I', 'http://terminology.hl7.org/CodeSystem/v2-0004'), + ('AMB', 'O', 'http://terminology.hl7.org/CodeSystem/v2-0004'), + ('PRENC', 'P', 'http://terminology.hl7.org/CodeSystem/v2-0004'), + ('AMB', 'R', 'http://terminology.hl7.org/CodeSystem/v2-0004') -- recurring patient + ) AS t (expected, found, found_system); diff --git a/cumulus_library/studies/core/reference_sql/builder_encounter.sql b/cumulus_library/studies/core/reference_sql/builder_encounter.sql index f20d76be..f024adb8 100644 --- a/cumulus_library/studies/core/reference_sql/builder_encounter.sql +++ b/cumulus_library/studies/core/reference_sql/builder_encounter.sql @@ -582,6 +582,7 @@ temp_encounter_completion AS ( SELECT ece.encounter_id, ( + -- Every time you add a resource here, update core-study-details.md BOOL_OR(ec.table_name = 'allergyintolerance') AND BOOL_OR(ec.table_name = 'condition') AND BOOL_OR(ec.table_name = 'diagnosticreport') @@ -705,7 +706,7 @@ SELECT DISTINCT concat('Encounter/', e.id) AS encounter_ref FROM temp_encounter AS e LEFT JOIN core__fhir_mapping_expected_act_encounter_code_v3 AS eac - ON e.class_code = eac.found + ON e.class_code = eac.found AND e.class_system = eac.found_system LEFT JOIN core__fhir_act_encounter_code_v3 AS ac ON eac.expected = ac.code INNER JOIN core__patient AS p ON e.subject_ref = p.subject_ref; @@ -735,6 +736,7 @@ temp_encounter_completion AS ( SELECT ece.encounter_id, ( + -- Every time you add a resource here, update core-study-details.md BOOL_OR(ec.table_name = 'allergyintolerance') AND BOOL_OR(ec.table_name = 'condition') AND BOOL_OR(ec.table_name = 'diagnosticreport') diff --git a/cumulus_library/studies/core/reference_sql/builder_prereq_tables.sql b/cumulus_library/studies/core/reference_sql/builder_prereq_tables.sql index 05489899..4ce4a040 100644 --- a/cumulus_library/studies/core/reference_sql/builder_prereq_tables.sql +++ b/cumulus_library/studies/core/reference_sql/builder_prereq_tables.sql @@ -258,23 +258,31 @@ SELECT * FROM -- ############################################################ -- FHIR mapping of as found Encounter codes to the expected encounter code from --- http://hl7.org/fhir/STU3/v3/ActEncounterCode/vs.html +-- http://hl7.org/fhir/R4/v3/ActEncounterCode/vs.html CREATE TABLE core__fhir_mapping_expected_act_encounter_code_v3 AS SELECT * FROM ( VALUES - ('AMB', 'AMB'), - ('AMB', 'R'), - ('AMB', 'O'), - ('EMER', 'EMER'), - ('EMER', 'E'), - ('FLD', 'FLD'), - ('HH', 'HH'), - ('IMP', 'IMP'), - ('ACUTE', 'ACUTE'), - ('NONAC', 'NONAC'), - ('PRENC', 'PRENC'), - ('SS', 'SS'), - ('VR', 'VR') - ) AS t (expected, found); + -- http://hl7.org/fhir/R4/v3/ActEncounterCode/vs.html + -- This is the modern, expected class system. + ('AMB', 'AMB', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('EMER', 'EMER', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('FLD', 'FLD', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('HH', 'HH', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('IMP', 'IMP', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('ACUTE', 'ACUTE', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('NONAC', 'NONAC', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('OBSENC', 'OBSENC', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('PRENC', 'PRENC', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('SS', 'SS', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + ('VR', 'VR', 'http://terminology.hl7.org/CodeSystem/v3-ActCode'), + -- http://terminology.hl7.org/CodeSystem/v2-0004 + -- This is an older class system, still in active use apparently (at BCH Cerner). + -- Unmapped codes: B (obstetrics), C (commercial), N (not applicable), U (unknown) + ('EMER', 'E', 'http://terminology.hl7.org/CodeSystem/v2-0004'), + ('IMP', 'I', 'http://terminology.hl7.org/CodeSystem/v2-0004'), + ('AMB', 'O', 'http://terminology.hl7.org/CodeSystem/v2-0004'), + ('PRENC', 'P', 'http://terminology.hl7.org/CodeSystem/v2-0004'), + ('AMB', 'R', 'http://terminology.hl7.org/CodeSystem/v2-0004') -- recurring patient + ) AS t (expected, found, found_system); diff --git a/tests/core/test_core_encounters.py b/tests/core/test_core_encounters.py new file mode 100644 index 00000000..ac922696 --- /dev/null +++ b/tests/core/test_core_encounters.py @@ -0,0 +1,25 @@ +"""Tests for core__encounter""" + +import json + +from tests import testbed_utils + + +def test_core_enc_class(tmp_path): + """Verify that we handle multiply rows as needed when multiple options appear""" + v2_sys = "http://terminology.hl7.org/CodeSystem/v2-0004" + v3_sys = "http://terminology.hl7.org/CodeSystem/v3-ActCode" + + testbed = testbed_utils.LocalTestbed(tmp_path) + testbed.add_encounter("o", **{"class": {"code": "O", "system": v2_sys}}) + testbed.add_encounter("obsenc", **{"class": {"code": "OBSENC", "system": v3_sys}}) + testbed.add_encounter("unsupported", **{"class": {"code": "?", "system": v3_sys}}) + + con = testbed.build() + df = con.sql("SELECT id, class_code, class_display FROM core__encounter ORDER BY id").df() + rows = json.loads(df.to_json(orient="records")) + assert rows == [ + {"id": "o", "class_code": "AMB", "class_display": "ambulatory"}, + {"id": "obsenc", "class_code": "OBSENC", "class_display": "observation encounter"}, + {"id": "unsupported", "class_code": None, "class_display": None}, + ]