ccls-ccls_engine 3.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (269) hide show
  1. data/README.rdoc +182 -0
  2. data/app/models/abstract.rb +181 -0
  3. data/app/models/abstract_search.rb +50 -0
  4. data/app/models/abstract_validations.rb +324 -0
  5. data/app/models/address.rb +70 -0
  6. data/app/models/address_type.rb +15 -0
  7. data/app/models/addressing.rb +147 -0
  8. data/app/models/aliquot.rb +44 -0
  9. data/app/models/aliquot_sample_format.rb +13 -0
  10. data/app/models/analysis.rb +14 -0
  11. data/app/models/bc_request.rb +20 -0
  12. data/app/models/candidate_control.rb +101 -0
  13. data/app/models/context.rb +23 -0
  14. data/app/models/context_data_source.rb +4 -0
  15. data/app/models/county.rb +16 -0
  16. data/app/models/data_source.rb +24 -0
  17. data/app/models/diagnosis.rb +23 -0
  18. data/app/models/document_type.rb +16 -0
  19. data/app/models/document_version.rb +27 -0
  20. data/app/models/enrollment.rb +78 -0
  21. data/app/models/enrollment_validations.rb +167 -0
  22. data/app/models/follow_up.rb +16 -0
  23. data/app/models/follow_up_type.rb +18 -0
  24. data/app/models/gift_card.rb +22 -0
  25. data/app/models/gift_card_search.rb +137 -0
  26. data/app/models/home_exposure_response.rb +24 -0
  27. data/app/models/homex_outcome.rb +75 -0
  28. data/app/models/hospital.rb +22 -0
  29. data/app/models/icf_master_id.rb +30 -0
  30. data/app/models/icf_master_tracker.rb +217 -0
  31. data/app/models/icf_master_tracker_change.rb +9 -0
  32. data/app/models/icf_master_tracker_update.rb +50 -0
  33. data/app/models/ineligible_reason.rb +26 -0
  34. data/app/models/instrument.rb +26 -0
  35. data/app/models/instrument_type.rb +17 -0
  36. data/app/models/instrument_version.rb +28 -0
  37. data/app/models/interview.rb +122 -0
  38. data/app/models/interview_method.rb +17 -0
  39. data/app/models/interview_outcome.rb +16 -0
  40. data/app/models/language.rb +28 -0
  41. data/app/models/live_birth_data_update.rb +142 -0
  42. data/app/models/operational_event.rb +99 -0
  43. data/app/models/operational_event_type.rb +31 -0
  44. data/app/models/organization.rb +28 -0
  45. data/app/models/patient.rb +63 -0
  46. data/app/models/patient_validations.rb +118 -0
  47. data/app/models/person.rb +28 -0
  48. data/app/models/phone_number.rb +105 -0
  49. data/app/models/phone_type.rb +15 -0
  50. data/app/models/project.rb +39 -0
  51. data/app/models/project_outcome.rb +19 -0
  52. data/app/models/race.rb +31 -0
  53. data/app/models/refusal_reason.rb +23 -0
  54. data/app/models/sample.rb +168 -0
  55. data/app/models/sample_kit.rb +14 -0
  56. data/app/models/sample_outcome.rb +16 -0
  57. data/app/models/sample_temperature.rb +14 -0
  58. data/app/models/sample_type.rb +37 -0
  59. data/app/models/search.rb +195 -0
  60. data/app/models/section.rb +18 -0
  61. data/app/models/state.rb +25 -0
  62. data/app/models/study_subject.rb +237 -0
  63. data/app/models/study_subject_abstracts.rb +47 -0
  64. data/app/models/study_subject_addresses.rb +34 -0
  65. data/app/models/study_subject_associations.rb +38 -0
  66. data/app/models/study_subject_duplicates.rb +111 -0
  67. data/app/models/study_subject_enrollments.rb +17 -0
  68. data/app/models/study_subject_homex_outcome.rb +22 -0
  69. data/app/models/study_subject_identifier.rb +153 -0
  70. data/app/models/study_subject_interviews.rb +25 -0
  71. data/app/models/study_subject_languages.rb +21 -0
  72. data/app/models/study_subject_operational_events.rb +66 -0
  73. data/app/models/study_subject_patient.rb +177 -0
  74. data/app/models/study_subject_pii.rb +74 -0
  75. data/app/models/study_subject_races.rb +25 -0
  76. data/app/models/study_subject_search.rb +260 -0
  77. data/app/models/study_subject_validations.rb +116 -0
  78. data/app/models/subject_language.rb +11 -0
  79. data/app/models/subject_race.rb +11 -0
  80. data/app/models/subject_relationship.rb +21 -0
  81. data/app/models/subject_type.rb +22 -0
  82. data/app/models/tracing_status.rb +20 -0
  83. data/app/models/transfer.rb +40 -0
  84. data/app/models/unit.rb +14 -0
  85. data/app/models/vital_status.rb +19 -0
  86. data/app/models/zip_code.rb +36 -0
  87. data/config/abstract_fields.yml +1038 -0
  88. data/config/abstract_sections.yml +77 -0
  89. data/config/home_exposure_response_fields.yml +583 -0
  90. data/config/icf_master_tracker_update.yml +56 -0
  91. data/config/live_birth_data_update.yml +56 -0
  92. data/config/shared_use_db.yml +4 -0
  93. data/generators/ccls_engine/USAGE +2 -0
  94. data/generators/ccls_engine/ccls_engine_generator.rb +123 -0
  95. data/generators/ccls_engine/templates/autotest_ccls_engine.rb +3 -0
  96. data/generators/ccls_engine/templates/ccls_engine.rake +12 -0
  97. data/generators/ccls_engine/templates/fixtures/address_types.yml +30 -0
  98. data/generators/ccls_engine/templates/fixtures/context_data_sources.yml +54 -0
  99. data/generators/ccls_engine/templates/fixtures/contexts.yml +19 -0
  100. data/generators/ccls_engine/templates/fixtures/data_sources.yml +40 -0
  101. data/generators/ccls_engine/templates/fixtures/diagnoses.yml +40 -0
  102. data/generators/ccls_engine/templates/fixtures/document_types.yml +65 -0
  103. data/generators/ccls_engine/templates/fixtures/document_versions.csv +155 -0
  104. data/generators/ccls_engine/templates/fixtures/follow_up_types.yml +16 -0
  105. data/generators/ccls_engine/templates/fixtures/hospitals.yml +114 -0
  106. data/generators/ccls_engine/templates/fixtures/ineligible_reasons.yml +35 -0
  107. data/generators/ccls_engine/templates/fixtures/instrument_types.yml +26 -0
  108. data/generators/ccls_engine/templates/fixtures/instrument_versions.yml +22 -0
  109. data/generators/ccls_engine/templates/fixtures/instruments.yml +22 -0
  110. data/generators/ccls_engine/templates/fixtures/interview_methods.yml +30 -0
  111. data/generators/ccls_engine/templates/fixtures/interview_outcomes.yml +31 -0
  112. data/generators/ccls_engine/templates/fixtures/languages.yml +34 -0
  113. data/generators/ccls_engine/templates/fixtures/operational_event_types.yml +141 -0
  114. data/generators/ccls_engine/templates/fixtures/organizations.yml +198 -0
  115. data/generators/ccls_engine/templates/fixtures/people.yml +130 -0
  116. data/generators/ccls_engine/templates/fixtures/phone_types.yml +30 -0
  117. data/generators/ccls_engine/templates/fixtures/project_outcomes.yml +25 -0
  118. data/generators/ccls_engine/templates/fixtures/projects.yml +59 -0
  119. data/generators/ccls_engine/templates/fixtures/races.yml +52 -0
  120. data/generators/ccls_engine/templates/fixtures/refusal_reasons.yml +55 -0
  121. data/generators/ccls_engine/templates/fixtures/sample_outcomes.yml +36 -0
  122. data/generators/ccls_engine/templates/fixtures/sample_temperatures.yml +16 -0
  123. data/generators/ccls_engine/templates/fixtures/sample_types.yml +147 -0
  124. data/generators/ccls_engine/templates/fixtures/sections.yml +31 -0
  125. data/generators/ccls_engine/templates/fixtures/states.yml +363 -0
  126. data/generators/ccls_engine/templates/fixtures/subject_relationships.yml +46 -0
  127. data/generators/ccls_engine/templates/fixtures/subject_types.yml +30 -0
  128. data/generators/ccls_engine/templates/fixtures/tracing_statuses.yml +30 -0
  129. data/generators/ccls_engine/templates/fixtures/units.yml +13 -0
  130. data/generators/ccls_engine/templates/fixtures/vital_statuses.yml +28 -0
  131. data/generators/ccls_engine/templates/functional/roles_controller_test.rb +142 -0
  132. data/generators/ccls_engine/templates/functional/sessions_controller_test.rb +19 -0
  133. data/generators/ccls_engine/templates/functional/users_controller_test.rb +94 -0
  134. data/generators/ccls_engine/templates/images/sort_down.png +0 -0
  135. data/generators/ccls_engine/templates/images/sort_up.png +0 -0
  136. data/generators/ccls_engine/templates/initializer.rb +28 -0
  137. data/generators/ccls_engine/templates/javascripts/ccls_engine.js +24 -0
  138. data/generators/ccls_engine/templates/javascripts/jquery-ui.js +763 -0
  139. data/generators/ccls_engine/templates/javascripts/jquery.js +154 -0
  140. data/generators/ccls_engine/templates/javascripts/jrails.js +1 -0
  141. data/generators/ccls_engine/templates/migrations/create_user_invitations.rb +18 -0
  142. data/generators/ccls_engine/templates/migrations/create_users.rb +33 -0
  143. data/generators/ccls_engine/templates/migrations/drop_user_invitations.rb +18 -0
  144. data/generators/ccls_engine/templates/stylesheets/ccls_engine.css +180 -0
  145. data/generators/ccls_engine/templates/stylesheets/user.css +35 -0
  146. data/generators/ccls_engine/templates/stylesheets/users.css +23 -0
  147. data/generators/ccls_engine/templates/unit/core_extension_test.rb +18 -0
  148. data/generators/ccls_engine/templates/unit/role_test.rb +30 -0
  149. data/generators/ccls_engine/templates/unit/user_test.rb +321 -0
  150. data/lib/ccls-ccls_engine.rb +1 -0
  151. data/lib/ccls_engine.rb +135 -0
  152. data/lib/ccls_engine/action_view_extension.rb +3 -0
  153. data/lib/ccls_engine/action_view_extension/base.rb +53 -0
  154. data/lib/ccls_engine/action_view_extension/form_builder.rb +39 -0
  155. data/lib/ccls_engine/active_record_extension.rb +2 -0
  156. data/lib/ccls_engine/active_record_extension/base.rb +70 -0
  157. data/lib/ccls_engine/active_record_shared.rb +8 -0
  158. data/lib/ccls_engine/assertions.rb +69 -0
  159. data/lib/ccls_engine/autotest.rb +54 -0
  160. data/lib/ccls_engine/ccls_user.rb +117 -0
  161. data/lib/ccls_engine/core_extension.rb +14 -0
  162. data/lib/ccls_engine/date_and_time_formats.rb +30 -0
  163. data/lib/ccls_engine/factories.rb +880 -0
  164. data/lib/ccls_engine/factory_test_helper.rb +276 -0
  165. data/lib/ccls_engine/helper.rb +112 -0
  166. data/lib/ccls_engine/icf_master_tracker_update_test_helper.rb +121 -0
  167. data/lib/ccls_engine/live_birth_data_update_test_helper.rb +110 -0
  168. data/lib/ccls_engine/package_test_helper.rb +49 -0
  169. data/lib/ccls_engine/shared_database.rb +20 -0
  170. data/lib/ccls_engine/tasks.rb +1 -0
  171. data/lib/ccls_engine/test_tasks.rb +52 -0
  172. data/lib/ccls_engine/translation_table.rb +86 -0
  173. data/lib/shared_migration.rb +5 -0
  174. data/lib/surveyor/survey_extensions.rb +125 -0
  175. data/lib/tasks/application.rake +286 -0
  176. data/lib/tasks/calnet_authenticated.rake +6 -0
  177. data/lib/tasks/common_lib.rake +7 -0
  178. data/lib/tasks/database.rake +288 -0
  179. data/lib/tasks/documentation.rake +71 -0
  180. data/lib/tasks/homex_import.rake +723 -0
  181. data/lib/tasks/odms_import.rake +1116 -0
  182. data/lib/tasks/simply_authorized.rake +6 -0
  183. data/lib/tasks/ucb_ccls_engine_tasks.rake +4 -0
  184. data/lib/tasks/use_db.rake +4 -0
  185. data/rails/init.rb +4 -0
  186. data/test/unit/ccls/abstract_search_test.rb +150 -0
  187. data/test/unit/ccls/abstract_test.rb +674 -0
  188. data/test/unit/ccls/address_test.rb +155 -0
  189. data/test/unit/ccls/address_type_test.rb +25 -0
  190. data/test/unit/ccls/addressing_test.rb +466 -0
  191. data/test/unit/ccls/aliquot_sample_format_test.rb +20 -0
  192. data/test/unit/ccls/aliquot_test.rb +156 -0
  193. data/test/unit/ccls/analysis_test.rb +31 -0
  194. data/test/unit/ccls/bc_request_test.rb +43 -0
  195. data/test/unit/ccls/candidate_control_test.rb +712 -0
  196. data/test/unit/ccls/context_data_source_test.rb +26 -0
  197. data/test/unit/ccls/context_test.rb +40 -0
  198. data/test/unit/ccls/core_extension_test.rb +17 -0
  199. data/test/unit/ccls/county_test.rb +34 -0
  200. data/test/unit/ccls/data_source_test.rb +41 -0
  201. data/test/unit/ccls/diagnosis_test.rb +51 -0
  202. data/test/unit/ccls/document_type_test.rb +35 -0
  203. data/test/unit/ccls/document_version_test.rb +68 -0
  204. data/test/unit/ccls/enrollment_test.rb +575 -0
  205. data/test/unit/ccls/follow_up_test.rb +23 -0
  206. data/test/unit/ccls/follow_up_type_test.rb +34 -0
  207. data/test/unit/ccls/gift_card_search_test.rb +153 -0
  208. data/test/unit/ccls/gift_card_test.rb +40 -0
  209. data/test/unit/ccls/home_exposure_response_test.rb +83 -0
  210. data/test/unit/ccls/homex_outcome_test.rb +199 -0
  211. data/test/unit/ccls/hospital_test.rb +102 -0
  212. data/test/unit/ccls/icf_master_id_test.rb +30 -0
  213. data/test/unit/ccls/icf_master_tracker_change_test.rb +14 -0
  214. data/test/unit/ccls/icf_master_tracker_test.rb +132 -0
  215. data/test/unit/ccls/icf_master_tracker_update_test.rb +176 -0
  216. data/test/unit/ccls/ineligible_reason_test.rb +48 -0
  217. data/test/unit/ccls/instrument_test.rb +62 -0
  218. data/test/unit/ccls/instrument_type_test.rb +39 -0
  219. data/test/unit/ccls/instrument_version_test.rb +71 -0
  220. data/test/unit/ccls/interview_method_test.rb +44 -0
  221. data/test/unit/ccls/interview_outcome_test.rb +34 -0
  222. data/test/unit/ccls/interview_test.rb +298 -0
  223. data/test/unit/ccls/language_test.rb +47 -0
  224. data/test/unit/ccls/live_birth_data_update_test.rb +358 -0
  225. data/test/unit/ccls/operational_event_test.rb +187 -0
  226. data/test/unit/ccls/operational_event_type_test.rb +51 -0
  227. data/test/unit/ccls/organization_test.rb +64 -0
  228. data/test/unit/ccls/patient_test.rb +538 -0
  229. data/test/unit/ccls/person_test.rb +55 -0
  230. data/test/unit/ccls/phone_number_test.rb +244 -0
  231. data/test/unit/ccls/phone_type_test.rb +32 -0
  232. data/test/unit/ccls/project_outcome_test.rb +34 -0
  233. data/test/unit/ccls/project_test.rb +60 -0
  234. data/test/unit/ccls/race_test.rb +37 -0
  235. data/test/unit/ccls/refusal_reason_test.rb +52 -0
  236. data/test/unit/ccls/role_test.rb +26 -0
  237. data/test/unit/ccls/sample_kit_test.rb +35 -0
  238. data/test/unit/ccls/sample_outcome_test.rb +34 -0
  239. data/test/unit/ccls/sample_temperature_test.rb +25 -0
  240. data/test/unit/ccls/sample_test.rb +363 -0
  241. data/test/unit/ccls/sample_type_test.rb +58 -0
  242. data/test/unit/ccls/section_test.rb +34 -0
  243. data/test/unit/ccls/state_test.rb +31 -0
  244. data/test/unit/ccls/study_subject_abstracts_test.rb +115 -0
  245. data/test/unit/ccls/study_subject_addresses_test.rb +93 -0
  246. data/test/unit/ccls/study_subject_duplicates_test.rb +407 -0
  247. data/test/unit/ccls/study_subject_enrollments_test.rb +65 -0
  248. data/test/unit/ccls/study_subject_homex_outcome_test.rb +64 -0
  249. data/test/unit/ccls/study_subject_identifier_test.rb +439 -0
  250. data/test/unit/ccls/study_subject_interviews_test.rb +26 -0
  251. data/test/unit/ccls/study_subject_languages_test.rb +142 -0
  252. data/test/unit/ccls/study_subject_operational_events_test.rb +53 -0
  253. data/test/unit/ccls/study_subject_patient_test.rb +249 -0
  254. data/test/unit/ccls/study_subject_pii_test.rb +278 -0
  255. data/test/unit/ccls/study_subject_races_test.rb +203 -0
  256. data/test/unit/ccls/study_subject_search_test.rb +704 -0
  257. data/test/unit/ccls/study_subject_test.rb +770 -0
  258. data/test/unit/ccls/subject_language_test.rb +43 -0
  259. data/test/unit/ccls/subject_race_test.rb +35 -0
  260. data/test/unit/ccls/subject_relationship_test.rb +43 -0
  261. data/test/unit/ccls/subject_type_test.rb +40 -0
  262. data/test/unit/ccls/tracing_status_test.rb +32 -0
  263. data/test/unit/ccls/transfer_test.rb +81 -0
  264. data/test/unit/ccls/translation_table_test.rb +40 -0
  265. data/test/unit/ccls/unit_test.rb +21 -0
  266. data/test/unit/ccls/user_test.rb +156 -0
  267. data/test/unit/ccls/vital_status_test.rb +36 -0
  268. data/test/unit/ccls/zip_code_test.rb +55 -0
  269. metadata +633 -0
