cqm-reports 3.1.2 → 3.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/lib/html-export/qdm-patient/data_element/_data_element_codes.mustache +1 -1
  4. data/lib/html-export/qdm-patient/data_element/_data_element_other_fields.mustache +1 -1
  5. data/lib/html-export/qdm-patient/qdm_patient.mustache +4 -4
  6. data/lib/html-export/qdm-patient/qdm_patient.rb +23 -1
  7. data/lib/qrda-export/catI-r5/qrda_templates/communication_performed.mustache +0 -1
  8. data/lib/qrda-export/catI-r5/qrda_templates/laboratory_test_performed.mustache +4 -0
  9. data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_performed.mustache +4 -0
  10. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_reaction_observation.mustache +1 -1
  11. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_reason.mustache +0 -1
  12. data/lib/qrda-export/catIII-r2-1/_continuous_variable_value.mustache +5 -5
  13. data/lib/qrda-export/catIII-r2-1/_header.mustache +7 -1
  14. data/lib/qrda-export/catIII-r2-1/_measure_data.mustache +0 -2
  15. data/lib/qrda-export/catIII-r2-1/_stratification.mustache +3 -5
  16. data/lib/qrda-export/catIII-r2-1/qrda3_r21.rb +7 -5
  17. data/lib/qrda-export/helper/aggregate_object_helper.rb +14 -18
  18. data/lib/qrda-export/helper/date_helper.rb +2 -2
  19. data/lib/qrda-import/base-importers/demographics_importer.rb +8 -7
  20. data/lib/qrda-import/base-importers/section_importer.rb +17 -3
  21. data/lib/qrda-import/data-element-importers/adverse_event_importer.rb +1 -1
  22. data/lib/qrda-import/data-element-importers/allergy_intolerance_importer.rb +1 -1
  23. data/lib/qrda-import/data-element-importers/assessment_order_importer.rb +1 -1
  24. data/lib/qrda-import/data-element-importers/assessment_performed_importer.rb +1 -1
  25. data/lib/qrda-import/data-element-importers/assessment_recommended_importer.rb +1 -1
  26. data/lib/qrda-import/data-element-importers/communication_performed_importer.rb +1 -1
  27. data/lib/qrda-import/data-element-importers/device_applied_importer.rb +1 -1
  28. data/lib/qrda-import/data-element-importers/device_order_importer.rb +1 -1
  29. data/lib/qrda-import/data-element-importers/device_recommended_importer.rb +1 -1
  30. data/lib/qrda-import/data-element-importers/diagnosis_importer.rb +1 -1
  31. data/lib/qrda-import/data-element-importers/diagnostic_study_order_importer.rb +1 -1
  32. data/lib/qrda-import/data-element-importers/diagnostic_study_performed_importer.rb +1 -1
  33. data/lib/qrda-import/data-element-importers/diagnostic_study_recommended_importer.rb +1 -1
  34. data/lib/qrda-import/data-element-importers/encounter_order_importer.rb +1 -1
  35. data/lib/qrda-import/data-element-importers/encounter_performed_importer.rb +12 -2
  36. data/lib/qrda-import/data-element-importers/encounter_recommended_importer.rb +1 -1
  37. data/lib/qrda-import/data-element-importers/family_history_importer.rb +1 -1
  38. data/lib/qrda-import/data-element-importers/immunization_administered_importer.rb +1 -1
  39. data/lib/qrda-import/data-element-importers/immunization_order_importer.rb +1 -1
  40. data/lib/qrda-import/data-element-importers/intervention_order_importer.rb +1 -1
  41. data/lib/qrda-import/data-element-importers/intervention_performed_importer.rb +1 -1
  42. data/lib/qrda-import/data-element-importers/intervention_recommended_importer.rb +1 -1
  43. data/lib/qrda-import/data-element-importers/laboratory_test_order_importer.rb +1 -1
  44. data/lib/qrda-import/data-element-importers/laboratory_test_performed_importer.rb +1 -1
  45. data/lib/qrda-import/data-element-importers/laboratory_test_recommended_importer.rb +1 -1
  46. data/lib/qrda-import/data-element-importers/medication_administered_importer.rb +1 -1
  47. data/lib/qrda-import/data-element-importers/medication_discharge_importer.rb +1 -1
  48. data/lib/qrda-import/data-element-importers/medication_dispensed_importer.rb +1 -1
  49. data/lib/qrda-import/data-element-importers/medication_order_importer.rb +1 -1
  50. data/lib/qrda-import/data-element-importers/patient_care_experience_importer.rb +1 -1
  51. data/lib/qrda-import/data-element-importers/physical_exam_order_importer.rb +1 -1
  52. data/lib/qrda-import/data-element-importers/physical_exam_performed_importer.rb +1 -1
  53. data/lib/qrda-import/data-element-importers/physical_exam_recommended_importer.rb +1 -1
  54. data/lib/qrda-import/data-element-importers/procedure_order_importer.rb +1 -1
  55. data/lib/qrda-import/data-element-importers/procedure_performed_importer.rb +1 -1
  56. data/lib/qrda-import/data-element-importers/procedure_recommended_importer.rb +1 -1
  57. data/lib/qrda-import/data-element-importers/provider_care_experience_importer.rb +1 -1
  58. data/lib/qrda-import/data-element-importers/substance_administered_importer.rb +1 -1
  59. data/lib/qrda-import/data-element-importers/substance_order_importer.rb +1 -1
  60. data/lib/qrda-import/data-element-importers/substance_recommended_importer.rb +1 -1
  61. data/lib/qrda-import/patient_importer.rb +12 -6
  62. metadata +17 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d999a13b64a6a37c2ad61c53c5325162a31eb948e95556a421474eb22cca735
4
- data.tar.gz: f4d69a6e256859b77ea3da62a332f48e358ca4a3589d1d08bbf57889b6977f20
3
+ metadata.gz: 440f42a620879552f2e979057f0ed822da436b56f5d89a12f9005789d93cc0fd
4
+ data.tar.gz: a89b92c7368674e8876d228e37f72c06fda05b4c09be469a39cf4b7c654edfa5
5
5
  SHA512:
6
- metadata.gz: 99e4bb97fe1ecbcb0a4f336b0e2e6d0f5d6d85dd05f539a4ea71ad28fbb091b9cf78c2c23605f0e1344c736b4fdc38e0cda8bc12efb2ca52f4f393f158f979c6
7
- data.tar.gz: 5c0b2e94fa51e623b071aecfc34537bc16efed7069d1bac433b178491462679fde863b24b6ee7cce9191b27e320d24fdfa004b0077f6e5be8492524f23cc89e5
6
+ metadata.gz: eca1d234de6ebd75e5ab88e1c19deb4422b08b589fb3e7ea5708fc1a166f3df692a9c530a5ffc7536ffe0e4d8d7585f67ce43dbcad2de2c7b8468a0eaf50a4b1
7
+ data.tar.gz: e69941a67e3345f3c907ce86422607a28778063ddcbdabae63325fa0b4dba0ff00d33bd076a7bc5afcbd66fd3ca9bcd0a672be16dce1e848b21766931140d272
data/Gemfile CHANGED
@@ -17,7 +17,7 @@ group :development do
17
17
  end
18
18
 
19
19
  group :test do
20
- gem 'cqm-models', '~> 3.0.3'
20
+ gem 'cqm-models', '~> 3.0'
21
21
  gem 'factory_girl', '~> 4.1.0'
22
22
  gem 'tailor', '~> 1.1.2'
23
23
  gem 'cane', '~> 2.3.0'
@@ -2,7 +2,7 @@
2
2
  <div class="div-table-body">
