cqm-reports 1.0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +33 -0
- data/README.md +27 -0
- data/Rakefile +16 -0
- data/lib/cqm_report.rb +77 -0
- data/lib/ext/code.rb +11 -0
- data/lib/ext/data_element.rb +24 -0
- data/lib/html-export/qdm-patient/_header_css.mustache +61 -0
- data/lib/html-export/qdm-patient/_javascript.mustache +52 -0
- data/lib/html-export/qdm-patient/data_element/_data_element.mustache +4 -0
- data/lib/html-export/qdm-patient/data_element/_data_element_codes.mustache +9 -0
- data/lib/html-export/qdm-patient/data_element/_data_element_other_fields.mustache +106 -0
- data/lib/html-export/qdm-patient/data_element/_data_element_times.mustache +44 -0
- data/lib/html-export/qdm-patient/qdm_patient.mustache +73 -0
- data/lib/html-export/qdm-patient/qdm_patient.rb +47 -0
- data/lib/qrda-export/catI-r5/_code.mustache +1 -0
- data/lib/qrda-export/catI-r5/_codes.mustache +10 -0
- data/lib/qrda-export/catI-r5/_header.mustache +28 -0
- data/lib/qrda-export/catI-r5/_measure_section.mustache +59 -0
- data/lib/qrda-export/catI-r5/_reporting_period.mustache +23 -0
- data/lib/qrda-export/catI-r5/qrda1_r5.mustache +209 -0
- data/lib/qrda-export/catI-r5/qrda1_r5.rb +220 -0
- data/lib/qrda-export/catI-r5/qrda_header/_author.mustache +26 -0
- data/lib/qrda-export/catI-r5/qrda_header/_custodian.mustache +43 -0
- data/lib/qrda-export/catI-r5/qrda_header/_documentation_of_service_event.mustache +88 -0
- data/lib/qrda-export/catI-r5/qrda_header/_information_recipient.mustache +7 -0
- data/lib/qrda-export/catI-r5/qrda_header/_legal_authenticator.mustache +25 -0
- data/lib/qrda-export/catI-r5/qrda_header/_participant.mustache +7 -0
- data/lib/qrda-export/catI-r5/qrda_header/_record_target.mustache +44 -0
- data/lib/qrda-export/catI-r5/qrda_templates/adverse_event.mustache +40 -0
- data/lib/qrda-export/catI-r5/qrda_templates/allergy_intolerance.mustache +42 -0
- data/lib/qrda-export/catI-r5/qrda_templates/assessment_order.mustache +25 -0
- data/lib/qrda-export/catI-r5/qrda_templates/assessment_performed.mustache +38 -0
- data/lib/qrda-export/catI-r5/qrda_templates/assessment_recommended.mustache +25 -0
- data/lib/qrda-export/catI-r5/qrda_templates/communication_performed.mustache +62 -0
- data/lib/qrda-export/catI-r5/qrda_templates/device_applied.mustache +41 -0
- data/lib/qrda-export/catI-r5/qrda_templates/device_order.mustache +38 -0
- data/lib/qrda-export/catI-r5/qrda_templates/device_recommended.mustache +37 -0
- data/lib/qrda-export/catI-r5/qrda_templates/diagnosis.mustache +55 -0
- data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_order.mustache +25 -0
- data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_performed.mustache +50 -0
- data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_recommended.mustache +21 -0
- data/lib/qrda-export/catI-r5/qrda_templates/encounter_order.mustache +35 -0
- data/lib/qrda-export/catI-r5/qrda_templates/encounter_performed.mustache +52 -0
- data/lib/qrda-export/catI-r5/qrda_templates/encounter_recommended.mustache +37 -0
- data/lib/qrda-export/catI-r5/qrda_templates/family_history.mustache +37 -0
- data/lib/qrda-export/catI-r5/qrda_templates/immunization_administered.mustache +35 -0
- data/lib/qrda-export/catI-r5/qrda_templates/immunization_order.mustache +46 -0
- data/lib/qrda-export/catI-r5/qrda_templates/intervention_order.mustache +24 -0
- data/lib/qrda-export/catI-r5/qrda_templates/intervention_performed.mustache +36 -0
- data/lib/qrda-export/catI-r5/qrda_templates/intervention_recommended.mustache +25 -0
- data/lib/qrda-export/catI-r5/qrda_templates/laboratory_test_order.mustache +24 -0
- data/lib/qrda-export/catI-r5/qrda_templates/laboratory_test_performed.mustache +42 -0
- data/lib/qrda-export/catI-r5/qrda_templates/laboratory_test_recommended.mustache +25 -0
- data/lib/qrda-export/catI-r5/qrda_templates/medication_active.mustache +32 -0
- data/lib/qrda-export/catI-r5/qrda_templates/medication_administered.mustache +39 -0
- data/lib/qrda-export/catI-r5/qrda_templates/medication_discharge.mustache +63 -0
- data/lib/qrda-export/catI-r5/qrda_templates/medication_dispensed.mustache +70 -0
- data/lib/qrda-export/catI-r5/qrda_templates/medication_order.mustache +64 -0
- data/lib/qrda-export/catI-r5/qrda_templates/patient_care_experience.mustache +14 -0
- data/lib/qrda-export/catI-r5/qrda_templates/patient_characteristic_clinical_trial_participant.mustache +18 -0
- data/lib/qrda-export/catI-r5/qrda_templates/patient_characteristic_expired.mustache +32 -0
- data/lib/qrda-export/catI-r5/qrda_templates/patient_characteristic_payer.mustache +14 -0
- data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_order.mustache +30 -0
- data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_performed.mustache +45 -0
- data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_recommended.mustache +30 -0
- data/lib/qrda-export/catI-r5/qrda_templates/procedure_order.mustache +32 -0
- data/lib/qrda-export/catI-r5/qrda_templates/procedure_performed.mustache +64 -0
- data/lib/qrda-export/catI-r5/qrda_templates/procedure_recommended.mustache +34 -0
- data/lib/qrda-export/catI-r5/qrda_templates/provider_care_experience.mustache +15 -0
- data/lib/qrda-export/catI-r5/qrda_templates/provider_characteristic.mustache +15 -0
- data/lib/qrda-export/catI-r5/qrda_templates/substance_recommended.mustache +35 -0
- data/lib/qrda-export/catI-r5/qrda_templates/symptom.mustache +48 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_admission_source.mustache +6 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_anatomical_location_site.mustache +1 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_author.mustache +29 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_author_participation.mustache +8 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_component.mustache +13 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_data_element_codes_as_values.mustache +10 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_days_supplied.mustache +6 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_encounter_diagnosis.mustache +21 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_facility_location.mustache +24 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_immunization_details.mustache +14 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_medication_details.mustache +36 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_medication_supply_request.mustache +17 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_method.mustache +1 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_ordinality.mustache +1 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_principal_diagnosis.mustache +8 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_reaction_observation.mustache +9 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_reason.mustache +12 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_related_to.mustache +6 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_results.mustache +24 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_severity.mustache +8 -0
- data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_status.mustache +8 -0
- data/lib/qrda-export/catIII-r2-1/_continuous_variable_value.mustache +17 -0
- data/lib/qrda-export/catIII-r2-1/_header.mustache +25 -0
- data/lib/qrda-export/catIII-r2-1/_measure_data.mustache +41 -0
- data/lib/qrda-export/catIII-r2-1/_measure_section.mustache +74 -0
- data/lib/qrda-export/catIII-r2-1/_reporting_period.mustache +23 -0
- data/lib/qrda-export/catIII-r2-1/_stratification.mustache +29 -0
- data/lib/qrda-export/catIII-r2-1/_supplemental_data.mustache +28 -0
- data/lib/qrda-export/catIII-r2-1/qrda3_r21.mustache +11 -0
- data/lib/qrda-export/catIII-r2-1/qrda3_r21.rb +127 -0
- data/lib/qrda-export/catIII-r2-1/qrda_header/_author.mustache +25 -0
- data/lib/qrda-export/catIII-r2-1/qrda_header/_custodian.mustache +17 -0
- data/lib/qrda-export/catIII-r2-1/qrda_header/_documentation_of_service_event.mustache +88 -0
- data/lib/qrda-export/catIII-r2-1/qrda_header/_legal_authenticator.mustache +25 -0
- data/lib/qrda-export/helper/aggregate_object_helper.rb +154 -0
- data/lib/qrda-export/helper/cat1_view_helper.rb +81 -0
- data/lib/qrda-export/helper/date_helper.rb +108 -0
- data/lib/qrda-export/helper/frequency_helper.rb +83 -0
- data/lib/qrda-export/helper/patient_view_helper.rb +46 -0
- data/lib/qrda-export/helper/view_helper.rb +28 -0
- data/lib/qrda-import/base-importers/demographics_importer.rb +38 -0
- data/lib/qrda-import/base-importers/section_importer.rb +237 -0
- data/lib/qrda-import/cda_identifier.rb +20 -0
- data/lib/qrda-import/data-element-importers/adverse_event_importer.rb +26 -0
- data/lib/qrda-import/data-element-importers/allergy_intolerance_importer.rb +24 -0
- data/lib/qrda-import/data-element-importers/assessment_order_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/assessment_performed_importer.rb +24 -0
- data/lib/qrda-import/data-element-importers/assessment_recommended_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/communication_performed_importer.rb +30 -0
- data/lib/qrda-import/data-element-importers/device_applied_importer.rb +22 -0
- data/lib/qrda-import/data-element-importers/device_order_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/device_recommended_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/diagnosis_importer.rb +24 -0
- data/lib/qrda-import/data-element-importers/diagnostic_study_order_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/diagnostic_study_performed_importer.rb +32 -0
- data/lib/qrda-import/data-element-importers/diagnostic_study_recommended_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/encounter_order_importer.rb +21 -0
- data/lib/qrda-import/data-element-importers/encounter_performed_importer.rb +46 -0
- data/lib/qrda-import/data-element-importers/encounter_recommended_importer.rb +21 -0
- data/lib/qrda-import/data-element-importers/family_history_importer.rb +21 -0
- data/lib/qrda-import/data-element-importers/immunization_administered_importer.rb +23 -0
- data/lib/qrda-import/data-element-importers/immunization_order_importer.rb +27 -0
- data/lib/qrda-import/data-element-importers/intervention_order_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/intervention_performed_importer.rb +23 -0
- data/lib/qrda-import/data-element-importers/intervention_recommended_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/laboratory_test_order_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/laboratory_test_performed_importer.rb +29 -0
- data/lib/qrda-import/data-element-importers/laboratory_test_recommended_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/medication_active_importer.rb +25 -0
- data/lib/qrda-import/data-element-importers/medication_administered_importer.rb +26 -0
- data/lib/qrda-import/data-element-importers/medication_discharge_importer.rb +32 -0
- data/lib/qrda-import/data-element-importers/medication_dispensed_importer.rb +37 -0
- data/lib/qrda-import/data-element-importers/medication_order_importer.rb +36 -0
- data/lib/qrda-import/data-element-importers/patient_care_experience_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/patient_characteristic_clinical_trial_participant_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/patient_characteristic_expired_importer.rb +22 -0
- data/lib/qrda-import/data-element-importers/patient_characteristic_payer_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/physical_exam_order_importer.rb +21 -0
- data/lib/qrda-import/data-element-importers/physical_exam_performed_importer.rb +27 -0
- data/lib/qrda-import/data-element-importers/physical_exam_recommended_importer.rb +21 -0
- data/lib/qrda-import/data-element-importers/procedure_order_importer.rb +23 -0
- data/lib/qrda-import/data-element-importers/procedure_performed_importer.rb +33 -0
- data/lib/qrda-import/data-element-importers/procedure_recommended_importer.rb +23 -0
- data/lib/qrda-import/data-element-importers/provider_care_experience_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/provider_characteristic_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/substance_administered_importer.rb +27 -0
- data/lib/qrda-import/data-element-importers/substance_order_importer.rb +29 -0
- data/lib/qrda-import/data-element-importers/substance_recommended_importer.rb +27 -0
- data/lib/qrda-import/data-element-importers/symptom_importer.rb +21 -0
- data/lib/qrda-import/entry_finder.rb +20 -0
- data/lib/qrda-import/entry_package.rb +16 -0
- data/lib/qrda-import/narrative_reference_handler.rb +33 -0
- data/lib/qrda-import/patient_importer.rb +128 -0
- data/lib/util/code_system_helper.rb +77 -0
- data/lib/util/hqmf_template_helper.rb +52 -0
- data/lib/util/hqmf_template_oid_map.json +654 -0
- data/lib/util/hqmfr2_template_oid_map.json +378 -0
- data/lib/util/hqmfr2cql_template_oid_map.json +390 -0
- data/lib/util/qrda_template_helper.rb +20 -0
- data/lib/util/qrdar5_1_template_oid_map.json +406 -0
- data/lib/util/qrdar5_template_oid_map.json +406 -0
- metadata +344 -0
@@ -0,0 +1,237 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class SectionImporter
|
4
|
+
attr_accessor :check_for_usable, :status_xpath, :code_xpath
|
5
|
+
|
6
|
+
def initialize(entry_finder)
|
7
|
+
@entry_finder = entry_finder
|
8
|
+
@code_xpath = "./cda:code"
|
9
|
+
@entry_id_map = {}
|
10
|
+
@check_for_usable = true
|
11
|
+
@entry_class = QDM::DataElement
|
12
|
+
end
|
13
|
+
|
14
|
+
# Traverses an HL7 CDA document passed in and creates an Array of Entry
|
15
|
+
# objects based on what it finds
|
16
|
+
# @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
|
17
|
+
# will have the "cda" namespace registered to "urn:hl7-org:v3"
|
18
|
+
# measure definition
|
19
|
+
# @return [Array] will be a list of Entry objects
|
20
|
+
def create_entries(doc, nrh = NarrativeReferenceHandler.new)
|
21
|
+
entry_list = []
|
22
|
+
@entry_id_map = {}
|
23
|
+
entry_elements = @entry_finder.entries(doc)
|
24
|
+
entry_elements.each do |entry_element|
|
25
|
+
entry = create_entry(entry_element, nrh)
|
26
|
+
if @check_for_usable
|
27
|
+
entry_list << entry if usable_entry?(entry)
|
28
|
+
else
|
29
|
+
entry_list << entry
|
30
|
+
end
|
31
|
+
end
|
32
|
+
[entry_list, @entry_id_map]
|
33
|
+
end
|
34
|
+
|
35
|
+
def usable_entry?(entry)
|
36
|
+
entry.dataElementCodes.present?
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_entry(entry_element, _nrh = NarrativeReferenceHandler.new)
|
40
|
+
entry = @entry_class.new
|
41
|
+
# This is the id found in the QRDA file
|
42
|
+
entry_qrda_id = extract_id(entry_element, @id_xpath)
|
43
|
+
# Create a hash to map all of entry.ids to the same QRDA ids. This will be used to merge QRDA entries
|
44
|
+
# that represent the same event.
|
45
|
+
@entry_id_map["#{entry_qrda_id.value}_#{entry_qrda_id.namingSystem}"] ||= []
|
46
|
+
@entry_id_map["#{entry_qrda_id.value}_#{entry_qrda_id.namingSystem}"] << entry.id
|
47
|
+
entry.dataElementCodes = extract_codes(entry_element, @code_xpath)
|
48
|
+
extract_dates(entry_element, entry)
|
49
|
+
if @result_xpath
|
50
|
+
entry.result = extract_result_values(entry_element)
|
51
|
+
end
|
52
|
+
extract_reason_or_negation(entry_element, entry)
|
53
|
+
entry
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def extract_id(parent_element, id_xpath)
|
59
|
+
id_element = parent_element.at_xpath(id_xpath)
|
60
|
+
return unless id_element
|
61
|
+
|
62
|
+
# If an extension is not included, use the root as the value. Other wise use the extension
|
63
|
+
value = id_element['extension'] || id_element['root']
|
64
|
+
identifier = QDM::Id.new(value: value, namingSystem: id_element['root'])
|
65
|
+
identifier
|
66
|
+
end
|
67
|
+
|
68
|
+
def extract_codes(coded_element, code_xpath)
|
69
|
+
code_list = []
|
70
|
+
code_elements = coded_element.xpath(code_xpath)
|
71
|
+
code_elements.each do |code_element|
|
72
|
+
code_list << code_if_present(code_element)
|
73
|
+
translations = code_element.xpath('cda:translation')
|
74
|
+
translations.each do |translation|
|
75
|
+
code_list << code_if_present(translation)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
code_list.compact
|
79
|
+
end
|
80
|
+
|
81
|
+
def code_if_present(code_element)
|
82
|
+
return unless code_element && code_element['codeSystem'] && code_element['code']
|
83
|
+
|
84
|
+
QDM::Code.new(code_element['code'], HQMF::Util::CodeSystemHelper.code_system_for(code_element['codeSystem']))
|
85
|
+
end
|
86
|
+
|
87
|
+
def extract_dates(parent_element, entry)
|
88
|
+
entry.authorDatetime = extract_time(parent_element, @author_datetime_xpath) if @author_datetime_xpath
|
89
|
+
entry.relevantPeriod = extract_interval(parent_element, @relevant_period_xpath) if @relevant_period_xpath
|
90
|
+
entry.prevalencePeriod = extract_interval(parent_element, @prevalence_period_xpath) if @prevalence_period_xpath
|
91
|
+
end
|
92
|
+
|
93
|
+
def extract_interval(parent_element, interval_xpath)
|
94
|
+
if parent_element.at_xpath("#{interval_xpath}/@value")
|
95
|
+
low_time = DateTime.parse(parent_element.at_xpath(interval_xpath)['value'])
|
96
|
+
high_time = DateTime.parse(parent_element.at_xpath(interval_xpath)['value'])
|
97
|
+
end
|
98
|
+
if parent_element.at_xpath("#{interval_xpath}/cda:low")
|
99
|
+
low_time = DateTime.parse(parent_element.at_xpath("#{interval_xpath}/cda:low")['value'])
|
100
|
+
end
|
101
|
+
if parent_element.at_xpath("#{interval_xpath}/cda:high")
|
102
|
+
high_time = if parent_element.at_xpath("#{interval_xpath}/cda:high")['value']
|
103
|
+
DateTime.parse(parent_element.at_xpath("#{interval_xpath}/cda:high")['value'])
|
104
|
+
else
|
105
|
+
DateTime.new(9999,1,1)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
if parent_element.at_xpath("#{interval_xpath}/cda:center")
|
109
|
+
low_time = Time.parse(parent_element.at_xpath("#{interval_xpath}/cda:center")['value'])
|
110
|
+
high_time = Time.parse(parent_element.at_xpath("#{interval_xpath}/cda:center")['value'])
|
111
|
+
end
|
112
|
+
QDM::Interval.new(low_time, high_time).shift_dates(0)
|
113
|
+
end
|
114
|
+
|
115
|
+
def extract_time(parent_element, datetime_xpath)
|
116
|
+
DateTime.parse(parent_element.at_xpath(datetime_xpath)['value']) if parent_element.at_xpath("#{datetime_xpath}/@value")
|
117
|
+
end
|
118
|
+
|
119
|
+
def frequency_as_coded_value(parent_element, frequency_xpath)
|
120
|
+
# Find the frequency interval in hours
|
121
|
+
frequency = extract_frequency_in_hours(parent_element, frequency_xpath)
|
122
|
+
# If a frequency interval is not found, return nil
|
123
|
+
return nil unless frequency[:low]
|
124
|
+
# If a frequency interval is found, search for a corresponding Direct Reference Code
|
125
|
+
key, value = Qrda::Export::Helper::FrequencyHelper::FREQUENCY_CODE_MAP.select { |_k,v| v[:low] == frequency['low'] && v[:high] == frequency['high'] && v[:institution_specified] == frequency['institution_specified'] && v[:unit] == frequency['unit'] }.first
|
126
|
+
# If a Direct Reference Code isn't found, return nil
|
127
|
+
return nil unless key
|
128
|
+
# If a Direct Reference Code is found, return that code
|
129
|
+
QDM::Code.new(key, HQMF::Util::CodeSystemHelper.code_system_for(value[:codeSystem]))
|
130
|
+
end
|
131
|
+
|
132
|
+
def extract_frequency_in_hours(parent_element, frequency_xpath)
|
133
|
+
# Need to go get low, high and institutionspecified
|
134
|
+
low = parent_element.at_xpath("#{frequency_xpath}/@value").value if parent_element.at_xpath("#{frequency_xpath}/@value")
|
135
|
+
low = parent_element.at_xpath("#{frequency_xpath}/cda:period/cda:low/@value").value if parent_element.at_xpath("#{frequency_xpath}/cda:period/cda:low/@value")
|
136
|
+
unit = parent_element.at_xpath("#{frequency_xpath}/@unit").value if parent_element.at_xpath("#{frequency_xpath}/@unit")
|
137
|
+
unit = parent_element.at_xpath("#{frequency_xpath}/cda:period/cda:low/@unit").value if parent_element.at_xpath("#{frequency_xpath}/cda:period/cda:low/@unit")
|
138
|
+
high = parent_element.at_xpath("#{frequency_xpath}/cda:period/cda:high/@value").value if parent_element.at_xpath("#{frequency_xpath}/cda:period/cda:high/@value")
|
139
|
+
institution_specified = parent_element.at_xpath("#{frequency_xpath}/@institutionSpecified") || false
|
140
|
+
# Expected units are H (hours) and D (days)
|
141
|
+
if unit && unit.upcase == 'D'
|
142
|
+
low = low * 24 if low
|
143
|
+
high = high * 34 if high
|
144
|
+
end
|
145
|
+
{ low: low, high: high, unit: unit, institution_specified: institution_specified }
|
146
|
+
end
|
147
|
+
|
148
|
+
def extract_result_values(parent_element)
|
149
|
+
result = []
|
150
|
+
parent_element.xpath(@result_xpath).each do |elem|
|
151
|
+
result << extract_result_value(elem)
|
152
|
+
end
|
153
|
+
result.size > 1 ? result : result.first
|
154
|
+
end
|
155
|
+
|
156
|
+
def extract_result_value(value_element)
|
157
|
+
return unless value_element && !value_element['nullFlavor']
|
158
|
+
|
159
|
+
value = value_element['value']
|
160
|
+
if value.present?
|
161
|
+
return value.strip.to_i if (value_element['unit'] == "1" || value_element['unit'].nil?)
|
162
|
+
|
163
|
+
return QDM::Quantity.new(value.strip.to_i, value_element['unit'])
|
164
|
+
elsif value_element['code'].present?
|
165
|
+
return code_if_present(value_element)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# extracts the reason or negation data. if an element is negated and the code has a null flavor, a random code is assigned for calculation
|
170
|
+
# coded_parent_element is the 'parent' element when the coded is nested (e.g., medication order)
|
171
|
+
def extract_reason_or_negation(parent_element, entry, coded_parent_element = nil)
|
172
|
+
coded_parent_element ||= parent_element
|
173
|
+
reason_element = parent_element.xpath(".//cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value | .//cda:entryRelationship[@typeCode='RSON']/cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.1.27']/cda:code")
|
174
|
+
negation_indicator = parent_element['negationInd']
|
175
|
+
unless reason_element.blank?
|
176
|
+
if negation_indicator.eql?('true')
|
177
|
+
entry.negationRationale = code_if_present(reason_element.first)
|
178
|
+
else
|
179
|
+
entry.reason = code_if_present(reason_element.first) unless @entry_does_not_have_reason
|
180
|
+
end
|
181
|
+
end
|
182
|
+
extract_negated_code(coded_parent_element, entry)
|
183
|
+
end
|
184
|
+
|
185
|
+
def extract_negated_code(coded_parent_element, entry)
|
186
|
+
code_elements = coded_parent_element.xpath(@code_xpath)
|
187
|
+
code_elements.each do |code_element|
|
188
|
+
if code_element['nullFlavor'] == 'NA' && code_element['sdtc:valueSet']
|
189
|
+
entry.dataElementCodes = [{ code: code_element['sdtc:valueSet'], codeSystem: 'NA_VALUESET' }]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def extract_scalar(parent_element, scalar_xpath)
|
195
|
+
scalar_element = parent_element.at_xpath(scalar_xpath)
|
196
|
+
return unless scalar_element
|
197
|
+
|
198
|
+
QDM::Quantity.new(scalar_element['value'].to_i, scalar_element['unit'])
|
199
|
+
end
|
200
|
+
|
201
|
+
def extract_components(parent_element)
|
202
|
+
component_elements = parent_element.xpath(@components_xpath)
|
203
|
+
components = []
|
204
|
+
component_elements&.each do |component_element|
|
205
|
+
component = QDM::Component.new
|
206
|
+
component.code = code_if_present(component_element.at_xpath('./cda:code'))
|
207
|
+
component.result = extract_result_value(component_element.at_xpath('./cda:value'))
|
208
|
+
components << component
|
209
|
+
end
|
210
|
+
components
|
211
|
+
end
|
212
|
+
|
213
|
+
def extract_facility_locations(parent_element)
|
214
|
+
facility_location_elements = parent_element.xpath(@facility_locations_xpath)
|
215
|
+
facility_locations = []
|
216
|
+
facility_location_elements&.each do |facility_location_element|
|
217
|
+
facility_location = QDM::FacilityLocation.new
|
218
|
+
participant_element = facility_location_element.at_xpath("./cda:participantRole[@classCode='SDLOC']/cda:code")
|
219
|
+
facility_location.code = code_if_present(participant_element)
|
220
|
+
facility_location.locationPeriod = extract_interval(facility_location_element, './cda:time')
|
221
|
+
facility_locations << facility_location
|
222
|
+
end
|
223
|
+
facility_locations
|
224
|
+
end
|
225
|
+
|
226
|
+
def extract_related_to(parent_element)
|
227
|
+
related_to_elements = parent_element.xpath(@related_to_xpath)
|
228
|
+
related_ids = []
|
229
|
+
related_to_elements.each do |related_to_element|
|
230
|
+
related_ids << extract_id(related_to_element, './sdtc:id')
|
231
|
+
end
|
232
|
+
related_ids
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'mongoid'
|
2
|
+
|
3
|
+
class CDAIdentifier
|
4
|
+
include Mongoid::Document
|
5
|
+
include Mongoid::Attributes::Dynamic
|
6
|
+
|
7
|
+
field :root, type: String
|
8
|
+
field :extension, type: String
|
9
|
+
embedded_in :cda_identifiable, polymorphic: true
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
return unless other.respond_to?(:root) && other.respond_to?(:extension)
|
13
|
+
|
14
|
+
root == other.root && extension == other.extension
|
15
|
+
end
|
16
|
+
|
17
|
+
def hash
|
18
|
+
"#{root}#{extension}".hash
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class AdverseEventImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.146']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:id'
|
7
|
+
@code_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.148']/cda:value"
|
8
|
+
@author_datetime_xpath = './cda:author/cda:time'
|
9
|
+
@relevant_period_xpath = './cda:effectiveTime'
|
10
|
+
@facility_locations_xpath = "./cda:participant[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.100']"
|
11
|
+
@severity_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.8']/cda:value"
|
12
|
+
@type_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.9']/cda:value"
|
13
|
+
@entry_class = QDM::AdverseEvent
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
17
|
+
adverse_event = super
|
18
|
+
adverse_event.severity = code_if_present(entry_element.at_xpath(@severity_xpath))
|
19
|
+
adverse_event.type = code_if_present(entry_element.at_xpath(@type_xpath))
|
20
|
+
adverse_event.facilityLocation = extract_facility_locations(entry_element)[0]
|
21
|
+
adverse_event
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class AllergyIntoleranceImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.147']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:id'
|
7
|
+
@code_xpath = './cda:participant/cda:participantRole/cda:playingEntity/cda:code'
|
8
|
+
@author_datetime_xpath = "./cda:author/cda:time"
|
9
|
+
@prevalence_period_xpath = "./cda:effectiveTime"
|
10
|
+
@severity_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.8']/cda:value"
|
11
|
+
@type_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.9']/cda:value"
|
12
|
+
@entry_class = QDM::AllergyIntolerance
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
16
|
+
allergy_intolerance = super
|
17
|
+
allergy_intolerance.severity = code_if_present(entry_element.at_xpath(@severity_xpath))
|
18
|
+
allergy_intolerance.type = code_if_present(entry_element.at_xpath(@type_xpath))
|
19
|
+
allergy_intolerance
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class AssessmentOrderImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.158']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:id'
|
7
|
+
@code_xpath = './cda:code'
|
8
|
+
@author_datetime_xpath = "./cda:author/cda:time"
|
9
|
+
@entry_class = QDM::AssessmentOrder
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
13
|
+
assessment_order = super
|
14
|
+
assessment_order
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class AssessmentPerformedImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.144']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:id'
|
7
|
+
@code_xpath = './cda:code'
|
8
|
+
@author_datetime_xpath = "./cda:author/cda:time"
|
9
|
+
@result_xpath = "./cda:value"
|
10
|
+
@method_xpath = './cda:methodCode'
|
11
|
+
@components_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.149']"
|
12
|
+
@entry_class = QDM::AssessmentPerformed
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
16
|
+
assessment_performed = super
|
17
|
+
assessment_performed.method = code_if_present(entry_element.at_xpath(@method_xpath))
|
18
|
+
assessment_performed.components = extract_components(entry_element)
|
19
|
+
assessment_performed
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class AssessmentRecommendedImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.145']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:id'
|
7
|
+
@code_xpath = './cda:code'
|
8
|
+
@author_datetime_xpath = "./cda:author/cda:time"
|
9
|
+
@entry_class = QDM::AssessmentRecommended
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
13
|
+
assessment_recommended = super
|
14
|
+
assessment_recommended
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class CommunicationPerformedImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:act[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.156']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@entry_does_not_have_reason = true
|
7
|
+
@id_xpath = './cda:id'
|
8
|
+
@code_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
|
9
|
+
@author_datetime_xpath = "./cda:author/cda:time"
|
10
|
+
@relevant_period_xpath = "./cda:effectiveTime"
|
11
|
+
@related_to_xpath = "./sdtc:inFulfillmentOf1/sdtc:actReference"
|
12
|
+
@category_xpath = './cda:code'
|
13
|
+
@medium_xpath = "./cda:participant[@typeCode='VIA']/cda:participantRole/cda:code"
|
14
|
+
@sender_xpath = "./cda:participant[@typeCode='AUT']/cda:participantRole/cda:code"
|
15
|
+
@recipient_xpath = "./cda:participant[@typeCode='IRCP']/cda:participantRole/cda:code"
|
16
|
+
@entry_class = QDM::CommunicationPerformed
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
20
|
+
communication_performed = super
|
21
|
+
communication_performed.category = code_if_present(entry_element.at_xpath(@category_xpath))
|
22
|
+
communication_performed.medium = code_if_present(entry_element.at_xpath(@medium_xpath))
|
23
|
+
communication_performed.sender = code_if_present(entry_element.at_xpath(@sender_xpath))
|
24
|
+
communication_performed.recipient = code_if_present(entry_element.at_xpath(@recipient_xpath))
|
25
|
+
communication_performed.relatedTo = extract_related_to(entry_element)
|
26
|
+
communication_performed
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class DeviceAppliedImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:procedure[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.7']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:id'
|
7
|
+
@code_xpath = './cda:participant/cda:participantRole/cda:playingDevice/cda:code'
|
8
|
+
@author_datetime_xpath = "./cda:author/cda:time"
|
9
|
+
@relevant_period_xpath = "./cda:effectiveTime"
|
10
|
+
@anatomical_location_site_xpath = "./cda:targetSiteCode"
|
11
|
+
@entry_class = QDM::DeviceApplied
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
15
|
+
device_applied = super
|
16
|
+
device_applied.anatomicalLocationSite = code_if_present(entry_element.at_xpath(@anatomical_location_site_xpath))
|
17
|
+
device_applied
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class DeviceOrderImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:act[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.130']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.9']/cda:id"
|
7
|
+
@code_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.9']/cda:participant/cda:participantRole/cda:playingDevice/cda:code"
|
8
|
+
@author_datetime_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.9']/cda:author/cda:time"
|
9
|
+
@entry_class = QDM::DeviceOrder
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
13
|
+
device_order = super
|
14
|
+
device_order
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class DeviceRecommendedImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:act[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.131']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.10']/cda:id"
|
7
|
+
@code_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.10']/cda:participant/cda:participantRole/cda:playingDevice/cda:code"
|
8
|
+
@author_datetime_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.10']/cda:author/cda:time"
|
9
|
+
@entry_class = QDM::DeviceRecommended
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
13
|
+
device_recommended = super
|
14
|
+
device_recommended
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class DiagnosisImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:act[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.137']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:entryRelationship/cda:observation/cda:id'
|
7
|
+
@code_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.135']/cda:value"
|
8
|
+
@author_datetime_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.135']/cda:author/cda:time"
|
9
|
+
@prevalence_period_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.135']/cda:effectiveTime"
|
10
|
+
@anatomical_location_site_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.135']/cda:targetSiteCode"
|
11
|
+
@severity_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.135']/cda:entryRelationship/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.8']/cda:value"
|
12
|
+
@entry_class = QDM::Diagnosis
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
16
|
+
diagnosis = super
|
17
|
+
diagnosis.anatomicalLocationSite = code_if_present(entry_element.at_xpath(@anatomical_location_site_xpath))
|
18
|
+
diagnosis.severity = code_if_present(entry_element.at_xpath(@severity_xpath))
|
19
|
+
diagnosis
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class DiagnosticStudyOrderImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.17']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:id'
|
7
|
+
@code_xpath = './cda:code'
|
8
|
+
@author_datetime_xpath = "./cda:author/cda:time"
|
9
|
+
@entry_class = QDM::DiagnosticStudyOrder
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
13
|
+
diagnostic_study_order = super
|
14
|
+
diagnostic_study_order
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class DiagnosticStudyPerformedImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.18']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:id'
|
7
|
+
@code_xpath = './cda:code'
|
8
|
+
@relevant_period_xpath = "./cda:effectiveTime"
|
9
|
+
@author_datetime_xpath = "./cda:author/cda:time"
|
10
|
+
@result_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.2']/cda:value"
|
11
|
+
@result_datetime_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.2']/cda:effectiveTime"
|
12
|
+
@status_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.93']/cda:value"
|
13
|
+
@method_xpath = './cda:methodCode'
|
14
|
+
@facility_locations_xpath = "./cda:participant[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.100']"
|
15
|
+
@components_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.149']"
|
16
|
+
@entry_class = QDM::DiagnosticStudyPerformed
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
20
|
+
diagnostic_study_performed = super
|
21
|
+
diagnostic_study_performed.resultDatetime = extract_time(entry_element, @result_datetime_xpath)
|
22
|
+
diagnostic_study_performed.resultDatetime ||= extract_interval(entry_element, @result_datetime_xpath).low
|
23
|
+
diagnostic_study_performed.status = code_if_present(entry_element.at_xpath(@status_xpath))
|
24
|
+
diagnostic_study_performed.method = code_if_present(entry_element.at_xpath(@method_xpath))
|
25
|
+
diagnostic_study_performed.facilityLocation = extract_facility_locations(entry_element)[0]
|
26
|
+
diagnostic_study_performed.components = extract_components(entry_element)
|
27
|
+
diagnostic_study_performed
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class DiagnosticStudyRecommendedImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.19']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:id'
|
7
|
+
@code_xpath = './cda:code'
|
8
|
+
@author_datetime_xpath = "./cda:author/cda:time"
|
9
|
+
@entry_class = QDM::DiagnosticStudyRecommended
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
13
|
+
diagnostic_study_recommended = super
|
14
|
+
diagnostic_study_recommended
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class EncounterOrderImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:act[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.132']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:entryRelationship/cda:encounter/cda:id'
|
7
|
+
@code_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.22']/cda:code"
|
8
|
+
@author_datetime_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.22']/cda:author/cda:time"
|
9
|
+
@facility_locations_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.22']/cda:participant[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.100']"
|
10
|
+
@entry_class = QDM::EncounterOrder
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
14
|
+
encounter_order = super
|
15
|
+
encounter_order.facilityLocation = extract_facility_locations(entry_element)[0]
|
16
|
+
encounter_order
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module QRDA
|
2
|
+
module Cat1
|
3
|
+
class EncounterPerformedImporter < SectionImporter
|
4
|
+
def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:act[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.133']"))
|
5
|
+
super(entry_finder)
|
6
|
+
@id_xpath = './cda:entryRelationship/cda:encounter/cda:id'
|
7
|
+
@code_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/cda:code"
|
8
|
+
@relevant_period_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/cda:effectiveTime"
|
9
|
+
@author_datetime_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/cda:author/cda:time"
|
10
|
+
@admission_source_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/cda:participant/cda:participantRole[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.151']/cda:code"
|
11
|
+
@discharge_disposition_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/sdtc:dischargeDispositionCode"
|
12
|
+
@facility_locations_xpath = "./cda:entryRelationship/cda:encounter/cda:participant[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.100']"
|
13
|
+
@principal_diagnosis_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/cda:entryRelationship/cda:observation[cda:code/@code='8319008']/cda:value"
|
14
|
+
@diagnosis_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/cda:entryRelationship/cda:act/cda:entryRelationship/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.4']"
|
15
|
+
@entry_class = QDM::EncounterPerformed
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
|
19
|
+
encounter_performed = super
|
20
|
+
encounter_performed.admissionSource = code_if_present(entry_element.at_xpath(@admission_source_xpath))
|
21
|
+
encounter_performed.dischargeDisposition = code_if_present(entry_element.at_xpath(@discharge_disposition_xpath))
|
22
|
+
encounter_performed.facilityLocations = extract_facility_locations(entry_element)
|
23
|
+
encounter_performed.principalDiagnosis = code_if_present(entry_element.at_xpath(@principal_diagnosis_xpath))
|
24
|
+
encounter_performed.diagnoses = extract_diagnoses(entry_element)
|
25
|
+
if encounter_performed&.relevantPeriod&.low && encounter_performed&.relevantPeriod&.high
|
26
|
+
los = encounter_performed.relevantPeriod.high - encounter_performed.relevantPeriod.low
|
27
|
+
encounter_performed.lengthOfStay = QDM::Quantity.new(los.to_i, 'd')
|
28
|
+
end
|
29
|
+
encounter_performed
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def extract_diagnoses(parent_element)
|
35
|
+
diagnosis_elements = parent_element.xpath(@diagnosis_xpath)
|
36
|
+
diagnosis_list = []
|
37
|
+
diagnosis_elements.each do |diagnosis_element|
|
38
|
+
diagnosis_value = diagnosis_element.at_xpath("./cda:value")
|
39
|
+
diagnosis_list << code_if_present(diagnosis_value)
|
40
|
+
end
|
41
|
+
diagnosis_list.empty? ? nil : diagnosis_list
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|