@@ -0,0 +1,26 @@
1
+ class Instrument < ActiveRecordShared
2
+
3
+ acts_as_list
4
+ default_scope :order => :position
5
+
6
+ acts_like_a_hash
7
+
8
+ belongs_to :project
9
+ belongs_to :interview_method
10
+ has_many :instrument_versions
11
+
12
+ validates_presence_of :project_id
13
+ validates_presence_of :project, :if => :project_id
14
+
15
+ validates_presence_of :name
16
+ validates_length_of :name, :maximum => 250, :allow_blank => true
17
+
18
+ validates_complete_date_for :began_use_on, :allow_nil => true
19
+ validates_complete_date_for :ended_use_on, :allow_nil => true
20
+
21
+ # Return name
22
+ def to_s
23
+ name
24
+ end
25
+
26
+ end
@@ -0,0 +1,17 @@
1
+ # == requires
2
+ # * description ( unique and > 3 chars )
3
+ # * project
4
+ class InstrumentType < ActiveRecordShared
5
+
6
+ acts_as_list
7
+ default_scope :order => :position
8
+
9
+ acts_like_a_hash
10
+
11
+ belongs_to :project
12
+ has_many :instrument_versions
13
+
14
+ validates_presence_of :project_id
15
+ validates_presence_of :project, :if => :project_id
16
+
17
+ end
@@ -0,0 +1,28 @@
1
+ # == requires
2
+ # * key ( unique )
3
+ # * description ( unique and > 3 chars )
4
+ # * interview_type_id
5
+ class InstrumentVersion < ActiveRecordShared
6
+
7
+ acts_as_list
8
+ default_scope :order => :position
9
+
10
+ acts_like_a_hash
11
+
12
+ belongs_to :language
13
+ belongs_to :instrument_type
14
+ belongs_to :instrument
15
+ has_many :interviews
16
+
17
+ validates_presence_of :instrument_type_id
18
+ validates_presence_of :instrument_type, :if => :instrument_type_id
19
+
20
+ validates_complete_date_for :began_use_on, :allow_nil => true
21
+ validates_complete_date_for :ended_use_on, :allow_nil => true
22
+
23
+ # Returns description
24
+ def to_s
25
+ description
26
+ end
27
+
28
+ end
@@ -0,0 +1,122 @@
1
+ # == requires
2
+ # * address_id
3
+ # * interviewer_id
4
+ # * study_subject_id
5
+ class Interview < ActiveRecordShared
6
+
7
+ belongs_to :study_subject
8
+ attr_protected( :study_subject_id, :study_subject )
9
+
10
+ ##
11
+ # why is this here? Homex for assigning interview outcome
12
+ accepts_nested_attributes_for :study_subject
13
+
14
+ belongs_to :address
15
+ belongs_to :interviewer, :class_name => 'Person'
16
+ belongs_to :instrument_version
17
+ belongs_to :interview_method
18
+ belongs_to :language
19
+ belongs_to :subject_relationship
20
+
21
+ delegate :is_other?, :to => :subject_relationship, :allow_nil => true, :prefix => true
22
+
23
+ validates_complete_date_for :began_on, :allow_nil => true
24
+ validates_complete_date_for :ended_on, :allow_nil => true
25
+ validates_complete_date_for :intro_letter_sent_on, :allow_nil => true
26
+
27
+ validates_length_of :subject_relationship_other, :maximum => 250, :allow_blank => true
28
+ validates_length_of :respondent_first_name, :maximum => 250, :allow_blank => true
29
+ validates_length_of :respondent_last_name, :maximum => 250, :allow_blank => true
30
+
31
+ validate :presence_of_subject_relationship_other,
32
+ :if => :subject_relationship_is_other?
33
+
34
+ validates_absence_of :subject_relationship_other,
35
+ :message => "not allowed",
36
+ :if => :subject_relationship_id_blank?
37
+
38
+ validates_inclusion_of :began_at_hour, :in => (1..12),
39
+ :allow_blank => true
40
+ validates_inclusion_of :began_at_minute, :in => (0..59),
41
+ :allow_blank => true
42
+ validates_format_of :began_at_meridiem, :with => /\A(AM|PM)\z/i,
43
+ :allow_blank => true
44
+ validates_inclusion_of :ended_at_hour, :in => (1..12),
45
+ :allow_blank => true
46
+ validates_inclusion_of :ended_at_minute, :in => (0..59),
47
+ :allow_blank => true
48
+ validates_format_of :ended_at_meridiem, :with => /\A(AM|PM)\z/i,
49
+ :allow_blank => true
50
+
51
+ before_save :update_intro_operational_event,
52
+ :if => :intro_letter_sent_on_changed?
53
+
54
+ before_save :set_began_at
55
+ before_save :set_ended_at
56
+ attr_protected :began_at
57
+ attr_protected :ended_at
58
+
59
+ # Returns string containing respondent's first and last name
60
+ def respondent_full_name
61
+ [respondent_first_name, respondent_last_name].compact.join(' ')
62
+ end
63
+
64
+ protected
65
+
66
+ def set_began_at
67
+ if [began_on, began_at_hour,began_at_minute,began_at_meridiem].all?
68
+ self.began_at = DateTime.parse(
69
+ "#{began_on} #{began_at_hour}:#{began_at_minute} #{began_at_meridiem}")
70
+ # "#{began_on} #{began_at_hour}:#{began_at_minute} #{began_at_meridiem} PST")
71
+ else
72
+ self.began_at = nil
73
+ end
74
+ end
75
+
76
+ def set_ended_at
77
+ if [ended_on, ended_at_hour,ended_at_minute,ended_at_meridiem].all?
78
+ self.ended_at = DateTime.parse(
79
+ "#{ended_on} #{ended_at_hour}:#{ended_at_minute} #{ended_at_meridiem}")
80
+ # "#{ended_on} #{ended_at_hour}:#{ended_at_minute} #{ended_at_meridiem} PST")
81
+ else
82
+ self.ended_at = nil
83
+ end
84
+ end
85
+
86
+ def subject_relationship_id_blank?
87
+ subject_relationship_id.blank?
88
+ end
89
+
90
+ def update_intro_operational_event
91
+ oet = OperationalEventType['intro']
92
+ hxe = study_subject.enrollments.find_by_project_id(Project['HomeExposures'].id)
93
+ if oet && hxe
94
+ oe = hxe.operational_events.find(:first,
95
+ :conditions => { :operational_event_type_id => oet.id } )
96
+ if oe
97
+ oe.update_attributes(
98
+ :description => oet.description,
99
+ :occurred_on => intro_letter_sent_on
100
+ )
101
+ else
102
+ # hxe.operational_events << OperationalEvent.create!(
103
+ OperationalEvent.create!(
104
+ :enrollment => hxe,
105
+ :operational_event_type => oet,
106
+ :description => oet.description,
107
+ :occurred_on => intro_letter_sent_on
108
+ )
109
+ end
110
+ end
111
+ end
112
+
113
+ # custom validation for custom message without standard attribute prefix
114
+ def presence_of_subject_relationship_other
115
+ if subject_relationship_other.blank?
116
+ errors.add(:subject_relationship_other, ActiveRecord::Error.new(
117
+ self, :base, :blank, {
118
+ :message => "You must specify a relationship with 'other relationship' is selected." } ) )
119
+ end
120
+ end
121
+
122
+ end
@@ -0,0 +1,17 @@
1
+ # don't know exactly
2
+ class InterviewMethod < ActiveRecordShared
3
+
4
+ acts_as_list
5
+ default_scope :order => :position
6
+
7
+ acts_like_a_hash
8
+
9
+ has_many :interviews
10
+ has_many :instruments
11
+
12
+ # Returns description
13
+ def to_s
14
+ description
15
+ end
16
+
17
+ end
@@ -0,0 +1,16 @@
1
+ # don't know exactly
2
+ class InterviewOutcome < ActiveRecordShared
3
+
4
+ acts_as_list
5
+ default_scope :order => :position
6
+
7
+ acts_like_a_hash
8
+
9
+ has_many :homex_outcomes
10
+
11
+ # Returns description
12
+ def to_s
13
+ description
14
+ end
15
+
16
+ end
@@ -0,0 +1,28 @@
1
+ # == requires
2
+ # * code ( unique )
3
+ # * description ( unique and > 3 chars )
4
+ class Language < ActiveRecordShared
5
+
6
+ acts_as_list
7
+ default_scope :order => :position
8
+
9
+ acts_like_a_hash
10
+
11
+ has_many :interviews
12
+ has_many :instrument_versions
13
+
14
+ validates_presence_of :code
15
+ validates_uniqueness_of :code
16
+
17
+ # Returns description
18
+ def to_s
19
+ description
20
+ end
21
+
22
+ # Returns boolean of comparison
23
+ # true only if key == 'other'
24
+ def is_other?
25
+ key == 'other'
26
+ end
27
+
28
+ end
@@ -0,0 +1,142 @@
1
+ class LiveBirthDataUpdate < ActiveRecordShared
2
+
3
+ has_attached_file :csv_file,
4
+ YAML::load(ERB.new(IO.read(File.expand_path(
5
+ File.join(File.dirname(__FILE__),'../..','config/live_birth_data_update.yml')
6
+ ))).result)[Rails.env]
7
+
8
+ def to_candidate_controls
9
+ results = []
10
+ if !self.csv_file_file_name.blank? &&
11
+ File.exists?(self.csv_file.path)
12
+ (f=FasterCSV.open( self.csv_file.path, 'rb',{
13
+ :headers => true })).each do |line|
14
+
15
+ # masterid,ca_co_status,biomom,biodad,date,mother_full_name,mother_maiden_name,father_full_name,child_full_name,child_dobm,child_dobd,child_doby,child_gender,birthplace_country,birthplace_state,birthplace_city,mother_hispanicity,mother_hispanicity_mex,mother_race,mother_race_other,father_hispanicity,father_hispanicity_mex,father_race,father_race_other
16
+
17
+ if line['ca_co_status'] == 'case'
18
+ study_subject = StudySubject.find_by_icf_master_id(line['masterid'])
19
+ if study_subject
20
+ results.push(study_subject)
21
+ else
22
+ results.push("Could not find study_subject with masterid #{line['masterid']}")
23
+ next
24
+ end
25
+ elsif line['ca_co_status'] == 'control'
26
+ study_subject = StudySubject.find_by_icf_master_id(line['masterid'])
27
+ unless study_subject
28
+ results.push("Could not find study_subject with masterid #{line['masterid']}")
29
+ next
30
+ end
31
+
32
+ dob = unless(
33
+ line['child_doby'].blank? ||
34
+ line['child_dobm'].blank? ||
35
+ line['child_dobd'].blank? )
36
+ Date.new(
37
+ line['child_doby'].to_i,
38
+ line['child_dobm'].to_i,
39
+ line['child_dobd'].to_i)
40
+ else
41
+ nil
42
+ end
43
+ child_names = line["child_full_name"].to_s.split_name
44
+ father_names = line["father_full_name"].to_s.split_name
45
+ mother_names = line["mother_full_name"].to_s.split_name
46
+ #
47
+ # incoming data may be strings, but
48
+ # nil DOES NOT EQUAL "" for integer comparison
49
+ # so MUST nilify blank integer fields or will never find
50
+ # the record and will create duplicates every time.
51
+ #
52
+ # biomom = ( ( line["biomom"].blank? ) ? nil : line["biomom"] )
53
+ # biodad = ( ( line["biodad"].blank? ) ? nil : line["biodad"] )
54
+ # mother_hispanicity = ( (line["mother_hispanicity"].blank? ) ?
55
+ # nil : line["mother_hispanicity"] )
56
+ # mother_race = ( (line["mother_race"].blank? ) ?
57
+ # nil : line["mother_race"] )
58
+ # father_hispanicity = ( (line["father_hispanicity"].blank? ) ?
59
+ # nil : line["father_hispanicity"] )
60
+ # father_race = ( (line["father_race"].blank? ) ?
61
+ # nil : line["father_race"] )
62
+
63
+ candidate_control_options = {
64
+ # :related_patid => identifier.patid,
65
+ :related_patid => study_subject.patid,
66
+ :mom_is_biomom => line["biomom"].nilify_blank,
67
+ :dad_is_biodad => line["biodad"].nilify_blank,
68
+ #"date":nil # some event's occurred on
69
+ :first_name => child_names[0],
70
+ :middle_name => child_names[1],
71
+ :last_name => child_names[2],
72
+ # :father_first_name => father_names[0], # doesn't exist
73
+ # :father_middle_name => father_names[1], # doesn't exist
74
+ # :father_last_name => father_names[2], # doesn't exist
75
+ :mother_first_name => mother_names[0],
76
+ :mother_middle_name => mother_names[1],
77
+ :mother_last_name => mother_names[2],
78
+ :mother_maiden_name => line["mother_maiden_name"],
79
+ :dob => dob,
80
+ :sex => line["child_gender"],
81
+ #"birthplace_country":"United States" # doesn't exist
82
+ #"birthplace_state":"CA" # doesn't exist
83
+ #"birthplace_city":"Oakland" # doesn't exist
84
+ :mother_hispanicity_id => line["mother_hispanicity"].nilify_blank,
85
+ #"mother_hispanicity_mex":"2" # doesn't exist
86
+ :mother_race_id => line["mother_race"].nilify_blank,
87
+ #"mother_race_other":nil # doesn't exist
88
+ :father_hispanicity_id => line["father_hispanicity"].nilify_blank,
89
+ #"father_hispanicity_mex":"2" # doesn't exist
90
+ :father_race_id => line["father_race"].nilify_blank
91
+ #"father_race_other":nil # doesn't exist
92
+ }
93
+ candidate_control = CandidateControl.find(:first,
94
+ :conditions => candidate_control_options )
95
+
96
+ if candidate_control.nil?
97
+ candidate_control = CandidateControl.create( candidate_control_options )
98
+ # TODO what if there's an error?
99
+ end
100
+ # unless candidate_control.new_record?
101
+ # results.push(candidate_control.id)
102
+ # end
103
+ results.push(candidate_control)
104
+
105
+ else
106
+ results.push("Unexpected ca_co_status :#{line['ca_co_status']}:")
107
+ end # elsif line['ca_co_status'] == 'control'
108
+ end # (f=FasterCSV.open( self.csv_file.path, 'rb',{ :headers => true })).each
109
+ end # if !self.csv_file_file_name.blank? && File.exists?(self.csv_file.path)
110
+ results # TODO why am I returning anything? will I use this later?
111
+ end # def to_candidate_controls
112
+
113
+ end
114
+
115
+
116
+ # Probably better to move this somewhere more appropriate
117
+ # Perhaps CommonLib::StringExtension
118
+ # Trying to get actual names from hospital, so, hopefully,
119
+ # this won't be needed.
120
+
121
+ String.class_eval do
122
+
123
+ def split_name
124
+ # Really only want to split on spaces so just remove the problem chars.
125
+ # May have to add others later.
126
+ names = self.gsub(/\240/,' ').split
127
+ first = names.shift.to_s.squish
128
+ last = names.pop.to_s.squish
129
+ middle = names.join(' ').squish
130
+ [first,middle,last]
131
+ end
132
+
133
+ end
134
+
135
+ # Object and not String because could be NilClass
136
+ Object.class_eval do
137
+
138
+ def nilify_blank
139
+ ( self.blank? ) ? nil : self
140
+ end
141
+
142
+ end
@@ -0,0 +1,99 @@
1
+ # == requires
2
+ # * operational_event_type_id
3
+ class OperationalEvent < ActiveRecordShared
4
+
5
+ default_scope :order => 'occurred_on DESC'
6
+ belongs_to :enrollment
7
+ belongs_to :operational_event_type
8
+
9
+ validates_presence_of :enrollment_id
10
+ validates_presence_of :enrollment, :if => :enrollment_id
11
+
12
+ validates_presence_of :operational_event_type_id
13
+ validates_presence_of :operational_event_type, :if => :operational_event_type_id
14
+
15
+ validates_complete_date_for :occurred_on, :allow_nil => true
16
+ validates_length_of :description, :maximum => 250, :allow_blank => true
17
+ validates_length_of :event_notes, :maximum => 65000, :allow_blank => true
18
+
19
+ # Returns description
20
+ def to_s
21
+ description
22
+ end
23
+
24
+ # TODO perhaps move the search stuff into OperationalEventSearch?
25
+
26
+ # find wrapper
27
+ def self.search(options={})
28
+ find(:all,
29
+ :joins => joins(options),
30
+ :order => order(options),
31
+ :conditions => conditions(options)
32
+ )
33
+ end
34
+
35
+ before_save :copy_operational_event_type_description
36
+
37
+ protected
38
+
39
+ def copy_operational_event_type_description
40
+ if self.description.blank?
41
+ self.description = operational_event_type.description
42
+ end
43
+ end
44
+
45
+ def self.valid_orders
46
+ %w( id occurred_on description type )
47
+ end
48
+
49
+ def self.valid_order?(order)
50
+ valid_orders.include?(order)
51
+ end
52
+
53
+ def self.order(options={})
54
+ if options.has_key?(:order) && valid_order?(options[:order])
55
+ order_string = case options[:order]
56
+ when 'type' then 'operational_event_types.description'
57
+ else options[:order]
58
+ end
59
+ dir = case options[:dir].try(:downcase)
60
+ when 'asc' then 'asc'
61
+ when 'desc' then 'desc'
62
+ else 'desc'
63
+ end
64
+ [order_string,dir].join(' ')
65
+ else
66
+ nil
67
+ end
68
+ end
69
+
70
+ def self.joins(options={})
71
+ # TODO may have to use sql for LEFT JOINS rather than the rails symbol
72
+ joins = []
73
+ if options.has_key?(:order) && valid_order?(options[:order])
74
+ case options[:order]
75
+ when 'type' then joins << :operational_event_type
76
+ # 'LEFT JOIN operational_event_types ON operational_events.operational_event_type_id = operational_event_types.id',
77
+ end
78
+ end
79
+ if options.has_key?(:study_subject_id) and !options[:study_subject_id].blank?
80
+ joins << :enrollment
81
+ # 'LEFT JOIN enrollments ON operational_events.enrollment_id = enrollments.id',
82
+ end
83
+ joins
84
+ end
85
+
86
+ def self.conditions(options={})
87
+ conditions = [[],[]]
88
+ if options.has_key?(:study_subject_id) and !options[:study_subject_id].blank?
89
+ conditions[0] << '(enrollments.study_subject_id = ?)'
90
+ conditions[1] << options[:study_subject_id]
91
+ end
92
+ unless conditions.flatten.empty?
93
+ [ conditions[0].join(' AND '), *(conditions[1].flatten) ]
94
+ else
95
+ nil
96
+ end
97
+ end
98
+
99
+ end