health-data-standards 0.8.1 → 1.0.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 (87) hide show
  1. data/Rakefile +1 -1
  2. data/lib/health-data-standards/export/ccr.rb +1 -1
  3. data/lib/health-data-standards/export/csv.rb +6 -1
  4. data/lib/health-data-standards/export/green_c32/entry.rb +1 -1
  5. data/lib/health-data-standards/export/green_c32/record.rb +15 -0
  6. data/lib/health-data-standards/export/template_helper.rb +0 -2
  7. data/lib/health-data-standards/export/view_helper.rb +28 -2
  8. data/lib/health-data-standards/import/c32/allergy_importer.rb +12 -8
  9. data/lib/health-data-standards/import/c32/care_goal_importer.rb +39 -0
  10. data/lib/health-data-standards/import/c32/condition_importer.rb +10 -4
  11. data/lib/health-data-standards/import/c32/encounter_importer.rb +16 -10
  12. data/lib/health-data-standards/import/c32/immunization_importer.rb +2 -2
  13. data/lib/health-data-standards/import/c32/insurance_provider_importer.rb +42 -0
  14. data/lib/health-data-standards/import/c32/medical_equipment_importer.rb +45 -0
  15. data/lib/health-data-standards/import/c32/medication_importer.rb +35 -48
  16. data/lib/health-data-standards/import/c32/organization_importer.rb +1 -1
  17. data/lib/health-data-standards/import/c32/patient_importer.rb +3 -3
  18. data/lib/health-data-standards/import/c32/procedure_importer.rb +12 -8
  19. data/lib/health-data-standards/import/c32/result_importer.rb +11 -14
  20. data/lib/health-data-standards/import/c32/section_importer.rb +60 -29
  21. data/lib/health-data-standards/import/ccda/allergy_importer.rb +20 -0
  22. data/lib/health-data-standards/import/ccda/care_goal_importer.rb +13 -0
  23. data/lib/health-data-standards/import/ccda/condition_importer.rb +20 -0
  24. data/lib/health-data-standards/import/ccda/encounter_importer.rb +18 -0
  25. data/lib/health-data-standards/import/ccda/immunization_importer.rb +16 -0
  26. data/lib/health-data-standards/import/ccda/insurance_provider_importer.rb +14 -0
  27. data/lib/health-data-standards/import/ccda/medical_equipment_importer.rb +16 -0
  28. data/lib/health-data-standards/import/ccda/medication_importer.rb +19 -0
  29. data/lib/health-data-standards/import/ccda/patient_importer.rb +29 -0
  30. data/lib/health-data-standards/import/ccda/procedure_importer.rb +17 -0
  31. data/lib/health-data-standards/import/ccda/result_importer.rb +13 -0
  32. data/lib/health-data-standards/import/ccda/vital_sign_importer.rb +12 -0
  33. data/lib/health-data-standards/import/ccr/patient_importer.rb +16 -3
  34. data/lib/health-data-standards/import/green_c32/advance_directive_importer.rb +14 -0
  35. data/lib/health-data-standards/import/green_c32/allergy_importer.rb +1 -1
  36. data/lib/health-data-standards/import/green_c32/care_goal_importer.rb +26 -0
  37. data/lib/health-data-standards/import/green_c32/condition_importer.rb +0 -6
  38. data/lib/health-data-standards/import/green_c32/encounter_importer.rb +1 -6
  39. data/lib/health-data-standards/import/green_c32/immunization_importer.rb +1 -1
  40. data/lib/health-data-standards/import/green_c32/medical_equipment_importer.rb +24 -0
  41. data/lib/health-data-standards/import/green_c32/medication_importer.rb +1 -1
  42. data/lib/health-data-standards/import/green_c32/procedure_importer.rb +2 -10
  43. data/lib/health-data-standards/import/green_c32/section_importer.rb +36 -5
  44. data/lib/health-data-standards/import/green_c32/social_history_importer.rb +1 -6
  45. data/lib/health-data-standards/import/green_c32/support_importer.rb +22 -0
  46. data/lib/health-data-standards/models/allergy.rb +1 -1
  47. data/lib/health-data-standards/models/condition.rb +3 -1
  48. data/lib/health-data-standards/models/encounter.rb +1 -3
  49. data/lib/health-data-standards/models/entry.rb +23 -21
  50. data/lib/health-data-standards/models/guarantor.rb +10 -0
  51. data/lib/health-data-standards/models/insurance_provider.rb +17 -0
  52. data/lib/health-data-standards/models/medical_equipment.rb +5 -0
  53. data/lib/health-data-standards/models/medication.rb +0 -2
  54. data/lib/health-data-standards/models/person.rb +4 -0
  55. data/lib/health-data-standards/models/personable.rb +13 -0
  56. data/lib/health-data-standards/models/procedure.rb +0 -2
  57. data/lib/health-data-standards/models/provider.rb +1 -6
  58. data/lib/health-data-standards/models/record.rb +11 -5
  59. data/lib/health-data-standards/models/support.rb +18 -0
  60. data/lib/health-data-standards.rb +28 -2
  61. data/templates/_advance_directive.gc32.erb +8 -0
  62. data/templates/_allergy.gc32.erb +17 -7
  63. data/templates/_care_goal.gc32.erb +8 -0
  64. data/templates/_condition.gc32.erb +4 -6
  65. data/templates/_conditions.c32.erb +3 -0
  66. data/templates/_encounter.gc32.erb +1 -7
  67. data/templates/_entry.gc32.erb +14 -0
  68. data/templates/_immunization.gc32.erb +4 -2
  69. data/templates/_insurance_provider.gc32.erb +0 -0
  70. data/templates/_medical_equipment.c32.erb +6 -0
  71. data/templates/_medical_equipment.gc32.erb +7 -0
  72. data/templates/_medication.gc32.erb +26 -14
  73. data/templates/_medications_no_current.c32.erb +26 -6
  74. data/templates/_name.gc32.erb +11 -0
  75. data/templates/_narrative_block.c32.erb +1 -1
  76. data/templates/_procedure.gc32.erb +6 -4
  77. data/templates/_result.gc32.erb +2 -8
  78. data/templates/_results.c32.erb +8 -2
  79. data/templates/_social_history.gc32.erb +3 -1
  80. data/templates/_support.gc32.erb +14 -0
  81. data/templates/_vital_sign.gc32.erb +2 -7
  82. data/templates/_vital_signs.c32.erb +8 -2
  83. data/templates/record.gc32.erb +81 -0
  84. data/templates/show.c32.erb +1 -1
  85. metadata +48 -16
  86. data/lib/health-data-standards/models/comment.rb +0 -2
  87. data/lib/health-data-standards/models/social_history.rb +0 -3
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ end
10
10
 
