health-data-standards 2.1.4 → 2.2.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.
@@ -69,6 +69,7 @@ require_relative 'health-data-standards/models/metadata/change_info'
69
69
  require_relative 'health-data-standards/models/metadata/link_info'
70
70
  require_relative 'health-data-standards/models/metadata/pedigree'
71
71
 
72
+ require_relative 'health-data-standards/import/c32/locatable_import_utils'
72
73
  require_relative 'health-data-standards/import/c32/section_importer'
73
74
  require_relative 'health-data-standards/import/c32/allergy_importer'
74
75
  require_relative 'health-data-standards/import/c32/encounter_importer'
@@ -3,12 +3,15 @@ module HealthDataStandards
3
3
  module TemplateHelper
4
4
  attr_accessor :template_format
5
5
  attr_accessor :template_subdir
6
+ attr_accessor :template_directory
6
7
 
7
8
  def template_root
9
+ @template_directory ||= File.dirname(__FILE__)
10
+
8
11
  if @template_subdir
9
- return File.join(File.dirname(__FILE__), '..', '..', '..', 'templates', @template_subdir)
12
+ return File.join(@template_directory, '..', '..', '..', 'templates', @template_subdir)
10
13
  else
11
- return File.join(File.dirname(__FILE__), '..', '..', '..', 'templates')
14
+ return File.join(@template_directory, '..', '..', '..', 'templates')
12
15
  end
13
16
  end
14
17
 
@@ -33,6 +36,7 @@ module HealthDataStandards
33
36
  rendering_context = RenderingContext.new(locals)
34
37
  rendering_context.template_format = self.template_format
35
38
  rendering_context.template_subdir = self.template_subdir
39
+ rendering_context.template_directory = self.template_directory
36
40
  eruby = Erubis::EscapedEruby.new(erb)
37
41
  eruby.result(rendering_context.my_binding)
38
42
  end
@@ -99,6 +99,51 @@ module HealthDataStandards
99
99
  end
100
100
  end
101
101
 
102
+ def convert_field_to_hash(field, codes)
103
+ if (codes.is_a? Hash)
104
+ clean_hash = {}
105
+
106
+ if codes['codeSystem']
107
+ if codes['title']
108
+ clean_hash[codes['codeSystem']] = codes['code'] + " (#{codes['title']})"
109
+ else
110
+ clean_hash[codes['codeSystem']] = codes['code']
111
+ end
112
+ elsif codes['_id']
113
+ codes.keys.reject {|key| ['_id'].include? key}.each do |hashkey|
114
+ value = codes[hashkey]
115
+ if value.nil?
116
+ clean_hash[hashkey.titleize] = 'none'
117
+ elsif value.is_a? Hash
118
+ hash_result = convert_field_to_hash(hashkey, value)
119
+ if hash_result.is_a? Hash
120
+ clean_hash[hashkey.titleize] = hash_result.map {|key, value| "#{key}: #{value}"}.join(' ')
121
+ else
122
+ clean_hash[hashkey.titleize] = hash_result
123
+ end
124
+ elsif value.is_a? Array
125
+ clean_hash[hashkey.titleize] = value.join(', ')
126
+ else
127
+ clean_hash[hashkey.titleize] = convert_field_to_hash(hashkey, value)
128
+ end
129
+ end
130
+ elsif codes['scalar']
131
+ return "#{codes['scalar']} #{codes['units']}"
132
+ else
133
+ return codes.map {|hashcode_set, hashcodes| "#{hashcode_set}: #{(hashcodes.respond_to? :join) ? hashcodes.join(', ') : hashcodes.to_s}"}.join(' ')
134
+ end
135
+
136
+ clean_hash
137
+ else
138
+ if codes && (field.match(/Time$/) || field.match(/\_time$/))
139
+ Entry.time_to_s(codes)
140
+ else
141
+ codes.to_s
142
+ end
143
+ end
144
+ end
145
+
146
+
102
147
  end
103
148
  end
104
149
  end
@@ -49,11 +49,7 @@ module HealthDataStandards
49
49
  def extract_ordinality(parent_element, entry)
