cqm-reports 1.0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +33 -0
  3. data/README.md +27 -0
  4. data/Rakefile +16 -0
  5. data/lib/cqm_report.rb +77 -0
  6. data/lib/ext/code.rb +11 -0
  7. data/lib/ext/data_element.rb +24 -0
  8. data/lib/html-export/qdm-patient/_header_css.mustache +61 -0
  9. data/lib/html-export/qdm-patient/_javascript.mustache +52 -0
  10. data/lib/html-export/qdm-patient/data_element/_data_element.mustache +4 -0
  11. data/lib/html-export/qdm-patient/data_element/_data_element_codes.mustache +9 -0
  12. data/lib/html-export/qdm-patient/data_element/_data_element_other_fields.mustache +106 -0
  13. data/lib/html-export/qdm-patient/data_element/_data_element_times.mustache +44 -0
  14. data/lib/html-export/qdm-patient/qdm_patient.mustache +73 -0
  15. data/lib/html-export/qdm-patient/qdm_patient.rb +47 -0
  16. data/lib/qrda-export/catI-r5/_code.mustache +1 -0
  17. data/lib/qrda-export/catI-r5/_codes.mustache +10 -0
  18. data/lib/qrda-export/catI-r5/_header.mustache +28 -0
  19. data/lib/qrda-export/catI-r5/_measure_section.mustache +59 -0
  20. data/lib/qrda-export/catI-r5/_reporting_period.mustache +23 -0
  21. data/lib/qrda-export/catI-r5/qrda1_r5.mustache +209 -0
  22. data/lib/qrda-export/catI-r5/qrda1_r5.rb +220 -0
  23. data/lib/qrda-export/catI-r5/qrda_header/_author.mustache +26 -0
  24. data/lib/qrda-export/catI-r5/qrda_header/_custodian.mustache +43 -0
  25. data/lib/qrda-export/catI-r5/qrda_header/_documentation_of_service_event.mustache +88 -0
  26. data/lib/qrda-export/catI-r5/qrda_header/_information_recipient.mustache +7 -0
  27. data/lib/qrda-export/catI-r5/qrda_header/_legal_authenticator.mustache +25 -0
  28. data/lib/qrda-export/catI-r5/qrda_header/_participant.mustache +7 -0
  29. data/lib/qrda-export/catI-r5/qrda_header/_record_target.mustache +44 -0
  30. data/lib/qrda-export/catI-r5/qrda_templates/adverse_event.mustache +40 -0
  31. data/lib/qrda-export/catI-r5/qrda_templates/allergy_intolerance.mustache +42 -0
  32. data/lib/qrda-export/catI-r5/qrda_templates/assessment_order.mustache +25 -0
  33. data/lib/qrda-export/catI-r5/qrda_templates/assessment_performed.mustache +38 -0
  34. data/lib/qrda-export/catI-r5/qrda_templates/assessment_recommended.mustache +25 -0
  35. data/lib/qrda-export/catI-r5/qrda_templates/communication_performed.mustache +62 -0
  36. data/lib/qrda-export/catI-r5/qrda_templates/device_applied.mustache +41 -0
  37. data/lib/qrda-export/catI-r5/qrda_templates/device_order.mustache +38 -0
  38. data/lib/qrda-export/catI-r5/qrda_templates/device_recommended.mustache +37 -0
  39. data/lib/qrda-export/catI-r5/qrda_templates/diagnosis.mustache +55 -0
  40. data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_order.mustache +25 -0
  41. data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_performed.mustache +50 -0
  42. data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_recommended.mustache +21 -0
  43. data/lib/qrda-export/catI-r5/qrda_templates/encounter_order.mustache +35 -0
  44. data/lib/qrda-export/catI-r5/qrda_templates/encounter_performed.mustache +52 -0
  45. data/lib/qrda-export/catI-r5/qrda_templates/encounter_recommended.mustache +37 -0
  46. data/lib/qrda-export/catI-r5/qrda_templates/family_history.mustache +37 -0
  47. data/lib/qrda-export/catI-r5/qrda_templates/immunization_administered.mustache +35 -0
  48. data/lib/qrda-export/catI-r5/qrda_templates/immunization_order.mustache +46 -0
  49. data/lib/qrda-export/catI-r5/qrda_templates/intervention_order.mustache +24 -0
  50. data/lib/qrda-export/catI-r5/qrda_templates/intervention_performed.mustache +36 -0
  51. data/lib/qrda-export/catI-r5/qrda_templates/intervention_recommended.mustache +25 -0
  52. data/lib/qrda-export/catI-r5/qrda_templates/laboratory_test_order.mustache +24 -0
  53. data/lib/qrda-export/catI-r5/qrda_templates/laboratory_test_performed.mustache +42 -0
  54. data/lib/qrda-export/catI-r5/qrda_templates/laboratory_test_recommended.mustache +25 -0
  55. data/lib/qrda-export/catI-r5/qrda_templates/medication_active.mustache +32 -0
  56. data/lib/qrda-export/catI-r5/qrda_templates/medication_administered.mustache +39 -0
  57. data/lib/qrda-export/catI-r5/qrda_templates/medication_discharge.mustache +63 -0
  58. data/lib/qrda-export/catI-r5/qrda_templates/medication_dispensed.mustache +70 -0
  59. data/lib/qrda-export/catI-r5/qrda_templates/medication_order.mustache +64 -0
  60. data/lib/qrda-export/catI-r5/qrda_templates/patient_care_experience.mustache +14 -0
  61. data/lib/qrda-export/catI-r5/qrda_templates/patient_characteristic_clinical_trial_participant.mustache +18 -0
  62. data/lib/qrda-export/catI-r5/qrda_templates/patient_characteristic_expired.mustache +32 -0
  63. data/lib/qrda-export/catI-r5/qrda_templates/patient_characteristic_payer.mustache +14 -0
  64. data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_order.mustache +30 -0
  65. data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_performed.mustache +45 -0
  66. data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_recommended.mustache +30 -0
  67. data/lib/qrda-export/catI-r5/qrda_templates/procedure_order.mustache +32 -0
  68. data/lib/qrda-export/catI-r5/qrda_templates/procedure_performed.mustache +64 -0
  69. data/lib/qrda-export/catI-r5/qrda_templates/procedure_recommended.mustache +34 -0
  70. data/lib/qrda-export/catI-r5/qrda_templates/provider_care_experience.mustache +15 -0
  71. data/lib/qrda-export/catI-r5/qrda_templates/provider_characteristic.mustache +15 -0
  72. data/lib/qrda-export/catI-r5/qrda_templates/substance_recommended.mustache +35 -0
  73. data/lib/qrda-export/catI-r5/qrda_templates/symptom.mustache +48 -0
  74. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_admission_source.mustache +6 -0
  75. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_anatomical_location_site.mustache +1 -0
  76. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_author.mustache +29 -0
  77. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_author_participation.mustache +8 -0
  78. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_component.mustache +13 -0
  79. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_data_element_codes_as_values.mustache +10 -0
  80. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_days_supplied.mustache +6 -0
  81. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_encounter_diagnosis.mustache +21 -0
  82. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_facility_location.mustache +24 -0
  83. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_immunization_details.mustache +14 -0
  84. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_medication_details.mustache +36 -0
  85. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_medication_supply_request.mustache +17 -0
  86. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_method.mustache +1 -0
  87. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_ordinality.mustache +1 -0
  88. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_principal_diagnosis.mustache +8 -0
  89. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_reaction_observation.mustache +9 -0
  90. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_reason.mustache +12 -0
  91. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_related_to.mustache +6 -0
  92. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_results.mustache +24 -0
  93. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_severity.mustache +8 -0
  94. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_status.mustache +8 -0
  95. data/lib/qrda-export/catIII-r2-1/_continuous_variable_value.mustache +17 -0
  96. data/lib/qrda-export/catIII-r2-1/_header.mustache +25 -0
  97. data/lib/qrda-export/catIII-r2-1/_measure_data.mustache +41 -0
  98. data/lib/qrda-export/catIII-r2-1/_measure_section.mustache +74 -0
  99. data/lib/qrda-export/catIII-r2-1/_reporting_period.mustache +23 -0
  100. data/lib/qrda-export/catIII-r2-1/_stratification.mustache +29 -0
  101. data/lib/qrda-export/catIII-r2-1/_supplemental_data.mustache +28 -0
  102. data/lib/qrda-export/catIII-r2-1/qrda3_r21.mustache +11 -0
  103. data/lib/qrda-export/catIII-r2-1/qrda3_r21.rb +127 -0
  104. data/lib/qrda-export/catIII-r2-1/qrda_header/_author.mustache +25 -0
  105. data/lib/qrda-export/catIII-r2-1/qrda_header/_custodian.mustache +17 -0
  106. data/lib/qrda-export/catIII-r2-1/qrda_header/_documentation_of_service_event.mustache +88 -0
  107. data/lib/qrda-export/catIII-r2-1/qrda_header/_legal_authenticator.mustache +25 -0
  108. data/lib/qrda-export/helper/aggregate_object_helper.rb +154 -0
  109. data/lib/qrda-export/helper/cat1_view_helper.rb +81 -0
  110. data/lib/qrda-export/helper/date_helper.rb +108 -0
  111. data/lib/qrda-export/helper/frequency_helper.rb +83 -0
  112. data/lib/qrda-export/helper/patient_view_helper.rb +46 -0
  113. data/lib/qrda-export/helper/view_helper.rb +28 -0
  114. data/lib/qrda-import/base-importers/demographics_importer.rb +38 -0
  115. data/lib/qrda-import/base-importers/section_importer.rb +237 -0
  116. data/lib/qrda-import/cda_identifier.rb +20 -0
  117. data/lib/qrda-import/data-element-importers/adverse_event_importer.rb +26 -0
  118. data/lib/qrda-import/data-element-importers/allergy_intolerance_importer.rb +24 -0
  119. data/lib/qrda-import/data-element-importers/assessment_order_importer.rb +19 -0
  120. data/lib/qrda-import/data-element-importers/assessment_performed_importer.rb +24 -0
  121. data/lib/qrda-import/data-element-importers/assessment_recommended_importer.rb +19 -0
  122. data/lib/qrda-import/data-element-importers/communication_performed_importer.rb +30 -0
  123. data/lib/qrda-import/data-element-importers/device_applied_importer.rb +22 -0
  124. data/lib/qrda-import/data-element-importers/device_order_importer.rb +19 -0
  125. data/lib/qrda-import/data-element-importers/device_recommended_importer.rb +19 -0
  126. data/lib/qrda-import/data-element-importers/diagnosis_importer.rb +24 -0
  127. data/lib/qrda-import/data-element-importers/diagnostic_study_order_importer.rb +19 -0
  128. data/lib/qrda-import/data-element-importers/diagnostic_study_performed_importer.rb +32 -0
  129. data/lib/qrda-import/data-element-importers/diagnostic_study_recommended_importer.rb +19 -0
  130. data/lib/qrda-import/data-element-importers/encounter_order_importer.rb +21 -0
  131. data/lib/qrda-import/data-element-importers/encounter_performed_importer.rb +46 -0
  132. data/lib/qrda-import/data-element-importers/encounter_recommended_importer.rb +21 -0
  133. data/lib/qrda-import/data-element-importers/family_history_importer.rb +21 -0
  134. data/lib/qrda-import/data-element-importers/immunization_administered_importer.rb +23 -0
  135. data/lib/qrda-import/data-element-importers/immunization_order_importer.rb +27 -0
  136. data/lib/qrda-import/data-element-importers/intervention_order_importer.rb +19 -0
  137. data/lib/qrda-import/data-element-importers/intervention_performed_importer.rb +23 -0
  138. data/lib/qrda-import/data-element-importers/intervention_recommended_importer.rb +19 -0
  139. data/lib/qrda-import/data-element-importers/laboratory_test_order_importer.rb +19 -0
  140. data/lib/qrda-import/data-element-importers/laboratory_test_performed_importer.rb +29 -0
  141. data/lib/qrda-import/data-element-importers/laboratory_test_recommended_importer.rb +19 -0
  142. data/lib/qrda-import/data-element-importers/medication_active_importer.rb +25 -0
  143. data/lib/qrda-import/data-element-importers/medication_administered_importer.rb +26 -0
  144. data/lib/qrda-import/data-element-importers/medication_discharge_importer.rb +32 -0
  145. data/lib/qrda-import/data-element-importers/medication_dispensed_importer.rb +37 -0
  146. data/lib/qrda-import/data-element-importers/medication_order_importer.rb +36 -0
  147. data/lib/qrda-import/data-element-importers/patient_care_experience_importer.rb +19 -0
  148. data/lib/qrda-import/data-element-importers/patient_characteristic_clinical_trial_participant_importer.rb +19 -0
  149. data/lib/qrda-import/data-element-importers/patient_characteristic_expired_importer.rb +22 -0
  150. data/lib/qrda-import/data-element-importers/patient_characteristic_payer_importer.rb +19 -0
  151. data/lib/qrda-import/data-element-importers/physical_exam_order_importer.rb +21 -0
  152. data/lib/qrda-import/data-element-importers/physical_exam_performed_importer.rb +27 -0
  153. data/lib/qrda-import/data-element-importers/physical_exam_recommended_importer.rb +21 -0
  154. data/lib/qrda-import/data-element-importers/procedure_order_importer.rb +23 -0
  155. data/lib/qrda-import/data-element-importers/procedure_performed_importer.rb +33 -0
  156. data/lib/qrda-import/data-element-importers/procedure_recommended_importer.rb +23 -0
  157. data/lib/qrda-import/data-element-importers/provider_care_experience_importer.rb +19 -0
  158. data/lib/qrda-import/data-element-importers/provider_characteristic_importer.rb +19 -0
  159. data/lib/qrda-import/data-element-importers/substance_administered_importer.rb +27 -0
  160. data/lib/qrda-import/data-element-importers/substance_order_importer.rb +29 -0
  161. data/lib/qrda-import/data-element-importers/substance_recommended_importer.rb +27 -0
  162. data/lib/qrda-import/data-element-importers/symptom_importer.rb +21 -0
  163. data/lib/qrda-import/entry_finder.rb +20 -0
  164. data/lib/qrda-import/entry_package.rb +16 -0
  165. data/lib/qrda-import/narrative_reference_handler.rb +33 -0
  166. data/lib/qrda-import/patient_importer.rb +128 -0
  167. data/lib/util/code_system_helper.rb +77 -0
  168. data/lib/util/hqmf_template_helper.rb +52 -0
  169. data/lib/util/hqmf_template_oid_map.json +654 -0
  170. data/lib/util/hqmfr2_template_oid_map.json +378 -0
  171. data/lib/util/hqmfr2cql_template_oid_map.json +390 -0
  172. data/lib/util/qrda_template_helper.rb +20 -0
  173. data/lib/util/qrdar5_1_template_oid_map.json +406 -0
  174. data/lib/util/qrdar5_template_oid_map.json +406 -0
  175. metadata +344 -0