11
11
  Cane::RakeTask.new(:quality) do |cane|
12
12
  cane.abc_max = 45
13
- cane.add_threshold 'coverage/covered_percent', :>=, 97
13
+ # cane.add_threshold 'coverage/covered_percent', :>=, 97
14
14
  cane.style_measure = 120
15
15
  cane.no_style = true
16
16
  cane.no_doc = true
@@ -392,7 +392,7 @@ module HealthDataStandards
392
392
  end
393
393
 
394
394
  def convert_to_ccr_time_string(time)
395
- converted_time = Time.at(time)
395
+ converted_time = Time.at(time).utc
396
396
  converted_time.strftime("%Y-%m-%dT%H:%M:%SZ")
397
397
  end
398
398
 
@@ -17,7 +17,12 @@ module HealthDataStandards
17
17
  end
18
18
 
19
19
  def extract_patient_data(patient)
20
- [patient.patient_id, patient.first, patient.last, patient.gender,patient.race,patient.ethnicity,Time.at(patient.birthdate).strftime('%m/%d/%Y')]
20
+ race = ''
21
+ ethnicity = ''
22
+ race = patient.race['name'] || patient.race if !patient.race.nil?
23
+ ethnicity = patient.ethnicity['name'] || patient.ethnicity if !patient.ethnicity.nil?
24
+
25
+ [patient.patient_id, patient.first, patient.last, patient.gender, race, ethnicity, Time.at(patient.birthdate).strftime('%m/%d/%Y')]
21
26
  end