50
50
  ordinality_element = parent_element.at_xpath(@ordinality_xpath)
51
51
  if ordinality_element
52
- entry.ordinality_code = {CodeSystemHelper.code_system_for(ordinality_element['codeSystem']) => [ordinality_element['code']]}
53
- case ordinality_element['code']
54
- when '8319008'
55
- entry.ordinality = :principal
56
- end
52
+ entry.ordinality = {CodeSystemHelper.code_system_for(ordinality_element['codeSystem']) => [ordinality_element['code']]}
57
53
  end
58
54
  end
59
55
 
@@ -0,0 +1,27 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module C32
4
+ # Helpers for importing C32 addresses and telecoms
5
+ module LocatableImportUtils
6
+ def import_address(address_element)
7
+ address = Address.new
8
+ address.use = address_element['use']
9
+ address.street = address_element.xpath("./cda:streetAddressLine").map {|street| street.text}
10
+ address.city = address_element.at_xpath("./cda:city").try(:text)
11
+ address.state = address_element.at_xpath("./cda:state").try(:text)
12
+ address.zip = address_element.at_xpath("./cda:postalCode").try(:text)
13
+ address.country = address_element.at_xpath("./cda:country").try(:text)
14
+ address
15
+ end
16
+
17
+ def import_telecom(telecom_element)
18
+ tele = Telecom.new
19
+ tele.value = telecom_element['value']
20
+ tele.use = telecom_element['use']
21
+ tele
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -11,6 +11,7 @@ module HealthDataStandards
11
11
 
12
12
  include Singleton
13
13
  include HealthDataStandards::Util
14
+ include HealthDataStandards::Import::C32::LocatableImportUtils
14
15
 
15
16
  # Creates a new PatientImporter with the following XPath expressions used to find content in
16
17
  # a HITSP C32:
@@ -150,10 +151,16 @@ module HealthDataStandards
150
151
  patient.race = { code: race_node['code'], code_set: 'CDC-RE' } if race_node
151
152
  ethnicity_node = patient_element.at_xpath('cda:ethnicGroupCode')
152
153
  patient.ethnicity = {code: ethnicity_node['code'], code_set: 'CDC-RE'} if ethnicity_node
153
-
154
154
  languages = patient_element.search('languageCommunication').map {|lc| lc.at_xpath('cda:languageCode')['code'] }
155
155
  patient.languages = languages unless languages.empty?
156
156
 
157
+ # parse address information
158
+ patient.addresses = doc.xpath('/cda:ClinicalDocument/cda:recordTarget/cda:patientRole/cda:addr').map do |addr_element|
159
+ import_address(addr_element)
160
+ end
161
+ patient.telecoms = doc.xpath('/cda:ClinicalDocument/cda:recordTarget/cda:patientRole/cda:telecom').map do |tele|
162
+ import_telecom(tele)
163
+ end
157
164
  end
158
165
  end
159
166
  end
@@ -4,6 +4,7 @@ module HealthDataStandards
4
4
  # Class that can be used to create an importer for a section of a HITSP C32 document. It usually
5
5
  # operates by selecting all CDA entries in a section and then creates entries for them.
6
6
  class SectionImporter
7
+ include HealthDataStandards::Import::C32::LocatableImportUtils
7
8
  include HealthDataStandards::Util
8
9
 
9
10
  attr_accessor :check_for_usable
@@ -157,23 +158,6 @@ module HealthDataStandards
157
158
  return person
158
159
  end
159
160
 
160
- def import_address(address_element)
161
- address = Address.new
162
- address.street = [address_element.at_xpath("./cda:streetAddressLine").try(:text)]
163
- address.city = address_element.at_xpath("./cda:city").try(:text)
164
- address.state = address_element.at_xpath("./cda:state").try(:text)
165
- address.zip = address_element.at_xpath("./cda:postalCode").try(:text)
166
- address.country = address_element.at_xpath("./cda:country").try(:text)
167
- address
168
- end
169
-
170
- def import_telecom(telecom_element)
171
- tele = Telecom.new
172
- tele.value = telecom_element['value']
173
- tele.use = telecom_element['use']
174
- tele
175
- end
176
-
177
161
  def extract_negation(parent_element, entry)
