health-data-standards 0.1.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/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
|