22
27
 
23
28
  extend self
@@ -6,7 +6,7 @@ module HealthDataStandards
6
6
 
7
7
  def export(object, object_type)
8
8
  self.template_format = "gc32"
9
- render(partial: object_type, locals: {object_type => object})
9
+ render(partial: object_type, locals: {object_type => object, type: object_type})
10
10
  end
11
11
  extend self
12
12
  end
@@ -0,0 +1,15 @@
1
+ module HealthDataStandards
2
+ module Export
3
+ module GreenC32
4
+ module Record
5
+ include TemplateHelper
6
+
7
+ def export(object)
8
+ self.template_format = "gc32"
9
+ render(template: "record", locals: {record: object})
10
+ end
11
+ extend self
12
+ end
13
+ end
14
+ end
15
+ end
@@ -14,8 +14,6 @@ module HealthDataStandards
14
14
  def partial(partial_name)
15
15
  template("_#{partial_name}")
16
16
  end
17
-
18
-
19
17
 
20
18
  def render(params)
21
19
  erb = nil
@@ -25,6 +25,19 @@ module HealthDataStandards
25
25
  code_string
26
26
  end
27
27
 
28
+ def gc32_effective_time(entry)
29
+ if entry.time
30
+ "<effectiveTime value=\"#{Time.at(entry.time)}\" />"
31
+ elsif entry.start_time || entry.end_time
32
+ time = "<effectiveTime>"
33
+ time += "<start value=\"#{Time.at(entry.start_time)}\" />" if entry.start_time
34
+ time += "<end value=\"#{Time.at(entry.end_time)}\" />" if entry.end_time
35
+ time += "</effectiveTime>"
36
+ else
37
+ "<effectiveTime />"
38
+ end
39
+ end
40
+
28
41
  def status_code_for(entry)
29
42
  case entry.status.to_s.downcase
30
43
  when 'active'
@@ -35,7 +48,8 @@ module HealthDataStandards
35
48
  '413322009'
36
49
  end
37
50
  end
38
-
51
+
52
+
39
53
  def value_or_null_flavor(time)
40
54
  if time
41
55
  return "value='#{Time.at(time).utc.to_formatted_s(:number)}'"
@@ -51,7 +65,19 @@ module HealthDataStandards
51
65
  end
52
66
 
53
67
  def time_if_not_nil(*args)
54
- args.compact.map {|t| Time.at(t)}.first
68
+ args.compact.map {|t| Time.at(t).utc}.first
69
+ end
70
+
71
+ def is_num?(str)
72
+ Float(str || "")
73
+ rescue ArgumentError
74
+ false
75
+ else
76
+ true
77
+ end
78
+
79
+ def is_bool?(str)
80
+ return ["true","false"].include? (str || "").downcase
55
81
  end
56
82
  end
57
83
  end
@@ -6,7 +6,11 @@ module HealthDataStandards
6
6
  def initialize
7
7
  @entry_xpath = "//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.18']"
8
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] "
9
+ @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value]"
10
+ @type_xpath = "./cda:code"
11
+ @reaction_xpath = "./cda:entryRelationship[@typeCode='MFST']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.54']/cda:value"
12
+ @severity_xpath = "./cda:entryRelationship[@typeCode='SUBJ']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.55']/cda:value"
13
+ @status_xpath = "./cda:entryRelationship[@typeCode='REFR']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.39']/cda:value"
10
14
  @id_map = {}
