health-data-standards 3.5.3 → 3.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -3
  3. data/README.md +10 -2
  4. data/lib/health-data-standards.rb +5 -28
  5. data/lib/health-data-standards/export/cat_1.rb +3 -2
  6. data/lib/health-data-standards/export/cat_1_r2.rb +11 -0
  7. data/lib/health-data-standards/ext/node.rb +1 -2
  8. data/lib/health-data-standards/import/bulk_record_importer.rb +4 -4
  9. data/lib/health-data-standards/import/bundle/importer.rb +62 -0
  10. data/lib/health-data-standards/import/c32/insurance_provider_importer.rb +10 -8
  11. data/lib/health-data-standards/import/cat1/patient_importer.rb +3 -3
  12. data/lib/health-data-standards/import/cat1/procedure_importer.rb +42 -0
  13. data/lib/health-data-standards/import/cda/medication_importer.rb +11 -11
  14. data/lib/health-data-standards/import/cda/section_importer.rb +13 -7
  15. data/lib/health-data-standards/models/cqm/aggregate_objects.rb +5 -1
  16. data/lib/health-data-standards/models/cqm/bundle.rb +5 -3
  17. data/lib/health-data-standards/models/cqm/measure.rb +1 -1
  18. data/lib/health-data-standards/models/entry.rb +5 -1
  19. data/lib/health-data-standards/models/record.rb +10 -0
  20. data/lib/health-data-standards/models/reference.rb +23 -0
  21. data/lib/health-data-standards/models/svs/value_set.rb +4 -3
  22. data/lib/health-data-standards/railtie.rb +1 -1
  23. data/lib/health-data-standards/tasks.rb +1 -0
  24. data/lib/health-data-standards/tasks/bundle.rake +84 -2
  25. data/lib/health-data-standards/util/vs_api.rb +40 -7
  26. data/lib/health-data-standards/validate/base_validator.rb +23 -0
  27. data/lib/health-data-standards/validate/data_validator.rb +85 -0
  28. data/lib/health-data-standards/validate/measure_validator.rb +127 -0
  29. data/lib/health-data-standards/validate/performance_rate_validator.rb +94 -0
  30. data/lib/health-data-standards/validate/reported_result_extractor.rb +170 -0
  31. data/lib/health-data-standards/validate/schema_validator.rb +24 -0
  32. data/lib/health-data-standards/validate/schematron/c_processor.rb +28 -0
  33. data/lib/health-data-standards/validate/schematron/java_processor.rb +93 -0
  34. data/lib/health-data-standards/validate/schematron_validator.rb +34 -0
  35. data/lib/health-data-standards/validate/validation_error.rb +10 -0
  36. data/lib/health-data-standards/validate/validators.rb +80 -0
  37. data/lib/hqmf-generator/fulfills.xml.erb +7 -0
  38. data/lib/hqmf-generator/hqmf-generator.rb +8 -3
  39. data/lib/hqmf-model/data_criteria.rb +3 -0
  40. data/lib/hqmf-model/types.rb +29 -0
  41. data/lib/hqmf-parser/2.0/data_criteria.rb +7 -0
  42. data/lib/hqmf-parser/2.0/types.rb +24 -0
  43. data/resources/schema/infrastructure/cda/CDA_SDTC.xsd +44 -0
  44. data/resources/schema/infrastructure/cda/POCD_MT000040_SDTC.xsd +1500 -0
  45. data/resources/schema/infrastructure/cda/SDTC.xsd +210 -0
  46. data/resources/schema/processable/coreschemas/NarrativeBlock.xsd +557 -0
  47. data/resources/schema/processable/coreschemas/datatypes-base_SDTC.xsd +1850 -0
  48. data/resources/schema/processable/coreschemas/datatypes.xsd +1375 -0
  49. data/resources/schema/processable/coreschemas/infrastructureRoot.xsd +27 -0
  50. data/resources/schema/processable/coreschemas/voc.xsd +2124 -0
  51. data/resources/schematron/iso-schematron-xslt1/ExtractSchFromRNG.xsl +75 -0
  52. data/resources/schematron/iso-schematron-xslt1/ExtractSchFromXSD.xsl +77 -0
  53. data/resources/schematron/iso-schematron-xslt1/iso_abstract_expand.xsl +297 -0
  54. data/resources/schematron/iso-schematron-xslt1/iso_dsdl_include.xsl +1509 -0
  55. data/resources/schematron/iso-schematron-xslt1/iso_schematron_message.xsl +55 -0
  56. data/resources/schematron/iso-schematron-xslt1/iso_schematron_skeleton_for_xslt1.xsl +1844 -0
  57. data/resources/schematron/iso-schematron-xslt1/iso_svrl_for_xslt1.xsl +605 -0
  58. data/resources/schematron/iso-schematron-xslt1/readme.txt +101 -0
  59. data/resources/schematron/iso-schematron-xslt1/schematron-skeleton-api.htm +723 -0
  60. data/resources/schematron/iso-schematron-xslt2/ExtractSchFromRNG-2.xsl +75 -0
  61. data/resources/schematron/iso-schematron-xslt2/ExtractSchFromXSD-2.xsl +77 -0
  62. data/resources/schematron/iso-schematron-xslt2/iso_abstract_expand.xsl +297 -0
  63. data/resources/schematron/iso-schematron-xslt2/iso_dsdl_include.xsl +1508 -0
  64. data/resources/schematron/iso-schematron-xslt2/iso_schematron_message_xslt2.xsl +55 -0
  65. data/resources/schematron/iso-schematron-xslt2/iso_schematron_skeleton_for_saxon.xsl +2299 -0
  66. data/resources/schematron/iso-schematron-xslt2/iso_svrl_for_xslt2.xsl +684 -0
  67. data/resources/schematron/iso-schematron-xslt2/readme.txt +100 -0
  68. data/resources/schematron/iso-schematron-xslt2/sch-messages-cs.xhtml +56 -0
  69. data/resources/schematron/iso-schematron-xslt2/sch-messages-de.xhtml +57 -0
  70. data/resources/schematron/iso-schematron-xslt2/sch-messages-en.xhtml +57 -0
  71. data/resources/schematron/iso-schematron-xslt2/sch-messages-fr.xhtml +54 -0
  72. data/resources/schematron/iso-schematron-xslt2/sch-messages-nl.xhtml +58 -0
  73. data/resources/schematron/iso-schematron-xslt2/schematron-skeleton-api.htm +723 -0
  74. data/resources/schematron/qrda/cat_1/CDAR2_QRDA_I_R1_D3_2015MAY_Schematron.sch +4676 -0
  75. data/resources/schematron/qrda/cat_1/voc.xml +1177 -0
  76. data/resources/schematron/qrda/cat_1_r2/QRDA Category I Release 2.sch +4069 -0
  77. data/resources/schematron/qrda/cat_1_r2/voc.xml +1065 -0
  78. data/resources/schematron/qrda/cat_3/QRDA Category III.sch +675 -0
  79. data/resources/schematron/qrda/cat_3/voc.xml +21 -0
  80. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.26.cat1.erb +18 -0
  81. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.32.cat1.erb +4 -0
  82. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.38.cat1.erb +5 -1
  83. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.4.cat1.erb +1 -0
  84. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.64.cat1.erb +20 -0
  85. data/templates/cat1/_fulfills.cat1.erb +14 -0
  86. data/templates/cat1/_organization.cat1.erb +2 -1
  87. data/templates/cat1/_patient_data.cat1.erb +1 -1
  88. data/templates/cat1/show.cat1.erb +5 -4
  89. data/templates/cat3/_performance_rate.cat3.erb +5 -1
  90. data/templates/cat3/show.cat3.erb +1 -1
  91. metadata +128 -109
  92. data/lib/health-data-standards/export/ccr.rb +0 -417
  93. data/lib/health-data-standards/export/green_c32/entry.rb +0 -18
  94. data/lib/health-data-standards/export/green_c32/export_generator.rb +0 -23
  95. data/lib/health-data-standards/export/green_c32/record.rb +0 -18
  96. data/lib/health-data-standards/export/helper/gc32_view_helper.rb +0 -39
  97. data/lib/health-data-standards/import/ccr/patient_importer.rb +0 -238
  98. data/lib/health-data-standards/import/ccr/product_importer.rb +0 -60
  99. data/lib/health-data-standards/import/ccr/provider_importer.rb +0 -49
  100. data/lib/health-data-standards/import/ccr/result_importer.rb +0 -49
  101. data/lib/health-data-standards/import/ccr/section_importer.rb +0 -135
  102. data/lib/health-data-standards/import/ccr/simple_importer.rb +0 -30
  103. data/lib/health-data-standards/import/green_c32/advance_directive_importer.rb +0 -14
  104. data/lib/health-data-standards/import/green_c32/allergy_importer.rb +0 -20
  105. data/lib/health-data-standards/import/green_c32/care_goal_importer.rb +0 -26
  106. data/lib/health-data-standards/import/green_c32/condition_importer.rb +0 -38
  107. data/lib/health-data-standards/import/green_c32/encounter_importer.rb +0 -33
  108. data/lib/health-data-standards/import/green_c32/immunization_importer.rb +0 -23
  109. data/lib/health-data-standards/import/green_c32/medical_equipment_importer.rb +0 -24
  110. data/lib/health-data-standards/import/green_c32/medication_importer.rb +0 -68
  111. data/lib/health-data-standards/import/green_c32/patient_importer.rb +0 -14
  112. data/lib/health-data-standards/import/green_c32/procedure_importer.rb +0 -27
  113. data/lib/health-data-standards/import/green_c32/result_importer.rb +0 -43
  114. data/lib/health-data-standards/import/green_c32/section_importer.rb +0 -186
  115. data/lib/health-data-standards/import/green_c32/social_history_importer.rb +0 -13
  116. data/lib/health-data-standards/import/green_c32/support_importer.rb +0 -22
  117. data/lib/health-data-standards/import/green_c32/vital_sign_importer.rb +0 -21
  118. data/templates/gc32/_address.gc32.erb +0 -9
  119. data/templates/gc32/_advance_directive.gc32.erb +0 -5
  120. data/templates/gc32/_allergy.gc32.erb +0 -12
  121. data/templates/gc32/_care_goal.gc32.erb +0 -8
  122. data/templates/gc32/_condition.gc32.erb +0 -10
  123. data/templates/gc32/_encounter.gc32.erb +0 -28
  124. data/templates/gc32/_entry.gc32.erb +0 -3
  125. data/templates/gc32/_entry_attributes.gc32.erb +0 -10
  126. data/templates/gc32/_immunization.gc32.erb +0 -9
  127. data/templates/gc32/_insurance_provider.gc32.erb +0 -28
  128. data/templates/gc32/_medical_equipment.gc32.erb +0 -6
  129. data/templates/gc32/_medication.gc32.erb +0 -91
  130. data/templates/gc32/_name.gc32.erb +0 -11
  131. data/templates/gc32/_organization.gc32.erb +0 -10
  132. data/templates/gc32/_person_attributes.gc32.erb +0 -7
  133. data/templates/gc32/_procedure.gc32.erb +0 -9
  134. data/templates/gc32/_provider.gc32.erb +0 -9
  135. data/templates/gc32/_result.gc32.erb +0 -12
  136. data/templates/gc32/_social_history.gc32.erb +0 -6
  137. data/templates/gc32/_support.gc32.erb +0 -15
  138. data/templates/gc32/_telecom.gc32.erb +0 -1
  139. data/templates/gc32/_vital_sign.gc32.erb +0 -4
  140. data/templates/gc32/record.gc32.erb +0 -97