178
162
  negation_indicator = parent_element['negationInd']
179
163
  unless negation_indicator.nil?
@@ -6,6 +6,7 @@ class Address
6
6
  field :state, type: String
7
7
  field :zip, type: String
8
8
  field :country, type: String
9
+ field :use, type: String
9
10
 
10
11
  embedded_in :locatable, polymorphic: true
11
12
  end
@@ -3,8 +3,7 @@ class Condition < Entry
3
3
  field :causeOfDeath, type: Boolean
4
4
  field :priority, type: Integer
5
5
  field :name, type: String
6
- field :ordinality, type: String
7
- field :ordinality_code, type: Hash
6
+ field :ordinality, type: Hash
8
7
  field :severity, type: Hash # Currently unsupported by any importers
9
8
 
10
9
  embeds_many :treating_provider, class_name: "Provider"
@@ -1,18 +1,26 @@
1
1
  class Encounter < Entry
2
-
3
2
  field :admitType, type: Hash
4
3
  field :dischargeDisposition, type: Hash
5
- field :admit_time, type: Integer
6
- field :discharge_time, type: Integer
4
+ field :admitTime, type: Integer
5
+ field :dischargeTime, type: Integer
6
+ field :transferTo, type: Hash
7
+ field :transferFrom, type: Hash
7
8
 
8
9
  embeds_one :facility
9
10
  embeds_one :reason, class_name: "Entry"
10
11
 
11
12
  belongs_to :performer, class_name: "Provider"
12
13
 
14
+ alias :admit_time :admitTime
15
+ alias :admit_time= :admitTime=
13
16
  alias :admit_type :admitType
14
17
  alias :admit_type= :admitType=
15
18
  alias :discharge_disposition :dischargeDisposition
16
19
  alias :discharge_disposition= :dischargeDisposition=
17
-
20
+ alias :discharge_time :dischargeTime
21
+ alias :discharge_time= :dischargeTime=
22
+ alias :transfer_to :transferTo
23
+ alias :transfer_to= :transferTo=
24
+ alias :transfer_from :transferFrom
25
+ alias :transfer_from= :transferFrom=
18
26
  end
@@ -20,6 +20,7 @@ class Entry
20
20
  field :negationInd, type: Boolean
21
21
  field :negationReason, type: Hash
22
22
  field :oid, type: String
23
+ field :reason, type: Hash
23
24
 
24
25
  alias :negation_ind :negationInd
25
26
  alias :negation_ind= :negationInd=
@@ -33,14 +34,18 @@ class Entry
33
34
 
34
35
  def times_to_s(nil_string='UNK')
35
36
  if start_time.present? || end_time.present?
36
- start_string = start_time ? Time.at(start_time).utc.to_formatted_s(:long_ordinal) : nil_string
37
- end_string = end_time ? Time.at(end_time).utc.to_formatted_s(:long_ordinal) : nil_string
37
+ start_string = start_time ? Entry.time_to_s(start_time) : nil_string
38
+ end_string = end_time ? Entry.time_to_s(end_time) : nil_string
38
39
  "#{start_string} - #{end_string}"
39
40
  elsif time.present?
40
41
  Time.at(time).utc.to_formatted_s(:long_ordinal)
41
42
  end
42
43
  end
43
44
 
45
+ def self.time_to_s(input_time)
46
+ Time.at(input_time).utc.to_formatted_s(:long_ordinal)
47
+ end
48
+
44
49
  # Entry previously had a status field that dropped the code set and converted
45
50
  # the status to a String. Entry now preserves the original code and code set.
46
51
  # This method is here to maintain backwards compatibility.
@@ -69,8 +74,8 @@ class Entry
69
74
  self.status_code = {'SNOMED-CT' => ['73425007']}
70
75
  when 'resolved'
71
76
  self.status_code = {'SNOMED-CT' => ['413322009']}
72
- when 'completed'
73
- self.status_code = {'HL7 ActStatus' => ['completed']}
77
+ else
78
+ self.status_code = {'HL7 ActStatus' => [status_text]}
74
79
  end
