health-data-standards 2.1.4 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/health-data-standards.rb +1 -0
- data/lib/health-data-standards/export/template_helper.rb +6 -2
- data/lib/health-data-standards/export/view_helper.rb +45 -0
- data/lib/health-data-standards/import/c32/condition_importer.rb +1 -5
- data/lib/health-data-standards/import/c32/locatable_import_utils.rb +27 -0
- data/lib/health-data-standards/import/c32/patient_importer.rb +8 -1
- data/lib/health-data-standards/import/c32/section_importer.rb +1 -17
- data/lib/health-data-standards/models/address.rb +1 -0
- data/lib/health-data-standards/models/condition.rb +1 -2
- data/lib/health-data-standards/models/encounter.rb +12 -4
- data/lib/health-data-standards/models/entry.rb +11 -4
- data/lib/health-data-standards/models/medical_equipment.rb +3 -0
- data/lib/health-data-standards/models/procedure.rb +6 -6
- data/lib/health-data-standards/models/record.rb +3 -1
- data/lib/health-data-standards/models/svs/value_set.rb +58 -14
- data/lib/health-data-standards/models/thing_with_codes.rb +1 -1
- data/lib/health-data-standards/util/code_system_helper.rb +11 -2
- data/lib/health-data-standards/util/hqmf_template_oid_map.json +6 -10
- data/templates/_code_with_reference.c32.erb +2 -2
- data/templates/html/_entry.html.erb +17 -14
- data/templates/html/_header.html.erb +24 -2
- data/templates/html/show.html.erb +0 -1
- data/templates/show.c32.erb +13 -6
- metadata +21 -4
@@ -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(
|
12
|
+
return File.join(@template_directory, '..', '..', '..', 'templates', @template_subdir)
|
10
13
|
else
|
11
|
-
return File.join(
|
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.
|
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?
|
@@ -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:
|
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 :
|
6
|
-
field :
|
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 ?
|
37
|
-
end_string = end_time ?
|
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
|
-
|
73
|
-
self.status_code = {'HL7 ActStatus' => [
|
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,
|
3
|
-
field :
|
4
|
-
field :ordinality, type:
|
5
|
-
field :
|
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 :
|
10
|
-
alias :
|
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
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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-
|
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":"
|
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":"
|
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":"
|
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})" :
|
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', '
|
50
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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">
|
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
|
-
|
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
|
|
data/templates/show.c32.erb
CHANGED
@@ -17,13 +17,20 @@
|
|
17
17
|
<recordTarget>
|
18
18
|
<patientRole>
|
19
19
|
<id root="Cypress" extension="<%= patient.id %>"/>
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
<
|
24
|
-
|
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
|
-
|
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.
|
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-
|
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.
|
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.
|
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
|