11
15
  end
12
16
 
@@ -25,17 +29,17 @@ module HealthDataStandards
25
29
  extract_codes(entry_element, allergy)
26
30
  extract_dates(entry_element, allergy)
27
31
  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
-
32
+
33
+ allergy.status = extract_status(entry_element, allergy)
34
+ allergy.type = extract_code(entry_element, @type_xpath)
35
+ allergy.reaction = extract_code(entry_element, @reaction_xpath)
36
+ allergy.severity = extract_code(entry_element, @severity_xpath)
37
+
35
38
  allergy_list << allergy
36
39
  end
37
40
  allergy_list
38
41
  end
42
+
39
43
  end
40
44
  end
41
45
  end
@@ -0,0 +1,39 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module C32
4
+ class CareGoalImporter < SectionImporter
5
+
6
+ def initialize
7
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.124']/cda:entry/cda:*[cda:templateId/@root='2.16.840.1.113883.10.20.1.25']"
8
+ end
9
+
10
+ def create_entries(doc, id_map = {})
11
+ goal_list = []
12
+ goal_elements = doc.xpath(@entry_xpath)
13
+ goal_elements.each do |goal_element|
14
+
15
+ importer = case goal_element.name
16
+ when "observation" then ResultImporter.new
17
+ when "supply" then MedicalEquipment.new
18
+ when "substanceAdministration" then MedicationImporter.new
19
+ when "encounter" then EncounterImporter.new
20
+ when "procedure" then ProcedureImporter.new
21
+ else SectionImporter.new(nil) #don't need entry xpath, since we already have the entry
22
+ end
23
+
24
+ entry = importer.create_entry(goal_element, id_map={})
25
+
26
+
27
+
28
+ if @check_for_usable
29
+ goal_list << entry if entry.usable?
30
+ else
31
+ goal_list << entry
32
+ end
33
+ end
34
+ goal_list
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -7,7 +7,10 @@ module HealthDataStandards
7
7
  @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.103']/cda:entry/cda:act/cda:entryRelationship/cda:observation"
8
8
  @code_xpath = "./cda:value"
9
9
  @status_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.50']/cda:value"
10
+ @priority_xpath = "./cda:priorityCode"
10
11
  @description_xpath = "./cda:text/cda:reference[@value]"
12
+ @provider_xpath = "./cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.1.27']/cda:performer"
13
+ @cod_xpath = "./cda:entryRelationship[@typeCode='CAUS']/cda:observation/cda:code[@code='419620001']"
11
14
  end
12
15
 
13
16
  def create_entries(doc, id_map = {})
@@ -21,12 +24,15 @@ module HealthDataStandards
21
24
  extract_codes(entry_element, condition)
22
25
  extract_dates(entry_element, condition)
23
26
  extract_status(entry_element, condition)
27
+ extract_priority(entry_element, condition)
24
28
  extract_description(entry_element, condition, id_map)
25
- extract_cause_of_death(entry_element, condition)
29
+ extract_cause_of_death(entry_element, condition) if @cod_xpath
26
30
  extract_type(entry_element, condition)
27
31
 
28
- entry_element.xpath("./cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.1.27']/cda:performer").each do |provider_element|
29
- condition.treating_provider < import_actor(provider_element)
32
+ if @provider_xpath
33
+ entry_element.xpath(@provider_xpath).each do |provider_element|
34
+ condition.treating_provider << import_actor(provider_element)
35
+ end
30
36
  end
31
37
 
32
38
  condition_list << condition
@@ -38,7 +44,7 @@ module HealthDataStandards
38
44
  private
39
45
 
40
46
  def extract_cause_of_death(entry_element, condition)
41
- cod = entry_element.at_xpath("./cda:entryRelationship[@typeCode='CAUS']/cda:observation/cda:code[@code='419620001']")
47
+ cod = entry_element.at_xpath(@cod_xpath)
42
48
  condition.cause_of_death = cod.present?