75
80
  end
76
81
 
@@ -105,6 +110,8 @@ class Entry
105
110
 
106
111
  # Checks if a code is in the list of possible codes
107
112
  # @param [Array] code_set an Array of Hashes that describe the values for code sets
113
+ # The hash has a key of "set" for the code system name and "values"
114
+ # for the actual code list
108
115
  # @return [true, false] whether the code is in the list of desired codes
109
116
  def is_in_code_set?(code_set)
110
117
  codes.keys.each do |code_system|
@@ -2,7 +2,10 @@ class MedicalEquipment < Entry
2
2
 
3
3
  field :manufacturer, type: String
4
4
  field :anatomicalStructure, type: Hash
5
+ field :removalTime, type: Integer
5
6
 
6
7
  alias :anatomical_structure :anatomicalStructure
7
8
  alias :anatomical_structure= :anatomicalStructure=
9
+ alias :removal_time :removalTime
10
+ alias :removal_time= :removalTime=
8
11
  end
@@ -1,11 +1,11 @@
1
1
  class Procedure < Entry
2
- field :site, type: Hash
3
- field :incisionDateTime, type: Integer
4
- field :ordinality, type: String
5
- field :ordinality_code, type: Hash
2
+ field :site, type: Hash
3
+ field :incisionTime, type: Integer
4
+ field :ordinality, type: Hash
5
+ field :source, type: Hash
6
6
 
7
7
  belongs_to :performer, class_name: "Provider"
8
8
 
9
- alias :incision_date_time :incisionDateTime
10
- alias :incision_date_time= :incisionDateTime=
9
+ alias :incision_time :incisionTime
10
+ alias :incision_time= :incisionTime=
11
11
  end
@@ -41,6 +41,8 @@ class Record
41
41
  :insurance_providers, :functional_statuses]
42
42
 
43
43
  embeds_many :provider_performances
44
+ embeds_many :addresses, as: :locatable
45
+ embeds_many :telecoms, as: :contactable
44
46
 
45
47
  scope :by_provider, ->(prov, effective_date) { (effective_date) ? where(provider_queries(prov.id, effective_date)) : where('provider_performances.provider_id'=>prov.id) }
46
48
  scope :by_patient_id, ->(id) { where(:medical_record_number => id) }
@@ -57,7 +59,7 @@ class Record
57
59
  matching_entries_by_section = Sections.map do |section|
58
60
  section_entries = self.send(section)
59
61
  if section_entries.present?
60
- section_entries.find_all { |entry| entry.oid == oid }
62
+ section_entries.find_all { |entry| (entry.respond_to? :oid) ? entry.oid == oid : false}
61
63
  else
62
64
  []
63
65
  end
@@ -2,28 +2,72 @@ module HealthDataStandards
2
2
  module SVS
3
3
  class ValueSet
4
4
 
5
- include Mongoid::Document
5
+ include Mongoid::Document
6
6
  field :oid, type: String
7
7
  field :display_name, type: String
8
8
  field :version, type: String
9
9
 
10
+ index({oid: 1})
11
+ index({display_name: 1})
10
12
  embeds_many :concepts
13
+ index "concepts.code" => 1
14
+ index "concepts.code_system" => 1
15
+ index "concepts.code_system_name" => 1
16
+ index "concepts.display_name" => 1
17
+
11
18
  scope :by_oid, ->(oid){where(:oid => oid)}
12
19
 
20
+ # Provides an Array of Hashes. Each code system gets its own Hash
21
+ # The hash has a key of "set" for the code system name and "values"
22
+ # for the actual code list
23
+ def code_set_map
24
+ codes = []
25
+ self.concepts.inject({}) do |memo, concept|
26
+ memo[concept.code_system_name] ||= []
27
+ memo[concept.code_system_name] << concept.code
28
+ memo
29
+ end.each_pair do |code_set, code_list|
30
+ codes << {"set" => code_set, "values" => code_list}
31
+ end
32
+
33
+ codes
34
+ end
35
+
13
36
  def self.load_from_xml(doc)