3
3
  {{#dataElementCodes}}
4
4
  <div class="div-head-row">
5
- <div class="div-table-head--no-border"><span class="criteria-heading">{{{code_system_name}}}:</span> {{code}}</div>
5
+ <div class="div-table-head--no-border"><span class="criteria-heading">{{{code_system_name}}}:</span> {{code}}{{{code_description}}}</div>
6
6
  </div>
7
7
  {{/dataElementCodes}}
8
8
  </div>
@@ -44,7 +44,7 @@
44
44
  {{/daysSupplied}}
45
45
  {{#diagnoses}}
46
46
  <div class="div-head-row">
47
- <div class="div-table-head--no-border"><span class="criteria-heading">Diagnosis:</span> {{{nested_code_string}}}</div>
47
+ <div class="div-table-head--no-border"><span class="criteria-heading">Diagnosis{{{diagnosis_rank_string}}}:</span> {{{nested_code_string}}}</div>
48
48
  </div>
49
49
  {{/diagnoses}}
50
50
  {{#dischargeDisposition}}
@@ -18,7 +18,7 @@
18
18
  <div class="div-table-head patient_narr_th panel-heading"><span class="td_label">Patient</span></div>
19
19
  <div class="div-table-head">{{given_name}} {{familyName}}</div>
20
20
  <div class="div-table-head patient_narr_th panel-heading"><span class="td_label">Sex</span></div>
21
- <div class="div-table-head">{{{gender}}}</div>
21
+ <div class="div-table-head">{{{gender}}}{{#demographic_code_description}}gender{{/demographic_code_description}}</div>
22
22
  </div>
23
23
  <div class="div-head-row patient_narr_tr panel panel-default patient-details">
24
24
  <div class="div-table-head patient_narr_th panel-heading"><span class="td_label">Date of birth</span></div>
@@ -28,13 +28,13 @@
28
28
  </div>
29
29
  <div class="div-head-row patient_narr_tr panel panel-default patient-details">
30
30
  <div class="div-table-head patient_narr_th panel-heading"><span class="td_label">Race</span></div>
31
- <div class="div-table-head">{{{race}}}</div>
31
+ <div class="div-table-head">{{{race}}}{{#demographic_code_description}}race{{/demographic_code_description}}</div>
32
32
  <div class="div-table-head patient_narr_th panel-heading"><span class="td_label">Ethnicity</span></div>
33
- <div class="div-table-head">{{{ethnic_group}}}</div>
33
+ <div class="div-table-head">{{{ethnic_group}}}{{#demographic_code_description}}ethnic_group{{/demographic_code_description}}</div>
34
34
  </div>
35
35
  <div class="div-head-row patient_narr_tr panel panel-default patient-details">
36
36
  <div class="div-table-head patient_narr_th panel-heading"><span class="td_label">Insurance Providers</span></div>
37
- <div class="div-table-head">{{{payer}}}</div>
37
+ <div class="div-table-head">{{{payer}}}{{#demographic_code_description}}payer{{/demographic_code_description}}</div>
38
38
  <div class="div-table-head patient_narr_th panel-heading"><span class="td_label">Patient IDs</span></div>
39
39
  <div class="div-table-head">{{{mrn}}} Cypress</div>
40
40
  </div>
@@ -91,13 +91,31 @@ class QdmPatient < Mustache
91
91
  end
92
92
 
93
93
  def code_for_element(element)
94
- "#{element['code']} (#{HQMF::Util::CodeSystemHelper.code_system_for(element['system'])})"
94
+ "#{element['code']} (#{HQMF::Util::CodeSystemHelper.code_system_for(element['system'])})#{code_description(element)}"
95
95
  end
96
96
 
97
97
  def code_system_name
98
98
  HQMF::Util::CodeSystemHelper.code_system_for(self['system'])
99
99
  end
100
100
 
101
+ def code_description(element = self)
102
+ has_descriptions = @patient.respond_to?(:code_description_hash) && !@patient.code_description_hash.empty?
103
+ # mongo keys cannot contain '.', so replace all '.', key example: '21112-8:2_16_840_1_113883_6_1'
104
+ return " - #{@patient.code_description_hash["#{element['code']}:#{element['system']}".tr('.', '_')]}" if has_descriptions
105
+ # no code description available
106
+ ""
107
+ end
108
+
109
+ def demographic_code_description(code)
110
+ # only have code, don't need code system
111
+ has_descriptions = code && @patient.respond_to?(:code_description_hash) && !@patient.code_description_hash.empty?
112
+ if has_descriptions
113
+ key = @patient.code_description_hash.keys.detect { |k| k.starts_with?("#{send(code)}:") }
114
+ return " - #{@patient.code_description_hash[key]}"
115
+ end
116
+ ""
117
+ end
118
+
101
119
  def result_string
102
120
  return unit_string if self['value']
103
121
  return code_code_system_string if self['code']
@@ -109,6 +127,10 @@ class QdmPatient < Mustache
109
127
  code_for_element(self['code'])
110
128
  end
111
129
 
130
+ def diagnosis_rank_string
131
+ " (rank: #{self['rank']})" if self['rank']
132
+ end
133
+
112
134
  def end_time?
113
135
  self['high'] && DateTime.parse(self['high']).year < 3000
114
136
  end
@@ -48,7 +48,6 @@
48
48
  <entryRelationship typeCode="REFR">
49
49
  <observation classCode="OBS" moodCode="EVN">
50
50
  <templateId root="2.16.840.1.113883.10.20.24.3.88" extension="2017-08-01"/>
51
- <id root="1.3.6.1.4.1.115" extension="{{object_id}}" />
52
51
  <code code="77301-0" codeSystem="2.16.840.1.113883.6.1" displayName="reason" codeSystemName="LOINC"/>
53
52
  <statusCode code="completed"/>
54
53
  <!-- QDM Attribute: Code -->
@@ -41,5 +41,9 @@
41
41
  <!-- QDM Attribute: Components -->
42
42
  {{> qrda_templates/template_partials/_component}}
43
43
  {{/components}}
44
+ {{#encounter_id}}
45
+ <!-- QDM Attribute: relatedTo -->
46
+ {{> qrda_templates/template_partials/_related_to}}
47
+ {{/encounter_id}}
44
48
  </observation>
45
49
  </entry>
@@ -48,5 +48,9 @@
48
48
  <!-- QDM Attribute: Components -->
49
49
  {{> qrda_templates/template_partials/_component}}
50
50
  {{/components}}
51
+ {{#encounter_id}}
52
+ <!-- QDM Attribute: relatedTo -->
53
+ {{> qrda_templates/template_partials/_related_to}}
54
+ {{/encounter_id}}
51
55
  </observation>
52
56
  </entry>
@@ -4,6 +4,6 @@
4
4
  <id root="4adc1020-7b14-11db-9fe1-0800200c9a64" />
5
5
  <code code="ASSERTION" codeSystem="2.16.840.1.113883.5.4" />
6
6
  <statusCode code="completed" />
7
- {{> qrda_templates/template_partials/_data_element_codes_as_values}}
7
+ <value xsi:type="CD" {{> _code}}/>
8
8
  </observation>
9
9
  </entryRelationship>
@@ -1,7 +1,6 @@
1
1
  <entryRelationship typeCode="RSON">
2
2
  <observation classCode="OBS" moodCode="EVN">
3
3
  <templateId root="2.16.840.1.113883.10.20.24.3.88" extension="2017-08-01"/>
4
- <id root="1.3.6.1.4.1.115" extension="{{random_id}}" />
5
4
  <code code="77301-0" codeSystem="2.16.840.1.113883.6.1" displayName="reason" codeSystemName="LOINC"/>
6
5
  {{#relevantPeriod}}
7
6
  {{{relevant_period}}}
@@ -2,16 +2,16 @@
2
2
  <observation classCode="OBS" moodCode="EVN">
3
3
  <templateId root="2.16.840.1.113883.10.20.27.3.2"/>
4
4
  <code nullFlavor="OTH">
5
- <originalText>Time Difference</originalText>
5
+ <originalText>Other</originalText>
6
6
  </code>
7
7
  <statusCode code="completed"/>
8
- <value xsi:type="PQ" value="{{value}}" unit="min"/>
9
- <methodCode code="MEDIAN" displayName="Median" codeSystem="2.16.840.1.113883.5.84" codeSystemName="ObservationMethod"/>
8
+ <value xsi:type="REAL" value="{{value}}"/>
9
+ <methodCode code="{{method}}" displayName="{{method}}" codeSystem="2.16.840.1.113883.5.84" codeSystemName="ObservationMethod"/>
10
10
  <reference typeCode="REFR">
11
11
  <!-- reference to the relevant measure observation in the eMeasure -->
12
12
  <externalObservation classCode="OBS" moodCode="EVN">
13
- <id root="{{id}}"/>
13
+ <id root="{{hqmf_id}}"/>
14
14
  </externalObservation>
15
15
  </reference>
16
16
  </observation>
17
- </entryRelationship>
17
+ </entryRelationship>
@@ -3,8 +3,14 @@
3
3
  <typeId root="2.16.840.1.113883.1.3" extension="POCD_HD000040"/>
4
4
  <!-- US Realm Header Template Id -->
5
5
  <templateId root="2.16.840.1.113883.10.20.27.1.1" extension="2017-06-01"/>
6
- <!-- QRDA Category III Report - CMS (V4) -->
6
+ {{#ry2022_submission?}}
7
+ <!-- QRDA Category III Report - CMS (V6) -->
8
+ <templateId root="2.16.840.1.113883.10.20.27.1.2" extension="2021-07-01"/>
9
+ {{/ry2022_submission?}}
10
+ {{^ry2022_submission?}}
11
+ <!-- QRDA Category III Report - CMS (V5) -->
7
12
  <templateId root="2.16.840.1.113883.10.20.27.1.2" extension="2020-05-01"/>
13
+ {{/ry2022_submission?}}
8
14
  <!-- This is the globally unique identifier for this QRDA document -->
9
15
  <id root="{{random_id}}"/>
10
16
  <!-- QRDA III document type code -->
@@ -27,11 +27,9 @@
27
27
  {{> _supplemental_data}}
28
28
  {{/population_supplemental_data}}
29
29
  {{/supplemental_data}}
30
- {{#msrpopl?}}
31
30
  {{#population_observation}}
32
31
  {{> _continuous_variable_value}}
33
32
  {{/population_observation}}
34
- {{/msrpopl?}}
35
33
  <reference typeCode="REFR">
36
34
  <externalObservation classCode="OBS" moodCode="EVN">
37
35
  <id root="{{id}}"/>
@@ -15,11 +15,9 @@
15
15
  <methodCode code="COUNT" displayName="Count" codeSystem="2.16.840.1.113883.5.84" codeSystemName="ObservationMethod"/>
16
16
  </observation>
17
17
  </entryRelationship>
18
- {{#msrpopl?}}
19
- {{#stratification_observation}}
20
- {{> _continuous_variable_value}}
21
- {{/stratification_observation}}
22
- {{/msrpopl?}}
18
+ {{#stratification_observation}}
19
+ {{> _continuous_variable_value}}
20
+ {{/stratification_observation}}
23
21
  <reference typeCode="REFR">
24
22
  <externalObservation classCode="OBS" moodCode="EVN">
25
23
  <id root="{{id}}"/>
@@ -27,6 +27,7 @@ class Qrda3R21 < Mustache
27
27
  @performance_period_start = options[:start_time]
28
28
  @performance_period_end = options[:end_time]
29
29
  @submission_program = options[:submission_program]
30
+ @ry2022_submission = options[:ry2022_submission]
30
31
  end
31
32
 
32
33
  def agg_results(measure_id, cache_entries, population_sets)
@@ -58,14 +59,11 @@ class Qrda3R21 < Mustache
58
59
  end
59
60
 
60
61
  def stratification_observation
61
- observation = @measure_result_hash[self['measure_id']].aggregate_count.populations.find {|p| p.type == "OBSERV"}
62
- stratification_observation = @measure_result_hash[self['measure_id']].aggregate_count.populations.find {|p| p.type == "OBSERV"}.stratifications.find {|s| s.id == self['id'] }
63
- stratification_observation.id = observation.id
64
- stratification_observation
62
+ self['observation']
65
63
  end
66
64
 
67
65
  def population_observation
68
- @measure_result_hash[self['measure_id']].aggregate_count.populations.find {|p| p.type == "OBSERV"}
66
+ self['observation']
69
67
  end
70
68
 
71
69
  def supplemental_template_ids
@@ -90,6 +88,10 @@ class Qrda3R21 < Mustache
90
88
  @submission_program == 'CPCPLUS'
91
89
  end
92
90
 
91
+ def ry2022_submission?
92
+ @ry2022_submission
93
+ end
94
+
93
95
  def payer_code?
94
96
  self['type'] == 'PAYER'
95
97
  end
@@ -57,23 +57,24 @@ module Qrda
57
57
  end
58
58
  end
59
59
  class Population
60
- attr_accessor :type, :value, :id, :stratifications, :supplemental_data
60
+ attr_accessor :type, :value, :id, :stratifications, :supplemental_data, :observation
61
61
 
62
62
  def initialize
63
63
  @stratifications = []
64
64
  end
65
65
 
66
- def add_stratification(id,value)
67
- stratifications << Stratification.new(id,value) unless stratifications.find {|st| st.id == id}
66
+ def add_stratification(id,value,observation)
67
+ stratifications << Stratification.new(id,value,observation) unless stratifications.find {|st| st.id == id}
68
68
  end
69
69
 
70
70
  end
71
71
 
72
72
  class Stratification
73
- attr_accessor :id, :value
74
- def initialize(id,value)
73
+ attr_accessor :id, :value, :observation
74
+ def initialize(id,value, observation)
75
75
  @id = id
76
76
  @value = value
77
+ @observation = observation
77
78
  end
78
79
 
79
80
  end
@@ -107,15 +108,17 @@ module Qrda
107
108
  def add_entry(cache_entry, population_sets)
108
109
  population_set = population_sets.where(population_set_id: cache_entry.pop_set_hash[:population_set_id]).first
109
110
  entry_populations = []
110
- %w[IPP DENOM NUMER NUMEX DENEX DENEXCEP MSRPOPL MSRPOPLEX OBSERV].each do |pop_code|
111
- next unless population_set.populations[pop_code] || pop_code == 'OBSERV'
111
+ %w[IPP DENOM NUMER NUMEX DENEX DENEXCEP MSRPOPL MSRPOPLEX].each do |pop_code|
112
+ next unless population_set.populations[pop_code]
112
113
 
113
114
  population = create_population_from_population_set(pop_code, population_set, cache_entry)
114
115
  if cache_entry.pop_set_hash[:stratification_id]
115
116
  strat_id = population_set.stratifications.where(stratification_id: cache_entry.pop_set_hash[:stratification_id]).first&.hqmf_id
116
- population.add_stratification(strat_id,cache_entry[pop_code])
117
+ observation = cache_entry['observations'][pop_code] if cache_entry['observations'] && cache_entry['observations'][pop_code]
118
+ population.add_stratification(strat_id,cache_entry[pop_code], observation)
117
119
  else
118
120
  population.value = cache_entry[pop_code]
121
+ population.observation = cache_entry['observations'][pop_code] if cache_entry['observations'] && cache_entry['observations'][pop_code]
119
122
  population.supplemental_data = cache_entry.supplemental_data[pop_code]
120
123
  end
121
124
  entry_populations << population if population
@@ -128,19 +131,12 @@ module Qrda
128
131
  end
129
132
 
130
133
  def create_population_from_population_set(pop_code, population_set, cache_entry)
131
- population = if pop_code == 'OBSERV'
132
- populations.find { |pop| pop.id == population_set.observations&.first&.hqmf_id }
133
- elsif pop_code != 'STRAT'
134
- populations.find { |pop| pop.id == population_set.populations[pop_code]&.hqmf_id }
135
- end
134
+ population = populations.find { |pop| pop.id == population_set.populations[pop_code]&.hqmf_id } if pop_code != 'STRAT'
136
135
  return population unless population.nil? && !cache_entry.pop_set_hash[:stratification_id]
136
+
137
137
  population = Population.new
138
138
  population.type = pop_code
139
- population.id = if pop_code == 'OBSERV'
140
- population_set.observations&.first&.hqmf_id
141
- else
142
- population_set.populations[pop_code]&.hqmf_id
143
- end
139
+ population.id = population_set.populations[pop_code]&.hqmf_id
144
140
  populations << population
145
141
  population
146
142
  end
@@ -101,7 +101,7 @@ module Qrda
101
101
  end
102
102
 
103
103
  def relevant_date_period_or_null_flavor
104
- return relevant_period if self['relevantPeriod']
104
+ return relevant_period if self['relevantPeriod'] && (self['relevantPeriod']['low'] || self['relevantPeriod']['high'])
105
105
  return relevant_date_time_value if self['relevantDatetime']
106
106
  "<effectiveTime nullFlavor='UNK'/>"
107
107
  end
@@ -128,4 +128,4 @@ module Qrda
128
128
  end
129
129
  end
130
130
  end
131
- end
131
+ end
@@ -1,7 +1,7 @@
1
1
  module QRDA
2
2
  module Cat1
3
3
  module DemographicsImporter
4
- def get_demographics(patient, doc)
4
+ def get_demographics(patient, doc, codes)
5
5
  patient_role_element = doc.at_xpath('/cda:ClinicalDocument/cda:recordTarget/cda:patientRole')
6
6
  patient_element = patient_role_element.at_xpath('./cda:patient')
7
7
  patient.givenNames = [patient_element.at_xpath('cda:name/cda:given').text]
@@ -9,28 +9,29 @@ module QRDA
9
9
  patient.qdmPatient.birthDatetime = DateTime.parse(patient_element.at_xpath('cda:birthTime')['value'])
10
10
  pcbd = QDM::PatientCharacteristicBirthdate.new
11
11
  pcbd.birthDatetime = patient.qdmPatient.birthDatetime
12
- pcbd.dataElementCodes = [{ code: '21112-8', system: '2.16.840.1.113883.6.1' }]
12
+ pcbd.dataElementCodes = [QDM::Code.new('21112-8', '2.16.840.1.113883.6.1')]
13
+ codes.add("21112-8:2.16.840.1.113883.6.1")
13
14
  patient.qdmPatient.dataElements << pcbd
14
15
 
15
16
  pcs = QDM::PatientCharacteristicSex.new
16
17
  code_element = patient_element.at_xpath('cda:administrativeGenderCode')
17
- pcs.dataElementCodes = [code_if_present(code_element)]
18
+ pcs.dataElementCodes = [code_if_present(code_element, codes)]
18
19
  patient.qdmPatient.dataElements << pcs unless pcs.dataElementCodes.compact.blank?
19
20
 
20
21
  pcr = QDM::PatientCharacteristicRace.new
21
22
  code_element = patient_element.at_xpath('cda:raceCode')
22
- pcr.dataElementCodes = [code_if_present(code_element)]
23
+ pcr.dataElementCodes = [code_if_present(code_element, codes)]
23
24
  patient.qdmPatient.dataElements << pcr unless pcr.dataElementCodes.compact.blank?
24
25
 
25
26
  pce = QDM::PatientCharacteristicEthnicity.new
26
27
  code_element = patient_element.at_xpath('cda:ethnicGroupCode')
27
- pce.dataElementCodes = [code_if_present(code_element)]
28
+ pce.dataElementCodes = [code_if_present(code_element, codes)]
28
29
  patient.qdmPatient.dataElements << pce unless pce.dataElementCodes.compact.blank?
29
30
  end
30
31
 
31
- def code_if_present(code_element)
32
+ def code_if_present(code_element, codes)
32
33
  return unless code_element && code_element['code'] && code_element['codeSystem']
33
-
34
+ codes.add("#{code_element['code']}:#{code_element['codeSystem']}")
34
35
  QDM::Code.new(code_element['code'], code_element['codeSystem'])
35
36
  end
36
37
  end
@@ -1,7 +1,7 @@
1
1
  module QRDA
2
2
  module Cat1
3
3
  class SectionImporter
4
- attr_accessor :check_for_usable, :status_xpath, :code_xpath, :warnings
4
+ attr_accessor :check_for_usable, :status_xpath, :code_xpath, :warnings, :codes, :codes_modifiers
5
5
 
6
6
  def initialize(entry_finder)
7
7
  @entry_finder = entry_finder
@@ -10,6 +10,8 @@ module QRDA
10
10
  @check_for_usable = true
11
11
  @entry_class = QDM::DataElement
12
12
  @warnings = []
13
+ @codes = Set.new
14
+ @codes_modifiers = {}
13
15
  end
14
16
 
15
17
  # Traverses an HL7 CDA document passed in and creates an Array of Entry
@@ -81,6 +83,7 @@ module QRDA
81
83
 
82
84
  def code_if_present(code_element)
83
85
  return unless code_element && code_element['code'] && code_element['codeSystem']
86
+ @codes.add("#{code_element['code']}:#{code_element['codeSystem']}")
84
87
  QDM::Code.new(code_element['code'], code_element['codeSystem'])
85
88
  end
86
89
 
@@ -94,7 +97,9 @@ module QRDA
94
97
  end
95
98
 
96
99
  def extract_interval(parent_element, interval_xpath)
97
- return nil unless parent_element.at_xpath(interval_xpath)
100
+ # nil if the time interval does not exist
101
+ return nil unless time_interval_exists(parent_element, interval_xpath)
102
+
98
103
  if parent_element.at_xpath("#{interval_xpath}/@value")
99
104
  low_time = DateTime.parse(parent_element.at_xpath(interval_xpath)['value'])
100
105
  high_time = DateTime.parse(parent_element.at_xpath(interval_xpath)['value'])
@@ -131,6 +136,14 @@ module QRDA
131
136
  QDM::Interval.new(low_time, high_time).shift_dates(0)
132
137
  end
133
138
 
139
+ def time_interval_exists(parent_element, interval_xpath)
140
+ # false if the time interval does not exist
141
+ return false unless parent_element.at_xpath(interval_xpath)
142
+ # false if the time element exists but has a null Flavor
143
+ return false if parent_element.at_xpath(interval_xpath)['nullFlavor']
144
+ true
145
+ end
146
+
134
147
  def extract_time(parent_element, datetime_xpath)
135
148
  DateTime.parse(parent_element.at_xpath(datetime_xpath)['value']) if parent_element.at_xpath("#{datetime_xpath}/@value")
136
149
  end
@@ -145,6 +158,7 @@ module QRDA
145
158
  # If a Direct Reference Code isn't found, return nil
146
159
  return nil unless key
147
160
  # If a Direct Reference Code is found, return that code
161
+ @codes.add("#{key}:#{value[:code_system]}")
148
162
  QDM::Code.new(key, value[:code_system])
149
163
  end
150
164
 
@@ -258,7 +272,7 @@ module QRDA
258
272
  participant_element = facility_location_element.at_xpath("./cda:participantRole[@classCode='SDLOC']/cda:code")
259
273
  facility_location.code = code_if_present(participant_element)
260
274
  facility_location.locationPeriod = extract_interval(facility_location_element, './cda:time')
261
- facility_locations << facility_location
275
+ facility_locations << facility_location if facility_location.code
262
276
  end
263
277
  facility_locations
264
278
  end
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
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'
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @relevant_date_time_xpath = './cda:effectiveTime[@value]'
10
10
  @facility_locations_xpath = "./cda:participant[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.100']"
11
11
  @severity_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.8']/cda:value"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:participant[@typeCode='CSM']/cda:participantRole/cda:playingEntity/cda:code"
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @prevalence_period_xpath = "./cda:effectiveTime"
10
10
  @severity_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.8']/cda:value"
11
11
  @type_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.9']/cda:value"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:code'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
10
10
  @entry_class = QDM::AssessmentOrder
11
11
  end
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:code'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @result_xpath = "./cda:value"
10
10
  @method_xpath = './cda:methodCode'
11
11
  @components_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.149']"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:code'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
10
10
  @entry_class = QDM::AssessmentRecommended
11
11
  end
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:entryRelationship[@typeCode='REFR']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @sent_datetime_xpath = "./cda:effectiveTime/cda:low"
10
10
  @received_datetime_xpath = "./cda:effectiveTime/cda:high"
11
11
  @related_to_xpath = "./sdtc:inFulfillmentOf1/sdtc:actReference"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:participant/cda:participantRole/cda:playingDevice/cda:code'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @relevant_period_xpath = "./cda:effectiveTime"
10
10
  @relevant_date_time_xpath = './cda:effectiveTime[@value]'
11
11
  @anatomical_location_site_xpath = "./cda:targetSiteCode"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.9']/cda:id"
7
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"
8
+ @author_datetime_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.9']/cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @reason_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.9']/cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
10
10
  @entry_class = QDM::DeviceOrder
11
11
  end
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.10']/cda:id"
7
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"
8
+ @author_datetime_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.10']/cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @reason_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.10']/cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
10
10
  @entry_class = QDM::DeviceRecommended
11
11
  end
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:entryRelationship/cda:observation/cda:id'
7
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"
8
+ @author_datetime_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.135']/cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @prevalence_period_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.135']/cda:effectiveTime"
10
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
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"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:code'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
10
10
  @entry_class = QDM::DiagnosticStudyOrder
11
11
  end
@@ -7,7 +7,7 @@ module QRDA
7
7
  @code_xpath = './cda:code'
8
8
  @relevant_period_xpath = "./cda:effectiveTime"
9
9
  @relevant_date_time_xpath = './cda:effectiveTime[@value]'
10
- @author_datetime_xpath = "./cda:author/cda:time"
10
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
11
11
  @result_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.2']/cda:value"
12
12
  @result_datetime_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.2']/cda:effectiveTime"
13
13
  @status_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.93']/cda:value"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:code'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @entry_class = QDM::DiagnosticStudyRecommended
10
10
  end
11
11
 
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:entryRelationship/cda:encounter/cda:id'
7
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"
8
+ @author_datetime_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.22']/cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
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
10
  @reason_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.22']/cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
11
11
  @priority_xpath = './cda:entryRelationship/cda:encounter/cda:priorityCode'
@@ -6,7 +6,7 @@ module QRDA
6
6
  @id_xpath = './cda:entryRelationship/cda:encounter/cda:id'
7
7
  @code_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/cda:code"
8
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"
9
+ @author_datetime_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
10
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
11
  @discharge_disposition_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/sdtc:dischargeDispositionCode"
12
12
  @facility_locations_xpath = "./cda:entryRelationship/cda:encounter/cda:participant[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.100']"
@@ -21,15 +21,25 @@ module QRDA
21
21
  encounter_performed.facilityLocations = extract_facility_locations(entry_element)
22
22
  encounter_performed.diagnoses = extract_diagnoses(entry_element)
23
23
  if encounter_performed&.relevantPeriod&.low && encounter_performed&.relevantPeriod&.high
24
- los = encounter_performed.relevantPeriod.high - encounter_performed.relevantPeriod.low
24
+ los = encounter_performed.relevantPeriod.high.to_date - encounter_performed.relevantPeriod.low.to_date
25
25
  encounter_performed.lengthOfStay = QDM::Quantity.new(los.to_i, 'd')
26
26
  end
27
27
  encounter_performed.participant = extract_entity(entry_element, "./cda:entryRelationship/cda:encounter//cda:participant[@typeCode='PRF']")
28
+ extract_modifier_code(encounter_performed, entry_element)
28
29
  encounter_performed
29
30
  end
30
31
 
31
32
  private
32
33
 
34
+ def extract_modifier_code(encounter_performed, entry_element)
35
+ code_element = entry_element.at_xpath(@code_xpath)
36
+ return unless code_element
37
+
38
+ qualifier_name = code_element.at_xpath('./cda:qualifier/cda:name')
39
+ qualifier_value = code_element.at_xpath('./cda:qualifier/cda:value')
40
+ codes_modifiers[encounter_performed.id] = { name: code_if_present(qualifier_name), value: code_if_present(qualifier_value), xpath_location: entry_element.path } if qualifier_value || qualifier_name
41
+ end
42
+
33
43
  def extract_diagnoses(parent_element)
34
44
  diagnosis_elements = parent_element.xpath(@diagnosis_xpath)
35
45
  diagnosis_list = []
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:entryRelationship/cda:encounter/cda:id'
7
7
  @code_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.24']/cda:code"
8
- @author_datetime_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.24']/cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.24']/cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @facility_locations_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.24']/cda:participant[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.100']"
10
10
  @reason_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.24']/cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
11
11
  @entry_class = QDM::EncounterRecommended
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:component/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.112']/cda:value"
8
- @author_datetime_xpath = "./cda:component/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.112']/cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:component/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.112']/cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @relationship_xpath = './cda:subject/cda:relatedSubject/cda:code'
10
10
  @entry_class = QDM::FamilyHistory
11
11
  end
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @relevant_date_time_xpath = './cda:effectiveTime'
10
10
  @dosage_xpath = "./cda:doseQuantity"
11
11
  @route_xpath = "./cda:routeCode"
@@ -6,7 +6,7 @@ module QRDA
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
8
8
  @active_datetime_xpath = "./cda:effectiveTime[@value]"
9
- @author_datetime_xpath = "./cda:author/cda:time"
9
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
10
10
  @dosage_xpath = "./cda:doseQuantity"
11
11
  @supply_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.167']/cda:quantity"
12
12
  @route_xpath = "./cda:routeCode"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:code'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
10
10
  @entry_class = QDM::InterventionOrder
11
11
  end
@@ -7,7 +7,7 @@ module QRDA
7
7
  @code_xpath = './cda:code'
8
8
  @relevant_period_xpath = "./cda:effectiveTime"
9
9
  @relevant_date_time_xpath = './cda:effectiveTime'
10
- @author_datetime_xpath = "./cda:author/cda:time"
10
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
11
11
  @result_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.2']/cda:value"
12
12
  @status_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.93']/cda:value"
13
13
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:code'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
10
10
  @entry_class = QDM::InterventionRecommended
11
11
  end
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:code'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
10
10
  @entry_class = QDM::LaboratoryTestOrder
11
11
  end
@@ -7,7 +7,7 @@ module QRDA
7
7
  @code_xpath = './cda:code'
8
8
  @relevant_period_xpath = "./cda:effectiveTime"
9
9
  @relevant_date_time_xpath = './cda:effectiveTime[@value]'
10
- @author_datetime_xpath = "./cda:author/cda:time"
10
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
11
11
  @status_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.93']/cda:value"
12
12
  @method_xpath = './cda:methodCode'
13
13
  @result_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.2']/cda:value"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:code'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
10
10
  @entry_class = QDM::LaboratoryTestRecommended
11
11
  end
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @relevant_period_xpath = "./cda:effectiveTime"
10
10
  @relevant_date_time_xpath = './cda:effectiveTime'
11
11
  @dosage_xpath = "./cda:doseQuantity"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:entryRelationship/cda:substanceAdministration/cda:id'
7
7
  @code_xpath = "./cda:entryRelationship/cda:substanceAdministration[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.16']/cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
8
- @author_datetime_xpath = "./cda:entryRelationship/cda:substanceAdministration[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.16']/cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:entryRelationship/cda:substanceAdministration[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.16']/cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.119']/cda:time"
9
9
  @refills_xpath = "./cda:entryRelationship/cda:substanceAdministration[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.16']/cda:repeatNumber"
10
10
  @dosage_xpath = "./cda:entryRelationship/cda:substanceAdministration[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.16']/cda:doseQuantity"
11
11
  @supply_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.99']/cda:quantity"
@@ -7,7 +7,7 @@ module QRDA
7
7
  @code_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.18']/cda:product/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
8
8
  @relevant_period_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.18']/cda:effectiveTime"
9
9
  @relevant_date_time_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.18']/cda:effectiveTime"
10
- @author_datetime_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.18']/cda:author/cda:time"
10
+ @author_datetime_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.18']/cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
11
11
  @refills_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.18']/cda:entryRelationship/cda:substanceAdministration/cda:repeatNumber"
12
12
  @dosage_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.18']/cda:entryRelationship/cda:substanceAdministration/cda:doseQuantity"
13
13
  @supply_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.18']/cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.99']/cda:quantity"
@@ -6,7 +6,7 @@ module QRDA
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
8
8
  @relevant_period_xpath = "./cda:effectiveTime"
9
- @author_datetime_xpath = "./cda:author/cda:time"
9
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
10
10
  @dosage_xpath = "./cda:doseQuantity"
11
11
  @supply_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.99']/cda:quantity"
12
12
  @frequency_xpath = "./cda:effectiveTime[@operator='A']/cda:period"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:value'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @entry_class = QDM::PatientCareExperience
10
10
  end
11
11
 
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:value"
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @anatomical_location_site_xpath = "./cda:targetSiteCode"
10
10
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
11
11
  @entry_class = QDM::PhysicalExamOrder
@@ -7,7 +7,7 @@ module QRDA
7
7
  @code_xpath = "./cda:code"
8
8
  @relevant_period_xpath = "./cda:effectiveTime"
9
9
  @relevant_date_time_xpath = './cda:effectiveTime'
10
- @author_datetime_xpath = "./cda:author/cda:time"
10
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
11
11
  @method_xpath = './cda:methodCode'
12
12
  @result_xpath = "./cda:value"
13
13
  @anatomical_location_site_xpath = "./cda:targetSiteCode"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:value"
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @anatomical_location_site_xpath = "./cda:targetSiteCode"
10
10
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
11
11
  @entry_class = QDM::PhysicalExamRecommended
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = './cda:code'
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @anatomical_location_site_xpath = "./cda:targetSiteCode"
10
10
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
11
11
  @rank_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.166']/cda:value/@value"
@@ -7,7 +7,7 @@ module QRDA
7
7
  @code_xpath = "./cda:code"
8
8
  @relevant_period_xpath = "./cda:effectiveTime"
9
9
  @relevant_date_time_xpath = './cda:effectiveTime'
10
- @author_datetime_xpath = "./cda:author/cda:time"
10
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
11
11
  @method_xpath = './cda:methodCode'
12
12
  @result_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.22.4.2']/cda:value"
13
13
  @status_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.93']/cda:value"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:code"
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @anatomical_location_site_xpath = "./cda:targetSiteCode"
10
10
  @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value"
11
11
  @rank_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.166']/cda:value/@value"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:value"
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @entry_class = QDM::ProviderCareExperience
10
10
  end
11
11
 
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @relevant_period_xpath = "./cda:effectiveTime"
10
10
  @relevant_date_time_xpath = './cda:effectiveTime'
11
11
  @dosage_xpath = "./cda:doseQuantity"
@@ -6,7 +6,7 @@ module QRDA
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
8
8
  @relevant_period_xpath = "./cda:effectiveTime"
9
- @author_datetime_xpath = "./cda:author/cda:time"
9
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
10
10
  @dosage_xpath = "./cda:doseQuantity"
11
11
  @supply_xpath = "./cda:entryRelationship/cda:supply[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.99']/cda:quantity"
12
12
  @frequency_xpath = "./cda:effectiveTime[@operator='A']/cda:period"
@@ -5,7 +5,7 @@ module QRDA
5
5
  super(entry_finder)
6
6
  @id_xpath = './cda:id'
7
7
  @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
8
- @author_datetime_xpath = "./cda:author/cda:time"
8
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
9
9
  @dosage_xpath = "./cda:doseQuantity"
10
10
  @frequency_xpath = "./cda:effectiveTime[@operator='A']/cda:period"
11
11
  @refills_xpath = "./cda:repeatNumber"
@@ -59,19 +59,21 @@ module QRDA
59
59
  @data_element_importers << SubstanceOrderImporter.new
60
60
  @data_element_importers << SubstanceRecommendedImporter.new
61
61
  @data_element_importers << SymptomImporter.new
62
- end
62
+ end
63
63
 
64
64
  def parse_cat1(doc)
65
65
  patient = CQM::Patient.new
66
66
  warnings = []
67
+ codes = Set.new
68
+ codes_modifiers = {}
67
69
  entry_id_map = {}
68
- import_data_elements(patient, doc, entry_id_map, warnings)
70
+ import_data_elements(patient, doc, entry_id_map, codes, codes_modifiers, warnings)
69
71
  normalize_references(patient, entry_id_map)
70
- get_demographics(patient, doc)
71
- [patient, warnings]
72
+ get_demographics(patient, doc, codes)
73
+ [patient, warnings, codes, codes_modifiers]
72
74
  end
73
75
 
74
- def import_data_elements(patient, doc, entry_id_map, warnings = [])
76
+ def import_data_elements(patient, doc, entry_id_map, codes = Set.new, codes_modifiers = {}, warnings = [])
75
77
  context = doc.xpath("/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section[cda:templateId/@root = '2.16.840.1.113883.10.20.24.2.1']")
76
78
  nrh = NarrativeReferenceHandler.new
77
79
  nrh.build_id_map(doc)
@@ -109,8 +111,12 @@ module QRDA
109
111
  patient.qdmPatient.dataElements << new_data_elements
110
112
  entry_id_map.merge!(id_map)
111
113
  warnings.concat(importer.warnings)
112
- # reset warnings after they're captured so that the importer can be re-used
114
+ codes.merge(importer.codes)
115
+ codes_modifiers.merge!(importer.codes_modifiers)
116
+ # reset warnings and codes after they're captured so that the importer can be re-used
113
117
  importer.warnings = []
118
+ importer.codes_modifiers = {}
119
+ importer.codes = Set.new
114
120
  end
115
121
  end
116
122
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cqm-reports
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.2
4
+ version: 3.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - The MITRE Corporation
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-24 00:00:00.000000000 Z
11
+ date: 2021-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cqm-models
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 3.0.3
19
+ version: '3.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 3.0.3
26
+ version: '3.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: cqm-validators
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 3.0.0
33
+ version: '3.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 3.0.0
40
+ version: '3.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mustache
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -84,16 +84,22 @@ dependencies:
84
84
  name: nokogiri
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 1.8.5
90
+ - - "<"
88
91
  - !ruby/object:Gem::Version
89
- version: '1.10'
92
+ version: 1.12.0
90
93
  type: :runtime
91
94
  prerelease: false
92
95
  version_requirements: !ruby/object:Gem::Requirement
93
96
  requirements:
94
- - - "~>"
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 1.8.5
100
+ - - "<"
95
101
  - !ruby/object:Gem::Version
96
- version: '1.10'
102
+ version: 1.12.0
97
103
  - !ruby/object:Gem::Dependency
98
104
  name: uuid
99
105
  requirement: !ruby/object:Gem::Requirement
@@ -358,7 +364,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
358
364
  - !ruby/object:Gem::Version
359
365
  version: '0'
360
366
  requirements: []
361
- rubygems_version: 3.0.8
367
+ rubygems_version: 3.1.4
362
368
  signing_key:
363
369
  specification_version: 4
364
370
  summary: A library for import and export of reports for use with electronic Clinical