43
49
  end
44
50
 
@@ -8,7 +8,8 @@ module HealthDataStandards
8
8
  @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.127']/cda:entry/cda:encounter"
9
9
  @code_xpath = "./cda:code"
10
10
  @status_xpath = "./cda:statusCode"
11
- @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
11
+ @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value]"
12
+ @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:act"
12
13
  @check_for_usable = true # Pilot tools will set this to false
13
14
  @id_map = {}
14
15
  end
@@ -23,22 +24,27 @@ module HealthDataStandards
23
24
  encounter_list = []
24
25
  entry_elements = doc.xpath(@entry_xpath)
25
26
  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)
27
+ encounter = create_entry(entry_element, id_map={})
30
28
  if @check_for_usable
31
29
  encounter_list << encounter if encounter.usable?
32
30
  else
33
31
  encounter_list << encounter
34
32
  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
33
  end
40
34
  encounter_list
41
35
  end
36
+
37
+ def create_entry(entry_element, id_map={})
38
+ encounter = Encounter.new
39
+ extract_codes(entry_element, encounter)
40
+ extract_dates(entry_element, encounter)
41
+ extract_description(entry_element, encounter, id_map)
42
+ extract_performer(entry_element, encounter)
43
+ extract_facility(entry_element, encounter)
44
+ extract_reason(entry_element, encounter, id_map)
45
+ extract_admission(entry_element, encounter)
46
+ encounter
47
+ end
42
48
 
43
49
  private
44
50
 
@@ -58,7 +64,7 @@ module HealthDataStandards
58
64
  end
59
65
 
60
66
  def extract_reason(parent_element, encounter, id_map)
61
- reason_element = parent_element.at_xpath("./cda:entryRelationship[@typeCode='RSON']/cda:act")
67
+ reason_element = parent_element.at_xpath(@reason_xpath)
62
68
  if reason_element
63
69
  reason = Entry.new
64
70
  extract_codes(reason_element, reason)
@@ -7,7 +7,7 @@ module HealthDataStandards
7
7
  @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.117']/cda:entry/cda:substanceAdministration"
8
8
  @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
9
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"
10
+ @refusal_reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.1.27']/cda:code"
11
11
  @check_for_usable = true # Pilot tools will set this to false
12
12
  end
13
13
 
@@ -42,7 +42,7 @@ module HealthDataStandards
42
42
  unless negation_indicator.nil?
43
43
  immunization.refusal_ind = negation_indicator.eql?('true')
44
44
  if immunization.refusal_ind
45
- refusal_reason_element = parent_element.at_xpath(@refusal_resason_xpath)
45
+ refusal_reason_element = parent_element.at_xpath(@refusal_reason_xpath)
46
46
  if refusal_reason_element
47
47
  immunization.refusal_reason = {'code' => refusal_reason_element['code'],
48
48
  'codeSystem' => 'HL7 No Immunization Reason'}
