cqm-reports 4.0.1 → 4.1.0

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 (30) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -2
  3. data/lib/html-export/qdm-patient/data_element/_data_element_other_fields.mustache +1 -1
  4. data/lib/html-export/qdm-patient/qdm_patient.rb +22 -5
  5. data/lib/qrda-export/catI-r5/qrda1_r5.rb +12 -0
  6. data/lib/qrda-export/catI-r5/qrda_header/_participant.mustache +3 -2
  7. data/lib/qrda-export/catI-r5/qrda_header/_record_target.mustache +9 -0
  8. data/lib/qrda-export/catI-r5/qrda_templates/encounter_performed.mustache +49 -56
  9. data/lib/qrda-export/catI-r5/qrda_templates/medication_discharge.mustache +1 -1
  10. data/lib/qrda-export/catI-r5/qrda_templates/medication_dispensed.mustache +1 -1
  11. data/lib/qrda-export/catI-r5/qrda_templates/medication_order.mustache +1 -1
  12. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_medication_details.mustache +1 -1
  13. data/lib/qrda-export/catI-r52/qrda1_r52.rb +258 -0
  14. data/lib/qrda-export/catI-r52/qrda_header/_participant.mustache +8 -0
  15. data/lib/qrda-export/catI-r52/qrda_header/_record_target.mustache +65 -0
  16. data/lib/qrda-export/catI-r52/qrda_templates/medication_order.mustache +70 -0
  17. data/lib/qrda-export/catIII/_header.mustache +2 -4
  18. data/lib/qrda-export/catIII/qrda_header/_participant_ehr.mustache +4 -1
  19. data/lib/qrda-export/catIII-r2-1/qrda_header/_participant_ehr.mustache +9 -0
  20. data/lib/qrda-export/helper/cat1_view_helper.rb +23 -5
  21. data/lib/qrda-export/helper/view_helper.rb +9 -1
  22. data/lib/qrda-import/base-importers/section_importer.rb +31 -4
  23. data/lib/qrda-import/data-element-importers/encounter_performed_importer.rb +12 -12
  24. data/lib/qrda-import/data-element-importers/medication_discharge_importer.rb +1 -1
  25. data/lib/qrda-import/data-element-importers/medication_dispensed_importer.rb +1 -1
  26. data/lib/qrda-import/data-element-importers/medication_order_importer.rb +1 -1
  27. data/lib/qrda-import/data-element-importers/substance_order_importer.rb +1 -1
  28. data/lib/qrda-import/data-element-importers/substance_recommended_importer.rb +1 -1
  29. data/lib/qrda-import/patient_importer.rb +22 -6
  30. metadata +10 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9916f810f725d5fff7cfbc0f961e588ad17cc2dc634b9d51a48517a92eb7c076
4
- data.tar.gz: f5080b36a062bb8197420ecfefcfcfb480ba3a8d99bbd63dabd9bc325e638043
3
+ metadata.gz: b0938369271d07282db5933dda15b47f0cbe346abbeff4a6004a23fcce61e680
4
+ data.tar.gz: 4ff25f7dfda32510cccb638966ab51eb76cb04c7ab31778fb2e95bc0cba88a2c
5
5
  SHA512:
6
- metadata.gz: 54c5b802bcbba1c16aa3701e4927daa32230081a54ae039540ce82ce7af79a34a2ae7c884bd8af0e40bf94e9f5016db0e8b98565d3d3b308350a2b2bd7c6345f
7
- data.tar.gz: e7e2e958018f24a2ebbb07faf8ad1f2762054e861f99c8fa89466682d46e1f461674391a160788fca9e13ea2022a086fac860feb17ad032040cb2dd39bc9b1cd
6
+ metadata.gz: 3c3c6bd90513f5f83610596a4789a30b0995569efcf7e6598a48f385a00d7cc869265c4f7f6b77c24c3130153df714ad3858d55e4b97f88168282d833e4a2961
7
+ data.tar.gz: 750f9df81d0cb2c633dbecc2b6be45a77c580dd7bc53defe6cc27ad592e0588cbebd563f3382e7d193f2cfcdf038728f3e01eee1f9fdbb2fc07e3a11f049afdb
data/Gemfile CHANGED
@@ -2,8 +2,6 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec :development_group => :test
4
4
 
5
- gem 'mongoid', '~> 6.4.2'
6
-
7
5
  gem 'protected_attributes_continued'
8
6
 
9
7
  group :development, :test do
@@ -49,7 +49,7 @@
49
49
  {{/daysSupplied}}
