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.
- 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
|