14
- doc.root.add_namespace_definition("vs","urn:ihe:iti:svs:2008")
15
- vs_element = doc.at_xpath("/vs:RetrieveValueSetResponse/vs:ValueSet")
16
- if vs_element
17
- vs = ValueSet.new(oid: vs_element["ID"], display_name: vs_element["displayName"], version: vs_element["version"])
18
- concepts = vs_element.xpath("//vs:Concept").collect do |con|
19
- Concept.new(code: con["code"],
20
- code_system_name: con["codeSystemName"],
21
- code_system_version: con["code_system_version"],
22
- display_name: con["displayName"],code_system: con["codeSystem"])
23
- end
24
- vs.concepts = concepts
25
- return vs
26
- end
37
+ doc.root.add_namespace_definition("vs","urn:ihe:iti:svs:2008")
38
+ vs_element = doc.at_xpath("/vs:RetrieveValueSetResponse/vs:ValueSet")
39
+ if vs_element
40
+ vs = ValueSet.new(oid: vs_element["ID"], display_name: vs_element["displayName"], version: vs_element["version"])
41
+ concepts = vs_element.xpath("//vs:Concept").collect do |con|
42
+ Concept.new(code: con["code"],
43
+ code_system_name: normalize_code_set_name(con["codeSystemName"]),
44
+ code_system_version: con["code_system_version"],
45
+ display_name: con["displayName"], code_system: con["codeSystem"])
46
+ end
47
+ vs.concepts = concepts
48
+ return vs
49
+ end
50
+ end
51
+
52
+ def self.normalize_code_set_name(code_set_name)
53
+ case code_set_name
54
+ when 'RXNORM'
55
+ 'RxNorm'
56
+ when 'ICD9CM'
57
+ 'ICD-9-CM'
58
+ when 'ICD10CM'
59
+ 'ICD-10-CM'
60
+ when 'ICD10PCS'
61
+ 'ICD-10-PCS'
62
+ when 'SNOMEDCT'
63
+ 'SNOMED-CT'
64
+ when 'CDCREC'
65
+ 'CDC Race'
66
+ when 'HSLOC'
67
+ 'HL7 Healthcare Service Location'
68
+ else
69
+ code_set_name
70
+ end
27
71
  end
28
72
  end
29
73
  end
@@ -14,7 +14,7 @@ module ThingWithCodes
14
14
  def self.convert_codes_to_s(codes)
15
15
  codes.map {|code_set, codes| "#{code_set}: #{codes.join(', ')}"}.join(' ')
16
16
  end
17
-
17
+
18
18
  # Will return a single code and code set if one exists in the code sets that are
19
19
  # passed in. Returns a hash with a key of code and code_set if found, nil otherwise
20
20
  def preferred_code(preferred_code_sets, codes_attribute=:codes)
@@ -9,7 +9,8 @@ module HealthDataStandards
9
9
  #'2.16.840.1.113883.3.88.12.80.32' => 'CPT', # Encounter Type from C32, a subset of CPT
10
10
  '2.16.840.1.113883.6.88' => 'RxNorm',
11
11
  '2.16.840.1.113883.6.103' => 'ICD-9-CM',
12
- '2.16.840.1.113883.6.104' => 'ICD-9-CM',
12
+ '2.16.840.1.113883.6.104' => 'ICD-9-PCS',
13
+ '2.16.840.1.113883.6.4' => 'ICD-10-PCS',
13
14
  '2.16.840.1.113883.6.90' => 'ICD-10-CM',
14
15
  '2.16.840.1.113883.6.14' => 'HCPCS',
15
16
  '2.16.840.1.113883.6.59' => 'CVX',
@@ -18,9 +19,16 @@ module HealthDataStandards
18
19
  '2.16.840.1.113883.3.88.12.80.20' => 'FDA',
19
20
  '2.16.840.1.113883.5.14' => 'HL7 ActStatus',
20
21
  '2.16.840.1.113883.6.259' => 'HL7 Healthcare Service Location',
22
+ '2.16.840.1.113883.12.112' => 'DischargeDisposition',
21
23
  '2.16.840.1.113883.5.4' => 'HL7 Act Code',
