cqm-reports 1.0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +33 -0
  3. data/README.md +27 -0
  4. data/Rakefile +16 -0
  5. data/lib/cqm_report.rb +77 -0
  6. data/lib/ext/code.rb +11 -0
  7. data/lib/ext/data_element.rb +24 -0
  8. data/lib/html-export/qdm-patient/_header_css.mustache +61 -0
  9. data/lib/html-export/qdm-patient/_javascript.mustache +52 -0
  10. data/lib/html-export/qdm-patient/data_element/_data_element.mustache +4 -0
  11. data/lib/html-export/qdm-patient/data_element/_data_element_codes.mustache +9 -0
  12. data/lib/html-export/qdm-patient/data_element/_data_element_other_fields.mustache +106 -0
  13. data/lib/html-export/qdm-patient/data_element/_data_element_times.mustache +44 -0
  14. data/lib/html-export/qdm-patient/qdm_patient.mustache +73 -0
  15. data/lib/html-export/qdm-patient/qdm_patient.rb +47 -0
  16. data/lib/qrda-export/catI-r5/_code.mustache +1 -0
  17. data/lib/qrda-export/catI-r5/_codes.mustache +10 -0
  18. data/lib/qrda-export/catI-r5/_header.mustache +28 -0
  19. data/lib/qrda-export/catI-r5/_measure_section.mustache +59 -0
  20. data/lib/qrda-export/catI-r5/_reporting_period.mustache +23 -0
  21. data/lib/qrda-export/catI-r5/qrda1_r5.mustache +209 -0
  22. data/lib/qrda-export/catI-r5/qrda1_r5.rb +220 -0
  23. data/lib/qrda-export/catI-r5/qrda_header/_author.mustache +26 -0
  24. data/lib/qrda-export/catI-r5/qrda_header/_custodian.mustache +43 -0
  25. data/lib/qrda-export/catI-r5/qrda_header/_documentation_of_service_event.mustache +88 -0
  26. data/lib/qrda-export/catI-r5/qrda_header/_information_recipient.mustache +7 -0
  27. data/lib/qrda-export/catI-r5/qrda_header/_legal_authenticator.mustache +25 -0
  28. data/lib/qrda-export/catI-r5/qrda_header/_participant.mustache +7 -0
  29. data/lib/qrda-export/catI-r5/qrda_header/_record_target.mustache +44 -0
  30. data/lib/qrda-export/catI-r5/qrda_templates/adverse_event.mustache +40 -0
  31. data/lib/qrda-export/catI-r5/qrda_templates/allergy_intolerance.mustache +42 -0
  32. data/lib/qrda-export/catI-r5/qrda_templates/assessment_order.mustache +25 -0
  33. data/lib/qrda-export/catI-r5/qrda_templates/assessment_performed.mustache +38 -0
  34. data/lib/qrda-export/catI-r5/qrda_templates/assessment_recommended.mustache +25 -0
  35. data/lib/qrda-export/catI-r5/qrda_templates/communication_performed.mustache +62 -0
  36. data/lib/qrda-export/catI-r5/qrda_templates/device_applied.mustache +41 -0
  37. data/lib/qrda-export/catI-r5/qrda_templates/device_order.mustache +38 -0
  38. data/lib/qrda-export/catI-r5/qrda_templates/device_recommended.mustache +37 -0
  39. data/lib/qrda-export/catI-r5/qrda_templates/diagnosis.mustache +55 -0
  40. data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_order.mustache +25 -0
  41. data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_performed.mustache +50 -0
  42. data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_recommended.mustache +21 -0
  43. data/lib/qrda-export/catI-r5/qrda_templates/encounter_order.mustache +35 -0
  44. data/lib/qrda-export/catI-r5/qrda_templates/encounter_performed.mustache +52 -0
  45. data/lib/qrda-export/catI-r5/qrda_templates/encounter_recommended.mustache +37 -0
  46. data/lib/qrda-export/catI-r5/qrda_templates/family_history.mustache +37 -0
  47. data/lib/qrda-export/catI-r5/qrda_templates/immunization_administered.mustache +35 -0
  48. data/lib/qrda-export/catI-r5/qrda_templates/immunization_order.mustache +46 -0
  49. data/lib/qrda-export/catI-r5/qrda_templates/intervention_order.mustache +24 -0
  50. data/lib/qrda-export/catI-r5/qrda_templates/intervention_performed.mustache +36 -0
  51. data/lib/qrda-export/catI-r5/qrda_templates/intervention_recommended.mustache +25 -0
  52. data/lib/qrda-export/catI-r5/qrda_templates/laboratory_test_order.mustache +24 -0
  53. data/lib/qrda-export/catI-r5/qrda_templates/laboratory_test_performed.mustache +42 -0
  54. data/lib/qrda-export/catI-r5/qrda_templates/laboratory_test_recommended.mustache +25 -0
  55. data/lib/qrda-export/catI-r5/qrda_templates/medication_active.mustache +32 -0
  56. data/lib/qrda-export/catI-r5/qrda_templates/medication_administered.mustache +39 -0
  57. data/lib/qrda-export/catI-r5/qrda_templates/medication_discharge.mustache +63 -0
  58. data/lib/qrda-export/catI-r5/qrda_templates/medication_dispensed.mustache +70 -0
  59. data/lib/qrda-export/catI-r5/qrda_templates/medication_order.mustache +64 -0
  60. data/lib/qrda-export/catI-r5/qrda_templates/patient_care_experience.mustache +14 -0
  61. data/lib/qrda-export/catI-r5/qrda_templates/patient_characteristic_clinical_trial_participant.mustache +18 -0
  62. data/lib/qrda-export/catI-r5/qrda_templates/patient_characteristic_expired.mustache +32 -0
  63. data/lib/qrda-export/catI-r5/qrda_templates/patient_characteristic_payer.mustache +14 -0
  64. data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_order.mustache +30 -0
  65. data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_performed.mustache +45 -0
  66. data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_recommended.mustache +30 -0
  67. data/lib/qrda-export/catI-r5/qrda_templates/procedure_order.mustache +32 -0
  68. data/lib/qrda-export/catI-r5/qrda_templates/procedure_performed.mustache +64 -0
  69. data/lib/qrda-export/catI-r5/qrda_templates/procedure_recommended.mustache +34 -0
  70. data/lib/qrda-export/catI-r5/qrda_templates/provider_care_experience.mustache +15 -0
  71. data/lib/qrda-export/catI-r5/qrda_templates/provider_characteristic.mustache +15 -0
  72. data/lib/qrda-export/catI-r5/qrda_templates/substance_recommended.mustache +35 -0
  73. data/lib/qrda-export/catI-r5/qrda_templates/symptom.mustache +48 -0
  74. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_admission_source.mustache +6 -0
  75. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_anatomical_location_site.mustache +1 -0
  76. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_author.mustache +29 -0
  77. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_author_participation.mustache +8 -0
  78. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_component.mustache +13 -0
  79. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_data_element_codes_as_values.mustache +10 -0
  80. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_days_supplied.mustache +6 -0
  81. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_encounter_diagnosis.mustache +21 -0
  82. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_facility_location.mustache +24 -0
  83. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_immunization_details.mustache +14 -0
  84. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_medication_details.mustache +36 -0
  85. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_medication_supply_request.mustache +17 -0
  86. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_method.mustache +1 -0
  87. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_ordinality.mustache +1 -0
  88. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_principal_diagnosis.mustache +8 -0
  89. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_reaction_observation.mustache +9 -0
  90. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_reason.mustache +12 -0
  91. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_related_to.mustache +6 -0
  92. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_results.mustache +24 -0
  93. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_severity.mustache +8 -0
  94. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_status.mustache +8 -0
  95. data/lib/qrda-export/catIII-r2-1/_continuous_variable_value.mustache +17 -0
  96. data/lib/qrda-export/catIII-r2-1/_header.mustache +25 -0
  97. data/lib/qrda-export/catIII-r2-1/_measure_data.mustache +41 -0
  98. data/lib/qrda-export/catIII-r2-1/_measure_section.mustache +74 -0
  99. data/lib/qrda-export/catIII-r2-1/_reporting_period.mustache +23 -0
  100. data/lib/qrda-export/catIII-r2-1/_stratification.mustache +29 -0
  101. data/lib/qrda-export/catIII-r2-1/_supplemental_data.mustache +28 -0
  102. data/lib/qrda-export/catIII-r2-1/qrda3_r21.mustache +11 -0
  103. data/lib/qrda-export/catIII-r2-1/qrda3_r21.rb +127 -0
  104. data/lib/qrda-export/catIII-r2-1/qrda_header/_author.mustache +25 -0
  105. data/lib/qrda-export/catIII-r2-1/qrda_header/_custodian.mustache +17 -0
  106. data/lib/qrda-export/catIII-r2-1/qrda_header/_documentation_of_service_event.mustache +88 -0
  107. data/lib/qrda-export/catIII-r2-1/qrda_header/_legal_authenticator.mustache +25 -0
  108. data/lib/qrda-export/helper/aggregate_object_helper.rb +154 -0
  109. data/lib/qrda-export/helper/cat1_view_helper.rb +81 -0
  110. data/lib/qrda-export/helper/date_helper.rb +108 -0
  111. data/lib/qrda-export/helper/frequency_helper.rb +83 -0
  112. data/lib/qrda-export/helper/patient_view_helper.rb +46 -0
  113. data/lib/qrda-export/helper/view_helper.rb +28 -0
  114. data/lib/qrda-import/base-importers/demographics_importer.rb +38 -0
  115. data/lib/qrda-import/base-importers/section_importer.rb +237 -0
  116. data/lib/qrda-import/cda_identifier.rb +20 -0
  117. data/lib/qrda-import/data-element-importers/adverse_event_importer.rb +26 -0
  118. data/lib/qrda-import/data-element-importers/allergy_intolerance_importer.rb +24 -0
  119. data/lib/qrda-import/data-element-importers/assessment_order_importer.rb +19 -0
  120. data/lib/qrda-import/data-element-importers/assessment_performed_importer.rb +24 -0
  121. data/lib/qrda-import/data-element-importers/assessment_recommended_importer.rb +19 -0
  122. data/lib/qrda-import/data-element-importers/communication_performed_importer.rb +30 -0
  123. data/lib/qrda-import/data-element-importers/device_applied_importer.rb +22 -0
  124. data/lib/qrda-import/data-element-importers/device_order_importer.rb +19 -0
  125. data/lib/qrda-import/data-element-importers/device_recommended_importer.rb +19 -0
  126. data/lib/qrda-import/data-element-importers/diagnosis_importer.rb +24 -0
  127. data/lib/qrda-import/data-element-importers/diagnostic_study_order_importer.rb +19 -0
  128. data/lib/qrda-import/data-element-importers/diagnostic_study_performed_importer.rb +32 -0
  129. data/lib/qrda-import/data-element-importers/diagnostic_study_recommended_importer.rb +19 -0
  130. data/lib/qrda-import/data-element-importers/encounter_order_importer.rb +21 -0
  131. data/lib/qrda-import/data-element-importers/encounter_performed_importer.rb +46 -0
  132. data/lib/qrda-import/data-element-importers/encounter_recommended_importer.rb +21 -0
  133. data/lib/qrda-import/data-element-importers/family_history_importer.rb +21 -0
  134. data/lib/qrda-import/data-element-importers/immunization_administered_importer.rb +23 -0
  135. data/lib/qrda-import/data-element-importers/immunization_order_importer.rb +27 -0
  136. data/lib/qrda-import/data-element-importers/intervention_order_importer.rb +19 -0
  137. data/lib/qrda-import/data-element-importers/intervention_performed_importer.rb +23 -0
  138. data/lib/qrda-import/data-element-importers/intervention_recommended_importer.rb +19 -0
  139. data/lib/qrda-import/data-element-importers/laboratory_test_order_importer.rb +19 -0
  140. data/lib/qrda-import/data-element-importers/laboratory_test_performed_importer.rb +29 -0
  141. data/lib/qrda-import/data-element-importers/laboratory_test_recommended_importer.rb +19 -0
  142. data/lib/qrda-import/data-element-importers/medication_active_importer.rb +25 -0
  143. data/lib/qrda-import/data-element-importers/medication_administered_importer.rb +26 -0
  144. data/lib/qrda-import/data-element-importers/medication_discharge_importer.rb +32 -0
  145. data/lib/qrda-import/data-element-importers/medication_dispensed_importer.rb +37 -0
  146. data/lib/qrda-import/data-element-importers/medication_order_importer.rb +36 -0
  147. data/lib/qrda-import/data-element-importers/patient_care_experience_importer.rb +19 -0
  148. data/lib/qrda-import/data-element-importers/patient_characteristic_clinical_trial_participant_importer.rb +19 -0
  149. data/lib/qrda-import/data-element-importers/patient_characteristic_expired_importer.rb +22 -0
  150. data/lib/qrda-import/data-element-importers/patient_characteristic_payer_importer.rb +19 -0
  151. data/lib/qrda-import/data-element-importers/physical_exam_order_importer.rb +21 -0
  152. data/lib/qrda-import/data-element-importers/physical_exam_performed_importer.rb +27 -0
  153. data/lib/qrda-import/data-element-importers/physical_exam_recommended_importer.rb +21 -0
  154. data/lib/qrda-import/data-element-importers/procedure_order_importer.rb +23 -0
  155. data/lib/qrda-import/data-element-importers/procedure_performed_importer.rb +33 -0
  156. data/lib/qrda-import/data-element-importers/procedure_recommended_importer.rb +23 -0
  157. data/lib/qrda-import/data-element-importers/provider_care_experience_importer.rb +19 -0
  158. data/lib/qrda-import/data-element-importers/provider_characteristic_importer.rb +19 -0
  159. data/lib/qrda-import/data-element-importers/substance_administered_importer.rb +27 -0
  160. data/lib/qrda-import/data-element-importers/substance_order_importer.rb +29 -0
  161. data/lib/qrda-import/data-element-importers/substance_recommended_importer.rb +27 -0
  162. data/lib/qrda-import/data-element-importers/symptom_importer.rb +21 -0
  163. data/lib/qrda-import/entry_finder.rb +20 -0
  164. data/lib/qrda-import/entry_package.rb +16 -0
  165. data/lib/qrda-import/narrative_reference_handler.rb +33 -0
  166. data/lib/qrda-import/patient_importer.rb +128 -0
  167. data/lib/util/code_system_helper.rb +77 -0
  168. data/lib/util/hqmf_template_helper.rb +52 -0
  169. data/lib/util/hqmf_template_oid_map.json +654 -0
  170. data/lib/util/hqmfr2_template_oid_map.json +378 -0
  171. data/lib/util/hqmfr2cql_template_oid_map.json +390 -0
  172. data/lib/util/qrda_template_helper.rb +20 -0
  173. data/lib/util/qrdar5_1_template_oid_map.json +406 -0
  174. data/lib/util/qrdar5_template_oid_map.json +406 -0
  175. 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