@@ -0,0 +1,88 @@
1
+ <documentationOf typeCode="DOC">
2
+ <serviceEvent classCode="PCPR">
3
+ <!-- care provision -->
4
+ <effectiveTime>
5
+ <low nullFlavor="UNK"/>
6
+ <high nullFlavor="UNK"/>
7
+ </effectiveTime>
8
+ <!-- You can include multiple performers, each with an NPI, TIN, CCN. -->
9
+ <performer typeCode="PRF">
10
+ <time>
11
+ <low nullFlavor="UNK"/>
12
+ <high nullFlavor="UNK"/>
13
+ </time>
14
+ {{#provider}}
15
+ <assignedEntity>
16
+ {{#provider_npi}}
17
+ <id extension="{{value}}" root="2.16.840.1.113883.4.6"/>
18
+ {{/provider_npi}}
19
+ {{#provider_ccn}}
20
+ <id extension="{{value}}" root="2.16.840.1.113883.4.336"/>
21
+ {{/provider_ccn}}
22
+ {{#specialty}}
23
+ <code code="{{specialty}}" codeSystem="2.16.840.1.113883.6.101" codeSystemName="Healthcare Provider Taxonomy (HIPAA)"/>
24
+ {{/specialty}}
25
+ {{#addresses}}
26
+ <addr use="HP">
27
+ <streetAddressLine>{{{provider_street}}}</streetAddressLine>
28
+ <city>{{city}}</city>
29
+ <state>{{state}}</state>
30
+ <postalCode>{{zip}}</postalCode>
31
+ <country>{{country}}</country>
32
+ </addr>
33
+ {{/addresses}}
34
+ <assignedPerson>
35
+ <name>
36
+ <given>{{{given_name}}}</given>
37
+ <family>{{familyName}}</family>
38
+ </name>
39
+ </assignedPerson>
40
+ <representedOrganization>
41
+ {{#provider_tin}}
42
+ <id extension="{{value}}" root="2.16.840.1.113883.4.2"/>
43
+ {{/provider_tin}}
44
+ {{#addresses}}
45
+ <addr use="HP">
46
+ <streetAddressLine>{{{provider_street}}}</streetAddressLine>
47
+ <city>{{city}}</city>
48
+ <state>{{state}}</state>
49
+ <postalCode>{{zip}}</postalCode>
50
+ <country>{{country}}</country>
51
+ </addr>
52
+ {{/addresses}}
53
+ </representedOrganization>
54
+ </assignedEntity>
55
+ {{/provider}}
56
+ {{^provider}}
57
+ <assignedEntity>
58
+ <id extension="1982671962" root="2.16.840.1.113883.4.6"/>
59
+ <id extension="463132" root="2.16.840.1.113883.4.336"/>
60
+ <code code="282N00000X" codeSystem="2.16.840.1.113883.6.101" codeSystemName="Healthcare Provider Taxonomy (HIPAA)"/>
61
+ <addr use="HP">
62
+ <streetAddressLine>16432 Jayme Viaduct Manor</streetAddressLine>
63
+ <city>Clairland</city>
64
+ <state>MS</state>
65
+ <postalCode>38796</postalCode>
66
+ <country>US</country>
67
+ </addr>
68
+ <assignedPerson>
69
+ <name>
70
+ <given>Daryl</given>
71
+ <family>Carroll</family>
72
+ </name>
73
+ </assignedPerson>
74
+ <representedOrganization>
75
+ <id extension="695939209" root="2.16.840.1.113883.4.2"/>
76
+ <addr use="HP">
77
+ <streetAddressLine>16432 Jayme Viaduct Manor</streetAddressLine>
78
+ <city>Clairland</city>
79
+ <state>MS</state>
80
+ <postalCode>38796</postalCode>
81
+ <country>US</country>
82
+ </addr>
83
+ </representedOrganization>
84
+ </assignedEntity>
85
+ {{/provider}}
86
+ </performer>
87
+ </serviceEvent>
88
+ </documentationOf>
@@ -0,0 +1,25 @@
1
+ <legalAuthenticator>
2
+ <time value="20180524170839"/>
3
+ <signatureCode code="S"/>
4
+ <assignedEntity>
5
+ <id root="bc01a5d1-3a34-4286-82cc-43eb04c972a7"/>
6
+ <addr>
7
+ <streetAddressLine>202 Burlington Rd.</streetAddressLine>
8
+ <city>Bedford</city>
9
+ <state>MA</state>
10
+ <postalCode>01730</postalCode>
11
+ <country>US</country>
12
+ </addr>
13
+ <telecom use="WP" value="tel:(781)271-3000"/>
14
+ <assignedPerson>
15
+ <name>
16
+ <given>Henry</given>
17
+ <family>Seven</family>
18
+ </name>
19
+ </assignedPerson>
20
+ <representedOrganization>
21
+ <id root="2.16.840.1.113883.19.5"/>
22
+ <name>Cypress</name>
23
+ </representedOrganization>
24
+ </assignedEntity>
25
+ </legalAuthenticator>
@@ -0,0 +1,154 @@
1
+ module Qrda
2
+ module Export
3
+ module Helper
4
+ module PopulationSelectors
5
+ def numerator
6
+ populations.find {|pop| pop.type == 'NUMER'}
7
+ end
8
+
9
+ def denominator
10
+ populations.find {|pop| pop.type == 'DENOM'}
11
+ end
12
+
13
+ def denominator_exceptions
14
+ populations.find {|pop| pop.type == 'DENEXCEP'}
15
+ end
16
+
17
+ def denominator_exclusions
18
+ populations.find {|pop| pop.type == 'DENEX'}
19
+ end
20
+
21
+ def population_count(population_type, population_id)
22
+ population = populations.find {|pop| pop.type == population_type && pop.id == population_id}
23
+ if population
24
+ population.value
25
+ else
26
+ 0
27
+ end
28
+ end
29
+
30
+ def population_id(population_type)
31
+ populations.find {|pop| pop.type == population_type}.id
32
+ end
33
+
34
+ def method_missing(method, *args, &block)
35
+ match_data = method.to_s.match(/^(.+)_count$/)
36
+ if match_data
37
+ population = send(match_data[1])
38
+ if population
39
+ population.value
40
+ else
41
+ 0
42
+ end
43
+ else
44
+ super
45
+ end
46
+ end
47
+
48
+ def respond_to_missing?(method, *args)
49
+ match_data = method.to_s.match(/^(.+)_count$/)
50
+ !match_data.nil? or super
51
+ end
52
+
53
+ # Returns true if there is more than one IPP or DENOM, etc.
54
+ def multiple_population_types?
55
+ population_groups = populations.group_by(&:type)
56
+ population_groups.values.any? { |pops| pops.size > 1 }
57
+ end
58
+ end
59
+ class Population
60
+ attr_accessor :type, :value, :id, :stratifications, :supplemental_data
61
+
62
+ def initialize
63
+ @stratifications = []
64
+ end
65
+
66
+ def add_stratification(id,value)
67
+ stratifications << Stratification.new(id,value) unless stratifications.find {|st| st.id == id}
68
+ end
69
+
70
+ end
71
+
72
+ class Stratification
73
+ attr_accessor :id, :value
74
+ def initialize(id,value)
75
+ @id = id
76
+ @value = value
77
+ end
78
+
79
+ end
80
+
81
+ class PopulationGroup
82
+ include PopulationSelectors
83
+ attr_accessor :populations
84
+ def performance_rate
85
+ numerator_count.to_f / (performance_rate_denominator)
86
+ end
87
+
88
+ def performance_rate_denominator
89
+ denominator_count - denominator_exclusions_count - denominator_exceptions_count
90
+ end
91
+
92
+ def is_cv?
93
+ populations.any? {|pop| pop.type == 'MSRPOPL'}
94
+ end
95
+
96
+ end
97
+
98
+ class AggregateCount
99
+ attr_accessor :measure_id, :populations, :population_groups
100
+
101
+ def initialize(measure_id)
102
+ @populations = []
103
+ @measure_id = measure_id
104
+ @population_groups = []
105
+ end
106
+
107
+ def add_entry(cache_entry, population_sets)
108
+ population_set = population_sets.where(population_set_id: cache_entry.pop_set_hash[:population_set_id]).first
109
+ 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'
112
+
113
+ population = create_population_from_population_set(pop_code, population_set, cache_entry)
114
+ if cache_entry.pop_set_hash[:stratification_id]
115
+ 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
+ else
118
+ population.value = cache_entry[pop_code]
119
+ population.supplemental_data = cache_entry.supplemental_data[pop_code]
120
+ end
121
+ entry_populations << population if population
122
+ end
123
+ return if population_groups.find {|pg| pg.populations.collect(&:id).sort == entry_populations.collect(&:id).sort }
124
+
125
+ pg = PopulationGroup.new
126
+ pg.populations = entry_populations
127
+ population_groups << pg
128
+ end
129
+
130
+ 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
136
+ return population unless population.nil? && !cache_entry.pop_set_hash[:stratification_id]
137
+ population = Population.new
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
144
+ populations << population
145
+ population
146
+ end
147
+
148
+ def is_cv?
149
+ populations.any? {|pop| pop.type == 'MSRPOPL'}
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,81 @@
1
+ module Qrda
2
+ module Export
3
+ module Helper
4
+ module Cat1ViewHelper
5
+ def negation_ind
6
+ self[:negationRationale].nil? ? "" : "negationInd=\"true\""
7
+ end
8
+
9
+ def negated
10
+ self[:negationRationale].nil? ? false : true
11
+ end
12
+
13
+ def multiple_codes?
14
+ self[:dataElementCodes].size > 1
15
+ end
16
+
17
+ def display_author_dispenser_id?
18
+ self['qdmCategory'] == 'medication' && self['qdmStatus'] == 'dispensed'
19
+ end
20
+
21
+ def display_author_prescriber_id?
22
+ self['qdmCategory'] == 'medication' && self['qdmStatus'] == 'order'
23
+ end
24
+
25
+ def id_or_null_flavor
26
+ return "<id root=\"#{self['namingSystem']}\" extension=\"#{self['value']}\"/>" if self['namingSystem'] && self['value']
27
+ "<id nullFlavor=\"NA\"/>"
28
+ end
29
+
30
+ def code_system_oid(data_element_code)
31
+ data_element_code['codeSystemOid'] || HQMF::Util::CodeSystemHelper.oid_for_code_system(data_element_code['codeSystem'])
32
+ end
33
+
34
+ def code_and_codesystem
35
+ if self['codeSystem'] == 'NA_VALUESET'
36
+ "nullFlavor=\"NA\" sdtc:valueSet=\"#{self['code']}\""
37
+ else
38
+ "code=\"#{self['code']}\" codeSystem=\"#{code_system_oid(self)}\" codeSystemName=\"#{self['codeSystem']}\""
39
+ end
40
+ end
41
+
42
+ def primary_code_and_codesystem
43
+ "code=\"#{self[:dataElementCodes][0]['code']}\" codeSystem=\"#{code_system_oid(self[:dataElementCodes][0])}\" codeSystemName=\"#{self[:dataElementCodes][0]['codeSystem']}\""
44
+ end
45
+
46
+ def translation_codes_and_codesystem_list
47
+ translation_list = ""
48
+ self[:dataElementCodes].each_with_index do |_dec, index|
49
+ next if index.zero?
50
+
51
+ translation_list += "<translation code=\"#{self[:dataElementCodes][index]['code']}\" codeSystem=\"#{code_system_oid(self[:dataElementCodes][index])}\" codeSystemName=\"#{self[:dataElementCodes][index]['codeSystem']}\"/>"
52
+ end
53
+ translation_list
54
+ end
55
+
56
+ def result_value
57
+ return "<value xsi:type=\"CD\" nullFlavor=\"UNK\"/>" unless self['result']
58
+
59
+ result_string = if self['result'].is_a? Array
60
+ result_value_as_string(self['result'][0])
61
+ elsif self['result'].is_a? Hash
62
+ result_value_as_string(self['result'])
63
+ elsif !self['result'].nil?
64
+ "<value xsi:type=\"PQ\" value=\"#{self['result']}\" unit=\"1\"/>"
65
+ end
66
+ result_string
67
+ end
68
+
69
+ def result_value_as_string(result)
70
+ return "<value xsi:type=\"CD\" nullFlavor=\"UNK\"/>" unless result
71
+ return "<value xsi:type=\"CD\" code=\"#{result['code']}\" codeSystem=\"#{code_system_oid(result)}\" codeSystemName=\"#{result['codeSystem']}\"/>" if result['code']
72
+ return "<value xsi:type=\"PQ\" value=\"#{result['value']}\" unit=\"#{result['unit']}\"/>" if result['unit']
73
+ end
74
+
75
+ def authordatetime_or_dispenserid?
76
+ self['authorDatetime'] || self['dispenserId']
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,108 @@
1
+ module Qrda
2
+ module Export
3
+ module Helper
4
+ module DateHelper
5
+ def value_or_null_flavor(time)
6
+ # this is a bit of a hack for a defineded undefined date
7
+ if time && DateTime.parse(time).year < 3000
8
+ "value='#{DateTime.parse(time).utc.to_formatted_s(:number)}'"
9
+ else
10
+ "nullFlavor='UNK'"
11
+ end
12
+ end
13
+
14
+ def performance_period_start
15
+ @performance_period_start.to_formatted_s(:number)
16
+ end
17
+
18
+ def performance_period_end
19
+ @performance_period_end.to_formatted_s(:number)
20
+ end
21
+
22
+ def current_time
23
+ Time.now.utc.to_formatted_s(:number)
24
+ end
25
+
26
+ def active_date_time
27
+ "<effectiveTime xsi:type='IVL_TS'>"\
28
+ "<low #{value_or_null_flavor(self['activeDatetime'])}/>"\
29
+ "</effectiveTime>"
30
+ end
31
+
32
+ def author_time
33
+ "<time #{value_or_null_flavor(self['authorDatetime'])}/>"
34
+ end
35
+
36
+ def author_effective_time
37
+ "<effectiveTime #{value_or_null_flavor(self['authorDatetime'])}/>"
38
+ end
39
+
40
+ def birth_date_time
41
+ "<birthTime #{value_or_null_flavor(self['birthDatetime'])}/>"
42
+ end
43
+
44
+ def result_date_time
45
+ "<effectiveTime #{value_or_null_flavor(self['resultDatetime'])}/>"
46
+ end
47
+
48
+ def expired_date_time
49
+ "<effectiveTime>"\
50
+ "<low #{value_or_null_flavor(self['expiredDatetime'])}/>"\
51
+ "</effectiveTime>"
52
+ end
53
+
54
+ def medication_supply_request_period
55
+ "<effectiveTime xsi:type='IVL_TS'>"\
56
+ "<low #{value_or_null_flavor(self['relevantPeriod']['low'])}/>"\
57
+ "<high #{value_or_null_flavor(self['relevantPeriod']['high'])}/>"\
58
+ "</effectiveTime>"
59
+ end
60
+
61
+ def medication_duration_author_effective_time
62
+ "<effectiveTime xsi:type='IVL_TS'>"\
63
+ "<low #{value_or_null_flavor(self['authorDatetime'])}/>"\
64
+ "<high nullFlavor='UNK'/>"\
65
+ "</effectiveTime>"
66
+ end
67
+
68
+ def prevalence_period
69
+ "<effectiveTime>"\
70
+ "<low #{value_or_null_flavor(self['prevalencePeriod']['low'])}/>"\
71
+ "<high #{value_or_null_flavor(self['prevalencePeriod']['high'])}/>"\
72
+ "</effectiveTime>"
73
+ end
74
+
75
+ def relevant_period
76
+ "<effectiveTime>"\
77
+ "<low #{value_or_null_flavor(self['relevantPeriod']['low'])}/>"\
78
+ "<high #{value_or_null_flavor(self['relevantPeriod']['high'])}/>"\
79
+ "</effectiveTime>"
80
+ end
81
+
82
+ def relevant_period_as_value
83
+ "<effectiveTime #{value_or_null_flavor(self['relevantPeriod']['low'])}/>"
84
+ end
85
+
86
+ def medication_duration_effective_time
87
+ "<effectiveTime xsi:type=\"IVL_TS\">"\
88
+ "<low #{value_or_null_flavor(self['relevantPeriod']['low'])}/>"\
89
+ "<high #{value_or_null_flavor(self['relevantPeriod']['high'])}/>"\
90
+ "</effectiveTime>"
91
+ end
92
+
93
+ def facility_period
94
+ "<low #{value_or_null_flavor(self['locationPeriod']['low'])}/>"\
95
+ "<high #{value_or_null_flavor(self['locationPeriod']['high'])}/>"
96
+ end
97
+
98
+ def incision_datetime
99
+ "<effectiveTime #{value_or_null_flavor(self['incisionDatetime'])}/>"
100
+ end
101
+
102
+ def completed_prevalence_period
103
+ self['prevalencePeriod']['high'] ? true : false
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,83 @@
1
+ module Qrda
2
+ module Export
3
+ module Helper
4
+ module FrequencyHelper
5
+ # FREQUENCY_CODE_MAP extracted from Direct Reference Codes in Opioid_v5_6_eCQM.xml (CMS460v0)
6
+ FREQUENCY_CODE_MAP = {
7
+ '396107007' => { low: 12, high: 24, unit: 'h', institution_specified: true, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', display_name: 'One to two times a day (qualifier value)' },
8
+ '396108002' => { low: 8, high: 24, unit: 'h', institution_specified: true, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', display_name: 'One to three times a day (qualifier value)' },
9
+ '396109005' => { low: 6, high: 24, unit: 'h', institution_specified: true, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', display_name: 'One to four times a day (qualifier value)' },
10
+ '396111001' => { low: 6, high: 12, unit: 'h', institution_specified: true, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', display_name: 'Two to four times a day (qualifier value)' },
11
+
12
+ '229797004' => { low: 24, high: nil, unit: 'h', institution_specified: true, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', code_system_version: '2018-03', display_name: 'Once daily (qualifier value)' },
13
+ '229799001' => { low: 12, high: nil, unit: 'h', institution_specified: true, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', code_system_version: '2018-03', display_name: 'Twice a day (qualifier value)' },
14
+ '229798009' => { low: 8, high: nil, unit: 'h', institution_specified: true, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', code_system_version: '2018-03', display_name: 'Three times daily (qualifier value)' },
15
+ '307439001' => { low: 6, high: nil, unit: 'h', institution_specified: true, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', code_system_version: '2018-03', display_name: 'Four times daily (qualifier value)' },
16
+
17
+ '225752000' => { low: 2, high: 4, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', display_name: 'Every two to four hours (qualifier value)' },
18
+ '225754004' => { low: 3, high: 4, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', display_name: 'Every three to four hours (qualifier value)' },
19
+ '396127008' => { low: 3, high: 6, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', display_name: 'Every three to six hours (qualifier value)' },
20
+ '396139000' => { low: 6, high: 8, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', display_name: 'Every six to eight hours (qualifier value)' },
21
+ '396140003' => { low: 8, high: 12, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', display_name: 'Every eight to twelve hours (qualifier value)' },
22
+
23
+ '225756002' => { low: 4, high: nil, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', display_name: 'Every four hours (qualifier value)' },
24
+ '307468000' => { low: 6, high: nil, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', code_system_version: '2018-03', display_name: 'Every six hours (qualifier value)' },
25
+ '307469008' => { low: 8, high: nil, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', code_system_version: '2018-03', display_name: 'Every eight hours (qualifier value)' },
26
+ '307470009' => { low: 12, high: nil, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', code_system_version: '2018-03', display_name: 'Every twelve hours (qualifier value)' },
27
+ '396125000' => { low: 24, high: nil, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', code_system_version: '2018-03', display_name: 'Every twenty four hours (qualifier value)' },
28
+ '396126004' => { low: 36, high: nil, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', code_system_version: '2018-03', display_name: 'Every thirty six hours (qualifier value)' },
29
+ '396131002' => { low: 48, high: nil, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', code_system_version: '2018-03', display_name: 'Every forty eight hours (qualifier value)' },
30
+ '396143001' => { low: 72, high: nil, unit: 'h', institution_specified: false, code_system: '2.16.840.1.113883.6.96', code_system_name: 'SNOMEDCT', code_system_version: '2018-03', display_name: 'Every seventy two hours (qualifier value)' }
31
+ }.freeze
32
+
33
+ def medication_frequency
34
+ # If the code matches one of the known Direct Reference Codes, export that time in hours. Otherwise default to "every twenty four hours" code
35
+ frequency_code_entry = FREQUENCY_CODE_MAP[self['code']] || FREQUENCY_CODE_MAP['396125000']
36
+ if !frequency_code_entry[:institution_specified]
37
+ if frequency_code_entry[:high].nil?
38
+ institution_not_specified_point_frequency(frequency_code_entry)
39
+ else
40
+ institution_not_specified_range_frequency(frequency_code_entry)
41
+ end
42
+ else
43
+ if frequency_code_entry[:high].nil?
44
+ institution_specified_point_frequency(frequency_code_entry)
45
+ else
46
+ institution_specified_range_frequency(frequency_code_entry)
47
+ end
48
+ end
49
+ end
50
+
51
+ def institution_not_specified_point_frequency(frequency_code_entry)
52
+ "<effectiveTime xsi:type='PIVL_TS' operator='A'>"\
53
+ "<period value='#{frequency_code_entry[:low]}' unit='#{frequency_code_entry[:unit]}'/>"\
54
+ "</effectiveTime>"
55
+ end
56
+
57
+ def institution_not_specified_range_frequency(frequency_code_entry)
58
+ "<effectiveTime xsi:type='PIVL_TS' operator='A'>"\
59
+ "<period xsi:type='IVL_PQ'>"\
60
+ "<low value='#{frequency_code_entry[:low]}' unit='#{frequency_code_entry[:unit]}'/>"\
61
+ "<high value='#{frequency_code_entry[:high]}' unit='#{frequency_code_entry[:unit]}'/>"\
62
+ "</period>"\
63
+ "</effectiveTime>"
64
+ end
65
+
66
+ def institution_specified_point_frequency(frequency_code_entry)
67
+ "<effectiveTime xsi:type='PIVL_TS' institutionSpecified='true' operator='A'>"\
68
+ "<period value='#{frequency_code_entry[:low]}' unit='#{frequency_code_entry[:unit]}'/>"\
69
+ "</effectiveTime>"
70
+ end
71
+
72
+ def institution_specified_range_frequency(frequency_code_entry)
73
+ "<effectiveTime xsi:type='PIVL_TS' institutionSpecified='true' operator='A'>"\
74
+ "<period xsi:type='IVL_PQ'>"\
75
+ "<low value='#{frequency_code_entry[:low]}' unit='#{frequency_code_entry[:unit]}'/>"\
76
+ "<high value='#{frequency_code_entry[:high]}' unit='#{frequency_code_entry[:unit]}'/>"\
77
+ "</period>"\
78
+ "</effectiveTime>"
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,46 @@
1
+ module Qrda
2
+ module Export
3
+ module Helper
4
+ module PatientViewHelper
5
+ def provider
6
+ JSON.parse(@provider.to_json) if @provider
7
+ end
8
+
9
+ def patient
10
+ JSON.parse(@patient.to_json)
11
+ end
12
+
13
+ def provider_street
14
+ self['street'].join('')
15
+ end
16
+
17
+ def provider_npi
18
+ return nil unless self['ids']
19
+ self['ids'].map { |id| id if id['namingSystem'] == '2.16.840.1.113883.4.6' }.compact
20
+ end
21
+
22
+ def provider_tin
23
+ return nil unless self['ids']
24
+ self['ids'].map { |id| id if id['namingSystem'] == '2.16.840.1.113883.4.2' }.compact
25
+ end
26
+
27
+ def provider_ccn
28
+ return nil unless self['ids']
29
+ self['ids'].map { |id| id if id['namingSystem'] == '2.16.840.1.113883.4.336' }.compact
30
+ end
31
+
32
+ def provider_type_code
33
+ self['specialty']
34
+ end
35
+
36
+ def mrn
37
+ @patient.id.to_s
38
+ end
39
+
40
+ def given_name
41
+ self['givenNames'].join(' ')
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,28 @@
1
+ require 'uuid'
2
+ module Qrda
3
+ module Export
4
+ module Helper
5
+ module ViewHelper
6
+ def measures
7
+ @measures.only(:hqmf_id, :hqmf_set_id, :description).as_json
8
+ end
9
+
10
+ def random_id
11
+ UUID.generate
12
+ end
13
+
14
+ def as_id
15
+ self['value']
16
+ end
17
+
18
+ def object_id
19
+ self[:_id]
20
+ end
21
+
22
+ def submission_program
23
+ @submission_program
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,38 @@
1
+ module QRDA
2
+ module Cat1
3
+ module DemographicsImporter
4
+ def get_demographics(patient, doc)
5
+ patient_role_element = doc.at_xpath('/cda:ClinicalDocument/cda:recordTarget/cda:patientRole')
6
+ patient_element = patient_role_element.at_xpath('./cda:patient')
7
+ patient.givenNames = [patient_element.at_xpath('cda:name/cda:given').text]
8
+ patient.familyName = patient_element.at_xpath('cda:name/cda:family').text
9
+ patient.qdmPatient.birthDatetime = DateTime.parse(patient_element.at_xpath('cda:birthTime')['value'])
10
+ pcbd = QDM::PatientCharacteristicBirthdate.new
11
+ pcbd.birthDatetime = patient.qdmPatient.birthDatetime
12
+ pcbd.dataElementCodes = [{ code: '21112-8', codeSystem: 'LOINC' }]
13
+ patient.qdmPatient.dataElements << pcbd
14
+
15
+ pcs = QDM::PatientCharacteristicSex.new
16
+ code_element = patient_element.at_xpath('cda:administrativeGenderCode')
17
+ pcs.dataElementCodes = [code_if_present(code_element)]
18
+ patient.qdmPatient.dataElements << pcs
19
+
20
+ pcr = QDM::PatientCharacteristicRace.new
21
+ code_element = patient_element.at_xpath('cda:raceCode')
22
+ pcr.dataElementCodes = [code_if_present(code_element)]
23
+ patient.qdmPatient.dataElements << pcr
24
+
25
+ pce = QDM::PatientCharacteristicEthnicity.new
26
+ code_element = patient_element.at_xpath('cda:ethnicGroupCode')
27
+ pce.dataElementCodes = [code_if_present(code_element)]
28
+ patient.qdmPatient.dataElements << pce
29
+ end
30
+
31
+ def code_if_present(code_element)
32
+ return unless code_element && code_element['codeSystem'] && code_element['code']
33
+
34
+ QDM::Code.new(code_element['code'], HQMF::Util::CodeSystemHelper.code_system_for(code_element['codeSystem']))
35
+ end
36
+ end
37
+ end
38
+ end