22
24
  '2.16.840.1.113883.1.11.18877' => 'HL7 Relationship Code',
23
- '2.16.840.1.113883.6.238' => 'CDC Race'
25
+ '2.16.840.1.113883.6.238' => 'CDC Race',
26
+ '2.16.840.1.113883.6.177' => 'NLM MeSH'
27
+ }
28
+
29
+ CODE_SYSTEM_ALIASES = {
30
+ 'FDA SPL' => 'NCI Thesaurus',
31
+ 'HSLOC' => 'HL7 Healthcare Service Location'
24
32
  }
25
33
 
26
34
  # Returns the name of a code system given an oid
@@ -34,6 +42,7 @@ module HealthDataStandards
34
42
  # @param [String] the name of the code system
35
43
  # @return [String] the oid of the code system
36
44
  def self.oid_for_code_system(code_system)
45
+ code_system = CODE_SYSTEM_ALIASES[code_system] if CODE_SYSTEM_ALIASES[code_system]
37
46
  CODE_SYSTEMS.invert[code_system]
38
47
  end
39
48
 
@@ -140,8 +140,8 @@
140
140
  "status":"resolved",
141
141
  "negation":false},
142
142
  "2.16.840.1.113883.3.560.1.32":{
143
- "definition":"diagnosis_family_history",
144
- "status":"",
143
+ "definition":"diagnosis",
144
+ "status":"family_history",
145
145
  "negation":false},
146
146
  "2.16.840.1.113883.3.560.1.23":{
147
147
  "definition":"diagnosis",
@@ -156,8 +156,8 @@
156
156
  "status":"resolved",
157
157
  "negation":true},
158
158
  "2.16.840.1.113883.3.560.1.132":{
159
- "definition":"diagnosis_family_history",
160
- "status":"",
159
+ "definition":"diagnosis",
160
+ "status":"family_history",
161
161
  "negation":true},
162
162
  "2.16.840.1.113883.3.560.1.123":{
163
163
  "definition":"diagnosis",
@@ -220,8 +220,8 @@
220
220
  "status":"ordered",
221
221
  "negation":false},
222
222
  "2.16.840.1.113883.3.560.1.199":{
223
- "definition":"medication_discharge",
224
- "status":"",
223
+ "definition":"medication",
224
+ "status":"discharge",
225
225
  "negation":false},
226
226
  "2.16.840.1.113883.3.560.1.13":{
227
227
  "definition":"medication",
@@ -275,10 +275,6 @@
275
275
  "definition":"medication",
276
276
  "status":"administered",
277
277
  "negation":true},