50
50
  {{#diagnoses}}
51
51
  <div class="div-head-row">
52
- <div class="div-table-head--no-border"><span class="criteria-heading">Diagnosis{{{diagnosis_rank_string}}}:</span> {{{nested_code_string}}}</div>
52
+ <div class="div-table-head--no-border"><span class="criteria-heading">Diagnosis:</span> {{{nested_code_string}}} {{{diagnosis_string}}}</div>
53
53
  </div>
54
54
  {{/diagnoses}}
55
55
  {{#dischargeDisposition}}
@@ -10,6 +10,7 @@ class QdmPatient < Mustache
10
10
  @patient = patient
11
11
  @qdmPatient = patient.qdmPatient
12
12
  @patient_addresses = patient['addresses']
13
+ @patient_email = patient['email']
13
14
  @patient_telecoms = patient['telecoms']
14
15
  end
15
16
 
@@ -35,6 +36,7 @@ class QdmPatient < Mustache
35
36
  def patient_telecoms
36
37
  @patient_telecoms ||= [CQM::Telecom.new(use: 'HP', value: '555-555-2003')]
37
38
  # create formatted telecoms
39
+ @patient_telecoms << CQM::Telecom.new(use: 'HP', value: @patient_email) if @patient_email
38
40
  @patient_telecoms.map { |telecom| "(#{telecom['use']}) #{telecom['value']}" }.join("<br>")
39
41
  end
40
42
 
@@ -52,8 +54,14 @@ class QdmPatient < Mustache
52
54
  end
53
55
 
54
56
  def unit_string
55
- return "#{self['value']} " if !self['unit'] || self['unit'] == '1'
56
- "#{self['value']} #{self['unit']}"
57
+ return trimed_value(self['value']).to_s if !self['unit'] || self['unit'] == '1'
58
+ "#{trimed_value(self['value'])} #{self['unit']}"
59
+ end
60
+
61
+ def trimed_value(number)
62
+ i = number.to_i
63
+ f = number.to_f
64
+ i == f ? i : f
57
65
  end
58
66
 
59
67
  def entity_string
@@ -120,15 +128,24 @@ class QdmPatient < Mustache
120
128
  return unit_string if self['value']
121
129
  return code_code_system_string if self['code']
122
130
 
123
- self['result']
131
+ # Checks to see if the result is a DateTime value, String, or Numeric
132
+ begin
133
+ DateTime.parse(self['result'])
134
+ rescue ArgumentError, TypeError
135
+ # If the value is not numeric, just print out the result
136
+ self['result'].is_a?(Numeric) ? trimed_value(self['result']) : self['result']
137
+ end
124
138
  end
125
139
 
126
140
  def nested_code_string
127
141
  code_for_element(self['code'])
128
142
  end
129
143
 
130
- def diagnosis_rank_string
131
- " (rank: #{self['rank']})" if self['rank']
144
+ def diagnosis_string
145
+ dx_string = ''
146
+ dx_string += "</br>&nbsp; rank: #{self['rank']}" if self['rank']
147
+ dx_string += "</br>&nbsp; presentOnAdmissionIndicator: #{self['presentOnAdmissionIndicator']['code']}" if self['presentOnAdmissionIndicator']
148
+ dx_string
132
149
  end
133
150
 
134
151
  def end_time?
@@ -16,9 +16,12 @@ class Qrda1R5 < Mustache
16
16
  @provider = options[:provider]
17
17
  @patient_address_option = options[:patient_addresses]
18
18
  @patient_telecom_option = options[:patient_telecoms]
19
+ @patient_email_option = options[:patient_email]
19
20
  @performance_period_start = options[:start_time]
20
21
  @performance_period_end = options[:end_time]
21
22
  @submission_program = options[:submission_program]
23
+ @medicare_beneficiary_identifier = options[:medicare_beneficiary_identifier]
24
+ @hicn = options[:hicn]
22
25
  end
23
26
 
24
27
  def patient_addresses
@@ -41,6 +44,15 @@ class Qrda1R5 < Mustache
41
44
  JSON.parse(@patient_telecom_option.to_json)
42
45
  end
43
46
 
47
+ def patient_email
48
+ return unless @patient_email_option
49
+ telecom_email = [CQM::Telecom.new(
50
+ use: 'HP',
51
+ value: @patient_email_option
52
+ )]
53
+ JSON.parse(telecom_email.to_json)
54
+ end
55
+
44
56
  def patient_characteristic_payer
45
57
  JSON.parse(@qdmPatient.get_data_elements('patient_characteristic', 'payer').to_json)
46
58
  end
@@ -1,7 +1,8 @@
1
1
  <participant typeCode="DEV">
2
2
  <associatedEntity classCode="RGPR">
3
3
  <!-- CMS EHR Certification Number (formerly known as Office of the
4
- National Coordinator Certification Number) -->
5
- <id extension="123456789" root="2.16.840.1.113883.3.2074.1"/>
4
+ National Coordinator Certification Number). Note, this is a test
5
+ file, and the provided ID is not for a certified product set. -->
6
+ <id extension="0015CPV4ZTB4WBU" root="2.16.840.1.113883.3.2074.1"/>
6
7
  </associatedEntity>
7
8
  </participant>
@@ -1,6 +1,12 @@
1
1
  <recordTarget>
2
2
  <patientRole>
3
3
  <id extension="{{mrn}}" root="1.3.6.1.4.1.115" />
4
+ {{#medicare_beneficiary_identifier}}
5
+ <id extension="{{medicare_beneficiary_identifier}}" root="2.16.840.1.113883.4.927" />
6
+ {{/medicare_beneficiary_identifier}}
7
+ {{#hicn}}
8
+ <id extension="{{hicn}}" root="2.16.840.1.113883.4.572" />
9
+ {{/hicn}}
4
10
  {{#patient_addresses}}
5
11
  <addr use="{{use}}">
6
12
  {{#street}}
@@ -15,6 +21,9 @@
15
21
  {{#patient_telecoms}}
16
22
  <telecom use="{{use}}" value="tel:{{value}}"/>
17
23
  {{/patient_telecoms}}
24
+ {{#patient_email}}
25
+ <telecom use="{{use}}" value="mailto:{{value}}"/>
26
+ {{/patient_email}}
18
27
  <patient>
19
28
  {{#patient}}
20
29
  <name>
@@ -1,58 +1,51 @@
1
1
  <entry>
2
- <act classCode="ACT" moodCode="EVN">
3
- <!--Encounter performed Act -->
4
- <templateId extension="2021-08-01" root="2.16.840.1.113883.10.20.24.3.133"/>
5
- <code code="ENC" codeSystem="2.16.840.1.113883.5.6" codeSystemName="ActClass" displayName="Encounter"/>
6
- <entryRelationship typeCode="SUBJ">
7
- <encounter classCode="ENC" moodCode="EVN">
8
- <!-- Encounter activities template -->
9
- <templateId extension="2015-08-01" root="2.16.840.1.113883.10.20.22.4.49"/>
10
- <!-- Encounter performed template -->
11
- <templateId extension="2021-08-01" root="2.16.840.1.113883.10.20.24.3.23"/>
12
- <id extension="{{object_id}}" root="1.3.6.1.4.1.115"/>
13
- <!-- QDM Attribute: Code -->
14
- {{> _codes}}
15
- <text>{{description}}</text>
16
- <statusCode code="completed"/>
17
- {{#relevantPeriod}}
18
- <!-- QDM Attribute: Relevant Period -->
19
- {{{relevant_period}}}
20
- {{/relevantPeriod}}
21
- {{#dischargeDisposition}}
22
- <!-- QDM Attribute: Discharge Disposition -->
23
- <sdtc:dischargeDispositionCode {{> _code}}/>
24
- {{/dischargeDisposition}}
25
- {{#authorDatetime}}
26
- <!-- QDM Attribute: Author dateTime -->
27
- {{> qrda_templates/template_partials/_author}}
28
- {{/authorDatetime}}
29
- {{#facilityLocations}}
30
- <!-- QDM Attribute: Facility Locations -->
31
- {{> qrda_templates/template_partials/_facility_location}}
32
- {{/facilityLocations}}
33
- {{#admissionSource}}
34
- <!-- QDM Attribute: Admission Source -->
35
- {{> qrda_templates/template_partials/_admission_source}}
36
- {{/admissionSource}}
37
- {{#participant}}
38
- <!-- QDM Attribute: Participant -->
39
- <participant typeCode="PRF">
40
- {{> qrda_templates/template_partials/_entity}}
41
- </participant>
42
- {{/participant}}
43
- {{#clazz}}
44
- <!-- QDM Attribute: Class -->
45
- {{> qrda_templates/template_partials/_encounter_class}}
46
- {{/clazz}}
47
- {{#diagnoses}}
48
- <!-- QDM Attribute: Diagnoses -->
49
- {{> qrda_templates/template_partials/_encounter_diagnosis_qdm}}
50
- {{/diagnoses}}
51
- {{#relatedTo}}
52
- <!-- QDM Attribute: relatedTo -->
53
- {{> qrda_templates/template_partials/_related_to}}
54
- {{/relatedTo}}
55
- </encounter>
56
- </entryRelationship>
57
- </act>
2
+ <encounter classCode="ENC" moodCode="EVN">
3
+ <!-- Encounter activities template -->
4
+ <templateId extension="2015-08-01" root="2.16.840.1.113883.10.20.22.4.49"/>
5
+ <!-- Encounter performed template -->
6
+ <templateId extension="2021-08-01" root="2.16.840.1.113883.10.20.24.3.23"/>
7
+ <id extension="{{object_id}}" root="1.3.6.1.4.1.115"/>
8
+ <!-- QDM Attribute: Code -->
9
+ {{> _codes}}
10
+ <text>{{description}}</text>
11
+ <statusCode code="completed"/>
12
+ {{#relevantPeriod}}
13
+ <!-- QDM Attribute: Relevant Period -->
14
+ {{{relevant_period}}}
15
+ {{/relevantPeriod}}
16
+ {{#dischargeDisposition}}
17
+ <!-- QDM Attribute: Discharge Disposition -->
18
+ <sdtc:dischargeDispositionCode {{> _code}}/>
19
+ {{/dischargeDisposition}}
20
+ {{#authorDatetime}}
21
+ <!-- QDM Attribute: Author dateTime -->
22
+ {{> qrda_templates/template_partials/_author}}
23
+ {{/authorDatetime}}
24
+ {{#facilityLocations}}
25
+ <!-- QDM Attribute: Facility Locations -->
26
+ {{> qrda_templates/template_partials/_facility_location}}
27
+ {{/facilityLocations}}
28
+ {{#admissionSource}}
29
+ <!-- QDM Attribute: Admission Source -->
30
+ {{> qrda_templates/template_partials/_admission_source}}
31
+ {{/admissionSource}}
32
+ {{#participant}}
33
+ <!-- QDM Attribute: Participant -->
34
+ <participant typeCode="PRF">
35
+ {{> qrda_templates/template_partials/_entity}}
36
+ </participant>
37
+ {{/participant}}
38
+ {{#clazz}}
39
+ <!-- QDM Attribute: Class -->
40
+ {{> qrda_templates/template_partials/_encounter_class}}
41
+ {{/clazz}}
42
+ {{#diagnoses}}
43
+ <!-- QDM Attribute: Diagnoses -->
44
+ {{> qrda_templates/template_partials/_encounter_diagnosis_qdm}}
45
+ {{/diagnoses}}
46
+ {{#relatedTo}}
47
+ <!-- QDM Attribute: relatedTo -->
48
+ {{> qrda_templates/template_partials/_related_to}}
49
+ {{/relatedTo}}
50
+ </encounter>
58
51
  </entry>
@@ -61,7 +61,7 @@
61
61
  {{/daysSupplied}}
62
62
  {{#supply}}
63
63
  <!-- QDM Attribute: Supply -->
64
- <entryRelationship typeCode="REFR">
64
+ <entryRelationship typeCode="COMP">
65
65
  {{> qrda_templates/template_partials/_medication_supply_request}}
66
66
  </entryRelationship>
67
67
  {{/supply}}
@@ -69,7 +69,7 @@
69
69
  </entryRelationship>
70
70
  {{#supply}}
71
71
  <!-- QDM Attribute: Supply -->
72
- <entryRelationship typeCode="REFR">
72
+ <entryRelationship typeCode="COMP">
73
73
  {{> qrda_templates/template_partials/_medication_supply_request}}
74
74
  </entryRelationship>
75
75
  {{/supply}}
@@ -62,7 +62,7 @@
62
62
  {{/daysSupplied}}
63
63
  {{#supply}}
64
64
  <!-- QDM Attribute: Supply -->
65
- <entryRelationship typeCode="REFR">
65
+ <entryRelationship typeCode="COMP">
66
66
  {{> qrda_templates/template_partials/_medication_supply_request}}
67
67
  </entryRelationship>
68
68
  {{/supply}}
@@ -17,7 +17,7 @@
17
17
  {{^negated}}
18
18
  {{#refills}}
19
19
  <!-- QDM Attribute: Refills -->
20
- <repeatNumber value="{{.}}"/>
20
+ <repeatNumber value="{{{refills_as_repeat_number}}}"/>
21
21
  {{/refills}}
22
22
  {{/negated}}
23
23
  {{#route}}
@@ -0,0 +1,258 @@
1
+ require 'mustache'
2
+ class Qrda1R52 < Mustache
3
+ include Qrda::Export::Helper::DateHelper
4
+ include Qrda::Export::Helper::ViewHelper
5
+ include Qrda::Export::Helper::Cat1ViewHelper
6
+ include Qrda::Export::Helper::PatientViewHelper
7
+ include Qrda::Export::Helper::FrequencyHelper
8
+ include HQMF::Util::EntityHelper
9
+
10
+ self.template_path = __dir__
11
+
12
+ def initialize(patient, measures, options = {})
13
+ @patient = patient
14
+ @qdmPatient = patient.qdmPatient
15
+ @measures = measures
16
+ @provider = options[:provider]
17
+ @patient_address_option = options[:patient_addresses]
18
+ @patient_telecom_option = options[:patient_telecoms]
19
+ @patient_email_option = options[:patient_email]
20
+ @performance_period_start = options[:start_time]
21
+ @performance_period_end = options[:end_time]
22
+ @submission_program = options[:submission_program]
23
+ @medicare_beneficiary_identifier = options[:medicare_beneficiary_identifier]
24
+ end
25
+
26
+ def patient_addresses
27
+ @patient_address_option ||= [CQM::Address.new(
28
+ use: 'HP',
29
+ street: ['202 Burlington Rd.'],
30
+ city: 'Bedford',
31
+ state: 'MA',
32
+ zip: '01730',
33
+ country: 'US'
34
+ )]
35
+ JSON.parse(@patient_address_option.to_json)
36
+ end
37
+
38
+ def patient_telecoms
39
+ @patient_telecom_option ||= [CQM::Telecom.new(
40
+ use: 'HP',
41
+ value: '555-555-2003'
42
+ )]
43
+ JSON.parse(@patient_telecom_option.to_json)
44
+ end
45
+
46
+ def patient_email
47
+ return unless @patient_email_option
48
+ telecom_email = [CQM::Telecom.new(
49
+ use: 'HP',
50
+ value: @patient_email_option
51
+ )]
52
+ JSON.parse(telecom_email.to_json)
53
+ end
54
+
55
+ def patient_characteristic_payer
56
+ JSON.parse(@qdmPatient.get_data_elements('patient_characteristic', 'payer').to_json)
57
+ end
58
+
59
+ def patient_characteristic_birthdate
60
+ JSON.parse(@qdmPatient.get_data_elements('patient_characteristic', 'birthdate').to_json)
61
+ end
62
+
63
+ def patient_characteristic_sex
64
+ JSON.parse(@qdmPatient.get_data_elements('patient_characteristic', 'gender').to_json)
65
+ end
66
+
67
+ def patient_characteristic_race
68
+ JSON.parse(@qdmPatient.get_data_elements('patient_characteristic', 'race').to_json)
69
+ end
70
+
71
+ def patient_characteristic_ethnicity
72
+ JSON.parse(@qdmPatient.get_data_elements('patient_characteristic', 'ethnicity').to_json)
73
+ end
74
+
75
+ def adverse_event
76
+ JSON.parse(@qdmPatient.get_data_elements('adverse_event', nil).to_json)
77
+ end
78
+
79
+ def allergy_intolerance
80
+ JSON.parse(@qdmPatient.get_data_elements('allergy', 'intolerance').to_json)
81
+ end
82
+
83
+ def assessment_order
84
+ JSON.parse(@qdmPatient.get_data_elements('assessment', 'order').to_json)
85
+ end
86
+
87
+ def assessment_performed
88
+ JSON.parse(@qdmPatient.get_data_elements('assessment', 'performed').to_json)
89
+ end
90
+
91
+ def assessment_recommended
92
+ JSON.parse(@qdmPatient.get_data_elements('assessment', 'recommended').to_json)
93
+ end
94
+
95
+ def communication_performed
96
+ JSON.parse(@qdmPatient.get_data_elements('communication', 'performed').to_json)
97
+ end
98
+
99
+ def diagnosis
100
+ JSON.parse(@qdmPatient.get_data_elements('condition', nil).to_json)
101
+ end
102
+
103
+ def device_applied
104
+ JSON.parse(@qdmPatient.get_data_elements('device', 'applied').to_json)
105
+ end
106
+
107
+ def device_order
108
+ JSON.parse(@qdmPatient.get_data_elements('device', 'order').to_json)
109
+ end
110
+
111
+ def device_recommended
112
+ JSON.parse(@qdmPatient.get_data_elements('device', 'recommended').to_json)
113
+ end
114
+
115
+ def diagnostic_study_order
116
+ JSON.parse(@qdmPatient.get_data_elements('diagnostic_study', 'order').to_json)
117
+ end
118
+
119
+ def diagnostic_study_performed
120
+ JSON.parse(@qdmPatient.get_data_elements('diagnostic_study', 'performed').to_json)
121
+ end
122
+
123
+ def diagnostic_study_recommended
124
+ JSON.parse(@qdmPatient.get_data_elements('diagnostic_study', 'recommended').to_json)
125
+ end
126
+
127
+ def encounter_order
128
+ JSON.parse(@qdmPatient.get_data_elements('encounter', 'order').to_json)
129
+ end
130
+
131
+ def encounter_performed
132
+ JSON.parse(@qdmPatient.get_data_elements('encounter', 'performed').to_json)
133
+ end
134
+
135
+ def encounter_recommended
136
+ JSON.parse(@qdmPatient.get_data_elements('encounter', 'recommended').to_json)
137
+ end
138
+
139
+ def family_history
140
+ JSON.parse(@qdmPatient.get_data_elements('family_history', nil).to_json)
141
+ end
142
+
143
+ def immunization_administered
144
+ JSON.parse(@qdmPatient.get_data_elements('immunization', 'administered').to_json)
145
+ end
146
+
147
+ def immunization_order
148
+ JSON.parse(@qdmPatient.get_data_elements('immunization', 'order').to_json)
149
+ end
150
+
151
+ def intervention_order
152
+ JSON.parse(@qdmPatient.get_data_elements('intervention', 'order').to_json)
153
+ end
154
+
155
+ def intervention_performed
156
+ JSON.parse(@qdmPatient.get_data_elements('intervention', 'performed').to_json)
157
+ end
158
+
159
+ def intervention_recommended
160
+ JSON.parse(@qdmPatient.get_data_elements('intervention', 'recommended').to_json)
161
+ end
162
+
163
+ def laboratory_test_order
164
+ JSON.parse(@qdmPatient.get_data_elements('laboratory_test', 'order').to_json)
165
+ end
166
+
167
+ def laboratory_test_performed
168
+ JSON.parse(@qdmPatient.get_data_elements('laboratory_test', 'performed').to_json)
169
+ end
170
+
171
+ def laboratory_test_recommended
172
+ JSON.parse(@qdmPatient.get_data_elements('laboratory_test', 'recommended').to_json)
173
+ end
174
+
175
+ def medication_active
176
+ JSON.parse(@qdmPatient.get_data_elements('medication', 'active').to_json)
177
+ end
178
+
179
+ def medication_administered
180
+ JSON.parse(@qdmPatient.get_data_elements('medication', 'administered').to_json) + JSON.parse(@qdmPatient.get_data_elements('substance', 'administered').to_json)
181
+ end
182
+
183
+ def medication_discharge
184
+ JSON.parse(@qdmPatient.get_data_elements('medication', 'discharge').to_json)
185
+ end
186
+
187
+ def medication_dispensed
188
+ JSON.parse(@qdmPatient.get_data_elements('medication', 'dispensed').to_json)
189
+ end
190
+
191
+ def medication_order
192
+ JSON.parse(@qdmPatient.get_data_elements('medication', 'order').to_json)
193
+ end
194
+
195
+ def patient_care_experience
196
+ JSON.parse(@qdmPatient.dataElements.where(hqmfOid: { '$in' => HQMF::Util::HQMFTemplateHelper.get_all_hqmf_oids('patient_care_experience', '') }).to_json)
197
+ end
198
+
199
+ def patient_characteristic_clinical_trial_participant
200
+ JSON.parse(@qdmPatient.get_data_elements('patient_characteristic', 'clinical_trial_participant').to_json)
201
+ end
202
+
203
+ def patient_characteristic_expired
204
+ JSON.parse(@qdmPatient.get_data_elements('patient_characteristic', 'expired').to_json)
205
+ end
206
+
207
+ def physical_exam_order
208
+ JSON.parse(@qdmPatient.get_data_elements('physical_exam', 'order').to_json)
209
+ end
210
+
211
+ def physical_exam_performed
212
+ JSON.parse(@qdmPatient.get_data_elements('physical_exam', 'performed').to_json)
213
+ end
214
+
215
+ def physical_exam_recommended
216
+ JSON.parse(@qdmPatient.get_data_elements('physical_exam', 'recommended').to_json)
217
+ end
218
+
219
+ def procedure_order
220
+ JSON.parse(@qdmPatient.get_data_elements('procedure', 'order').to_json)
221
+ end
222
+
223
+ def procedure_performed
224
+ JSON.parse(@qdmPatient.get_data_elements('procedure', 'performed').to_json)
225
+ end
226
+
227
+ def procedure_recommended
228
+ JSON.parse(@qdmPatient.get_data_elements('procedure', 'recommended').to_json)
229
+ end
230
+
231
+ def program_participation
232
+ JSON.parse(@qdmPatient.get_data_elements('participation', nil).to_json)
233
+ end
234
+
235
+ def provider_care_experience
236
+ JSON.parse(@qdmPatient.dataElements.where(hqmfOid: { '$in' => HQMF::Util::HQMFTemplateHelper.get_all_hqmf_oids('provider_care_experience', '') }).to_json)
237
+ end
238
+
239
+ def related_person
240
+ JSON.parse(@qdmPatient.get_data_elements('related_person', nil).to_json)
241
+ end
242
+
243
+ def substance_administered
244
+ JSON.parse(@qdmPatient.get_data_elements('substance', 'administered').to_json)
245
+ end
246
+
247
+ def substance_order
248
+ JSON.parse(@qdmPatient.get_data_elements('substance', 'order').to_json)
249
+ end
250
+
251
+ def substance_recommended
252
+ JSON.parse(@qdmPatient.get_data_elements('substance', 'recommended').to_json)
253
+ end
254
+
255
+ def symptom
256
+ JSON.parse(@qdmPatient.get_data_elements('symptom', nil).to_json)
257
+ end
258
+ end
@@ -0,0 +1,8 @@
1
+ <participant typeCode="DEV">
2
+ <associatedEntity classCode="RGPR">
3
+ <!-- CMS EHR Certification Number (formerly known as Office of the
4
+ National Coordinator Certification Number). Note, this is a test
5
+ file, and the provided ID is not for a certified product set. -->
6
+ <id extension="0015CPV4ZTB4WBU" root="2.16.840.1.113883.3.2074.1"/>
7
+ </associatedEntity>
8
+ </participant>
@@ -0,0 +1,65 @@
1
+ <recordTarget>
2
+ <patientRole>
3
+ <id extension="{{mrn}}" root="1.3.6.1.4.1.115" />
4
+ {{#medicare_beneficiary_identifier}}
5
+ <id extension="{{medicare_beneficiary_identifier}}" root="2.16.840.1.113883.4.927" />
6
+ {{/medicare_beneficiary_identifier}}
7
+ {{#patient_addresses}}
8
+ <addr use="{{use}}">
9
+ {{#street}}
10
+ <streetAddressLine>{{.}}</streetAddressLine>
11
+ {{/street}}
12
+ <city>{{city}}</city>
13
+ <state>{{state}}</state>
14
+ <postalCode>{{zip}}</postalCode>
15
+ <country>{{country}}</country>
16
+ </addr>
17
+ {{/patient_addresses}}
18
+ {{#patient_telecoms}}
19
+ <telecom use="{{use}}" value="tel:{{value}}"/>
20
+ {{/patient_telecoms}}
21
+ {{#patient_email}}
22
+ <telecom use="{{use}}" value="mailto:{{value}}"/>
23
+ {{/patient_email}}
24
+ <patient>
25
+ {{#patient}}
26
+ <name>
27
+ <given>{{given_name}}</given>
28
+ <family>{{familyName}}</family>
29
+ </name>
30
+ {{/patient}}
31
+ {{#patient_characteristic_sex}}
32
+ {{#dataElementCodes}}
33
+ <administrativeGenderCode {{> _code}}/>
34
+ {{/dataElementCodes}}
35
+ {{/patient_characteristic_sex}}
36
+ {{^patient_characteristic_sex}}
37
+ <administrativeGenderCode nullFlavor="UNK"/>
38
+ {{/patient_characteristic_sex}}
39
+ {{#patient_characteristic_birthdate}}
40
+ {{{birth_date_time}}}
41
+ {{/patient_characteristic_birthdate}}
42
+ {{#patient_characteristic_race}}
43
+ {{#dataElementCodes}}
44
+ <raceCode {{> _code}}/>
45
+ {{/dataElementCodes}}
46
+ {{/patient_characteristic_race}}
47
+ {{^patient_characteristic_race}}
48
+ <raceCode nullFlavor="UNK"/>
49
+ {{/patient_characteristic_race}}
50
+ {{#patient_characteristic_ethnicity}}
51
+ {{#dataElementCodes}}
52
+ <ethnicGroupCode {{> _code}}/>
53
+ {{/dataElementCodes}}
54
+ {{/patient_characteristic_ethnicity}}
55
+ {{^patient_characteristic_ethnicity}}
56
+ <ethnicGroupCode nullFlavor="UNK"/>
57
+ {{/patient_characteristic_ethnicity}}
58
+ <languageCommunication>
59
+ <templateId root="2.16.840.1.113883.3.88.11.83.2" assigningAuthorityName="HITSP/C83"/>
60
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.2.1" assigningAuthorityName="IHE/PCC"/>
61
+ <languageCode code="eng"/>
62
+ </languageCommunication>
63
+ </patient>
64
+ </patientRole>
65
+ </recordTarget>
@@ -0,0 +1,70 @@
1
+ <entry>
2
+ <!--Medication Order -->
3
+ <substanceAdministration classCode="SBADM" moodCode="RQO" {{{negation_ind}}}>
4
+ <templateId root="2.16.840.1.113883.10.20.22.4.42" extension="2014-06-09"/>
5
+ <!-- Medication, Order template -->
6
+ <templateId root="2.16.840.1.113883.10.20.24.3.47" extension="2019-12-01"/>
7
+ <id root="1.3.6.1.4.1.115" extension="{{object_id}}"/>
8
+ <text>{{description}}</text>
9
+ <statusCode code="active"/>
10
+ {{#relevantPeriod}}
11
+ <!-- QDM Attribute: Relevant Period -->
12
+ {{{medication_duration_effective_time}}}
13
+ {{/relevantPeriod}}
14
+ {{^relevantPeriod}}
15
+ {{#authorDatetime}}
16
+ <!-- QDM Attribute: Relevant Period -->
17
+ {{{medication_duration_author_effective_time}}}
18
+ {{/authorDatetime}}
19
+ {{/relevantPeriod}}
20
+ {{> qrda_templates/template_partials/_medication_details}}
21
+ <consumable>
22
+ <manufacturedProduct classCode="MANU">
23
+ <!-- Medication Information (consolidation) template -->
24
+ <templateId root="2.16.840.1.113883.10.20.22.4.23" extension="2014-06-09"/>
25
+ <id root="{{random_id}}"/>
26
+ <manufacturedMaterial>
27
+ <!-- QDM Attribute: Code -->
28
+ {{> _codes}}
29
+ </manufacturedMaterial>
30
+ </manufacturedProduct>
31
+ </consumable>
32
+ {{#authorDatetime}}
33
+ <!-- QDM Attribute: Author dateTime -->
34
+ {{> qrda_templates/template_partials/_author}}
35
+ {{/authorDatetime}}
36
+ {{#setting}}
37
+ <participant typeCode="LOC">
38
+ <participantRole>
39
+ <!-- QDM Attribute: Setting -->
40
+ <code {{> _code}}/>
41
+ </participantRole>
42
+ </participant>
43
+ {{/setting}}
44
+ {{#prescriber}}
45
+ <!-- QDM Attribute: Prescriber -->
46
+ <participant typeCode="PRF">
47
+ {{> qrda_templates/template_partials/_entity}}
48
+ </participant>
49
+ {{/prescriber}}
50
+ {{#reason}}
51
+ <!-- QDM Attribute: Reason -->
52
+ {{> qrda_templates/template_partials/_reason}}
53
+ {{/reason}}
54
+ {{#negationRationale}}
55
+ <!-- QDM Attribute: Negation Rationale -->
56
+ {{> qrda_templates/template_partials/_reason}}
57
+ {{/negationRationale}}
58
+ {{#daysSupplied}}
59
+ <entryRelationship typeCode="REFR">
60
+ {{> qrda_templates/template_partials/_days_supplied}}
61
+ </entryRelationship>
62
+ {{/daysSupplied}}
63
+ {{#supply}}
64
+ <!-- QDM Attribute: Supply -->
65
+ <entryRelationship typeCode="COMP">
66
+ {{> qrda_templates/template_partials/_medication_supply_request}}
67
+ </entryRelationship>
68
+ {{/supply}}
69
+ </substanceAdministration>
70
+ </entry>
@@ -3,10 +3,8 @@
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="2020-12-01"/>
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?}}
6
+ <!-- QRDA Category III Report - CMS (V7) -->
7
+ <templateId root="2.16.840.1.113883.10.20.27.1.2" extension="2022-12-01"/>
10
8
  <!-- This is the globally unique identifier for this QRDA document -->
11
9
  <id root="{{random_id}}"/>
12
10
  <!-- QRDA III document type code -->
@@ -1,6 +1,9 @@
1
1
  <participant typeCode="DEV">
2
2
  <associatedEntity classCode="RGPR">
3
- <id root="2.16.840.1.113883.3.2074.1" extension="12345abcde67890"/>
3
+ <!-- CMS EHR Certification Number (formerly known as Office of the
4
+ National Coordinator Certification Number). Note, this is a test
5
+ file, and the provided ID is not for a certified product set. -->
6
+ <id root="2.16.840.1.113883.3.2074.1" extension="0015CPV4ZTB4WBU"/>
4
7
  <code code="129465004" displayName="medical record, device" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED-CT"/>
5
8
  </associatedEntity>
6
9
  </participant>
@@ -0,0 +1,9 @@
1
+ <participant typeCode="DEV">
2
+ <associatedEntity classCode="RGPR">
3
+ <!-- CMS EHR Certification Number (formerly known as Office of the
4
+ National Coordinator Certification Number). Note, this is a test
5
+ file, and the provided ID is not for a certified product set. -->
6
+ <id root="2.16.840.1.113883.3.2074.1" extension="0015CPV4ZTB4WBU"/>
7
+ <code code="129465004" displayName="medical record, device" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED-CT"/>
8
+ </associatedEntity>
9
+ </participant>
@@ -55,22 +55,30 @@ module Qrda
55
55
  self['value'].to_f
56
56
  end
57
57
 
58
+ def refills_as_repeat_number
59
+ self['refills'] + 1
60
+ end
61
+
58
62
  def dose_quantity_value
59
- return "<doseQuantity value=\"#{value_as_float}\" unit=\"#{self['unit']}\"/>" if self['unit']
63
+ return "<doseQuantity value=\"#{value_as_float}\" unit=\"#{self['unit']}\"/>" if self['unit'] && self['unit'] != ''
60
64
  "<doseQuantity value=\"#{value_as_float}\" />"
61
65
  end
62
66
 
63
67
  def result_value
64
68
  return "<value xsi:type=\"CD\" nullFlavor=\"UNK\"/>" unless self['result']
65
-
66
69
  result_string = if self['result'].is_a? Array
67
70
  result_value_as_string(self['result'][0])
68
71
  elsif self['result'].is_a? Hash
69
72
  result_value_as_string(self['result'])
70
73
  elsif self['result'].is_a? String
71
- "<value xsi:type=\"ST\">#{self['result']}</value>"
74
+ begin
75
+ DateTime.parse self['result']
76
+ "<value xsi:type=\"TS\" #{value_or_null_flavor(self['result'])}/>"
77
+ rescue StandardError
78
+ "<value xsi:type=\"ST\">#{self['result']}</value>"
79
+ end
72
80
  elsif !self['result'].nil?
73
- "<value xsi:type=\"PQ\" value=\"#{self['result']}\" unit=\"1\"/>"
81
+ integer_or_pq(self['result'])
74
82
  end
75
83
  result_string
76
84
  end
@@ -79,7 +87,17 @@ module Qrda
79
87
  return "<value xsi:type=\"CD\" nullFlavor=\"UNK\"/>" unless result
80
88
  oid = result['system'] || result['codeSystem']
81
89
  return "<value xsi:type=\"CD\" code=\"#{result['code']}\" codeSystem=\"#{oid}\" codeSystemName=\"#{HQMF::Util::CodeSystemHelper.code_system_for(oid)}\"/>" if result['code']
82
- return "<value xsi:type=\"PQ\" value=\"#{result['value']}\" unit=\"#{result['unit']}\"/>" if result['unit']
90
+ return integer_or_pq(result['value'], result['unit']) if result['unit'] && result['unit'] != ''
91
+ end
92
+
93
+ def integer_or_pq(number, unit = nil)
94
+ i = number.to_i
95
+ f = number.to_f
96
+ if i == f
97
+ unit ? "<value xsi:type=\"PQ\" value=\"#{i}\" unit=\"#{unit}\"/>" : "<value xsi:type=\"INT\" value=\"#{i}\"/>"
98
+ else
99
+ unit ? "<value xsi:type=\"PQ\" value=\"#{f}\" unit=\"#{unit}\"/>" : "<value xsi:type=\"REAL\" value=\"#{f}\"/>"
100
+ end
83
101
  end
84
102
 
85
103
  def authordatetime_or_dispenserid?
@@ -4,7 +4,7 @@ module Qrda
4
4
  module Helper
5
5
  module ViewHelper
6
6
  def measures
7
- @measures.only(:hqmf_id, :hqmf_set_id, :description).as_json
7
+ @measures.as_json
8
8
  end
9
9
 
10
10
  def random_id
@@ -22,6 +22,14 @@ module Qrda
22
22
  def submission_program
23
23
  @submission_program
24
24
  end
25
+
26
+ def medicare_beneficiary_identifier
27
+ @medicare_beneficiary_identifier
28
+ end
29
+
30
+ def hicn
31
+ @hicn
32
+ end
25
33
  end
26
34
  end
27
35
  end
@@ -47,8 +47,8 @@ module QRDA
47
47
  entry_qrda_id = extract_id(entry_element, @id_xpath)
48
48
  # Create a hash to map all of entry.ids to the same QRDA ids. This will be used to merge QRDA entries
49
49
  # that represent the same event.
50
- @entry_id_map["#{entry_qrda_id.value}_#{entry_qrda_id.namingSystem}"] ||= []
51
- @entry_id_map["#{entry_qrda_id.value}_#{entry_qrda_id.namingSystem}"] << entry.id
50
+ @entry_id_map["#{entry_qrda_id.value}***#{entry_qrda_id.namingSystem}"] ||= []
51
+ @entry_id_map["#{entry_qrda_id.value}***#{entry_qrda_id.namingSystem}"] << entry.id
52
52
  entry.dataElementCodes = extract_codes(entry_element, @code_xpath)
53
53
  extract_dates(entry_element, entry)
54
54
  if @result_xpath
@@ -77,7 +77,12 @@ module QRDA
77
77
  code_list << code_if_present(code_element)
78
78
  translations = code_element.xpath('cda:translation')
79
79
  translations.each do |translation|
80
- code_list << code_if_present(translation)
80
+ translation_code = code_if_present(translation)
81
+ next unless translation_code
82
+
83
+ code_list << translation_code
84
+ @warnings << ValidationError.new(message: "Translation code #{translation_code.system}:#{translation_code.code} may not be used for eCQM calculation by a receiving system. Ensure that the root code includes a code from the eCQM valueset.",
85
+ location: coded_element.path)
81
86
  end
82
87
  end
83
88
  code_list.compact
@@ -193,7 +198,14 @@ module QRDA
193
198
  return unless value_element && !value_element['nullFlavor']
194
199
  value = value_element['value']
195
200
  if value.present?
196
- return value.strip.to_f if (value_element['unit'] == "1" || value_element['unit'].nil?)
201
+ if ['TS'].include? value_element.at_xpath("@xsi:type")&.value
202
+ begin
203
+ return DateTime.parse(value_element['value'])
204
+ rescue StandardError
205
+ return nil
206
+ end
207
+ end
208
+ return value.strip.to_f if unitless?(value_element)
197
209
 
198
210
  return QDM::Quantity.new(value.strip.to_f, value_element['unit'])
199
211
  elsif value_element['code'].present?
@@ -208,6 +220,12 @@ module QRDA
208
220
  end
209
221
  end
210
222
 
223
+ def unitless?(value_element)
224
+ return true if value_element['unit'].nil?
225
+ return true if value_element['unit'] == '1'
226
+ return true if value_element['unit'][0] == '{' && value_element['unit'][-1] == '}'
227
+ end
228
+
211
229
  def extract_reason(parent_element)
212
230
  return unless @reason_xpath
213
231
  reason_element = parent_element.xpath(@reason_xpath)
@@ -254,6 +272,15 @@ module QRDA
254
272
  QDM::Quantity.new(scalar_element['value'].to_f, scalar_element['unit'])
255
273
  end
256
274
 
275
+ def extract_refills(parent_element, repeat_number_xpath)
276
+ repeat_number_element = parent_element.at_xpath(repeat_number_xpath)
277
+ return unless repeat_number_element && repeat_number_element['value'].present?
278
+
279
+ # Refills is the Repeat Number - 1
280
+ repeat_number = repeat_number_element['value'].to_i
281
+ repeat_number.positive? ? repeat_number - 1 : 0
282
+ end
283
+
257
284
  def extract_components(parent_element)
258
285
  component_elements = parent_element.xpath(@components_xpath)
259
286
  components = []
@@ -1,18 +1,18 @@
1
1
  module QRDA
2
2
  module Cat1
3
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']"))
4
+ def initialize(entry_finder = QRDA::Cat1::EntryFinder.new("./cda:entry/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']"))
5
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:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/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
- @clazz_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/cda:entryRelationship/cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.171']/cda:code"
14
- @diagnosis_xpath = "./cda:entryRelationship/cda:encounter[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.23']/cda:entryRelationship/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.168']"
15
- @related_to_xpath = "./cda:entryRelationship/cda:encounter/sdtc:inFulfillmentOf1/sdtc:actReference"
6
+ @id_xpath = './cda:id'
7
+ @code_xpath = "./cda:code"
8
+ @relevant_period_xpath = "./cda:effectiveTime"
9
+ @author_datetime_xpath = "./cda:author[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.155']/cda:time"
10
+ @admission_source_xpath = "./cda:participant/cda:participantRole[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.151']/cda:code"
11
+ @discharge_disposition_xpath = "./sdtc:dischargeDispositionCode"
12
+ @facility_locations_xpath = "./cda:participant[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.100']"
13
+ @clazz_xpath = "./cda:entryRelationship/cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.171']/cda:code"
14
+ @diagnosis_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.168']"
15
+ @related_to_xpath = "./sdtc:inFulfillmentOf1/sdtc:actReference"
16
16
  @entry_class = QDM::EncounterPerformed
17
17
  end
18
18
 
@@ -27,7 +27,7 @@ module QRDA
27
27
  los = encounter_performed.relevantPeriod.high.to_date - encounter_performed.relevantPeriod.low.to_date
28
28
  encounter_performed.lengthOfStay = QDM::Quantity.new(los.to_i, 'd')
29
29
  end
30
- entity = extract_entity(entry_element, "./cda:entryRelationship/cda:encounter//cda:participant[@typeCode='PRF']")
30
+ entity = extract_entity(entry_element, "./cda:participant[@typeCode='PRF']")
31
31
  encounter_performed.participant.concat(entity) if entity
32
32
  extract_modifier_code(encounter_performed, entry_element)
33
33
  encounter_performed.relatedTo = extract_related_to(entry_element)
@@ -18,7 +18,7 @@ module QRDA
18
18
 
19
19
  def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
20
20
  medication_discharge = super
21
- medication_discharge.refills = extract_scalar(entry_element, @refills_xpath)&.value
21
+ medication_discharge.refills = extract_refills(entry_element, @refills_xpath)
22
22
  medication_discharge.dosage = extract_scalar(entry_element, @dosage_xpath)
23
23
  medication_discharge.supply = extract_scalar(entry_element, @supply_xpath)
24
24
  medication_discharge.frequency = frequency_as_coded_value(entry_element, @frequency_xpath)
@@ -19,7 +19,7 @@ module QRDA
19
19
 
20
20
  def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
21
21
  medication_dispensed = super
22
- medication_dispensed.refills = extract_scalar(entry_element, @refills_xpath)&.value
22
+ medication_dispensed.refills = extract_refills(entry_element, @refills_xpath)
23
23
  medication_dispensed.dosage = extract_scalar(entry_element, @dosage_xpath)
24
24
  medication_dispensed.supply = extract_scalar(entry_element, @supply_xpath)
25
25
  medication_dispensed.frequency = frequency_as_coded_value(entry_element, @frequency_xpath)
@@ -25,7 +25,7 @@ module QRDA
25
25
  medication_order.dosage = extract_scalar(entry_element, @dosage_xpath)
26
26
  medication_order.supply = extract_scalar(entry_element, @supply_xpath)
27
27
  medication_order.frequency = frequency_as_coded_value(entry_element, @frequency_xpath)
28
- medication_order.refills = extract_scalar(entry_element, @refills_xpath)&.value
28
+ medication_order.refills = extract_refills(entry_element, @refills_xpath)
29
29
  medication_order.route = code_if_present(entry_element.at_xpath(@route_xpath))
30
30
  medication_order.setting = code_if_present(entry_element.at_xpath(@setting_xpath))
31
31
  medication_order.daysSupplied = extract_scalar(entry_element, @days_supplied_xpath)&.value
@@ -21,7 +21,7 @@ module QRDA
21
21
  substance_order.dosage = extract_scalar(entry_element, @dosage_xpath)
22
22
  substance_order.supply = extract_scalar(entry_element, @supply_xpath)
23
23
  substance_order.frequency = frequency_as_coded_value(entry_element, @frequency_xpath)
24
- substance_order.refills = extract_scalar(entry_element, @refills_xpath)&.value
24
+ substance_order.refills = extract_refills(entry_element, @refills_xpath)
25
25
  substance_order.route = code_if_present(entry_element.at_xpath(@route_xpath))
26
26
  substance_order.reason = extract_reason(entry_element)
27
27
  substance_order
@@ -18,7 +18,7 @@ module QRDA
18
18
  substance_recommended = super
19
19
  substance_recommended.dosage = extract_scalar(entry_element, @dosage_xpath)
20
20
  substance_recommended.frequency = frequency_as_coded_value(entry_element, @frequency_xpath)
21
- substance_recommended.refills = extract_scalar(entry_element, @refills_xpath)&.value
21
+ substance_recommended.refills = extract_refills(entry_element, @refills_xpath)
22
22
  substance_recommended.route = code_if_present(entry_element.at_xpath(@route_xpath))
23
23
  substance_recommended.reason = extract_reason(entry_element)
24
24
  entity = extract_entity(entry_element, "./cda:participant[@typeCode='PRF']")
@@ -67,7 +67,7 @@ module QRDA
67
67
  codes_modifiers = {}
68
68
  entry_id_map = {}
69
69
  import_data_elements(patient, doc, entry_id_map, codes, codes_modifiers, warnings)
70
- normalize_references(patient, entry_id_map)
70
+ normalize_references(patient, entry_id_map, warnings)
71
71
  get_demographics(patient, doc, codes)
72
72
  [patient, warnings, codes, codes_modifiers]
73
73
  end
@@ -80,9 +80,19 @@ module QRDA
80
80
  data_elements, id_map = importer.create_entries(context, nrh)
81
81
  new_data_elements = []
82
82
 
83
- id_map.each_value do |elem_ids|
84
- elem_id = elem_ids.first
83
+ id_map.each_pair do |key, elem_ids|
84
+ split_id = key.split('***')
85
+ id_string = "#{split_id[1]}(root), #{split_id[0]}(extension)"
86
+ warnings << ValidationError.new(message: "Two or more entries share the Id: #{id_string}.") if elem_ids.length > 1
87
+ elem_id = elem_ids.last
85
88
  data_element = data_elements.find { |de| de.id == elem_id }
89
+
90
+ # If a data_element isn't returned, there was an issue parsing the template, provide a warning
91
+ if data_element.nil?
92
+ warnings << ValidationError.new(message: "Error parsing template with Id: #{id_string}.")
93
+ next
94
+ end
95
+
86
96
  # Keep the first element with a shared ID
87
97
  new_data_elements << data_element
88
98
 
@@ -94,7 +104,7 @@ module QRDA
94
104
  unique_element_keys << key_elements_for_determining_encounter_uniqueness(data_element)
95
105
 
96
106
  # Loop through all other data elements with the same id
97
- elem_ids[1,elem_ids.length].each do |dup_id|
107
+ elem_ids[0,elem_ids.length - 1].each do |dup_id|
98
108
  dup_element = data_elements.find { |de| de.id == dup_id }
99
109
  dup_element_keys = key_elements_for_determining_encounter_uniqueness(dup_element)
100
110
  # See if a previously selected data element shared all of the keys files
@@ -134,13 +144,19 @@ module QRDA
134
144
  record.deathdate = DateTime.parse(entry_elements.at_xpath("./cda:effectiveTime/cda:low")['value']).to_i
135
145
  end
136
146
 
137
- def normalize_references(patient, entry_id_map)
147
+ def normalize_references(patient, entry_id_map, warnings)
138
148
  patient.qdmPatient.dataElements.each do |data_element|
139
149
  next unless data_element.respond_to?(:relatedTo) && data_element.relatedTo
140
150
 
141
151
  relations_to_add = []
142
152
  data_element.relatedTo.each do |related_to|
143
- relations_to_add += entry_id_map["#{related_to['value']}_#{related_to['namingSystem']}"]
153
+ relation_to_add = entry_id_map["#{related_to['value']}***#{related_to['namingSystem']}"]
154
+ # Add the relation if it can be found, otherwise return a warning
155
+ relations_to_add += relation_to_add unless relation_to_add.nil?
156
+ if relation_to_add.nil?
157
+ id_warning_str = "Related To Id: #{related_to['namingSystem']}(root), #{related_to['value']}(extension) cannot be found in QRDA file."
158
+ warnings << ValidationError.new(message: id_warning_str)
159
+ end
144
160
  end
145
161
  data_element.relatedTo = relations_to_add.map(&:to_s)
146
162
  end
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: 4.0.1
4
+ version: 4.1.0
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: 2022-05-09 00:00:00.000000000 Z
11
+ date: 2023-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cqm-models
@@ -89,7 +89,7 @@ dependencies:
89
89
  version: 1.8.5
90
90
  - - "<"
91
91
  - !ruby/object:Gem::Version
92
- version: 1.14.0
92
+ version: 1.15.0
93
93
  type: :runtime
94
94
  prerelease: false
95
95
  version_requirements: !ruby/object:Gem::Requirement
@@ -99,7 +99,7 @@ dependencies:
99
99
  version: 1.8.5
100
100
  - - "<"
101
101
  - !ruby/object:Gem::Version
102
- version: 1.14.0
102
+ version: 1.15.0
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: uuid
105
105
  requirement: !ruby/object:Gem::Requirement
@@ -263,6 +263,11 @@ files:
263
263
  - lib/qrda-export/catI-r5/qrda_templates/template_partials/_results.mustache
264
264
  - lib/qrda-export/catI-r5/qrda_templates/template_partials/_severity.mustache
265
265
  - lib/qrda-export/catI-r5/qrda_templates/template_partials/_status.mustache
266
+ - lib/qrda-export/catI-r52/qrda1_r52.rb
267
+ - lib/qrda-export/catI-r52/qrda_header/_participant.mustache
268
+ - lib/qrda-export/catI-r52/qrda_header/_record_target.mustache
269
+ - lib/qrda-export/catI-r52/qrda_templates/medication_order.mustache
270
+ - lib/qrda-export/catIII-r2-1/qrda_header/_participant_ehr.mustache
266
271
  - lib/qrda-export/catIII/_continuous_variable_value.mustache
267
272
  - lib/qrda-export/catIII/_header.mustache
268
273
  - lib/qrda-export/catIII/_measure_data.mustache
@@ -365,7 +370,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
365
370
  - !ruby/object:Gem::Version
366
371
  version: '0'
367
372
  requirements: []
368
- rubygems_version: 3.1.6
373
+ rubygems_version: 3.1.4
369
374
  signing_key:
370
375
  specification_version: 4
371
376
  summary: A library for import and export of reports for use with electronic Clinical