health-data-standards 0.3.0 → 0.5.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.
- data/Gemfile +5 -2
- data/Rakefile +6 -1
- data/VERSION +1 -1
- data/lib/health-data-standards.rb +27 -2
- data/lib/health-data-standards/export/view_helper.rb +15 -16
- data/lib/health-data-standards/ext/string.rb +5 -0
- data/lib/health-data-standards/ext/symbol.rb +8 -0
- data/lib/health-data-standards/import/c32/allergy_importer.rb +42 -0
- data/lib/health-data-standards/import/c32/encounter_importer.rb +80 -0
- data/lib/health-data-standards/import/c32/immunization_importer.rb +61 -0
- data/lib/health-data-standards/import/c32/medication_importer.rb +138 -0
- data/lib/health-data-standards/import/c32/patient_importer.rb +139 -0
- data/lib/health-data-standards/import/c32/procedure_importer.rb +55 -0
- data/lib/health-data-standards/import/c32/result_importer.rb +58 -0
- data/lib/health-data-standards/import/c32/section_importer.rb +214 -0
- data/lib/health-data-standards/import/c32/vital_sign_importer.rb +12 -0
- data/lib/health-data-standards/models/allergy.rb +4 -0
- data/lib/health-data-standards/models/encounter.rb +7 -0
- data/lib/health-data-standards/models/entry.rb +131 -3
- data/lib/health-data-standards/models/fulfillment_history.rb +11 -0
- data/lib/health-data-standards/models/immunization.rb +5 -0
- data/lib/health-data-standards/models/lab_result.rb +4 -0
- data/lib/health-data-standards/models/medication.rb +25 -0
- data/lib/health-data-standards/models/order_information.rb +9 -0
- data/lib/health-data-standards/models/procedure.rb +4 -0
- data/lib/health-data-standards/models/record.rb +1 -0
- data/lib/health-data-standards/util/code_system_helper.rb +41 -0
- data/lib/health-data-standards/util/hl7_helper.rb +25 -0
- data/templates/_allergies.c32.erb +3 -1
- data/templates/_care_goals.c32.erb +1 -1
- data/templates/_code_with_reference.c32.erb +10 -5
- data/templates/_conditions.c32.erb +2 -2
- data/templates/_encounters.c32.erb +2 -1
- data/templates/_immunizations.c32.erb +2 -1
- data/templates/_medical_equipment.c32.erb +1 -1
- data/templates/_medications.c32.erb +2 -1
- data/templates/_narrative_block.c32.erb +14 -0
- data/templates/_procedures.c32.erb +2 -1
- data/templates/_results.c32.erb +2 -2
- data/templates/_social_history.c32.erb +1 -1
- data/templates/_vital_signs.c32.erb +2 -2
- metadata +37 -16
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
require 'rake/testtask'
|
2
2
|
|
3
|
-
Rake::TestTask.new do |t|
|
3
|
+
Rake::TestTask.new(:test_unit) do |t|
|
4
4
|
t.libs << "test"
|
5
5
|
t.test_files = FileList['test/**/*_test.rb']
|
6
6
|
t.verbose = true
|
7
|
+
end
|
8
|
+
|
9
|
+
task :test => [:test_unit] do
|
10
|
+
require 'cover_me'
|
11
|
+
CoverMe.complete!
|
7
12
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
@@ -2,9 +2,16 @@ require 'erubis'
|
|
2
2
|
require 'active_support'
|
3
3
|
require 'mongoid'
|
4
4
|
require 'uuid'
|
5
|
-
require 'quality-measure-engine'
|
6
5
|
require 'builder'
|
7
6
|
require 'csv'
|
7
|
+
require 'nokogiri'
|
8
|
+
|
9
|
+
# Freedom patches
|
10
|
+
require_relative 'health-data-standards/ext/symbol'
|
11
|
+
require_relative 'health-data-standards/ext/string'
|
12
|
+
|
13
|
+
require_relative 'health-data-standards/util/hl7_helper'
|
14
|
+
require_relative 'health-data-standards/util/code_system_helper'
|
8
15
|
|
9
16
|
require_relative 'health-data-standards/export/template_helper'
|
10
17
|
require_relative 'health-data-standards/export/view_helper'
|
@@ -14,4 +21,22 @@ require_relative 'health-data-standards/export/ccr'
|
|
14
21
|
require_relative 'health-data-standards/export/csv'
|
15
22
|
|
16
23
|
require_relative 'health-data-standards/models/entry'
|
17
|
-
require_relative 'health-data-standards/models/
|
24
|
+
require_relative 'health-data-standards/models/allergy'
|
25
|
+
require_relative 'health-data-standards/models/encounter'
|
26
|
+
require_relative 'health-data-standards/models/immunization'
|
27
|
+
require_relative 'health-data-standards/models/fulfillment_history'
|
28
|
+
require_relative 'health-data-standards/models/order_information'
|
29
|
+
require_relative 'health-data-standards/models/medication'
|
30
|
+
require_relative 'health-data-standards/models/procedure'
|
31
|
+
require_relative 'health-data-standards/models/lab_result'
|
32
|
+
require_relative 'health-data-standards/models/record'
|
33
|
+
|
34
|
+
require_relative 'health-data-standards/import/c32/section_importer'
|
35
|
+
require_relative 'health-data-standards/import/c32/allergy_importer'
|
36
|
+
require_relative 'health-data-standards/import/c32/encounter_importer'
|
37
|
+
require_relative 'health-data-standards/import/c32/immunization_importer'
|
38
|
+
require_relative 'health-data-standards/import/c32/medication_importer'
|
39
|
+
require_relative 'health-data-standards/import/c32/procedure_importer'
|
40
|
+
require_relative 'health-data-standards/import/c32/result_importer'
|
41
|
+
require_relative 'health-data-standards/import/c32/vital_sign_importer'
|
42
|
+
require_relative 'health-data-standards/import/c32/patient_importer'
|
@@ -1,23 +1,22 @@
|
|
1
1
|
module HealthDataStandards
|
2
2
|
module Export
|
3
3
|
module ViewHelper
|
4
|
-
def code_display(entry,
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
def code_display(entry, options={})
|
5
|
+
options['tag_name'] ||= 'code'
|
6
|
+
code_string = nil
|
7
|
+
preferred_code = entry.preferred_code(options['preferred_code_sets'])
|
8
|
+
if preferred_code
|
9
|
+
code_system_oid = HealthDataStandards::Util::CodeSystemHelper.oid_for_code_system(preferred_code['code_set'])
|
10
|
+
code_string = "<#{options['tag_name']} code=\"#{preferred_code['code']}\" codeSystem=\"#{code_system_oid}\" #{options['extra_content']}>"
|
9
11
|
else
|
10
|
-
|
11
|
-
entry.codes.each_pair {|key, values| values.each {|v| all_codes << {:set => key, :value => v}}}
|
12
|
-
first_code = all_codes.first
|
13
|
-
code_string = "<#{tag_name} code=\"#{first_code[:value]}\" codeSystem=\"#{QME::Importer::CodeSystemHelper.oid_for_code_system(first_code[:set])}\">\n"
|
14
|
-
code_string += "<originalText>#{ERB::Util.html_escape entry.description}</originalText>\n"
|
15
|
-
all_codes[1..-1].each do |cv|
|
16
|
-
code_string += "<translation code=\"#{cv[:value]}\" codeSystem=\"#{QME::Importer::CodeSystemHelper.oid_for_code_system(cv[:set])}\"/>\n"
|
17
|
-
end
|
18
|
-
code_string += "</#{tag_name}>"
|
19
|
-
code_string
|
12
|
+
code_string = "<#{options['tag_name']} nullFlavor=\"UNK\" #{options['extra_content']}>"
|
20
13
|
end
|
14
|
+
code_string += "<originalText>#{ERB::Util.html_escape entry.description}</originalText>"
|
15
|
+
entry.translation_codes(options['preferred_code_sets']).each do |translation|
|
16
|
+
code_string += "<translation code=\"#{translation['code']}\" codeSystem=\"#{HealthDataStandards::Util::CodeSystemHelper.oid_for_code_system(translation['code_set'])}\"/>\n"
|
17
|
+
end
|
18
|
+
code_string += "</#{options['tag_name']}>"
|
19
|
+
code_string
|
21
20
|
end
|
22
21
|
|
23
22
|
def status_code_for(entry)
|
@@ -29,7 +28,7 @@ module HealthDataStandards
|
|
29
28
|
when 'resolved'
|
30
29
|
'413322009'
|
31
30
|
end
|
32
|
-
end
|
31
|
+
end
|
33
32
|
end
|
34
33
|
end
|
35
34
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module C32
|
4
|
+
class AllergyImporter < SectionImporter
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@entry_xpath = "//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.18']"
|
8
|
+
@code_xpath = "./cda:participant/cda:participantRole/cda:playingEntity/cda:code"
|
9
|
+
@description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
|
10
|
+
@id_map = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
# Traverses that HITSP C32 document passed in using XPath and creates an Array of Entry
|
14
|
+
# objects based on what it finds
|
15
|
+
# @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
|
16
|
+
# will have the "cda" namespace registered to "urn:hl7-org:v3"
|
17
|
+
# measure definition
|
18
|
+
# @return [Array] will be a list of Entry objects
|
19
|
+
def create_entries(doc,id_map = {})
|
20
|
+
@id_map = id_map
|
21
|
+
allergy_list = []
|
22
|
+
entry_elements = doc.xpath(@entry_xpath)
|
23
|
+
entry_elements.each do |entry_element|
|
24
|
+
allergy = Allergy.new
|
25
|
+
extract_codes(entry_element, allergy)
|
26
|
+
extract_dates(entry_element, allergy)
|
27
|
+
extract_description(entry_element, allergy, id_map)
|
28
|
+
|
29
|
+
allergy.reaction = extract_code(entry_element,
|
30
|
+
"./cda:entryRelationship[@typeCode='MFST']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.54']/cda:value")
|
31
|
+
|
32
|
+
allergy.severity = extract_code(entry_element,
|
33
|
+
"./cda:entryRelationship[@typeCode='MFST']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.54']/cda:entryRelationship[@typeCode='SUBJ']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.55']/cda:value")
|
34
|
+
|
35
|
+
allergy_list << allergy
|
36
|
+
end
|
37
|
+
allergy_list
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module C32
|
4
|
+
# TODO Extract Discharge Disposition
|
5
|
+
class EncounterImporter < SectionImporter
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.127']/cda:entry/cda:encounter"
|
9
|
+
@code_xpath = "./cda:code"
|
10
|
+
@status_xpath = "./cda:statusCode"
|
11
|
+
@description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
|
12
|
+
@check_for_usable = true # Pilot tools will set this to false
|
13
|
+
@id_map = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
# Traverses that HITSP C32 document passed in using XPath and creates an Array of Entry
|
17
|
+
# objects based on what it finds
|
18
|
+
# @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
|
19
|
+
# will have the "cda" namespace registered to "urn:hl7-org:v3"
|
20
|
+
# measure definition
|
21
|
+
# @return [Array] will be a list of Entry objects
|
22
|
+
def create_entries(doc,id_map = {})
|
23
|
+
encounter_list = []
|
24
|
+
entry_elements = doc.xpath(@entry_xpath)
|
25
|
+
entry_elements.each do |entry_element|
|
26
|
+
encounter = Encounter.new
|
27
|
+
extract_codes(entry_element, encounter)
|
28
|
+
extract_dates(entry_element, encounter)
|
29
|
+
extract_description(entry_element, encounter, id_map)
|
30
|
+
if @check_for_usable
|
31
|
+
encounter_list << encounter if encounter.usable?
|
32
|
+
else
|
33
|
+
encounter_list << encounter
|
34
|
+
end
|
35
|
+
extract_performer(entry_element, encounter)
|
36
|
+
extract_facility(entry_element, encounter)
|
37
|
+
extract_reason(entry_element, encounter, id_map)
|
38
|
+
extract_admission(entry_element, encounter)
|
39
|
+
end
|
40
|
+
encounter_list
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def extract_performer(parent_element, encounter)
|
46
|
+
performer_element = parent_element.at_xpath("./cda:performer")
|
47
|
+
encounter.performer = import_actor(performer_element) if performer_element
|
48
|
+
end
|
49
|
+
|
50
|
+
def extract_facility(parent_element, encounter)
|
51
|
+
participant_element = parent_element.at_xpath("./cda:participant[@typeCode='LOC']/cda:participantRole[@classCode='SDLOC']")
|
52
|
+
encounter.facility = {}
|
53
|
+
if (participant_element)
|
54
|
+
encounter.facility['organizationName'] = participant_element.at_xpath("./cda:playingEntity/cda:name").try(:text)
|
55
|
+
addresses = participant_element.xpath("./cda:addr").try(:map) {|ae| import_address(ae)}
|
56
|
+
encounter.facility['addresses'] = addresses
|
57
|
+
telecoms = participant_element.xpath("./cda:telecom").try(:map) {|te| import_telecom(te)}
|
58
|
+
encounter.facility['telcoms'] = telecoms
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def extract_reason(parent_element, encounter, id_map)
|
63
|
+
reason_element = parent_element.at_xpath("./cda:entryRelationship[@typeCode='RSON']/cda:act")
|
64
|
+
if reason_element
|
65
|
+
reason = Entry.new
|
66
|
+
extract_codes(reason_element, reason)
|
67
|
+
extract_description(reason_element, reason, id_map)
|
68
|
+
extract_status(reason_element, reason)
|
69
|
+
extract_dates(reason_element, reason)
|
70
|
+
encounter.reason = reason
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def extract_admission(parent_element, encounter)
|
75
|
+
encounter.admit_type = extract_code(parent_element, "./cda:priorityCode")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module C32
|
4
|
+
class ImmunizationImporter < SectionImporter
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.117']/cda:entry/cda:substanceAdministration"
|
8
|
+
@code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
|
9
|
+
@description_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code/cda:originalText/cda:reference[@value]"
|
10
|
+
@refusal_resason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.1.27']/cda:code"
|
11
|
+
@check_for_usable = true # Pilot tools will set this to false
|
12
|
+
end
|
13
|
+
|
14
|
+
# Traverses that HITSP C32 document passed in using XPath and creates an Array of Entry
|
15
|
+
# objects based on what it finds
|
16
|
+
# @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
|
17
|
+
# will have the "cda" namespace registered to "urn:hl7-org:v3"
|
18
|
+
# measure definition
|
19
|
+
# @return [Array] will be a list of Entry objects
|
20
|
+
def create_entries(doc,id_map = {})
|
21
|
+
immunization_list = []
|
22
|
+
entry_elements = doc.xpath(@entry_xpath)
|
23
|
+
entry_elements.each do |entry_element|
|
24
|
+
immunization = Immunization.new
|
25
|
+
extract_codes(entry_element, immunization)
|
26
|
+
extract_dates(entry_element, immunization)
|
27
|
+
extract_description(entry_element, immunization, id_map)
|
28
|
+
extract_refusal(entry_element, immunization)
|
29
|
+
extract_performer(entry_element, immunization)
|
30
|
+
if @check_for_usable
|
31
|
+
immunization_list << immunization if immunization.usable?
|
32
|
+
else
|
33
|
+
immunization_list << immunization
|
34
|
+
end
|
35
|
+
end
|
36
|
+
immunization_list
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def extract_refusal(parent_element, immunization)
|
41
|
+
negation_indicator = parent_element['negationInd']
|
42
|
+
unless negation_indicator.nil?
|
43
|
+
immunization.refusal_ind = negation_indicator.eql?('true')
|
44
|
+
if immunization.refusal_ind
|
45
|
+
refusal_reason_element = parent_element.at_xpath(@refusal_resason_xpath)
|
46
|
+
if refusal_reason_element
|
47
|
+
immunization.refusal_reason = {'code' => refusal_reason_element['code'],
|
48
|
+
'codeSystem' => 'HL7 No Immunization Reason'}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def extract_performer(parent_element, immunization)
|
55
|
+
performer_element = parent_element.at_xpath("./cda:performer")
|
56
|
+
immunization.performer = import_actor(performer_element) if performer_element
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module C32
|
4
|
+
|
5
|
+
# TODO: Coded Product Name, Free Text Product Name, Coded Brand Name and Free Text Brand name need to be pulled out separatelty
|
6
|
+
# This would mean overriding extract_codes
|
7
|
+
# TODO: Patient Instructions needs to be implemented. Will likely be a reference to the narrative section
|
8
|
+
# TODO: Couldn't find an example medication reaction. Isn't clear to me how it should be implemented from the specs, so
|
9
|
+
# reaction is not implemented.
|
10
|
+
# TODO: Couldn't find an example dose indicator. Isn't clear to me how it should be implemented from the specs, so
|
11
|
+
# dose indicator is not implemented.
|
12
|
+
# TODO: Fill Status is not implemented. Couldn't figure out which entryRelationship it should be nested in
|
13
|
+
class MedicationImporter < SectionImporter
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.112']/cda:entry/cda:substanceAdministration"
|
17
|
+
@code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
|
18
|
+
@description_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code/cda:originalText/cda:reference[@value]"
|
19
|
+
|
20
|
+
@check_for_usable = true # Pilot tools will set this to false
|
21
|
+
end
|
22
|
+
|
23
|
+
# Traverses that HITSP C32 document passed in using XPath and creates an Array of Entry
|
24
|
+
# objects based on what it finds
|
25
|
+
# @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
|
26
|
+
# will have the "cda" namespace registered to "urn:hl7-org:v3"
|
27
|
+
# measure definition
|
28
|
+
# @return [Array] will be a list of Entry objects
|
29
|
+
def create_entries(doc,id_map = {})
|
30
|
+
medication_list = []
|
31
|
+
entry_elements = doc.xpath(@entry_xpath)
|
32
|
+
entry_elements.each do |entry_element|
|
33
|
+
medication = Medication.new
|
34
|
+
extract_codes(entry_element, medication)
|
35
|
+
extract_dates(entry_element, medication)
|
36
|
+
extract_description(entry_element, medication, id_map)
|
37
|
+
|
38
|
+
if medication.description.present?
|
39
|
+
medication.free_text_sig = medication.description
|
40
|
+
end
|
41
|
+
|
42
|
+
extract_administration_timing(entry_element, medication)
|
43
|
+
|
44
|
+
medication.route = extract_code(entry_element, "./cda:routeCode")
|
45
|
+
medication.dose = extract_scalar(entry_element, "./cda:doseQuantity")
|
46
|
+
medication.site = extract_code(entry_element, "./cda:approachSiteCode", 'SNOMED-CT')
|
47
|
+
|
48
|
+
extract_dose_restriction(entry_element, medication)
|
49
|
+
|
50
|
+
medication.product_form = extract_code(entry_element, "./cda:administrationUnitCode", 'NCI Thesaurus')
|
51
|
+
medication.delivery_method = extract_code(entry_element, "./cda:code", 'SNOMED-CT')
|
52
|
+
medication.type_of_medication = extract_code(entry_element,
|
53
|
+
"./cda:entryRelationship[@typeCode='SUBJ']/cda:observation[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.8.1']/cda:code", 'SNOMED-CT')
|
54
|
+
medication.indication = extract_code(entry_element,
|
55
|
+
"./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.28']/cda:code", 'SNOMED-CT')
|
56
|
+
medication.vehicle = extract_code(entry_element,
|
57
|
+
"cda:participant/cda:participantRole[cda:code/@code='412307009' and cda:code/@codeSystem='2.16.840.1.113883.6.96']/cda:playingEntity/cda:code", 'SNOMED-CT')
|
58
|
+
|
59
|
+
extract_order_information(entry_element, medication)
|
60
|
+
|
61
|
+
extract_fulfillment_history(entry_element, medication)
|
62
|
+
|
63
|
+
if @check_for_usable
|
64
|
+
medication_list << medication if medication.usable?
|
65
|
+
else
|
66
|
+
medication_list << medication_list
|
67
|
+
end
|
68
|
+
end
|
69
|
+
medication_list
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def extract_fulfillment_history(parent_element, medication)
|
75
|
+
fhs = parent_element.xpath("./cda:entryRelationship/cda:supply[@moodCode='EVN']")
|
76
|
+
if fhs
|
77
|
+
fhs.each do |fh_element|
|
78
|
+
fulfillment_history = FulfillmentHistory.new
|
79
|
+
fulfillment_history.prescription_number = fh_element.at_xpath('./cda:id').try(:[], 'root')
|
80
|
+
actor_element = fh_element.at_xpath('./cda:performer')
|
81
|
+
if actor_element
|
82
|
+
fulfillment_history.provider = import_actor(actor_element)
|
83
|
+
addr_element = actor_element.at_xpath("./cda:assignedEntity/cda:addr")
|
84
|
+
if addr_element
|
85
|
+
fulfillment_history.dispensing_pharmacy_location = import_address(addr_element)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
hl7_timestamp = fh_element.at_xpath('./cda:effectiveTime').try(:[], 'value')
|
89
|
+
fulfillment_history.dispense_date = HL7Helper.timestamp_to_integer(hl7_timestamp) if hl7_timestamp
|
90
|
+
fulfillment_history.quantity_dispensed = extract_scalar(fh_element, "./cda:quantity")
|
91
|
+
fulfillment_history.fill_number = fh_element.at_xpath("./cda:entryRelationship[@typeCode='COMP']/cda:sequenceNumber").try(:[], 'value').to_i
|
92
|
+
medication.fulfillmentHistory << fulfillment_history
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def extract_order_information(parent_element, medication)
|
98
|
+
order_elements = parent_element.xpath("./cda:entryRelationship[@typeCode='REFR']/cda:supply[@moodCode='INT']")
|
99
|
+
if order_elements
|
100
|
+
order_elements.each do |order_element|
|
101
|
+
order_information = OrderInformation.new
|
102
|
+
|
103
|
+
order_information.order_number = order_element.at_xpath('./cda:id').try(:[], 'root')
|
104
|
+
order_information.fills = order_element.at_xpath('./cda:repeatNumber').try(:[], 'value').try(:to_i)
|
105
|
+
order_information.quantity_ordered = extract_scalar(order_element, "./cda:quantity")
|
106
|
+
|
107
|
+
medication.orderInformation << order_information
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def extract_administration_timing(parent_element, medication)
|
113
|
+
administration_timing_element = parent_element.at_xpath("./cda:effectiveTime[2]")
|
114
|
+
if administration_timing_element
|
115
|
+
at = {}
|
116
|
+
if administration_timing_element['institutionSpecified']
|
117
|
+
at['institutionSpecified'] = administration_timing_element['institutionSpecified'].to_boolean
|
118
|
+
end
|
119
|
+
at['period'] = extract_scalar(administration_timing_element, "./cda:period")
|
120
|
+
if at.present?
|
121
|
+
medication.administration_timing = at
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def extract_dose_restriction(parent_element, medication)
|
127
|
+
dre = parent_element.at_xpath("./cda:maxDoseQuantity")
|
128
|
+
if dre
|
129
|
+
dr = {}
|
130
|
+
dr['numerator'] = extract_scalar(dre, "./cda:numerator")
|
131
|
+
dr['denominator'] = extract_scalar(dre, "./cda:denominator")
|
132
|
+
medication.dose_restriction = dr
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|