ccls-ccls_engine 3.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +182 -0
- data/app/models/abstract.rb +181 -0
- data/app/models/abstract_search.rb +50 -0
- data/app/models/abstract_validations.rb +324 -0
- data/app/models/address.rb +70 -0
- data/app/models/address_type.rb +15 -0
- data/app/models/addressing.rb +147 -0
- data/app/models/aliquot.rb +44 -0
- data/app/models/aliquot_sample_format.rb +13 -0
- data/app/models/analysis.rb +14 -0
- data/app/models/bc_request.rb +20 -0
- data/app/models/candidate_control.rb +101 -0
- data/app/models/context.rb +23 -0
- data/app/models/context_data_source.rb +4 -0
- data/app/models/county.rb +16 -0
- data/app/models/data_source.rb +24 -0
- data/app/models/diagnosis.rb +23 -0
- data/app/models/document_type.rb +16 -0
- data/app/models/document_version.rb +27 -0
- data/app/models/enrollment.rb +78 -0
- data/app/models/enrollment_validations.rb +167 -0
- data/app/models/follow_up.rb +16 -0
- data/app/models/follow_up_type.rb +18 -0
- data/app/models/gift_card.rb +22 -0
- data/app/models/gift_card_search.rb +137 -0
- data/app/models/home_exposure_response.rb +24 -0
- data/app/models/homex_outcome.rb +75 -0
- data/app/models/hospital.rb +22 -0
- data/app/models/icf_master_id.rb +30 -0
- data/app/models/icf_master_tracker.rb +217 -0
- data/app/models/icf_master_tracker_change.rb +9 -0
- data/app/models/icf_master_tracker_update.rb +50 -0
- data/app/models/ineligible_reason.rb +26 -0
- data/app/models/instrument.rb +26 -0
- data/app/models/instrument_type.rb +17 -0
- data/app/models/instrument_version.rb +28 -0
- data/app/models/interview.rb +122 -0
- data/app/models/interview_method.rb +17 -0
- data/app/models/interview_outcome.rb +16 -0
- data/app/models/language.rb +28 -0
- data/app/models/live_birth_data_update.rb +142 -0
- data/app/models/operational_event.rb +99 -0
- data/app/models/operational_event_type.rb +31 -0
- data/app/models/organization.rb +28 -0
- data/app/models/patient.rb +63 -0
- data/app/models/patient_validations.rb +118 -0
- data/app/models/person.rb +28 -0
- data/app/models/phone_number.rb +105 -0
- data/app/models/phone_type.rb +15 -0
- data/app/models/project.rb +39 -0
- data/app/models/project_outcome.rb +19 -0
- data/app/models/race.rb +31 -0
- data/app/models/refusal_reason.rb +23 -0
- data/app/models/sample.rb +168 -0
- data/app/models/sample_kit.rb +14 -0
- data/app/models/sample_outcome.rb +16 -0
- data/app/models/sample_temperature.rb +14 -0
- data/app/models/sample_type.rb +37 -0
- data/app/models/search.rb +195 -0
- data/app/models/section.rb +18 -0
- data/app/models/state.rb +25 -0
- data/app/models/study_subject.rb +237 -0
- data/app/models/study_subject_abstracts.rb +47 -0
- data/app/models/study_subject_addresses.rb +34 -0
- data/app/models/study_subject_associations.rb +38 -0
- data/app/models/study_subject_duplicates.rb +111 -0
- data/app/models/study_subject_enrollments.rb +17 -0
- data/app/models/study_subject_homex_outcome.rb +22 -0
- data/app/models/study_subject_identifier.rb +153 -0
- data/app/models/study_subject_interviews.rb +25 -0
- data/app/models/study_subject_languages.rb +21 -0
- data/app/models/study_subject_operational_events.rb +66 -0
- data/app/models/study_subject_patient.rb +177 -0
- data/app/models/study_subject_pii.rb +74 -0
- data/app/models/study_subject_races.rb +25 -0
- data/app/models/study_subject_search.rb +260 -0
- data/app/models/study_subject_validations.rb +116 -0
- data/app/models/subject_language.rb +11 -0
- data/app/models/subject_race.rb +11 -0
- data/app/models/subject_relationship.rb +21 -0
- data/app/models/subject_type.rb +22 -0
- data/app/models/tracing_status.rb +20 -0
- data/app/models/transfer.rb +40 -0
- data/app/models/unit.rb +14 -0
- data/app/models/vital_status.rb +19 -0
- data/app/models/zip_code.rb +36 -0
- data/config/abstract_fields.yml +1038 -0
- data/config/abstract_sections.yml +77 -0
- data/config/home_exposure_response_fields.yml +583 -0
- data/config/icf_master_tracker_update.yml +56 -0
- data/config/live_birth_data_update.yml +56 -0
- data/config/shared_use_db.yml +4 -0
- data/generators/ccls_engine/USAGE +2 -0
- data/generators/ccls_engine/ccls_engine_generator.rb +123 -0
- data/generators/ccls_engine/templates/autotest_ccls_engine.rb +3 -0
- data/generators/ccls_engine/templates/ccls_engine.rake +12 -0
- data/generators/ccls_engine/templates/fixtures/address_types.yml +30 -0
- data/generators/ccls_engine/templates/fixtures/context_data_sources.yml +54 -0
- data/generators/ccls_engine/templates/fixtures/contexts.yml +19 -0
- data/generators/ccls_engine/templates/fixtures/data_sources.yml +40 -0
- data/generators/ccls_engine/templates/fixtures/diagnoses.yml +40 -0
- data/generators/ccls_engine/templates/fixtures/document_types.yml +65 -0
- data/generators/ccls_engine/templates/fixtures/document_versions.csv +155 -0
- data/generators/ccls_engine/templates/fixtures/follow_up_types.yml +16 -0
- data/generators/ccls_engine/templates/fixtures/hospitals.yml +114 -0
- data/generators/ccls_engine/templates/fixtures/ineligible_reasons.yml +35 -0
- data/generators/ccls_engine/templates/fixtures/instrument_types.yml +26 -0
- data/generators/ccls_engine/templates/fixtures/instrument_versions.yml +22 -0
- data/generators/ccls_engine/templates/fixtures/instruments.yml +22 -0
- data/generators/ccls_engine/templates/fixtures/interview_methods.yml +30 -0
- data/generators/ccls_engine/templates/fixtures/interview_outcomes.yml +31 -0
- data/generators/ccls_engine/templates/fixtures/languages.yml +34 -0
- data/generators/ccls_engine/templates/fixtures/operational_event_types.yml +141 -0
- data/generators/ccls_engine/templates/fixtures/organizations.yml +198 -0
- data/generators/ccls_engine/templates/fixtures/people.yml +130 -0
- data/generators/ccls_engine/templates/fixtures/phone_types.yml +30 -0
- data/generators/ccls_engine/templates/fixtures/project_outcomes.yml +25 -0
- data/generators/ccls_engine/templates/fixtures/projects.yml +59 -0
- data/generators/ccls_engine/templates/fixtures/races.yml +52 -0
- data/generators/ccls_engine/templates/fixtures/refusal_reasons.yml +55 -0
- data/generators/ccls_engine/templates/fixtures/sample_outcomes.yml +36 -0
- data/generators/ccls_engine/templates/fixtures/sample_temperatures.yml +16 -0
- data/generators/ccls_engine/templates/fixtures/sample_types.yml +147 -0
- data/generators/ccls_engine/templates/fixtures/sections.yml +31 -0
- data/generators/ccls_engine/templates/fixtures/states.yml +363 -0
- data/generators/ccls_engine/templates/fixtures/subject_relationships.yml +46 -0
- data/generators/ccls_engine/templates/fixtures/subject_types.yml +30 -0
- data/generators/ccls_engine/templates/fixtures/tracing_statuses.yml +30 -0
- data/generators/ccls_engine/templates/fixtures/units.yml +13 -0
- data/generators/ccls_engine/templates/fixtures/vital_statuses.yml +28 -0
- data/generators/ccls_engine/templates/functional/roles_controller_test.rb +142 -0
- data/generators/ccls_engine/templates/functional/sessions_controller_test.rb +19 -0
- data/generators/ccls_engine/templates/functional/users_controller_test.rb +94 -0
- data/generators/ccls_engine/templates/images/sort_down.png +0 -0
- data/generators/ccls_engine/templates/images/sort_up.png +0 -0
- data/generators/ccls_engine/templates/initializer.rb +28 -0
- data/generators/ccls_engine/templates/javascripts/ccls_engine.js +24 -0
- data/generators/ccls_engine/templates/javascripts/jquery-ui.js +763 -0
- data/generators/ccls_engine/templates/javascripts/jquery.js +154 -0
- data/generators/ccls_engine/templates/javascripts/jrails.js +1 -0
- data/generators/ccls_engine/templates/migrations/create_user_invitations.rb +18 -0
- data/generators/ccls_engine/templates/migrations/create_users.rb +33 -0
- data/generators/ccls_engine/templates/migrations/drop_user_invitations.rb +18 -0
- data/generators/ccls_engine/templates/stylesheets/ccls_engine.css +180 -0
- data/generators/ccls_engine/templates/stylesheets/user.css +35 -0
- data/generators/ccls_engine/templates/stylesheets/users.css +23 -0
- data/generators/ccls_engine/templates/unit/core_extension_test.rb +18 -0
- data/generators/ccls_engine/templates/unit/role_test.rb +30 -0
- data/generators/ccls_engine/templates/unit/user_test.rb +321 -0
- data/lib/ccls-ccls_engine.rb +1 -0
- data/lib/ccls_engine.rb +135 -0
- data/lib/ccls_engine/action_view_extension.rb +3 -0
- data/lib/ccls_engine/action_view_extension/base.rb +53 -0
- data/lib/ccls_engine/action_view_extension/form_builder.rb +39 -0
- data/lib/ccls_engine/active_record_extension.rb +2 -0
- data/lib/ccls_engine/active_record_extension/base.rb +70 -0
- data/lib/ccls_engine/active_record_shared.rb +8 -0
- data/lib/ccls_engine/assertions.rb +69 -0
- data/lib/ccls_engine/autotest.rb +54 -0
- data/lib/ccls_engine/ccls_user.rb +117 -0
- data/lib/ccls_engine/core_extension.rb +14 -0
- data/lib/ccls_engine/date_and_time_formats.rb +30 -0
- data/lib/ccls_engine/factories.rb +880 -0
- data/lib/ccls_engine/factory_test_helper.rb +276 -0
- data/lib/ccls_engine/helper.rb +112 -0
- data/lib/ccls_engine/icf_master_tracker_update_test_helper.rb +121 -0
- data/lib/ccls_engine/live_birth_data_update_test_helper.rb +110 -0
- data/lib/ccls_engine/package_test_helper.rb +49 -0
- data/lib/ccls_engine/shared_database.rb +20 -0
- data/lib/ccls_engine/tasks.rb +1 -0
- data/lib/ccls_engine/test_tasks.rb +52 -0
- data/lib/ccls_engine/translation_table.rb +86 -0
- data/lib/shared_migration.rb +5 -0
- data/lib/surveyor/survey_extensions.rb +125 -0
- data/lib/tasks/application.rake +286 -0
- data/lib/tasks/calnet_authenticated.rake +6 -0
- data/lib/tasks/common_lib.rake +7 -0
- data/lib/tasks/database.rake +288 -0
- data/lib/tasks/documentation.rake +71 -0
- data/lib/tasks/homex_import.rake +723 -0
- data/lib/tasks/odms_import.rake +1116 -0
- data/lib/tasks/simply_authorized.rake +6 -0
- data/lib/tasks/ucb_ccls_engine_tasks.rake +4 -0
- data/lib/tasks/use_db.rake +4 -0
- data/rails/init.rb +4 -0
- data/test/unit/ccls/abstract_search_test.rb +150 -0
- data/test/unit/ccls/abstract_test.rb +674 -0
- data/test/unit/ccls/address_test.rb +155 -0
- data/test/unit/ccls/address_type_test.rb +25 -0
- data/test/unit/ccls/addressing_test.rb +466 -0
- data/test/unit/ccls/aliquot_sample_format_test.rb +20 -0
- data/test/unit/ccls/aliquot_test.rb +156 -0
- data/test/unit/ccls/analysis_test.rb +31 -0
- data/test/unit/ccls/bc_request_test.rb +43 -0
- data/test/unit/ccls/candidate_control_test.rb +712 -0
- data/test/unit/ccls/context_data_source_test.rb +26 -0
- data/test/unit/ccls/context_test.rb +40 -0
- data/test/unit/ccls/core_extension_test.rb +17 -0
- data/test/unit/ccls/county_test.rb +34 -0
- data/test/unit/ccls/data_source_test.rb +41 -0
- data/test/unit/ccls/diagnosis_test.rb +51 -0
- data/test/unit/ccls/document_type_test.rb +35 -0
- data/test/unit/ccls/document_version_test.rb +68 -0
- data/test/unit/ccls/enrollment_test.rb +575 -0
- data/test/unit/ccls/follow_up_test.rb +23 -0
- data/test/unit/ccls/follow_up_type_test.rb +34 -0
- data/test/unit/ccls/gift_card_search_test.rb +153 -0
- data/test/unit/ccls/gift_card_test.rb +40 -0
- data/test/unit/ccls/home_exposure_response_test.rb +83 -0
- data/test/unit/ccls/homex_outcome_test.rb +199 -0
- data/test/unit/ccls/hospital_test.rb +102 -0
- data/test/unit/ccls/icf_master_id_test.rb +30 -0
- data/test/unit/ccls/icf_master_tracker_change_test.rb +14 -0
- data/test/unit/ccls/icf_master_tracker_test.rb +132 -0
- data/test/unit/ccls/icf_master_tracker_update_test.rb +176 -0
- data/test/unit/ccls/ineligible_reason_test.rb +48 -0
- data/test/unit/ccls/instrument_test.rb +62 -0
- data/test/unit/ccls/instrument_type_test.rb +39 -0
- data/test/unit/ccls/instrument_version_test.rb +71 -0
- data/test/unit/ccls/interview_method_test.rb +44 -0
- data/test/unit/ccls/interview_outcome_test.rb +34 -0
- data/test/unit/ccls/interview_test.rb +298 -0
- data/test/unit/ccls/language_test.rb +47 -0
- data/test/unit/ccls/live_birth_data_update_test.rb +358 -0
- data/test/unit/ccls/operational_event_test.rb +187 -0
- data/test/unit/ccls/operational_event_type_test.rb +51 -0
- data/test/unit/ccls/organization_test.rb +64 -0
- data/test/unit/ccls/patient_test.rb +538 -0
- data/test/unit/ccls/person_test.rb +55 -0
- data/test/unit/ccls/phone_number_test.rb +244 -0
- data/test/unit/ccls/phone_type_test.rb +32 -0
- data/test/unit/ccls/project_outcome_test.rb +34 -0
- data/test/unit/ccls/project_test.rb +60 -0
- data/test/unit/ccls/race_test.rb +37 -0
- data/test/unit/ccls/refusal_reason_test.rb +52 -0
- data/test/unit/ccls/role_test.rb +26 -0
- data/test/unit/ccls/sample_kit_test.rb +35 -0
- data/test/unit/ccls/sample_outcome_test.rb +34 -0
- data/test/unit/ccls/sample_temperature_test.rb +25 -0
- data/test/unit/ccls/sample_test.rb +363 -0
- data/test/unit/ccls/sample_type_test.rb +58 -0
- data/test/unit/ccls/section_test.rb +34 -0
- data/test/unit/ccls/state_test.rb +31 -0
- data/test/unit/ccls/study_subject_abstracts_test.rb +115 -0
- data/test/unit/ccls/study_subject_addresses_test.rb +93 -0
- data/test/unit/ccls/study_subject_duplicates_test.rb +407 -0
- data/test/unit/ccls/study_subject_enrollments_test.rb +65 -0
- data/test/unit/ccls/study_subject_homex_outcome_test.rb +64 -0
- data/test/unit/ccls/study_subject_identifier_test.rb +439 -0
- data/test/unit/ccls/study_subject_interviews_test.rb +26 -0
- data/test/unit/ccls/study_subject_languages_test.rb +142 -0
- data/test/unit/ccls/study_subject_operational_events_test.rb +53 -0
- data/test/unit/ccls/study_subject_patient_test.rb +249 -0
- data/test/unit/ccls/study_subject_pii_test.rb +278 -0
- data/test/unit/ccls/study_subject_races_test.rb +203 -0
- data/test/unit/ccls/study_subject_search_test.rb +704 -0
- data/test/unit/ccls/study_subject_test.rb +770 -0
- data/test/unit/ccls/subject_language_test.rb +43 -0
- data/test/unit/ccls/subject_race_test.rb +35 -0
- data/test/unit/ccls/subject_relationship_test.rb +43 -0
- data/test/unit/ccls/subject_type_test.rb +40 -0
- data/test/unit/ccls/tracing_status_test.rb +32 -0
- data/test/unit/ccls/transfer_test.rb +81 -0
- data/test/unit/ccls/translation_table_test.rb +40 -0
- data/test/unit/ccls/unit_test.rb +21 -0
- data/test/unit/ccls/user_test.rb +156 -0
- data/test/unit/ccls/vital_status_test.rb +36 -0
- data/test/unit/ccls/zip_code_test.rb +55 -0
- metadata +633 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
# Extraction of answers from the survey
|
2
|
+
class HomeExposureResponse < ActiveRecordShared
|
3
|
+
|
4
|
+
belongs_to :study_subject
|
5
|
+
attr_protected :study_subject_id, :study_subject
|
6
|
+
|
7
|
+
# NEEDS to be here to match the uniqueness index in the database.
|
8
|
+
validates_uniqueness_of :study_subject_id, :allow_nil => true
|
9
|
+
|
10
|
+
validates_length_of :additional_comments, :maximum => 65000, :allow_blank => true
|
11
|
+
|
12
|
+
def self.fields
|
13
|
+
# db: db field name
|
14
|
+
# human: humanized field
|
15
|
+
@@fields ||= YAML::load( ERB.new( IO.read(
|
16
|
+
File.join(File.dirname(__FILE__),'../../config/home_exposure_response_fields.yml')
|
17
|
+
)).result)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.db_field_names
|
21
|
+
fields.collect{|f|f[:db]}
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# don't know exactly
|
2
|
+
class HomexOutcome < ActiveRecordShared
|
3
|
+
|
4
|
+
acts_as_list
|
5
|
+
default_scope :order => :position
|
6
|
+
|
7
|
+
belongs_to :study_subject
|
8
|
+
attr_protected :study_subject_id, :study_subject
|
9
|
+
belongs_to :sample_outcome
|
10
|
+
belongs_to :interview_outcome
|
11
|
+
|
12
|
+
validates_uniqueness_of :study_subject_id, :allow_nil => true
|
13
|
+
validates_presence_of :sample_outcome_on, :if => :sample_outcome_id?
|
14
|
+
validates_presence_of :interview_outcome_on, :if => :interview_outcome_id?
|
15
|
+
validates_complete_date_for :interview_outcome_on, :allow_nil => true
|
16
|
+
validates_complete_date_for :sample_outcome_on, :allow_nil => true
|
17
|
+
|
18
|
+
before_save :create_interview_outcome_update,
|
19
|
+
:if => :interview_outcome_id_changed?
|
20
|
+
|
21
|
+
before_save :create_sample_outcome_update,
|
22
|
+
:if => :sample_outcome_id_changed?
|
23
|
+
|
24
|
+
class NoHomeExposureEnrollment < StandardError # :nodoc:
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
# Create OperationalEvent regarding the interview outcome
|
30
|
+
def create_interview_outcome_update
|
31
|
+
operational_event_type = case interview_outcome
|
32
|
+
when InterviewOutcome['scheduled']
|
33
|
+
OperationalEventType['scheduled']
|
34
|
+
when InterviewOutcome['complete']
|
35
|
+
OperationalEventType['iv_complete']
|
36
|
+
else nil
|
37
|
+
end
|
38
|
+
unless operational_event_type.nil?
|
39
|
+
if hxe = study_subject.enrollments.find_by_project_id(Project['HomeExposures'].id)
|
40
|
+
OperationalEvent.create!(
|
41
|
+
:enrollment => hxe,
|
42
|
+
:operational_event_type => operational_event_type,
|
43
|
+
:occurred_on => interview_outcome_on
|
44
|
+
)
|
45
|
+
else
|
46
|
+
raise NoHomeExposureEnrollment
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Create OperationalEvent regarding the sample outcome
|
52
|
+
def create_sample_outcome_update
|
53
|
+
operational_event_type = case sample_outcome
|
54
|
+
when SampleOutcome['sent']
|
55
|
+
OperationalEventType['kit_sent']
|
56
|
+
when SampleOutcome['received']
|
57
|
+
OperationalEventType['sample_received']
|
58
|
+
when SampleOutcome['complete']
|
59
|
+
OperationalEventType['sample_complete']
|
60
|
+
else nil
|
61
|
+
end
|
62
|
+
unless operational_event_type.nil?
|
63
|
+
if hxe = study_subject.enrollments.find_by_project_id(Project['HomeExposures'].id)
|
64
|
+
OperationalEvent.create!(
|
65
|
+
:enrollment => hxe,
|
66
|
+
:operational_event_type => operational_event_type,
|
67
|
+
:occurred_on => sample_outcome_on
|
68
|
+
)
|
69
|
+
else
|
70
|
+
raise NoHomeExposureEnrollment
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Hospital < ActiveRecordShared
|
2
|
+
|
3
|
+
acts_as_list
|
4
|
+
default_scope :order => :position
|
5
|
+
|
6
|
+
belongs_to :organization
|
7
|
+
|
8
|
+
# database will default to false
|
9
|
+
validates_inclusion_of :has_irb_waiver, :in => [ true, false ]
|
10
|
+
|
11
|
+
# if organization_id is not unique, using find_by_organization_id as I do
|
12
|
+
# WILL cause problems as it will only ever return the first match
|
13
|
+
validates_presence_of :organization_id
|
14
|
+
validates_presence_of :organization, :if => :organization_id
|
15
|
+
validates_uniqueness_of :organization_id, :allow_blank => true
|
16
|
+
|
17
|
+
named_scope :waivered, :conditions => { :has_irb_waiver => true }
|
18
|
+
named_scope :nonwaivered, :conditions => { :has_irb_waiver => false }
|
19
|
+
|
20
|
+
delegate :to_s, :to => :organization, :allow_nil => true
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class IcfMasterId < ActiveRecordShared
|
2
|
+
|
3
|
+
#+------------------+------------+------+-----+---------+----------------+
|
4
|
+
#| Field | Type | Null | Key | Default | Extra |
|
5
|
+
#+------------------+------------+------+-----+---------+----------------+
|
6
|
+
#| id | int(11) | NO | PRI | NULL | auto_increment |
|
7
|
+
#| icf_master_id | varchar(9) | YES | UNI | NULL | |
|
8
|
+
#| assigned_on | date | YES | | NULL | |
|
9
|
+
#| created_at | datetime | YES | | NULL | |
|
10
|
+
#| updated_at | datetime | YES | | NULL | |
|
11
|
+
#| study_subject_id | int(11) | YES | UNI | NULL | |
|
12
|
+
#+------------------+------------+------+-----+---------+----------------+
|
13
|
+
|
14
|
+
belongs_to :study_subject
|
15
|
+
attr_protected( :study_subject_id, :study_subject )
|
16
|
+
|
17
|
+
# probably shouldn't add validations as this won't be created by users. yet.
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
icf_master_id
|
21
|
+
end
|
22
|
+
|
23
|
+
# a named scope would be nice but
|
24
|
+
def self.next_unused
|
25
|
+
find(:first,
|
26
|
+
:conditions => ['study_subject_id IS NULL']
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
class IcfMasterTracker < ActiveRecordShared
|
2
|
+
|
3
|
+
# can I attr_protected for update only?
|
4
|
+
# or perhaps find_or_create_by_masterid?
|
5
|
+
# Of course that may create the new_tracker_record
|
6
|
+
# And then on update it would create all the others?
|
7
|
+
|
8
|
+
validates_presence_of :Masterid
|
9
|
+
validates_uniqueness_of :Masterid, :allow_blank => true
|
10
|
+
attr_protected :Masterid
|
11
|
+
|
12
|
+
# validate all string field lengths ?
|
13
|
+
validates_length_of :last_update_attempt_errors, :maximum => 65000, :allow_blank => true
|
14
|
+
|
15
|
+
belongs_to :study_subject
|
16
|
+
attr_protected( :study_subject_id, :study_subject )
|
17
|
+
|
18
|
+
before_save :attach_study_subject
|
19
|
+
before_save :flag_for_update
|
20
|
+
before_save :save_all_changes
|
21
|
+
|
22
|
+
named_scope :have_changed, :conditions => {
|
23
|
+
:flagged_for_update => true
|
24
|
+
}
|
25
|
+
|
26
|
+
# This may not be the best way to update.
|
27
|
+
# We may have to implement something like BackgrounDRb.
|
28
|
+
# Updating the actual data may require a number of SQL searches
|
29
|
+
# to find the appropriate columns which could consume enough
|
30
|
+
# time to trigger a timeout. In addition, there may not be
|
31
|
+
# enough information here to determine the correct model
|
32
|
+
# to update, but we'll see how it progresses.
|
33
|
+
# If we do use BackgrounDRb, we'll probably need an additional
|
34
|
+
# column to flag has having been updated to be set in
|
35
|
+
# a before_save callback. This would then need unset by
|
36
|
+
# the BackgrounDRb worker when complete.
|
37
|
+
# after_save :update_models
|
38
|
+
|
39
|
+
def attach_study_subject
|
40
|
+
unless study_subject_id
|
41
|
+
self.study_subject = StudySubject.find_by_icf_master_id(self.Masterid)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def ignorable_changes
|
46
|
+
# %w{id flagged_for_update study_subject_id Masterid created_at updated_at}
|
47
|
+
%w{ id created_at updated_at
|
48
|
+
flagged_for_update last_update_attempt_errors last_update_attempted_at }
|
49
|
+
end
|
50
|
+
|
51
|
+
def unignorable_changes
|
52
|
+
changes.dup.delete_keys!(*ignorable_changes)
|
53
|
+
end
|
54
|
+
|
55
|
+
def flag_for_update
|
56
|
+
self.flagged_for_update = true unless unignorable_changes.empty?
|
57
|
+
end
|
58
|
+
|
59
|
+
def save_all_changes
|
60
|
+
if new_record?
|
61
|
+
IcfMasterTrackerChange.create(
|
62
|
+
:icf_master_id => self.Masterid,
|
63
|
+
# 5 t.date :master_tracker_date # Hmm.
|
64
|
+
:new_tracker_record => true
|
65
|
+
)
|
66
|
+
else
|
67
|
+
unignorable_changes.each do |field,values|
|
68
|
+
IcfMasterTrackerChange.create(
|
69
|
+
:icf_master_id => self.Masterid,
|
70
|
+
# 5 t.date :master_tracker_date # Hmm.
|
71
|
+
:modified_column => field,
|
72
|
+
:previous_value => values[0],
|
73
|
+
:new_value => values[1]
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.update_models_flagged_for_update
|
80
|
+
puts "Searching for changed Icf Master Tracker records."
|
81
|
+
changed_records = self.have_changed
|
82
|
+
if changed_records.empty?
|
83
|
+
puts "- Found no changed records."
|
84
|
+
else
|
85
|
+
puts "- Found #{changed_records} changed records."
|
86
|
+
changed_records.each do |record|
|
87
|
+
# record.last_update_attempted_at = Time.now
|
88
|
+
# unless record.study_subject_id.nil?
|
89
|
+
# try to update models
|
90
|
+
# if successful
|
91
|
+
# record.flagged_for_update = false
|
92
|
+
# record.last_update_attempt_errors = nil
|
93
|
+
# else
|
94
|
+
# set last_update_attempt_error
|
95
|
+
# leave flagged_for_update as true
|
96
|
+
# end
|
97
|
+
# else
|
98
|
+
# record.last_update_attempt_errors = "study_subject is nil. Nothing to update."
|
99
|
+
# leave flagged_for_update as true
|
100
|
+
# end
|
101
|
+
# record.save
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
# def update_models
|
110
|
+
# #
|
111
|
+
# # "Masterid","Motherid","Record_Owner","Datereceived","Lastatt","Lastdisp",
|
112
|
+
# # "Currphone","Vacauthrecd","Recollect","Needpreincentive","Active_Phone",
|
113
|
+
# # "Recordsentformatching","Recordreceivedfrommatching","Sentpreincentive",
|
114
|
+
# # "Releasedtocati","Confirmedcaticontact","Refused","Deceasednotification",
|
115
|
+
# # "Eligible","Confirmationpacketsent","Catiprotocolexhausted",
|
116
|
+
# # "Newphonenumreleasedtocati","Pleanotificationsent",
|
117
|
+
# # "Casereturnedtoberkeleyfornewinf","Casereturnedfromberkeley","Caticomplete",
|
118
|
+
# # "Kitmothersent","Kitinfantsent","Kitchildsent","Kitadolescentsent",
|
119
|
+
# # "Kitmotherrefusedcode","Kitchildrefusedcode","Noresponsetoplea",
|
120
|
+
# # "Responsereceivedfromplea","Senttoinpersonfollowup","Kitmotherrecd",
|
121
|
+
# # "Kitchildrecvd","Thankyousent","Physrequestsent","Physresponsereceived"
|
122
|
+
# #
|
123
|
+
# # Most of the columns are dates which probably correspond to an enrollment or sample.
|
124
|
+
# #Table: samples
|
125
|
+
# #+------------------------------+---------------
|
126
|
+
# #| Field | Type
|
127
|
+
# #+------------------------------+--------------
|
128
|
+
# #| aliquot_sample_format_id | int(11)
|
129
|
+
# #| sample_type_id | int(11)
|
130
|
+
# #| study_subject_id | int(11)
|
131
|
+
# #| unit_id | int(11)
|
132
|
+
# #| order_no | int(11)
|
133
|
+
# #| quantity_in_sample | decimal(10,0)
|
134
|
+
# #| aliquot_or_sample_on_receipt | varchar(255)
|
135
|
+
# #| sent_to_subject_on | date
|
136
|
+
# #| received_by_ccls_on | date
|
137
|
+
# #| sent_to_lab_on | date
|
138
|
+
# #| received_by_lab_on | date
|
139
|
+
# #| aliquotted_on | date
|
140
|
+
# #| external_id | varchar(255)
|
141
|
+
# #| external_id_source | varchar(255)
|
142
|
+
# #| receipt_confirmed_on | date
|
143
|
+
# #| receipt_confirmed_by | varchar(255)
|
144
|
+
# #| future_use_prohibited | tinyint(1)
|
145
|
+
# #| collected_on | date
|
146
|
+
# #| location_id | int(11)
|
147
|
+
# #
|
148
|
+
# # if study_subject_id and dirty
|
149
|
+
# # Consider Record_Owner field?
|
150
|
+
# # Which project?
|
151
|
+
# # add operational event with differences to study subject
|
152
|
+
# # update models
|
153
|
+
# # end
|
154
|
+
#
|
155
|
+
# if study_subject_id and changed?
|
156
|
+
# # puts
|
157
|
+
# # puts "Tracker has subject and has changed so begin updating"
|
158
|
+
# # puts self.changes
|
159
|
+
# #
|
160
|
+
# # Which changes matter?
|
161
|
+
# # There are many validations, so what to do if update fails?
|
162
|
+
# # If subject doesn't initially exist (shouldn't happen),
|
163
|
+
# # then these updates will NEVER be added as the record
|
164
|
+
# # "changes" won't be changed. Will need another condition
|
165
|
+
# # to update everything if study_subject_id is new.
|
166
|
+
# # Again, this shouldn't actually ever happen as the Masterid
|
167
|
+
# # is assigned to a subject by us, meaning the subject exists
|
168
|
+
# # before giving it to ICF.
|
169
|
+
#
|
170
|
+
# # unignored_changes = changes.dup.delete_keys!(*ignorable_changes)
|
171
|
+
# unless unignorable_changes.empty?
|
172
|
+
# # description = []
|
173
|
+
# # unignorable_changes.each { |field,values|
|
174
|
+
# # description << "#{field} changed from #{values[0]} to #{values[1]}"
|
175
|
+
# # }
|
176
|
+
# # OperationalEvent.create!(
|
177
|
+
# # :enrollment => study_subject.enrollments.find_or_create_by_project_id(
|
178
|
+
# # Project[:ccls].id),
|
179
|
+
# # :operational_event_type => OperationalEventType[:other],
|
180
|
+
# ##
|
181
|
+
# ## description can only be 250 chars so this fails in testing
|
182
|
+
# ## when creating new tracker as everything has changed.
|
183
|
+
# ## Change description to text? Will 65000 chars be enough?
|
184
|
+
# ##
|
185
|
+
# ## :description => description.join("\n")
|
186
|
+
# # :description => "Icf Master Tracker caused changes."
|
187
|
+
# # )
|
188
|
+
# end
|
189
|
+
# # else
|
190
|
+
# # puts
|
191
|
+
# # puts "Tracker has no subject so skipping updating"
|
192
|
+
# end
|
193
|
+
# end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
__END__
|
198
|
+
|
199
|
+
|
200
|
+
changed?() public
|
201
|
+
|
202
|
+
Returns true if any attribute have unsaved changes, false otherwise.
|
203
|
+
|
204
|
+
person.changed? # => false
|
205
|
+
person.name = 'bob'
|
206
|
+
person.changed? # => true
|
207
|
+
|
208
|
+
|
209
|
+
changes() public
|
210
|
+
|
211
|
+
Map of changed attrs => [original value, new value].
|
212
|
+
|
213
|
+
person.changes # => {}
|
214
|
+
person.name = 'bob'
|
215
|
+
person.changes # => { 'name' => ['bill', 'bob'] }
|
216
|
+
|
217
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class IcfMasterTrackerUpdate < 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/icf_master_tracker_update.yml')
|
6
|
+
))).result)[Rails.env]
|
7
|
+
|
8
|
+
|
9
|
+
# This doesn't really do much of anything yet.
|
10
|
+
def parse
|
11
|
+
results = []
|
12
|
+
if !self.csv_file_file_name.blank? &&
|
13
|
+
File.exists?(self.csv_file.path)
|
14
|
+
(f=FasterCSV.open( self.csv_file.path, 'rb',{
|
15
|
+
:headers => true })).each do |line|
|
16
|
+
|
17
|
+
# "Masterid","Motherid","Record_Owner","Datereceived","Lastatt","Lastdisp","Currphone","Vacauthrecd","Recollect","Needpreincentive","Active_Phone","Recordsentformatching","Recordreceivedfrommatching","Sentpreincentive","Releasedtocati","Confirmedcaticontact","Refused","Deceasednotification","Eligible","Confirmationpacketsent","Catiprotocolexhausted","Newphonenumreleasedtocati","Pleanotificationsent","Casereturnedtoberkeleyfornewinf","Casereturnedfromberkeley","Caticomplete","Kitmothersent","Kitinfantsent","Kitchildsent","Kitadolescentsent","Kitmotherrefusedcode","Kitchildrefusedcode","Noresponsetoplea","Responsereceivedfromplea","Senttoinpersonfollowup","Kitmotherrecd","Kitchildrecvd","Thankyousent","Physrequestsent","Physresponsereceived"
|
18
|
+
|
19
|
+
#
|
20
|
+
# The IcfMasterTracker will include an after_save or something that will
|
21
|
+
# determine what has changed and update appropriately. It may also
|
22
|
+
# create OperationalEvents to document the data changes. As it is
|
23
|
+
# theoretically possible that the Masterid does not exist in the identifiers
|
24
|
+
# table, perhaps add a successfully_updated_models flag which could
|
25
|
+
# be used?
|
26
|
+
#
|
27
|
+
icf_master_tracker = IcfMasterTracker.find_or_create_by_Masterid(line['Masterid'])
|
28
|
+
# NO BANG. Don't want to raise any errors.
|
29
|
+
successfully_updated = icf_master_tracker.update_attributes(line.to_hash)
|
30
|
+
#
|
31
|
+
# errors = icf_master_tracker.errors.full_messages.to_sentence
|
32
|
+
# These won't be validation errors as there shouldn't be any.
|
33
|
+
# Perhaps "no column by that name" errors if csv file changes?
|
34
|
+
#
|
35
|
+
# Add successfully_updated value?
|
36
|
+
# icf_master_tracker.update_attribute(:sucessfully_updated, successfully_updated)
|
37
|
+
# will the above include the line's attributes?
|
38
|
+
#
|
39
|
+
# Add update_errors column?
|
40
|
+
# icf_master_tracker.update_attribute(:update_errors, errors)
|
41
|
+
#
|
42
|
+
|
43
|
+
results.push(icf_master_tracker)
|
44
|
+
|
45
|
+
end # (f=FasterCSV.open( self.csv_file.path, 'rb',{ :headers => true })).each
|
46
|
+
end # if !self.csv_file_file_name.blank? && File.exists?(self.csv_file.path)
|
47
|
+
results # TODO why am I returning anything? will I use this later?
|
48
|
+
end # def parse
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# == requires
|
2
|
+
# * description (unique and > 3 chars)
|
3
|
+
class IneligibleReason < ActiveRecordShared
|
4
|
+
|
5
|
+
acts_as_list
|
6
|
+
default_scope :order => :position
|
7
|
+
|
8
|
+
acts_like_a_hash
|
9
|
+
|
10
|
+
has_many :enrollments
|
11
|
+
|
12
|
+
validates_length_of :ineligible_context,
|
13
|
+
:maximum => 250, :allow_blank => true
|
14
|
+
|
15
|
+
# Returns description
|
16
|
+
def to_s
|
17
|
+
description
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns boolean of comparison
|
21
|
+
# true only if key == 'other'
|
22
|
+
def is_other?
|
23
|
+
key == 'other'
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|