ncs_mdes 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ##
4
+ # A script to generate disposition_codes.yml from the MDES 2.2
5
+ # spreadsheet's Dispositions tab.
6
+ #
7
+ # This script requires the 'roo' gem, which is not included in
8
+ # ncs_mdes's gemspec because it has a huge number of dependencies and
9
+ # is not needed at runtime.
10
+
11
+ require 'rubygems'
12
+ require 'roo'
13
+ require 'yaml'
14
+
15
+ MDES_XLSX = ARGV.first or fail 'Please provide the path to the MDES spreadsheet'
16
+ TARGET = File.expand_path('../disposition_codes.yml', __FILE__)
17
+ SHEET_NAME = 'Dispositions'
18
+
19
+ MAPPED_COLUMNS = {
20
+ 'A' => 'final_category',
21
+ 'B' => 'sub_category',
22
+ 'C' => 'disposition'
23
+ }
24
+
25
+ def normalize_whitespace(s)
26
+ s.strip.gsub(/\s+/, " ")
27
+ end
28
+
29
+ book = Excelx.new(MDES_XLSX)
30
+
31
+ # This is the array of hashes that will eventually be serialized to
32
+ # disposition_codes.yml.
33
+ dispositions = []
34
+
35
+ current_event = nil
36
+ current_category_code = nil
37
+ 1.upto(book.last_row(SHEET_NAME)) do |row_number|
38
+ a, b = %w(A B).collect { |col| book.cell(row_number, col, SHEET_NAME) }
39
+ if a =~ /Category\s+(\d)\s+\((.*?)\)\s+Disposition\s+Codes/
40
+ current_event = normalize_whitespace $2
41
+ current_category_code = $1.to_i
42
+ puts "Collecting for category #{current_event} (#{current_category_code})"
43
+ elsif b =~ /\S/ && a !~ /FINAL/
44
+ disposition_hash = MAPPED_COLUMNS.inject({}) do |h, (col, key)|
45
+ h[key] = normalize_whitespace(book.cell(row_number, col, SHEET_NAME)); h
46
+ end
47
+ disposition_hash['event'] = current_event
48
+ disposition_hash['category_code'] = current_category_code
49
+ disposition_hash['interim_code'], disposition_hash['final_code'] =
50
+ normalize_whitespace(book.cell(row_number, 'D', SHEET_NAME)).split('/')
51
+
52
+ puts disposition_hash.inspect if disposition_hash['interim_code'] =~ /^02/
53
+ dispositions << disposition_hash
54
+ end
55
+ end
56
+
57
+ File.open(TARGET, 'w') { |f| f.write dispositions.to_yaml }
@@ -0,0 +1,452 @@
1
+ foreign_keys:
2
+ birth_visit:
3
+ new_address_id: address
4
+ mail_address_id: address
5
+ new_address_b_id: address
6
+
7
+ birth_visit_2:
8
+ new_address_id: address
9
+ mail_address_id: address
10
+ new_address_b_id: address
11
+
12
+ birth_visit_baby_name:
13
+ bv_id: birth_visit
14
+
15
+ birth_visit_baby_name_2:
16
+ bv_id: birth_visit_2
17
+
18
+ birth_visit_decorate_room:
19
+ bv_id: birth_visit
20
+
21
+ birth_visit_decorate_room_2:
22
+ bv_id: birth_visit_2
23
+
24
+ birth_visit_li:
25
+ new_address_id: address
26
+ mail_address_id: address
27
+ new_address_b_id: address
28
+
29
+ birth_visit_renovate_room:
30
+ bv_id: birth_visit
31
+
32
+ birth_visit_renovate_room_2:
33
+ bv_id: birth_visit_2
34
+
35
+ drf_therm_verification:
36
+ equip_id: env_equipment
37
+
38
+ eighteen_mth_mother:
39
+ c_addr1_id: address
40
+ c_addr2_id: address
41
+ r_p_id: participant
42
+
43
+ eighteen_mth_mother_2:
44
+ c_addr1_id: address
45
+ c_addr2_id: address
46
+ r_p_id: participant
47
+
48
+ eighteen_mth_mother_cond:
49
+ eighteen_mth_habits_id: eighteen_mth_mother_habits
50
+
51
+ eighteen_mth_mother_saq:
52
+ asq18_address_id: address
53
+ r_p_id: participant
54
+
55
+ env_equipment_prob_log:
56
+ equip_id: env_equipment
57
+ staff_id_reviewer: staff
58
+
59
+ event:
60
+ participant_id: participant
61
+
62
+ household_enumeration_hidden_du:
63
+ hdu_address_id: address
64
+
65
+ incident:
66
+ inc_staff_reporter_id: staff
67
+ inc_staff_supervisor_id: staff
68
+ inc_recip_is_participant: participant
69
+ inc_recip_is_du: dwelling_unit
70
+ inc_recip_is_staff: staff
71
+ inc_recip_is_family: person
72
+ inc_recip_is_acquaintance: person
73
+ inc_contact_person: person
74
+
75
+ nine_mth_mother:
76
+ r_p_id: participant
77
+
78
+ participant_consent:
79
+ person_who_consented_id: person
80
+ person_wthdrw_consent_id: person
81
+
82
+ participant_vis_consent:
83
+ vis_person_who_consented_id: person
84
+
85
+ participant_rvis:
86
+ rvis_person: person
87
+
88
+ pb_recruitment:
89
+ address_pb_id: address
90
+
91
+ pb_recruitment_2:
92
+ address_pb_id: address
93
+
94
+ pb_recruitment_info_source:
95
+ pb_recruitment_id: pb_recruitment
96
+
97
+ pb_recruitment_info_source_2:
98
+ pb_recruitment_id: pb_recruitment_2
99
+
100
+ pb_recruitment_prov_source:
101
+ pb_recruitment_id: pb_recruitment
102
+
103
+ pb_recruitment_prov_source_2:
104
+ pb_recruitment_id: pb_recruitment_2
105
+
106
+ pb_recruitment_prov_svc:
107
+ pb_recruitment_id: pb_recruitment
108
+
109
+ pb_recruitment_prov_svc_2:
110
+ pb_recruitment_id: pb_recruitment_2
111
+
112
+ person:
113
+ new_address_id: address
114
+
115
+ prec_therm_cert:
116
+ equip_id: env_equipment
117
+
118
+ pre_preg:
119
+ c_addr1_id: address
120
+ c_addr2_id: address
121
+
122
+ preg_screen_eh:
123
+ mail_address_id: address
124
+ new_address_id: address
125
+
126
+ preg_screen_eh_2:
127
+ mail_address_id: address
128
+ new_address_id: address
129
+
130
+ preg_screen_eh_know_ncs:
131
+ ps_eh_id: preg_screen_eh
132
+
133
+ preg_screen_eh_know_ncs_2:
134
+ ps_eh_id: preg_screen_eh_2
135
+
136
+ preg_screen_eh_race:
137
+ ps_eh_id: preg_screen_eh
138
+
139
+ preg_screen_eh_race_2:
140
+ ps_eh_id: preg_screen_eh_2
141
+
142
+ preg_screen_hi:
143
+ mail_address_id: address
144
+ new_address_id: address
145
+
146
+ preg_screen_hi_2:
147
+ mail_address_id: address
148
+ new_address_id: address
149
+
150
+ preg_screen_hi_know_ncs:
151
+ ps_hi_id: preg_screen_hi
152
+
153
+ preg_screen_hi_know_ncs_2:
154
+ ps_hi_id: preg_screen_hi_2
155
+
156
+ preg_screen_hi_race:
157
+ ps_hi_id: preg_screen_hi
158
+
159
+ preg_screen_hi_race_2:
160
+ ps_hi_id: preg_screen_hi_2
161
+
162
+ preg_screen_pb:
163
+ mail_address_id: address
164
+ new_address_id: address
165
+
166
+ preg_screen_pb_2:
167
+ mail_address_id: address
168
+ new_address_id: address
169
+
170
+ preg_screen_pb_know_ncs:
171
+ ps_pb_id: preg_screen_pb
172
+
173
+ preg_screen_pb_know_ncs_2:
174
+ ps_pb_id: preg_screen_pb_2
175
+
176
+ preg_screen_pb_race:
177
+ ps_pb_id: preg_screen_pb
178
+
179
+ preg_screen_pb_race_2:
180
+ ps_pb_id: preg_screen_pb_2
181
+
182
+ preg_visit_1:
183
+ b_address_id: address
184
+ c_addr1_id: address
185
+ c_addr2_id: address
186
+
187
+ preg_visit_1_2:
188
+ b_address_id: address
189
+ c_addr1_id: address
190
+ c_addr2_id: address
191
+
192
+ preg_visit_1_commute:
193
+ pv1_id: preg_visit_1
194
+
195
+ preg_visit_1_commute_2:
196
+ pv1_id: preg_visit_1_2
197
+
198
+ preg_visit_1_cool:
199
+ pv1_id: preg_visit_1
200
+
201
+ preg_visit_1_cool_2:
202
+ pv1_id: preg_visit_1_2
203
+
204
+ preg_visit_1_diagnose_2:
205
+ pv1_id: preg_visit_1
206
+
207
+ preg_visit_1_diagnose_2_2:
208
+ pv1_id: preg_visit_1_2
209
+
210
+ preg_visit_1_heat2:
211
+ pv1_id: preg_visit_1
212
+
213
+ preg_visit_1_heat2_2:
214
+ pv1_id: preg_visit_2
215
+
216
+ preg_visit_1_local_trav:
217
+ pv1_id: preg_visit_1
218
+
219
+ preg_visit_1_local_trav_2:
220
+ pv1_id: preg_visit_1_2
221
+
222
+ preg_visit_1_nonenglish2_2:
223
+ pv1_id: preg_visit_1_2
224
+
225
+ preg_visit_1_pdecorate_room:
226
+ pv1_id: preg_visit_1
227
+
228
+ preg_visit_1_pdecorate_room_2:
229
+ pv1_id: preg_visit_1_2
230
+
231
+ preg_visit_1_pet_type:
232
+ pv1_id: preg_visit_1
233
+
234
+ preg_visit_1_pet_type_2:
235
+ pv1_id: preg_visit_1_2
236
+
237
+ preg_visit_1_prenovate2_room:
238
+ pv1_id: preg_visit_1
239
+
240
+ preg_visit_1_prenovate_room:
241
+ pv1_id: preg_visit_1
242
+
243
+ preg_visit_1_prenovate_room_2:
244
+ pv1_id: preg_visit_1_2
245
+
246
+ preg_visit_1_room_mold:
247
+ pv1_id: preg_visit_1
248
+
249
+ preg_visit_1_room_mold_2:
250
+ pv1_id: preg_visit_1_2
251
+
252
+ preg_visit_1_saq_2:
253
+ f_addr_id: address
254
+
255
+ preg_visit_1_saq_3:
256
+ f_addr_id: address
257
+
258
+ preg_visit_1_sp_race:
259
+ pv1_id: preg_visit_1
260
+
261
+ preg_visit_1_sp_race_2:
262
+ pv1_id: preg_visit_1_2
263
+
264
+ preg_visit_2:
265
+ b_address_id: address
266
+ c_addr1_id: address
267
+ c_addr2_id: address
268
+
269
+ preg_visit_2_2:
270
+ b_address_id: address
271
+ c_addr1_id: address
272
+ c_addr2_id: address
273
+
274
+ preg_visit_2_cool:
275
+ pv2_id: preg_visit_2
276
+
277
+ preg_visit_2_cool_2:
278
+ pv2_id: preg_visit_2_2
279
+
280
+ preg_visit_2_diagnose_2:
281
+ pv2_id: preg_visit_2
282
+
283
+ preg_visit_2_diagnose_2_2:
284
+ pv2_id: preg_visit_2_2
285
+
286
+ preg_visit_2_heat2:
287
+ pv2_id: preg_visit_2
288
+
289
+ preg_visit_2_heat2_2:
290
+ pv2_id: preg_visit_2_2
291
+
292
+ preg_visit_2_pdecorate2_room:
293
+ pv2_id: preg_visit_2
294
+
295
+ preg_visit_2_pdecorate2_room_2:
296
+ pv2_id: preg_visit_2_2
297
+
298
+ preg_visit_2_prenovate_room:
299
+ pv2_id: preg_visit_2
300
+
301
+ preg_visit_2_prenovate_room_2:
302
+ pv2_id: preg_visit_2_2
303
+
304
+ preg_visit_2_room_mold:
305
+ pv2_id: preg_visit_2
306
+
307
+ preg_visit_2_room_mold_2:
308
+ pv2_id: preg_visit_2_2
309
+
310
+ preg_visit_li:
311
+ b_address_id: address
312
+
313
+ preg_visit_li_2:
314
+ b_address_id: address
315
+
316
+ preg_visit_li_cool:
317
+ pv_li_id: preg_visit_li
318
+
319
+ preg_visit_li_cool_2:
320
+ pv_li_id: preg_visit_li_2
321
+
322
+ ref_freezer_verification:
323
+ equip_id: env_equipment
324
+
325
+ sample_receipt_store:
326
+ equip_id: env_equipment
327
+
328
+ sample_shipping:
329
+ staff_id_track: staff
330
+
331
+ six_mth_mother:
332
+ c_addr1_id: address
333
+ c_addr2_id: address
334
+ r_p_id: participant
335
+
336
+ six_mth_saq_formula_type:
337
+ six_mth_saq_id: six_mth_saq
338
+
339
+ six_mth_saq_2:
340
+ r_p_id: participant
341
+
342
+ six_mth_saq_formula_type_2:
343
+ six_mth_saq_id: six_mth_saq_2
344
+
345
+ six_mth_saq_supp:
346
+ six_mth_saq_id: six_mth_saq
347
+
348
+ six_mth_saq_supp_2:
349
+ six_mth_saq_id: six_mth_saq_2
350
+
351
+ six_mth_saq_water:
352
+ six_mth_saq_id: six_mth_saq
353
+
354
+ six_mth_saq_water_2:
355
+ six_mth_saq_id: six_mth_saq_2
356
+
357
+ spec_blood:
358
+ # According to the corresponding instrument, equip_id is manually entered
359
+ # and not a reference to another table.
360
+ equip_id: false
361
+
362
+ spec_blood_2:
363
+ # According to the corresponding instrument, equip_id is manually entered
364
+ # and not a reference to another table.
365
+ equip_id: false
366
+
367
+ spec_cord_blood_specimen:
368
+ spec_cord_blood_id: spec_cord_blood
369
+
370
+ spec_cord_blood_specimen_2:
371
+ spec_cord_blood_id: spec_cord_blood_2
372
+
373
+ spec_receipt:
374
+ # Insufficient info to determine what this is supposed to link to
375
+ storage_container_id: false
376
+ equip_id: spec_equipment
377
+
378
+ spec_shipping:
379
+ # Insufficient info to determine what this is supposed to link to
380
+ shipper_id: false
381
+
382
+ spec_storage:
383
+ equip_id: spec_equipment
384
+
385
+ staff_exp_mngmnt_tasks:
386
+ staff_weekly_expense_id: staff_weekly_expense
387
+
388
+ staff_exp_data_cllctn_tasks:
389
+ staff_weekly_expense_id: staff_weekly_expense
390
+
391
+ three_mth_mother:
392
+ r_p_id: participant
393
+
394
+ trh_meter_calibration:
395
+ equip_id: spec_equipment
396
+
397
+ twelve_mth_mother:
398
+ c_addr1_id: address
399
+ c_addr2_id: address
400
+ r_p_id: participant
401
+
402
+ twelve_mth_saq_2:
403
+ r_p_id: participant
404
+
405
+ twelve_mth_saq_formula_brand:
406
+ twelve_mth_saq_id: twelve_mth_saq
407
+
408
+ twelve_mth_saq_formula_brand_2:
409
+ twelve_mth_saq_id: twelve_mth_saq_2
410
+
411
+ twelve_mth_saq_formula_type:
412
+ twelve_mth_saq_id: twelve_mth_saq
413
+
414
+ twelve_mth_saq_formula_type_2:
415
+ twelve_mth_saq_id: twelve_mth_saq_2
416
+
417
+ twelve_mth_saq_supplement:
418
+ twelve_mth_saq_id: twelve_mth_saq
419
+
420
+ twelve_mth_saq_supplement_2:
421
+ twelve_mth_saq_id: twelve_mth_saq_2
422
+
423
+ twelve_mth_saq_water:
424
+ twelve_mth_saq_id: twelve_mth_saq
425
+
426
+ twelve_mth_saq_water_2:
427
+ twelve_mth_saq_id: twelve_mth_saq_2
428
+
429
+ twenty_four_mth_mother:
430
+ c_addr1_id: address
431
+ c_addr2_id: address
432
+ r_p_id: participant
433
+
434
+ twenty_four_mth_mother_2:
435
+ c_addr1_id: address
436
+ c_addr2_id: address
437
+ r_p_id: participant
438
+
439
+ twenty_four_mth_mother_otc:
440
+ twenty_four_mth_mother_id: twenty_four_mth_mother
441
+
442
+ twenty_four_mth_mother_prescr:
443
+ twenty_four_mth_mother_id: twenty_four_mth_mother
444
+
445
+ twenty_four_mth_mother_suppl:
446
+ twenty_four_mth_mother_id: twenty_four_mth_mother
447
+
448
+ twenty_four_mth_saq:
449
+ asq24_address_id: address
450
+ r_p_id: participant
451
+
452
+
@@ -51,6 +51,10 @@ module NcsNavigator::Mdes
51
51
  create('1.2', '1.2/Data_Transmission_Schema_V1.2.xsd')
