ccls-ccls_engine 3.11.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.
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