@@ -0,0 +1,42 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module C32
4
+ class InsuranceProviderImporter < SectionImporter
5
+
6
+ def initialize
7
+ @entry_xpath = "//cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.1.26']"
8
+ end
9
+
10
+ def create_entries(doc, id_map={})
11
+ doc.xpath(@entry_xpath).map do |payer_element|
12
+ ip = InsuranceProvider.new
13
+ ip.type = extract_code(payer_element, "./cda:code")
14
+ ip.payer = import_organization(payer_element.at_xpath("./cda:performer/cda:assignedEntity"))
15
+ ip.guarantors = extract_guarantors(payer_element.xpath("./cda:performer/cda:assignedEntity"))
16
+ ip.subscriber = import_person(payer_element.at_xpath("./cda:participant[@typeCode='HLD']/cda:participantRole"))
17
+ member_info_element = payer_element.at_xpath("cda:participant[@typeCode='COV']")
18
+ extract_dates(member_info_element, ip, "time")
19
+ name = payer_element.at_xpath("./cda:entryRelationship[@typeCode='REFR']/cda:act[@classCode='ACT' and @moodCode='DEF']/cda:text")
20
+ ip.name = name.try(:text)
21
+ patient_element = member_info_element.at_xpath("./cda:participantRole[@classCode='PAT']")
22
+ ip.member_id = patient_element.at_xpath("./cda:id")
23
+ ip.relationship = extract_code(patient_element, "./cda:code")
24
+ ip.financial_responsibility_type = extract_code(payer_element, "./cda:performer/cda:assignedEntity/cda:code")
25
+ end
26
+ end
27
+
28
+ def extract_guarantors(guarantor_elements)
29
+ guarantor_elements.map do |guarantor_element|
30
+ guarantor = Guarantor.new
31
+ guarantor.person = import_person(guarantor_element.at_xpath("./cda:assignedPerson"))
32
+ guarantor.organization = import_organization(guarantor_element.at_xpath("./cda:representedOrganization"))
33
+ extract_dates(guarantor_element, guarantor, element_name="time")
34
+ guarantor
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,45 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module C32
4
+ class MedicalEquipmentImporter < SectionImporter
5
+
6
+ def initialize
7
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.128']/cda:entry/cda:supply"
8
+ @code_xpath = "./cda:participant/cda:participantRole/cda:playingDevice/cda:code"
9
+ @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value]"
10
+ @check_for_usable = true
11
+ end
12
+
13
+ def create_entries(doc,id_map = {})
14
+ entry_list = []
15
+ entry_elements = doc.xpath(@entry_xpath)
16
+ entry_elements.each do |entry_element|
17
+ entry = create_entry(entry_element, id_map)
18
+ if @check_for_usable
19
+ entry_list << entry if entry.usable?
20
+ else
21
+ entry_list << entry
22
+ end
23
+ end
24
+ entry_list
25
+ end
26
+
27
+ def create_entry(entry_element, id_map={})
28
+ entry = MedicalEquipment.new
29
+ extract_codes(entry_element, entry)
30
+ extract_dates(entry_element, entry)
31
+ extract_value(entry_element, entry)
32
+
33
+ extract_description(entry_element, entry, id_map)
34
+ extract_manufacturer(entry_element, entry)
35
+ entry
36
+ end
37
+
38
+ def extract_manufacturer(entry_element, entry)
39
+ manufacturer = entry_element.at_xpath("./cda:participant/cda:participantRole/cda:scopingEntity/cda:desc").try(:inner_text)
40
+ entry.manufacturer = manufacturer.strip if manufacturer
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -16,57 +16,42 @@ module HealthDataStandards
16
16
  @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.112']/cda:entry/cda:substanceAdministration"
17
17
  @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
18
18
  @description_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code/cda:originalText/cda:reference[@value]"
19
-
19
+ @type_of_med_xpath = "./cda:entryRelationship[@typeCode='SUBJ']/cda:observation[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.8.1']/cda:code"
20
+ @indication_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.28']/cda:code"
21
+ @vehicle_xpath = "cda:participant/cda:participantRole[cda:code/@code='412307009' and cda:code/@codeSystem='2.16.840.1.113883.6.96']/cda:playingEntity/cda:code"
22
+ @fill_number_xpath = "./cda:entryRelationship[@typeCode='COMP']/cda:sequenceNumber/@value"
20
23
  @check_for_usable = true # Pilot tools will set this to false
21
24
  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
25
 
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
67
- end
26
+ def create_entry(entry_element, id_map={})
27
+ medication = Medication.new
28
+ extract_codes(entry_element, medication)
29
+ extract_dates(entry_element, medication)
30
+ extract_description(entry_element, medication, id_map)
31
+
32
+ if medication.description.present?
33
+ medication.free_text = medication.description
68
34
  end