52
52
  when '2.0'
53
53
  create('2.0', '2.0/NCS_Transmission_Schema_2.0.01.02.xml', '2.0.01.02')
54
+ when '2.1'
55
+ create('2.1', '2.1/NCS_Transmission_Schema_2.1.00.00.xsd', '2.1.00.00')
56
+ when '2.2'
57
+ create('2.2', '2.2/NCS_Transmission_Schema_2.2.01.00.xsd', '2.2.01.00')
54
58
  else
55
59
  raise "MDES #{version} is not supported by this version of ncs_mdes"
56
60
  end
@@ -91,7 +91,7 @@ module NcsNavigator::Mdes
91
91
  tables.each { |t|
92
92
  fk_overrides = heuristic_overrides['foreign_keys'][t.name] || { }
93
93
  t.variables.each { |v|
94
- v.resolve_foreign_key!(tables, fk_overrides[v.name], :log => @log)
94
+ v.resolve_foreign_key!(tables, fk_overrides[v.name], :log => @log, :in_table => t)
95
95
  }
96
96
  }
97
97
  }
@@ -175,12 +175,13 @@ module NcsNavigator::Mdes
175
175
  # @return [void]
176
176
  def resolve_foreign_key!(tables, override_name=nil, options={})
177
177
  log = options[:log] || NcsNavigator::Mdes.default_logger
