health-data-standards 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +6 -0
- data/README.md +38 -0
- data/Rakefile +7 -0
- data/VERSION +1 -0
- data/lib/health-data-standards.rb +15 -0
- data/lib/health-data-standards/export/c32.rb +14 -0
- data/lib/health-data-standards/export/ccr.rb +375 -0
- data/lib/health-data-standards/export/rendering_context.rb +14 -0
- data/lib/health-data-standards/export/template_helper.rb +35 -0
- data/lib/health-data-standards/export/view_helper.rb +35 -0
- data/lib/health-data-standards/models/entry.rb +51 -0
- data/lib/health-data-standards/models/record.rb +21 -0
- data/templates/_allergies.c32.erb +57 -0
- data/templates/_care_goals.c32.erb +24 -0
- data/templates/_code_with_reference.c32.erb +8 -0
- data/templates/_conditions.c32.erb +61 -0
- data/templates/_encounters.c32.erb +28 -0
- data/templates/_immunizations.c32.erb +41 -0
- data/templates/_medical_equipment.c32.erb +34 -0
- data/templates/_medications.c32.erb +40 -0
- data/templates/_narrative_block.c32.erb +20 -0
- data/templates/_procedures.c32.erb +29 -0
- data/templates/_results.c32.erb +59 -0
- data/templates/_social_history.c32.erb +26 -0
- data/templates/_vital_signs.c32.erb +48 -0
- data/templates/show.c32.erb +103 -0
- metadata +127 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
This is a project to generate and consume HITSP C32, ASTM CCR and PQRI
|
2
|
+
|
3
|
+
Environment
|
4
|
+
===========
|
5
|
+
|
6
|
+
This project currently uses Ruby 1.9.2 and is built using [Bundler](http://gembundler.com/). To get all of the dependencies for the project, first install bundler:
|
7
|
+
|
8
|
+
gem install bundler
|
9
|
+
|
10
|
+
Then run bundler to grab all of the necessary gems:
|
11
|
+
|
12
|
+
bundle install
|
13
|
+
|
14
|
+
The Quality Measure engine relies on a MongoDB [MongoDB](http://www.mongodb.org/) running a minimum of version 1.8.* or higher. To get and install Mongo refer to:
|
15
|
+
|
16
|
+
http://www.mongodb.org/display/DOCS/Quickstart
|
17
|
+
|
18
|
+
Project Practices
|
19
|
+
=================
|
20
|
+
|
21
|
+
Please try to follow our [Coding Style Guides](http://github.com/eedrummer/styleguide). Additionally, we will be using git in a pattern similar to [Vincent Driessen's workflow](http://nvie.com/posts/a-successful-git-branching-model/). While feature branches are encouraged, they are not required to work on the project.
|
22
|
+
|
23
|
+
License
|
24
|
+
=======
|
25
|
+
|
26
|
+
Copyright 2011 The MITRE Corporation
|
27
|
+
|
28
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
29
|
+
you may not use this file except in compliance with the License.
|
30
|
+
You may obtain a copy of the License at
|
31
|
+
|
32
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
33
|
+
|
34
|
+
Unless required by applicable law or agreed to in writing, software
|
35
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
36
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
37
|
+
See the License for the specific language governing permissions and
|
38
|
+
limitations under the License.
|
data/Rakefile
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'erubis'
|
2
|
+
require 'active_support'
|
3
|
+
require 'mongoid'
|
4
|
+
require 'uuid'
|
5
|
+
require 'quality-measure-engine'
|
6
|
+
require 'builder'
|
7
|
+
|
8
|
+
require_relative 'health-data-standards/export/template_helper'
|
9
|
+
require_relative 'health-data-standards/export/view_helper'
|
10
|
+
require_relative 'health-data-standards/export/rendering_context'
|
11
|
+
require_relative 'health-data-standards/export/c32'
|
12
|
+
require_relative 'health-data-standards/export/ccr'
|
13
|
+
|
14
|
+
require_relative 'health-data-standards/models/entry'
|
15
|
+
require_relative 'health-data-standards/models/record'
|
@@ -0,0 +1,375 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Export
|
3
|
+
module CCR
|
4
|
+
# Builds a CCR XML document representing the patient.
|
5
|
+
#
|
6
|
+
# @return [Builder::XmlMarkup] CCR XML representation of patient data
|
7
|
+
def export(patient)
|
8
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
9
|
+
xml.ContinuityOfCareRecord("xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
|
10
|
+
"xsi:schemaLocation" => "urn:astm-org:CCR CCR_20051109.xsd http://www.w3.org/2001/XMLSchema xmldsig-core-schema.xsd",
|
11
|
+
"xmlns" => "urn:astm-org:CCR") do
|
12
|
+
xml.CCRDocumentObjectID(patient.id)
|
13
|
+
xml.Language do
|
14
|
+
xml.Text("English")
|
15
|
+
end
|
16
|
+
xml.Version("V1.0")
|
17
|
+
xml.DateTime do
|
18
|
+
#TODO: Need to fix this and not be a hard-coded value
|
19
|
+
xml.ExactDateTime(Time.now.xmlschema)
|
20
|
+
end
|
21
|
+
xml.Patient do
|
22
|
+
xml.ActorID(patient.id)
|
23
|
+
end
|
24
|
+
xml.From do
|
25
|
+
xml.ActorLink do
|
26
|
+
xml.ActorID("AA0002")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
to_ccr_purpose(xml)
|
30
|
+
xml.body do
|
31
|
+
to_ccr_problems(xml, patient)
|
32
|
+
to_ccr_vitals(xml, patient)
|
33
|
+
to_ccr_results(xml, patient)
|
34
|
+
to_ccr_encounters(xml, patient)
|
35
|
+
to_ccr_medications(xml, patient)
|
36
|
+
to_ccr_immunizations(xml, patient)
|
37
|
+
to_ccr_procedures(xml, patient)
|
38
|
+
to_ccr_allergies(xml, patient)
|
39
|
+
end
|
40
|
+
to_ccr_actors(xml, patient)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
extend self
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def code_section(xml, codes)
|
49
|
+
xml.Code do
|
50
|
+
if codes.present?
|
51
|
+
codes.each_pair do |code_set, coded_values|
|
52
|
+
coded_values.each do |coded_value|
|
53
|
+
xml.Value(coded_value)
|
54
|
+
xml.CodingSystem(code_set)
|
55
|
+
#TODO: Need to fix this and not be a hard-coded value
|
56
|
+
xml.Version("2005")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def active_status_and_source(xml, patient)
|
64
|
+
xml.Status do
|
65
|
+
xml.Text("Active")
|
66
|
+
end
|
67
|
+
xml.Source do
|
68
|
+
xml.Actor do
|
69
|
+
xml.ActorID(patient.id)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Builds the XML snippet for the problems section inside the CCR standard
|
75
|
+
#
|
76
|
+
# @return [Builder::XmlMarkup] CCR XML representation of patient data
|
77
|
+
def to_ccr_problems(xml, patient)
|
78
|
+
if patient.conditions.present?
|
79
|
+
xml.Problems do
|
80
|
+
patient.conditions.each_with_index do |condition, index|
|
81
|
+
xml.Problem do
|
82
|
+
xml.CCRDataObjectID("PR000#{index + 1}")
|
83
|
+
xml.DateTime do
|
84
|
+
xml.Type do
|
85
|
+
xml.Text("Start date")
|
86
|
+
end
|
87
|
+
#time
|
88
|
+
xml.ExactDateTime(convert_to_ccr_time_string(condition.time))
|
89
|
+
end
|
90
|
+
xml.Type do
|
91
|
+
#TODO: Need to fix this and not be a hard-coded value
|
92
|
+
xml.Text("Diagnosis")
|
93
|
+
end
|
94
|
+
xml.Description do
|
95
|
+
xml.Text(condition.description)
|
96
|
+
code_section(xml, condition.codes)
|
97
|
+
end
|
98
|
+
active_status_and_source(xml, patient)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Builds the XML snippet for the encounters section inside the CCR standard
|
106
|
+
#
|
107
|
+
# @return [Builder::XmlMarkup] CCR XML representation of patient data
|
108
|
+
def to_ccr_encounters(xml, patient)
|
109
|
+
if patient.encounters.present?
|
110
|
+
xml.Encounters do
|
111
|
+
patient.encounters.each_with_index do |encounter, index|
|
112
|
+
xml.Encounter do
|
113
|
+
xml.CCRDataObjectID("EN000#{index + 1}")
|
114
|
+
xml.DateTime do
|
115
|
+
xml.Type do
|
116
|
+
xml.Text("Encounter Date")
|
117
|
+
end
|
118
|
+
#time
|
119
|
+
xml.ExactDateTime(convert_to_ccr_time_string(encounter.time))
|
120
|
+
end
|
121
|
+
xml.Description do
|
122
|
+
xml.Text(encounter.description)
|
123
|
+
code_section(xml, encounter.codes)
|
124
|
+
end
|
125
|
+
active_status_and_source(xml, patient)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Builds the XML snippet for the vitals section inside the CCR standard
|
133
|
+
#
|
134
|
+
# @return [Builder::XmlMarkup] CCR XML representation of patient data
|
135
|
+
def to_ccr_vitals(xml, patient)
|
136
|
+
if patient.vital_signs.present?
|
137
|
+
xml.VitalSigns do
|
138
|
+
patient.vital_signs.each_with_index do |vital_sign, index|
|
139
|
+
xml.Result do
|
140
|
+
xml.CCRDataObjectID("VT000#{index + 1}")
|
141
|
+
xml.DateTime do
|
142
|
+
xml.Type do
|
143
|
+
xml.Text("Start date")
|
144
|
+
end
|
145
|
+
#time
|
146
|
+
xml.ExactDateTime(convert_to_ccr_time_string(vital_sign.time))
|
147
|
+
end
|
148
|
+
xml.Description do
|
149
|
+
xml.Text(vital_sign.description)
|
150
|
+
code_section(xml, vital_sign.codes)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Builds the XML snippet for the medications section inside the CCR standard
|
159
|
+
#
|
160
|
+
# @return [Builder::XmlMarkup] CCR XML representation of patient data
|
161
|
+
def to_ccr_medications(xml, patient)
|
162
|
+
if patient.medications.present?
|
163
|
+
xml.Medications do
|
164
|
+
patient.medications.each_with_index do |medication, index|
|
165
|
+
xml.Medication do
|
166
|
+
xml.CCRDataObjectID("MD000#{index + 1}")
|
167
|
+
xml.DateTime do
|
168
|
+
xml.Type do
|
169
|
+
xml.Text("Prescription Date")
|
170
|
+
end
|
171
|
+
#time
|
172
|
+
xml.ExactDateTime(convert_to_ccr_time_string(medication.time))
|
173
|
+
end
|
174
|
+
xml.Type do
|
175
|
+
xml.Text("Medication")
|
176
|
+
end
|
177
|
+
active_status_and_source(xml, patient)
|
178
|
+
xml.Product do
|
179
|
+
xml.ProductName do
|
180
|
+
xml.Text(medication.description)
|
181
|
+
end
|
182
|
+
xml.BrandName do
|
183
|
+
xml.Text(medication.description)
|
184
|
+
code_section(xml, medication.codes)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Builds the XML snippet for the medications section inside the CCR standard
|
194
|
+
#
|
195
|
+
# @return [Builder::XmlMarkup] CCR XML representation of patient data
|
196
|
+
def to_ccr_immunizations(xml, patient)
|
197
|
+
if patient.immunizations.present?
|
198
|
+
xml.Immunizations do
|
199
|
+
patient.immunizations.each_with_index do |immunization, index|
|
200
|
+
xml.Immunization do
|
201
|
+
xml.CCRDataObjectID("IM000#{index + 1}")
|
202
|
+
xml.DateTime do
|
203
|
+
xml.Type do
|
204
|
+
xml.Text("Prescription Date")
|
205
|
+
end
|
206
|
+
#time
|
207
|
+
xml.ExactDateTime(convert_to_ccr_time_string(immunization.time))
|
208
|
+
end
|
209
|
+
xml.Type do
|
210
|
+
xml.Text("Immunization")
|
211
|
+
end
|
212
|
+
active_status_and_source(xml, patient)
|
213
|
+
xml.Product do
|
214
|
+
xml.ProductName do
|
215
|
+
xml.Text(immunization.description)
|
216
|
+
end
|
217
|
+
xml.BrandName do
|
218
|
+
xml.Text(immunization.description)
|
219
|
+
code_section(xml, immunization.codes)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Builds the XML snippet for the lab section inside the CCR standard
|
229
|
+
#
|
230
|
+
# @return [Builder::XmlMarkup] CCR XML representation of patient data
|
231
|
+
def to_ccr_results(xml, patient)
|
232
|
+
if patient.results.present?
|
233
|
+
xml.Results do
|
234
|
+
patient.results.each_with_index do |lab_result, index|
|
235
|
+
xml.Result do
|
236
|
+
xml.CCRDataObjectID("LB000#{index + 1}")
|
237
|
+
xml.DateTime do
|
238
|
+
xml.Type do
|
239
|
+
xml.Text("Start date")
|
240
|
+
end
|
241
|
+
#time
|
242
|
+
xml.ExactDateTime(convert_to_ccr_time_string(lab_result.time))
|
243
|
+
end
|
244
|
+
xml.Description do
|
245
|
+
xml.Text(lab_result.description)
|
246
|
+
code_section(xml, lab_result.codes)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
# Builds the XML snippet for the procedures section inside the CCR standard
|
255
|
+
#
|
256
|
+
# @return [Builder::XmlMarkup] CCR XML representation of patient data
|
257
|
+
def to_ccr_procedures(xml, patient)
|
258
|
+
if patient.procedures.present?
|
259
|
+
xml.Procedures do
|
260
|
+
patient.procedures.each_with_index do |procedure, index|
|
261
|
+
xml.Procedure do
|
262
|
+
xml.CCRDataObjectID("PR000#{index + 1}")
|
263
|
+
xml.DateTime do
|
264
|
+
xml.Type do
|
265
|
+
xml.Text("Service date")
|
266
|
+
end
|
267
|
+
#time
|
268
|
+
xml.ExactDateTime(convert_to_ccr_time_string(procedure.time))
|
269
|
+
end
|
270
|
+
xml.Description do
|
271
|
+
xml.Text(procedure.description)
|
272
|
+
code_section(xml, procedure.codes)
|
273
|
+
end
|
274
|
+
xml.Status do
|
275
|
+
xml.Text("Active")
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def to_ccr_allergies(xml, patient)
|
284
|
+
if patient.allergies.present?
|
285
|
+
xml.Alerts do
|
286
|
+
patient.allergies.each_with_index do |allergy, index|
|
287
|
+
xml.Alert do
|
288
|
+
xml.CCRDataObjectID("AL000#{index + 1}")
|
289
|
+
xml.DateTime do
|
290
|
+
xml.Type do
|
291
|
+
xml.Text("Initial Occurrence")
|
292
|
+
end
|
293
|
+
#time
|
294
|
+
xml.ExactDateTime(convert_to_ccr_time_string(allergy.time))
|
295
|
+
end
|
296
|
+
xml.Type do
|
297
|
+
xml.Text("Allergy")
|
298
|
+
end
|
299
|
+
xml.Description do
|
300
|
+
xml.Text(allergy.description)
|
301
|
+
code_section(xml, allergy.codes)
|
302
|
+
end
|
303
|
+
xml.Status do
|
304
|
+
xml.Text("Current")
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
# Builds the XML snippet for a actors section inside the CCR standard
|
313
|
+
#
|
314
|
+
# @return [Builder::XmlMarkup] CCR XML representation of patient data
|
315
|
+
def to_ccr_actors(xml, patient)
|
316
|
+
xml.Actors do
|
317
|
+
xml.Actor do
|
318
|
+
xml.ActorObjectID("AA0001")
|
319
|
+
xml.Person do
|
320
|
+
xml.Name do
|
321
|
+
xml.CurrentName do
|
322
|
+
xml.Given(patient.first)
|
323
|
+
xml.Family(patient.last)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
xml.DateOfBirth do
|
328
|
+
xml.ExactDateTime(convert_to_ccr_time_string(patient.birthdate))
|
329
|
+
if (patient.gender)
|
330
|
+
xml.Gender do
|
331
|
+
if (patient.gender.upcase == "M")
|
332
|
+
xml.Text("Male")
|
333
|
+
elsif (patient.gender.upcase == "F")
|
334
|
+
xml.Text("Female")
|
335
|
+
else
|
336
|
+
xml.Text("Undifferentiated")
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
# Builds the XML snippet for a purpose section inside the CCR standard
|
346
|
+
#
|
347
|
+
# @return [Builder::XmlMarkup] CCR XML representation of patient data
|
348
|
+
def to_ccr_purpose(xml)
|
349
|
+
xml.Purpose do
|
350
|
+
xml.Description do
|
351
|
+
xml.Text("Cypress Test Patient CCR XML Record")
|
352
|
+
end
|
353
|
+
xml.Indications do
|
354
|
+
xml.Indication do
|
355
|
+
xml.Source do
|
356
|
+
xml.Actor do
|
357
|
+
xml.ActorID("AA0002")
|
358
|
+
end
|
359
|
+
end
|
360
|
+
xml.InternalCCRLink do
|
361
|
+
xml.LinkID
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
def convert_to_ccr_time_string(time)
|
369
|
+
converted_time = Time.at(time)
|
370
|
+
converted_time.strftime("%Y-%m-%dT%H:%M:%SZ")
|
371
|
+
end
|
372
|
+
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|