69
- medication_list
35
+
36
+ extract_administration_timing(entry_element, medication)
37
+
38
+ medication.route = extract_code(entry_element, "./cda:routeCode")
39
+ medication.dose = extract_scalar(entry_element, "./cda:doseQuantity")
40
+ medication.site = extract_code(entry_element, "./cda:approachSiteCode", 'SNOMED-CT')
41
+
42
+ extract_dose_restriction(entry_element, medication)
43
+
44
+ medication.product_form = extract_code(entry_element, "./cda:administrationUnitCode", 'NCI Thesaurus')
45
+ medication.delivery_method = extract_code(entry_element, "./cda:code", 'SNOMED-CT')
46
+ medication.type_of_medication = extract_code(entry_element, @type_of_med_xpath, 'SNOMED-CT') if @type_of_med_xpath
47
+ medication.indication = extract_code(entry_element, @indication_xpath, 'SNOMED-CT')
48
+ medication.vehicle = extract_code(entry_element, @vehicle_xpath, 'SNOMED-CT')
49
+
50
+ extract_order_information(entry_element, medication)
51
+
52
+ extract_fulfillment_history(entry_element, medication)
53
+
54
+ medication
70
55
  end
71
56
 
72
57
  private
@@ -84,7 +69,8 @@ module HealthDataStandards
84
69
  hl7_timestamp = fh_element.at_xpath('./cda:effectiveTime').try(:[], 'value')
85
70
  fulfillment_history.dispense_date = HL7Helper.timestamp_to_integer(hl7_timestamp) if hl7_timestamp
86
71
  fulfillment_history.quantity_dispensed = extract_scalar(fh_element, "./cda:quantity")
87
- fulfillment_history.fill_number = fh_element.at_xpath("./cda:entryRelationship[@typeCode='COMP']/cda:sequenceNumber").try(:[], 'value').to_i
72
+ fill_number = fh_element.at_xpath(@fill_number_xpath).try(:text)
73
+ fulfillment_history.fill_number = fill_number.to_i if fill_number
88
74
  medication.fulfillmentHistory << fulfillment_history
89
75
  end
90
76
  end
@@ -128,6 +114,7 @@ module HealthDataStandards
128
114
  medication.dose_restriction = dr
129
115
  end
130
116
  end
117
+
131
118
  end
132
119
  end
133
120
  end
@@ -11,7 +11,7 @@ module HealthDataStandards
11
11
  def extract_organization(org_element)
12
12
  return unless org_element
13
13
  org = Organization.new
14
- org.name = org_element.at_xpath("./name").try(:text)
14
+ org.name = org_element.at_xpath("./cda:name | ./cda:representedOrganization/cda:name").try(:text)
15
15
  org.addresses = org_element.xpath("./cda:addr").map { |addr| import_address(addr) }
16
16
  org.telecoms = org_element.xpath("./cda:telecom").map { |tele| import_telecom(tele) }
17
17
  org
@@ -61,11 +61,11 @@ module HealthDataStandards
61
61
  @section_importers[:medications] = MedicationImporter.new
62
62
  @section_importers[:conditions] = ConditionImporter.new
63
63
  @section_importers[:social_history] = SectionImporter.new("//cda:observation[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.19']")
64
- @section_importers[:care_goals] = SectionImporter.new("//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.25']")
65
- @section_importers[:medical_equipment] = SectionImporter.new("//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.128']/cda:entry/cda:supply",
66
- "./cda:participant/cda:participantRole/cda:playingDevice/cda:code")
64
+ @section_importers[:care_goals] = CareGoalImporter.new
65
+ @section_importers[:medical_equipment] = MedicalEquipmentImporter.new
67
66
  @section_importers[:allergies] = AllergyImporter.new
68
67
  @section_importers[:immunizations] = ImmunizationImporter.new
68
+ @section_importers[:insurance_providers] = InsuranceProviderImporter.new
69
69
  end