178
+ source_table = options[:in_table] ? options[:in_table].name : '[unspecified table]'
178
179
 
179
180
  case override_name
180
181
  when String
181
182
  self.table_reference = tables.detect { |t| t.name == override_name }
182
183
  unless table_reference
183
- log.warn("Foreign key #{name.inspect} explicitly mapped " <<
184
+ log.warn("Foreign key #{name.inspect} in #{source_table} explicitly mapped " <<
184
185
  "to unknown table #{override_name.inspect}.")
185
186
  end
186
187
  when nil
@@ -192,14 +193,15 @@ module NcsNavigator::Mdes
192
193
 
193
194
  case candidates.size
194
195
  when 0
195
- log.warn("Foreign key not resolvable: " <<
196
+ log.warn("Foreign key in #{source_table} not resolvable: " <<
196
197
  "no tables have a primary key named #{name.inspect}.")
197
198
  when 1
198
199
  self.table_reference = candidates.first
199
200
  else
200
201
  log.warn(
201
- "#{candidates.size} possible parent tables found for foreign key #{name.inspect}: " <<
202
- "#{candidates.collect { |c| c.name.inspect }.join(', ')}. None used due to ambiguity.")
202
+ "#{candidates.size} possible parent tables found for foreign key #{name.inspect} " <<
203
+ "in #{source_table}: #{candidates.collect { |c| c.name.inspect }.join(', ')}. " <<
204
+ "None used due to ambiguity.")
203
205
  end
204
206
  end
205
207
  end
@@ -1,5 +1,5 @@
1
1
  module NcsNavigator
2
2
  module Mdes
3
- VERSION = '0.5.0'
3
+ VERSION = '0.6.0'
4
4
  end
5
5
  end
@@ -72,23 +72,29 @@ module NcsNavigator::Mdes
72
72
  end
73
73
 
74
74
  describe '.get' do
75
- describe '1.2' do
76
- subject { SourceDocuments.get('1.2') }
77
-
78
- it 'has the correct path for the schema' do
79
- subject.schema.should =~ %r{1.2/Data_Transmission_Schema_V1.2.xsd$}
80
- end
75
+ shared_examples 'version docs' do
76
+ subject { SourceDocuments.get(version) }
81
77
 
82
78
  it 'has the correct path for the overrides' do
83
- subject.heuristic_overrides.should =~ %r{1.2/heuristic_overrides.yml$}
79
+ subject.heuristic_overrides.should =~ %r{#{version}/heuristic_overrides.yml$}
84
80
  end
85
81
 
86
82
  it 'has the correct path for the disposition codes' do
87
- subject.disposition_codes.should =~ %r{1.2/disposition_codes.yml$}
83
+ subject.disposition_codes.should =~ %r{#{version}/disposition_codes.yml$}
88
84
  end
89
85
 
90
86
  it 'is of the specified version' do
91
- subject.version.should == '1.2'
87
+ subject.version.should == version
88
+ end
89
+ end
90
+
91
+ describe '1.2' do
92
+ let(:version) { '1.2' }
93
+
94
+ include_context 'version docs'
95
+
96
+ it 'has the correct path for the schema' do
97
+ subject.schema.should =~ %r{1.2/Data_Transmission_Schema_V1.2.xsd$}
92
98
  end
93
99
 
94
100
  it 'has no more specific specification_version' do
@@ -97,26 +103,44 @@ module NcsNavigator::Mdes
97
103
  end
98
104
 
99
105
  describe '2.0' do
100
- subject { SourceDocuments.get('2.0') }
106
+ let(:version) { '2.0' }
107
+
108
+ include_context 'version docs'
101
109
 
102
110
  it 'has the correct path for the schema' do
103
111
  subject.schema.should =~ %r{2.0/NCS_Transmission_Schema_2.0.01.02.xml$}
104
112
  end
105
113
 
106
- it 'has the correct path for the overrides' do
107
- subject.heuristic_overrides.should =~ %r{2.0/heuristic_overrides.yml$}
114
+ it 'has a different specification_version' do
115
+ subject.specification_version.should == '2.0.01.02'
108
116
  end
117
+ end
109
118
 
110
- it 'has the correct path for the disposition codes' do
111
- subject.disposition_codes.should =~ %r{2.0/disposition_codes.yml$}
119
+ describe '2.1' do
120
+ let(:version) { '2.1' }
121
+
122
+ include_context 'version docs'
123
+
124
+ it 'has the correct path for the schema' do
125
+ subject.schema.should =~ %r{2.1/NCS_Transmission_Schema_2.1.00.00.xsd$}
112
126
  end
113
127
 
114
- it 'is of the specified version' do
115
- subject.version.should == '2.0'
128
+ it 'has a different specification_version' do
129
+ subject.specification_version.should == '2.1.00.00'
130
+ end
131
+ end
132
+
133
+ describe '2.2' do
134
+ let(:version) { '2.2' }
135
+
136
+ include_context 'version docs'
137
+
138
+ it 'has the correct path for the schema' do
139
+ subject.schema.should =~ %r{2.2/NCS_Transmission_Schema_2.2.01.00.xsd$}
116
140
  end
117
141
 
118
142
  it 'has a different specification_version' do
119
- subject.specification_version.should == '2.0.01.02'
143
+ subject.specification_version.should == '2.2.01.00'
120
144
  end
121
145
  end
122
146