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.
- 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
|