@@ -1,18 +0,0 @@
1
- module HealthDataStandards
2
- module Export
3
- module GreenC32
4
- class Record
5
- def initialize
6
- template_helper = TemplateHelper.new('gc32', 'gc32')
7
- @rendering_context = RenderingContext.new
8
- @rendering_context.template_helper = template_helper
9
- @rendering_context.extensions = [HealthDataStandards::Export::Helper::GC32ViewHelper]
10
- end
11
-
12
- def export(patient)
13
- @rendering_context.render(:template => 'record', :locals => {:record => patient})
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,39 +0,0 @@
1
- module HealthDataStandards
2
- module Export
3
- module Helper
4
- module GC32ViewHelper
5
- def gc32_code_display(entry, options={})
6
- code_display(entry, options.merge("exclude_null_flavor" => true))
7
- end
8
-
9
- def gc32_effective_time(entry)
10
- if entry.time
11
- "<effectiveTime value=\"#{Time.at(entry.time).xmlschema}\" />"
12
- elsif entry.start_time || entry.end_time
13
- gc32_interval(entry, "effectiveTime", :start_time, :end_time)
14
- else
15
- "<effectiveTime />"
16
- end
17
- end
18
-
19
- def gc32_interval(entry, tag_name, start_attribute, end_attribute)
20
- time = "<#{tag_name}>"
21
- time += "<start value=\"#{Time.at(entry.send(start_attribute)).xmlschema}\" />" if entry.send(start_attribute)
22
- time += "<end value=\"#{Time.at(entry.send(end_attribute)).xmlschema}\" />" if entry.send(end_attribute)
23
- time += "</#{tag_name}>"
24
- end
25
-
26
- def quantity_display(value, tag_name="value")
27
- return unless value
28
- if value.respond_to?(:scalar)
29
- "<#{tag_name} amount=\"#{value.scalar}\" unit=\"#{value.units}\" />"
30
- elsif value['scalar'].present?
31
- "<#{tag_name} amount=\"#{value['scalar']}\" unit=\"#{value['units']}\" />"
32
- else
33
- "<#{tag_name} amount=\"#{value['value']}\" unit=\"#{value['unit']}\" />"
34
- end
35
- end
36
- end
37
- end
38
- end
39
- end
@@ -1,238 +0,0 @@
1
- require "time"
2
-
3
- module HealthDataStandards
4
- module Import
5
- module CCR
6
- # This class is the central location for taking an ASTM CCR XML document and converting it
7
- # into the processed form we store in MongoDB. The class does this by running each measure
8
- # independently on the XML document
9
- #
10
- # This class is a Singleton. It should be accessed by calling PatientImporter.instance
11
- class PatientImporter
12
-
13
- include Singleton
14
-
15
- Gender = {"male" => "M", "female" => "F"}
16
-
17
- # Creates a new PatientImporter with the following XPath expressions used to find content in
18
- # an ASTM CCR
19
- #
20
- # Encounter entries
21
- # //ccr:Encounters/ccr:Encounter
22
- # Procedure entries
23
- # //ccr:Procedures/ccr:Procedure
24
- #
25
- # Result entries -
26
- # //ccr:Results/ccr:Result
27
- #
28
- # Vital sign entries
29
- # //ccr:VitalSigns/ccr:Result
30
- #
31
- # Medication entries
32
- # //ccr:Medications/ccr:Medication
33
- #
34
- # Codes for medications are found in the Product sections
35
- # ./ccr:Product
36
- #
37
- # Condition entries
38
- # //ccr:Problems/ccr:Problem
39
- #
40
- # Social History entries
41
- # //ccr:SocialHistory/ccr:SocialHistoryElement
42
- #
43
- # Care Goal entries
44
- # //ccr:Goals/ccr:Goal
45
- #
46
- # Allergy entries
47
- # //ccr:Alerts/ccr:Alert
48
- #
49
- # Immunization entries
50
- # //ccr:Immunizations/ccr:Immunization
51
- #
52
- # Codes for immunizations are found in the substanceAdministration with the following relative XPath
53
- # ./ccr:Product
54
-
55
- def initialize (check_usable = true)
56
- @measure_importers = {}
57
- @section_importers = {}
58
- @section_importers[:encounters] = SimpleImporter.new("//ccr:Encounters/ccr:Encounter",:encounters)
59
- @section_importers[:procedures] = SimpleImporter.new("//ccr:Procedures/ccr:Procedure",:procedures)
60
- @section_importers[:results] = ResultImporter.new("//ccr:Results/ccr:Result",:results)
61
- @section_importers[:vital_signs] = ResultImporter.new("//ccr:VitalSigns/ccr:Result",:vital_signs)
62
- @section_importers[:medications] = ProductImporter.new("//ccr:Medications/ccr:Medication", :medications)
63
- @section_importers[:conditions] = SimpleImporter.new("//ccr:Problems/ccr:Problem",:conditions)
64
- @section_importers[:social_history] = SimpleImporter.new("//ccr:SocialHistory/ccr:SocialHistoryElement", :social_history)
65
- @section_importers[:care_goals] = SimpleImporter.new("//ccr:Goals/ccr:Goal",:care_goals)
66
- @section_importers[:medical_equipment] = ProductImporter.new("//ccr:Equipment/ccr:EquipmentElement",:medical_equipment)
67
- @section_importers[:allergies] = SimpleImporter.new("//ccr:Alerts/ccr:Alert",:allergies)
68
- @section_importers[:immunizations] = ProductImporter.new("//ccr:Immunizations/ccr:Immunization",:immunizations)
69
- end
70
-
71
-
72
- # @param [boolean] value for check_usable_entries...importer uses true, stats uses false
73
- def check_usable(check_usable_entries)
74
- @section_importers.each_pair do |section, importer|
75
- importer.check_for_usable = check_usable_entries
76
- end
77
- end
78
-
79
- # Parses a ASTM CCR document and returns a Hash of of the patient.
80
- #
81
- # @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
82
- # will have the "ccr" namespace registered to ""urn:astm-org:CCR""
83
- # @return [Hash] a representation of the patient that can be inserted into MongoDB
84
- def parse_ccr(doc, patient_id_xpath="//ccr:ContinuityOfCareRecord/ccr:Patient/ccr:ActorID")
85
- ccr_patient = {}
86
- entries = create_hash(doc)
87
- get_demographics(ccr_patient, doc, patient_id_xpath)
88
- process_events(ccr_patient, entries)
89
- Record.new(ccr_patient)
90
- end
91
- #
92
- # # Parses a patient hash containing demographic and event information
93
- # #
94
- # # @param [Hash] patient_hash patient data
95
- # # @return [Hash] a representation of the patient that can be inserted into MongoDB
96
- # def parse_hash(patient_hash)
97
- # patient_record = {}
98
- # patient_record['first'] = patient_hash['first']
99
- # patient_record['patient_id'] = patient_hash['patient_id']
100
- # patient_record['last'] = patient_hash['last']
101
- # patient_record['gender'] = patient_hash['gender']
102
- # patient_record['patient_id'] = patient_hash['patient_id']
103
- # patient_record['birthdate'] = patient_hash['birthdate']
104
- # patient_record['race'] = patient_hash['race']
105
- # patient_record['ethnicity'] = patient_hash['ethnicity']
106
- # patient_record['languages'] = patient_hash['languages']
107
- # patient_record['addresses'] = patient_hash['addresses']
108
- # event_hash = {}
109
- # patient_hash['events'].each do |key, value|
110
- # event_hash[key.intern] = parse_events(value)
111
- # end
112
- # process_events(patient_record, event_hash)
113
- # end
114
-
115
- # Adds the entries and denormalized measure information to the patient_record.
116
- # Each Entry will be converted to a Hash and stored in an Array under the appropriate
117
- # section key, such as medications. Measure information is listed under the measures
118
- # key which has a Hash value. The Hash has the measure id as a key, and the denormalized
119
- # measure information as a value
120
- #
121
- # @param patient_record - Hash with basic patient demographic information
122
- # @entries - Hash of entries with section names a keys and an Array of Entry values
123
- def process_events(patient_record, entries)
124
- patient_record['measures'] = {}
125
- @measure_importers.each_pair do |measure_id, importer|
126
- patient_record['measures'][measure_id] = importer.parse(entries)
127
- end
128
-
129
-
130
- entries.each_pair do |key, value|
131
- patient_record[key] = value.map do |e|
132
- if e.usable?
133
- e.to_hash
134
- else
135
- nil
136
- end
137
- end.compact
138
- end
139
- patient_record
140
- end
141
-
142
- # # Parses a list of event hashes into an array of Entry objects
143
- # #
144
- # # @param [Array] event_list list of event hashes
145
- # # @return [Array] array of Entry objects
146
- # def parse_events(event_list)
147
- # event_list.collect do |event|
148
- # if event.class==String.class
149
- # # skip String elements in the event list, patient randomization templates
150
- # # introduce String elements to simplify tailing-comma handling when generating
151
- # # JSON using ERb
152
- # nil
153
- # else
154
- # QME::Importer::Entry.from_event_hash(event)
155
- # end
156
- # end.compact
157
- # end
158
-
159
- # Adds a measure to run on a CCR that is passed in
160
- #
161
- # @param [MeasureBase] measure an Class that can extract information from a CCR that is necessary
162
- # to calculate the measure
163
- def add_measure(measure_id, importer)
164
- @measure_importers[measure_id] = importer
165
- end
166
-
167
- # Create a simple representation of the patient from an ASTM CCR
168
- #
169
- # @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
170
- # will have the "ccr" namespace registered to ""urn:astm-org:CCR""
171
- # @return [Hash] a represnetation of the patient with symbols as keys for each section
172
- def create_hash(doc, check_usable_entries = false)
173
- ccr_patient = {}
174
- @section_importers.each_pair do |section, importer|
175
- importer.check_for_usable = check_usable_entries
176
- ccr_patient[section] = importer.create_entries(doc)
177
- end
178
- ccr_patient
179
- end
180
-
181
- # Inspects a CCR document and populates the patient Hash with first name, last name
182
- # birth date and gender.
183
- #
184
- # @param [Hash] patient A hash that is used to represent the patient
185
- # @param [Nokogiri::XML::Node] doc The CCR document parsed by Nokogiri
186
- def get_demographics(patient, doc, patient_id_xpath)
187
- patientActorID = doc.at_xpath("//ccr:ContinuityOfCareRecord/ccr:Patient/ccr:ActorID").content
188
- patientActor = doc.at_xpath("//ccr:ContinuityOfCareRecord/ccr:Actors/ccr:Actor[ccr:ActorObjectID = \"#{patientActorID}\"]")
189
- patientID = patientActor.at_xpath(patient_id_xpath).try(:content)
190
- patientID ||= patientActorID
191
-
192
- name_element = patientActor.at_xpath('./ccr:Person/ccr:Name')
193
-
194
- if name_element
195
- if name_element.at_xpath("./ccr:CurrentName")
196
- patient['first'] = name_element.at_xpath('./ccr:CurrentName/ccr:Given').try(:content)
197
- patient['last'] = name_element.at_xpath('./ccr:CurrentName/ccr:Family').try(:content)
198
- elsif name_element.at_xpath("./ccr:DisplayName")
199
- # this will not work in all cases, but we're using it as a last resort if no CurrentName is found
200
- first, last = name_element.at_xpath("./ccr:DisplayName").content.split(" ")
201
- patient['first'] = first.strip
202
- patient['last'] = last.strip
203
- end
204
- end
205
-
206
-
207
- birthdate = patientActor.at_xpath('./ccr:Person//ccr:DateOfBirth/ccr:ExactDateTime | ./ccr:Person//ccr:DateOfBirth/ccr:ApproximateDateTime')
208
- patient['birthdate'] = Time.parse(birthdate.content).to_i if birthdate
209
-
210
- gender_string = patientActor.at_xpath('./ccr:Person/ccr:Gender/ccr:Text').content.downcase
211
- patient['gender'] = Gender[gender_string.downcase]
212
- #race_node = doc.at_xpath('/ccr:placeholder') #how do you find this?
213
- race = doc.at_xpath('//ccr:SocialHistory/ccr:SocialHistoryElement[./ccr:Type/ccr:Text = "Race"]/ccr:Description/ccr:Code[./ccr:CodingSystem = "CDC-RE"]/ccr:Value')
214
- ethnicity = doc.at_xpath('//ccr:SocialHistory/ccr:SocialHistoryElement[./ccr:Type/ccr:Text = "Ethnicity"]/ccr:Description/ccr:Code[./ccr:CodingSystem = "CDC-RE"]/ccr:Value')
215
-
216
- if ethnicity
217
- patient[:ethnicity] = {"code" => ethnicity.text, "codeSystem" => 'CDC-RE'}
218
- end
219
-
220
-
221
- if race
222
- patient[:race] = {"code" => race.text, "codeSystem" => 'CDC-RE'}
223
- end
224
-
225
-
226
-
227
- #ethnicity_node = doc.at_xpath()
228
-
229
-
230
- # languages = doc.at_xpath()
231
- patient['languages'] = nil
232
-
233
- patient['medical_record_number'] = patientID
234
- end
235
- end
236
- end
237
- end
238
- end
@@ -1,60 +0,0 @@
1
- module HealthDataStandards
2
- module Import
3
- module CCR
4
- class ProductImporter < SectionImporter
5
-
6
- # Traverses that ASTM CCR document passed in using XPath and creates an Array of Entry
7
- # objects based on what it finds
8
- # @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
9
- # will have the "ccr" namespace registered to "urn:astm-org:CCR"
10
- # measure definition
11
- # @return [Array] will be a list of Entry objects
12
- def create_entries(doc)
13
- entry_list = []
14
- entry_elements = doc.xpath(@entry_xpath)
15
- entry_elements.each do |entry_element|
16
- entry = Entry.new
17
- product = entry_element.at_xpath("./ccr:Product")
18
- process_product(product,entry)
19
- extract_dates(entry_element, entry)
20
- extract_status(entry_element, entry)
21
- if @check_for_usable
22
- entry_list << entry if entry.usable?
23
- else
24
- entry_list << entry
25
- end
26
- end
27
- entry_list
28
- end
29
-
30
- # Add the codes from a <Product> block subsection to an Entry
31
- def process_product_codes(node, entry)
32
- codes = node.xpath("./ccr:Code")
33
- if codes.size > 0
34
- found_code = true
35
- codes.each do |code|
36
- normalize_coding_system(code)
37
- codetext = code.at_xpath("./ccr:CodingSystem").content
38
- entry.add_code(code.at_xpath("./ccr:Value").content, codetext)
39
- end
40
- end
41
- end
42
-
43
- # Special handling for the medications section
44
- def process_product (product, entry)
45
- productName = product.at_xpath("./ccr:ProductName")
46
- brandName = product.at_xpath("./ccr:BrandName")
47
- productNameText = productName.at_xpath("./ccr:Text")
48
- brandNameText = brandName.at_xpath("./ccr:Text") if brandName
49
- entry.description = productNameText.content if productNameText
50
- process_product_codes(productName, entry) # we throw any codes found within the productName and brandName into the same entry
51
- process_product_codes(brandName, entry) if brandName
52
- end
53
-
54
-
55
- def create_product_entries(doc)
56
- end
57
- end
58
- end
59
- end
60
- end
@@ -1,49 +0,0 @@
1
- require "date"
2
- # require "date/delta"
3
-
4
- module HealthDataStandards
5
- module Import
6
- module CCR
7
- class ProviderImporter
8
- include Singleton
9
- include ProviderImportUtils
10
-
11
- # Extract Healthcare Providers from CCR
12
- #
13
- # @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
14
- # will have the "ccr" namespace registered to "urn:astm-org:CCR"
15
- # @return [Array] an array of providers found in the document
16
-
17
- def create_provider(actor)
18
- # Differentiate care providers by content of this field
19
- provider = {}
20
- if actor.at_xpath('./ccr:Person/ccr:Name/ccr:CurrentName/ccr:Given')
21
- provider[:given_name] = extract_data(actor, './ccr:Person/ccr:Name/ccr:CurrentName/ccr:Given')
22
- provider[:family_name] = extract_data(actor, './ccr:Person/ccr:Name/ccr:CurrentName/ccr:Family')
23
- provider[:specialty] = extract_data(actor, './ccr:Specialty/ccr:Text')
24
- end
25
-
26
- provider[:specialty] = extract_data(actor, './ccr:Specialty/ccr:Text')
27
-
28
-
29
- npi_ids = actor.at_xpath("./ccr:IDs[ccr:Type/ccr:Text = \"NPI\"]")
30
- if npi_ids
31
- npi_id = npi_ids.at_xpath("./ccr:ID")
32
- npi = npi_id.content
33
- provider[:npi] = npi if Provider.valid_npi?(npi)
34
- end
35
-
36
- find_or_create_provider(provider)
37
- end
38
-
39
-
40
- def extract_providers(doc)
41
-
42
- # Providers are identified as the 'Source' for entries in the CCR. Sources can also include the patient, relatives, insurance companies, etc
43
- provider_elements = doc.xpath("//ccr:ContinuityOfCareRecord/ccr:Actors/ccr:Actor[ccr:IDs/ccr:Type/ccr:Text=\"NPI\"]")
44
- provider_elements.map { |pv| ProviderPerformance.new(provider: create_provider(pv)) }
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,49 +0,0 @@
1
- module HealthDataStandards
2
- module Import
3
- module CCR
4
- class ResultImporter < SectionImporter
5
-
6
- # Traverses that ASTM CCR document passed in using XPath and creates an Array of Entry
7
- # objects based on what it finds
8
- # @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
9
- # will have the "ccr" namespace registered to "urn:astm-org:CCR"
10
- # measure definition
11
- # @return [Array] will be a list of Entry objects
12
- def create_entries(doc)
13
- entry_list = []
14
- entry_elements = doc.xpath(@entry_xpath)
15
- entry_elements.each do |entry_element|
16
- # Grab the time and the description from the Result node
17
- dummy_entry = Entry.new
18
- extract_dates(entry_element, dummy_entry)
19
- dummy_entry.description = ""
20
- if entry_element.at_xpath("./ccr:Description/ccr:Text")
21
- dummy_entry.description = entry_element.at_xpath("./ccr:Description/ccr:Text").content
22
- end
23
- # Iterate over embedded tests
24
- # Grab the values and the description from the Test nodes
25
- # For each test, create an entry with the time from the Result, the description a concatenation of the Result and Test descriptions,
26
- # and the value from the Test
27
-
28
- tests = entry_element.xpath("./ccr:Test")
29
- tests.each do |test|
30
- entry = Entry.new
31
- entry = dummy_entry.clone # copies time and description
32
- extract_codes(test, entry)
33
- extract_value(test, entry)
34
- extract_status(test, entry)
35
- extract_dates(test, entry)
36
- entry.description = dummy_entry.description + ": " + entry.description
37
- if @check_for_usable
38
- entry_list << entry if entry.usable?
39
- else
40
- entry_list << entry
41
- end
42
- end
43
- end
44
- entry_list
45
- end
46
- end
47
- end
48
- end
49
- end