278
- "2.16.840.1.113883.3.560.1.19":{
279
- "definition":"physical_exam",
280
- "status":"",
281
- "negation":false},
282
278
  "2.16.840.1.113883.3.560.1.18":{
283
279
  "definition":"physical_exam",
284
280
  "status":"",
@@ -2,12 +2,12 @@
2
2
  if preferred_code
3
3
  code_system_oid = HealthDataStandards::Util::CodeSystemHelper.oid_for_code_system(preferred_code['code_set'])
4
4
  -%>
5
- <code code="<%= preferred_code['code'] %>" codeSystem="<%= code_system_oid %>" displayName="<%= entry.description %>">
5
+ <code code="<%= preferred_code['code'] %>" codeSystem="<%= code_system_oid %>" codeSystemName="<%= preferred_code['code_set'] %>" displayName="<%= entry.description %>">
6
6
  <% else -%>
7
7
  <code nullFlavor="UNK">
8
8
  <% end -%>
9
9
  <originalText><reference value="#<%= section %>-desc-<%= i %>"/></originalText>
10
10
  <% entry.translation_codes(preferred_code_sets).each do |translation| -%>
11
- <translation code="<%= translation['code'] %>" codeSystem="<%= HealthDataStandards::Util::CodeSystemHelper.oid_for_code_system(translation['code_set']) %>" />
11
+ <translation code="<%= translation['code'] %>" codeSystem="<%= HealthDataStandards::Util::CodeSystemHelper.oid_for_code_system(translation['code_set']) %>" codeSystemName="<%= translation['code_set'] %>"/>
12
12
  <% end -%>
13
13
  </code>
@@ -15,7 +15,7 @@
15
15
  <%
16
16
  matches = []
17
17
  codes.each do |code|
18
- matches.concat(concept_map[set][code].values)
18
+ matches.concat(concept_map[set][code].values) if concept_map[set][code]
19
19
  end
20
20
  %>
21
21
  <ul id="<%=entry.id%>_<%=set%>" style="display: none; position: absolute; background: #EEE; padding: 10px; padding-left: 30px; width: 600px; z-index: 3000;">
@@ -37,7 +37,7 @@
37
37
  <% value.codes.each do |system, vals| %>
38
38
  <%= system %>: <%= vals.join(',') %>
39
39
  <% end %>
40
- <%= (value.description ? "(#{value.description})" : "(UNKNOWN CODED VALUE)")%>
40
+ <%= (value.description ? "(#{value.description})" : '')%>
41
41
  <br/>
42
42
  <% else %>
43
43
  UNKNOWN VALUE
@@ -46,19 +46,22 @@
46
46
  </td>
47
47
  <td>
48
48
  <%
49
- (entry.attributes.keys.reject {|key| ['codes', 'time', 'description', 'mood_code', 'values', '_id', '_type', 'start_time', 'end_time', 'status_code', 'negationInd', 'negationReason', 'oid'].include? key}).each do |field|
50
- field_value = ThingWithCodes.convert_codes_to_s(entry.attributes[field]) rescue entry.attributes[field].to_s
49
+ (entry.attributes.keys.reject {|key| ['codes', 'time', 'description', 'mood_code', 'values', '_id', '_type', 'start_time', 'end_time', 'status_code', 'negationInd', 'oid'].include? key}).each do |field|
50
+ field_value = convert_field_to_hash(field, entry.attributes[field])
51
+
51
52
  %>
52
- <%= field %>: (<b><%= field_value %></b>)
53
- <%
54
- end
55
- if entry.negationInd
56
- negation_reason = ''
57
- if entry.negationReason
58
- negation_reason = ThingWithCodes.convert_codes_to_s(entry.negationReason) rescue entry.negationReason.to_s
59
- end
60
- %>
61
- negation: <%= negation_reason %>
53
+ <% if field_value && !field_value.empty? %>
54
+ <dl>
55
+ <% if field_value.is_a? Hash %>
56
+ <dt><b><%= field.titleize %>:</b></dt>
57
+ <% field_value.keys.each do |fieldkey| %>
58
+ <dd><%= fieldkey %>: <i><%= field_value[fieldkey] %></i></dd>
59
+ <% end %>
60
+ <% else %>
61
+ <dt><b><%= field.titleize %></b>: <%= field_value%></dt>
62
+ <% end %>
63
+ <dl>
64
+ <% end %>
62
65
  <%
63
66
  end
64
67
  %>
@@ -26,7 +26,29 @@
26
26
  </tr>
27
27
  <tr>
28
28
  <td bgcolor="#3399ff"><span class="td_label">Contact info</span></td>
29
- <td colspan="3"> Pirmary Home: 202 Burlington Rd. Bedford, MA 01730<br />Tel: +1-781-271-3000</td>
29
+ <td colspan="3">
30
+ <% if patient.addresses %>
31
+ <% patient.addresses.each do |addr| %>
32
+ <% addr.street.each do |street| %>
33
+ <%= "#{street}," %>
34
+ <% end %>
35
+ <%= "#{addr.city}, #{addr.state}, #{addr.zip}." %>
36
+ <% if addr.use %>
37
+ (<%= addr.use %>)
38
+ <% end %>
39
+ <br />
40
+ <% end %>
41
+ <% end %>
42
+ <% if patient.telecoms %>
43
+ <% patient.telecoms.each do |telecom| %>
44
+ <%= telecom.value %>
45
+ <% if telecom.use %>
46
+ (<%= telecom.use %>)
47
+ <% end %>
48
+ <br />
49
+ <% end %>
50
+ <% end %>
51
+ </td>
30
52
  </tr>
31
53
  </tbody>
32
54
  </table>
@@ -51,7 +73,7 @@
51
73
  <tr>
52
74
  <td bgcolor="#3399ff"><span class="td_label">Contact info</span></td>
53
75
  <td>
54
- <br />Tel: +1-781-271-3000<br />
76
+ Tel: +1-781-271-3000<br />
55
77
  </td>
56
78
  </tr>
57
79
  </tbody>
@@ -112,7 +112,6 @@
112
112
  <div>
113
113
  <h3><a href="#" onclick="toggle('table_by_encounter');" id="toggle_button">View By Encounter</a></h3>
114
114
  </div>
115
-
116
115
  <%== render :partial => 'entries_by_section', :locals => {patient: patient, concept_map: concept_map} %>
117
116
  <%== render :partial => 'entries_by_encounter', :locals => {patient: patient, concept_map: concept_map} %>
118
117
 
@@ -17,13 +17,20 @@
17
17
  <recordTarget>
18
18
  <patientRole>
19
19
  <id root="Cypress" extension="<%= patient.id %>"/>
20
- <addr use="HP">
21
- <streetAddressLine>202 Burlington Rd.</streetAddressLine>
22
- <city>Bedford</city>
23
- <state>MA</state>
24
- <postalCode>01730</postalCode>
20
+ <% patient.addresses.each do |address| %>
21
+ <addr <%= address.use ? "use='#{address.use}'" : "" %>>
22
+ <% address.street.each do |street| %>
23
+ <streetAddressLine><%= street %></streetAddressLine>
24
+ <% end %>
25
+ <city><%= address.city %></city>
26
+ <state><%= address.state %></state>
27
+ <postalCode><%= address.zip %></postalCode>
28
+ <country><%= address.country %></country>
25
29
  </addr>
26
- <telecom value="tel:+1-781-271-3000"/>
30
+ <% end %>
31
+ <% patient.telecoms.each do |telecom| %>
32
+ <telecom value='<%= telecom.value %>' <%= telecom.use ? "use='#{telecom.use}'" : "" %>/>
33
+ <% end %>
27
34
  <patient>
28
35
  <name>
29
36
  <given><%= patient.first %></given>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: health-data-standards
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.4
4
+ version: 2.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2012-11-15 00:00:00.000000000 Z
15
+ date: 2012-12-19 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rest-client
@@ -53,7 +53,7 @@ dependencies:
53
53
  requirements:
54
54
  - - ~>
55
55
  - !ruby/object:Gem::Version
56
- version: 3.0.6
56
+ version: 3.0.14
57
57
  type: :runtime
58
58
  prerelease: false
59
59
  version_requirements: !ruby/object:Gem::Requirement
@@ -61,7 +61,23 @@ dependencies:
61
61
  requirements:
62
62
  - - ~>
63
63
  - !ruby/object:Gem::Version
64
- version: 3.0.6
64
+ version: 3.0.14
65
+ - !ruby/object:Gem::Dependency
66
+ name: activesupport
67
+ requirement: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ~>
71
+ - !ruby/object:Gem::Version
72
+ version: 3.2.9
73
+ type: :runtime
74
+ prerelease: false
75
+ version_requirements: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ~>
79
+ - !ruby/object:Gem::Version
80
+ version: 3.2.9
65
81
  - !ruby/object:Gem::Dependency
66
82
  name: uuid
67
83
  requirement: !ruby/object:Gem::Requirement
@@ -137,6 +153,7 @@ files:
137
153
  - lib/health-data-standards/import/c32/encounter_importer.rb
138
154
  - lib/health-data-standards/import/c32/immunization_importer.rb
139
155
  - lib/health-data-standards/import/c32/insurance_provider_importer.rb
156
+ - lib/health-data-standards/import/c32/locatable_import_utils.rb
140
157
  - lib/health-data-standards/import/c32/medical_equipment_importer.rb
141
158
  - lib/health-data-standards/import/c32/medication_importer.rb
142
159
  - lib/health-data-standards/import/c32/organization_importer.rb