70
70
 
71
71
  def build_id_map(doc)
@@ -6,9 +6,8 @@ module HealthDataStandards
6
6
  class ProcedureImporter < SectionImporter
7
7
 
8
8
  def initialize
9
- @entry_xpath = "//cda:procedure[cda:templateId/@root='2.16.840.1.113883.10.20.1.29']"
9
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.1.12']/cda:entry/cda:procedure"
10
10
  @code_xpath = "./cda:code"
11
- @status_xpath = "./cda:statusCode"
12
11
  @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
13
12
  @check_for_usable = true # Pilot tools will set this to false
14
13
  end
@@ -23,20 +22,25 @@ module HealthDataStandards
23
22
  procedure_list = []
24
23
  entry_elements = doc.xpath(@entry_xpath)
25
24
  entry_elements.each do |entry_element|
26
- procedure = Procedure.new
27
- extract_codes(entry_element, procedure)
28
- extract_dates(entry_element, procedure)
29
- extract_description(entry_element, procedure, id_map)
25
+ procedure = create_entry(entry_element, id_map)
30
26
  if @check_for_usable
31
27
  procedure_list << procedure if procedure.usable?
32
28
  else
33
29
  procedure_list << procedure
34
30
  end
35
- extract_performer(entry_element, procedure)
36
- extract_site(entry_element, procedure)
37
31
  end
38
32
  procedure_list
39
33
  end
34
+
35
+ def create_entry(entry_element, id_map={})
36
+ procedure = Procedure.new
37
+ extract_codes(entry_element, procedure)
38
+ extract_dates(entry_element, procedure)
39
+ extract_description(entry_element, procedure, id_map)
40
+ extract_performer(entry_element, procedure)
41
+ extract_site(entry_element, procedure)
42
+ procedure
43
+ end
40
44
 
41
45
  private
42
46
 
@@ -5,7 +5,6 @@ module HealthDataStandards
5
5
  def initialize
6
6
  @entry_xpath = "//cda:observation[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.15.1'] | //cda:observation[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.15']"
7
7
  @code_xpath = "./cda:code"
8
- @status_xpath = "./cda:statusCode"
9
8
  @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
10
9
  @check_for_usable = true # Pilot tools will set this to false
11
10
  end
@@ -20,13 +19,7 @@ module HealthDataStandards
20
19
  result_list = []
21
20
  entry_elements = doc.xpath(@entry_xpath)
22
21
  entry_elements.each do |entry_element|
23
- result = LabResult.new
24
- extract_codes(entry_element, result)
25
- extract_dates(entry_element, result)
26
- extract_value(entry_element, result)
27
- extract_status(entry_element, result)
28
- extract_description(entry_element, result, id_map)
29
- extract_interpretation(entry_element, result)
22
+ result = create_entry(entry_element, id_map)
30
23
  if @check_for_usable
31
24
  result_list << result if result.usable?
32
25
  else
@@ -35,6 +28,16 @@ module HealthDataStandards
35
28
  end
36
29
  result_list
37
30
  end
31
+
32
+ def create_entry(entry_element, id_map={})
33
+ result = LabResult.new
34
+ extract_codes(entry_element, result)
35
+ extract_dates(entry_element, result)
36
+ extract_value(entry_element, result)
37
+ extract_description(entry_element, result, id_map)
38
+ extract_interpretation(entry_element, result)
39
+ result
40
+ end
38
41
 
39
42
  private
40
43
  def extract_interpretation(parent_element, result)
@@ -46,12 +49,6 @@ module HealthDataStandards
46
49
  end
47
50
  end
48
51
 
49
- def extract_status(parent_element, result)
50
- status_code_element = parent_element.at_xpath(@status_xpath)
51
- if status_code_element
52
- result.status = status_code_element['code']
53
- end
54
- end
55
52
  end
56
53
  end
57
54
  end