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,31 @@
|
|
|
1
|
+
# == requires
|
|
2
|
+
# * key ( unique )
|
|
3
|
+
# * description ( unique and > 3 chars )
|
|
4
|
+
class OperationalEventType < ActiveRecordShared
|
|
5
|
+
|
|
6
|
+
acts_as_list
|
|
7
|
+
default_scope :order => :position
|
|
8
|
+
|
|
9
|
+
acts_like_a_hash
|
|
10
|
+
|
|
11
|
+
has_many :operational_events
|
|
12
|
+
|
|
13
|
+
validates_presence_of :event_category
|
|
14
|
+
validates_uniqueness_of :event_category
|
|
15
|
+
validates_length_of :event_category,
|
|
16
|
+
:in => 4..250, :allow_blank => true
|
|
17
|
+
|
|
18
|
+
# Returns event_category.
|
|
19
|
+
def to_s
|
|
20
|
+
"#{event_category}:#{description}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.categories
|
|
24
|
+
find(:all,
|
|
25
|
+
:conditions => 'event_category IS NOT NULL',
|
|
26
|
+
:order => 'event_category ASC',
|
|
27
|
+
:group => :event_category
|
|
28
|
+
).collect(&:event_category)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# == requires
|
|
2
|
+
# * name ( unique and > 3 chars )
|
|
3
|
+
class Organization < ActiveRecordShared
|
|
4
|
+
|
|
5
|
+
acts_as_list
|
|
6
|
+
default_scope :order => :position
|
|
7
|
+
|
|
8
|
+
acts_like_a_hash(:value => :name)
|
|
9
|
+
|
|
10
|
+
belongs_to :person
|
|
11
|
+
has_many :aliquots, :foreign_key => 'owner_id'
|
|
12
|
+
has_many :incoming_transfers, :class_name => 'Transfer',
|
|
13
|
+
:foreign_key => 'to_organization_id'
|
|
14
|
+
has_many :outgoing_transfers, :class_name => 'Transfer',
|
|
15
|
+
:foreign_key => 'from_organization_id'
|
|
16
|
+
# has_many :hospitals
|
|
17
|
+
has_one :hospital
|
|
18
|
+
has_many :patients
|
|
19
|
+
|
|
20
|
+
validates_presence_of :name
|
|
21
|
+
validates_uniqueness_of :name
|
|
22
|
+
|
|
23
|
+
# Returns name
|
|
24
|
+
def to_s
|
|
25
|
+
name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Patient related study_subject info.
|
|
2
|
+
class Patient < ActiveRecordShared
|
|
3
|
+
|
|
4
|
+
belongs_to :study_subject
|
|
5
|
+
belongs_to :organization
|
|
6
|
+
belongs_to :diagnosis
|
|
7
|
+
|
|
8
|
+
delegate :is_other?, :to => :diagnosis, :allow_nil => true, :prefix => true
|
|
9
|
+
|
|
10
|
+
attr_protected( :study_subject_id, :study_subject )
|
|
11
|
+
|
|
12
|
+
include PatientValidations
|
|
13
|
+
|
|
14
|
+
# Would it be better to do this before_validation?
|
|
15
|
+
before_save :format_raf_zip, :if => :raf_zip_changed?
|
|
16
|
+
|
|
17
|
+
after_save :trigger_update_matching_study_subjects_reference_date,
|
|
18
|
+
:if => :admit_date_changed?
|
|
19
|
+
|
|
20
|
+
after_save :trigger_setting_was_under_15_at_dx,
|
|
21
|
+
:if => :admit_date_changed?
|
|
22
|
+
|
|
23
|
+
protected
|
|
24
|
+
|
|
25
|
+
# Simply squish the zip removing leading and trailing spaces.
|
|
26
|
+
def format_raf_zip
|
|
27
|
+
# zip was nil during import and skipping validations
|
|
28
|
+
self.raf_zip.squish! unless raf_zip.nil?
|
|
29
|
+
# convert to 12345-1234
|
|
30
|
+
if !self.raf_zip.nil? and self.raf_zip.length > 5
|
|
31
|
+
old = self.raf_zip.gsub(/\D/,'')
|
|
32
|
+
self.raf_zip = "#{old[0..4]}-#{old[5..8]}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def trigger_setting_was_under_15_at_dx
|
|
37
|
+
logger.debug "DEBUG: calling update_patient_was_under_15_at_dx from Patient:#{self.attributes['id']}"
|
|
38
|
+
logger.debug "DEBUG: Admit date changed from:#{admit_date_was}:to:#{admit_date}"
|
|
39
|
+
if study_subject
|
|
40
|
+
logger.debug "DEBUG: study_subject:#{study_subject.id}"
|
|
41
|
+
study_subject.update_patient_was_under_15_at_dx
|
|
42
|
+
else
|
|
43
|
+
# This should never happen, except in testing.
|
|
44
|
+
logger.warn "WARNING: Patient(#{self.attributes['id']}) is missing study_subject"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
#
|
|
48
|
+
# logger levels are ... debug, info, warn, error, and fatal.
|
|
49
|
+
#
|
|
50
|
+
def trigger_update_matching_study_subjects_reference_date
|
|
51
|
+
logger.debug "DEBUG: calling update_study_subjects_reference_date_matching from Patient:#{self.attributes['id']}"
|
|
52
|
+
logger.debug "DEBUG: Admit date changed from:#{admit_date_was}:to:#{admit_date}"
|
|
53
|
+
if study_subject
|
|
54
|
+
logger.debug "DEBUG: study_subject:#{study_subject.id}"
|
|
55
|
+
# study_subject.update_matching_study_subjects_reference_date
|
|
56
|
+
study_subject.update_study_subjects_reference_date_matching
|
|
57
|
+
else
|
|
58
|
+
# This should never happen, except in testing.
|
|
59
|
+
logger.warn "WARNING: Patient(#{self.attributes['id']}) is missing study_subject"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Simply extracted some code to clean up model.
|
|
3
|
+
# I'd like to do this to all of the really big classes
|
|
4
|
+
# but let's see how this goes first.
|
|
5
|
+
#
|
|
6
|
+
module PatientValidations
|
|
7
|
+
def self.included(base)
|
|
8
|
+
# Must delay the calls to these ActiveRecord methods
|
|
9
|
+
# or it will raise many "undefined method"s.
|
|
10
|
+
base.class_eval do
|
|
11
|
+
|
|
12
|
+
validates_presence_of :admit_date
|
|
13
|
+
validate :presence_of_organization_id
|
|
14
|
+
validates_presence_of :diagnosis_id
|
|
15
|
+
validate :presence_of_hospital_no
|
|
16
|
+
validates_length_of :hospital_no, :maximum => 25, :allow_blank => true
|
|
17
|
+
validates_uniqueness_of :hospital_no, :scope => :organization_id
|
|
18
|
+
validates_past_date_for :admit_date
|
|
19
|
+
validates_past_date_for :diagnosis_date
|
|
20
|
+
validates_past_date_for :treatment_began_on
|
|
21
|
+
validate :admit_date_is_after_dob
|
|
22
|
+
validate :diagnosis_date_is_after_dob
|
|
23
|
+
validate :treatment_began_on_is_after_diagnosis_date
|
|
24
|
+
validate :subject_is_case
|
|
25
|
+
validates_complete_date_for :admit_date, :allow_nil => true
|
|
26
|
+
validates_complete_date_for :diagnosis_date, :allow_nil => true
|
|
27
|
+
validates_complete_date_for :treatment_began_on, :allow_nil => true
|
|
28
|
+
|
|
29
|
+
validates_length_of :raf_zip, :maximum => 10, :allow_blank => true
|
|
30
|
+
|
|
31
|
+
validates_format_of :raf_zip,
|
|
32
|
+
:with => /\A\s*\d{5}(-)?(\d{4})?\s*\z/,
|
|
33
|
+
:message => "should be 12345 or 12345-1234",
|
|
34
|
+
:allow_blank => true
|
|
35
|
+
|
|
36
|
+
validates_presence_of :other_diagnosis, :if => :diagnosis_is_other?
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
validates_inclusion_of :was_under_15_at_dx, :was_previously_treated,
|
|
40
|
+
:was_ca_resident_at_diagnosis,
|
|
41
|
+
:in => YNDK.valid_values, :allow_nil => true
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
protected
|
|
45
|
+
|
|
46
|
+
##
|
|
47
|
+
# This validation does not work when using nested attributes as
|
|
48
|
+
# the study_subject has not been resolved yet, unless this is an update.
|
|
49
|
+
# This results in a similar validation in Subject.
|
|
50
|
+
def admit_date_is_after_dob
|
|
51
|
+
if !admit_date.blank? &&
|
|
52
|
+
!study_subject.blank? &&
|
|
53
|
+
!study_subject.dob.blank? &&
|
|
54
|
+
study_subject.dob.to_date != Date.parse('1/1/1900') &&
|
|
55
|
+
admit_date < study_subject.dob &&
|
|
56
|
+
admit_date.to_date != Date.parse('1/1/1900')
|
|
57
|
+
errors.add(:admit_date, "is before study_subject's dob.")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
##
|
|
62
|
+
# This validation does not work when using nested attributes as
|
|
63
|
+
# the study_subject has not been resolved yet, unless this is an update.
|
|
64
|
+
# This results in a similar validation in Subject.
|
|
65
|
+
def diagnosis_date_is_after_dob
|
|
66
|
+
if !diagnosis_date.blank? &&
|
|
67
|
+
!study_subject.blank? &&
|
|
68
|
+
!study_subject.dob.blank? &&
|
|
69
|
+
diagnosis_date < study_subject.dob
|
|
70
|
+
errors.add(:diagnosis_date, "is before study_subject's dob.")
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
##
|
|
75
|
+
# Both are patient dates so this doesn't need in subject!
|
|
76
|
+
# custom validation and custom message
|
|
77
|
+
def treatment_began_on_is_after_diagnosis_date
|
|
78
|
+
if !treatment_began_on.blank? &&
|
|
79
|
+
!diagnosis_date.blank? &&
|
|
80
|
+
treatment_began_on < diagnosis_date
|
|
81
|
+
# errors.add(:treatment_began_on, "is before diagnosis_date.")
|
|
82
|
+
errors.add(:treatment_began_on, ActiveRecord::Error.new(
|
|
83
|
+
self, :base, :blank, {
|
|
84
|
+
:message => "Date treatment began must be on or after the diagnosis date." } ) )
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
##
|
|
89
|
+
# This validation does not work when using nested attributes as
|
|
90
|
+
# the study_subject has not been resolved yet, unless this is an update.
|
|
91
|
+
# This results in a similar validation in Subject.
|
|
92
|
+
def subject_is_case
|
|
93
|
+
if study_subject and !study_subject.is_case?
|
|
94
|
+
errors.add(:study_subject,"must be case to have patient info")
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# custom validation for custom message without standard attribute prefix
|
|
99
|
+
def presence_of_organization_id
|
|
100
|
+
if organization_id.blank?
|
|
101
|
+
errors.add(:organization_id, ActiveRecord::Error.new(
|
|
102
|
+
self, :base, :blank, {
|
|
103
|
+
:message => "Treating institution can't be blank." } ) )
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# custom validation for custom message without standard attribute prefix
|
|
108
|
+
def presence_of_hospital_no
|
|
109
|
+
if hospital_no.blank?
|
|
110
|
+
errors.add(:hospital_no, ActiveRecord::Error.new(
|
|
111
|
+
self, :base, :blank, {
|
|
112
|
+
:message => "Hospital record number can't be blank." } ) )
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end # class_eval
|
|
117
|
+
end # included
|
|
118
|
+
end # PatientValidations
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# don't know exactly
|
|
2
|
+
class Person < ActiveRecordShared
|
|
3
|
+
|
|
4
|
+
acts_as_list
|
|
5
|
+
default_scope :order => :position
|
|
6
|
+
|
|
7
|
+
# belongs_to :context
|
|
8
|
+
has_many :interviews, :foreign_key => 'interviewer_id'
|
|
9
|
+
has_many :organizations
|
|
10
|
+
|
|
11
|
+
validates_presence_of :last_name
|
|
12
|
+
validates_length_of :first_name, :maximum => 250, :allow_blank => true
|
|
13
|
+
validates_length_of :last_name, :maximum => 250, :allow_blank => true
|
|
14
|
+
validates_length_of :honorific, :maximum => 250, :allow_blank => true
|
|
15
|
+
|
|
16
|
+
named_scope :interviewers, :conditions => { :person_type_id => 3 }
|
|
17
|
+
|
|
18
|
+
# Returns string containing first and last name
|
|
19
|
+
def full_name
|
|
20
|
+
"#{first_name} #{last_name}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Returns full_name
|
|
24
|
+
def to_s
|
|
25
|
+
full_name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# A study_subject's phone number
|
|
2
|
+
class PhoneNumber < ActiveRecordShared
|
|
3
|
+
|
|
4
|
+
acts_as_list :scope => :study_subject_id
|
|
5
|
+
default_scope :order => :position
|
|
6
|
+
|
|
7
|
+
belongs_to :study_subject
|
|
8
|
+
belongs_to :phone_type
|
|
9
|
+
belongs_to :data_source
|
|
10
|
+
|
|
11
|
+
# TODO test this. Also may not need current_user now.
|
|
12
|
+
# This works in the console and such, but ActiveScaffold tries
|
|
13
|
+
# to use it in a join, but it is in a different database so fails.
|
|
14
|
+
# May be able to make it work in AS, but need to fiddle.
|
|
15
|
+
# belongs_to :verified_by, :foreign_key => 'verified_by_uid',
|
|
16
|
+
# :class_name => 'User', :primary_key => 'uid'
|
|
17
|
+
|
|
18
|
+
delegate :is_other?, :to => :data_source, :allow_nil => true, :prefix => true
|
|
19
|
+
|
|
20
|
+
validates_presence_of :phone_number
|
|
21
|
+
|
|
22
|
+
validates_presence_of :phone_type_id
|
|
23
|
+
validates_presence_of :phone_type, :if => :phone_type_id
|
|
24
|
+
|
|
25
|
+
validates_presence_of :why_invalid, :if => :is_not_valid?
|
|
26
|
+
validates_presence_of :how_verified, :if => :is_verified?
|
|
27
|
+
validates_presence_of :data_source_other, :if => :data_source_is_other?
|
|
28
|
+
validates_length_of :why_invalid, :maximum => 250, :allow_blank => true
|
|
29
|
+
validates_length_of :how_verified, :maximum => 250, :allow_blank => true
|
|
30
|
+
|
|
31
|
+
# Want to ensure contains 10 digits.
|
|
32
|
+
# I'm kinda surprised that this regex works.
|
|
33
|
+
validates_format_of :phone_number, :with => /\A(\D*\d\D*){10}\z/,
|
|
34
|
+
:allow_blank => true
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
attr_protected :study_subject_id, :study_subject
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
validates_inclusion_of :current_phone, :is_valid,
|
|
45
|
+
:in => YNDK.valid_values, :allow_nil => true
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
named_scope :current, :conditions => [
|
|
49
|
+
'current_phone IS NOT NULL AND current_phone != 2'
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
named_scope :historic, :conditions => [
|
|
53
|
+
'current_phone IS NULL OR current_phone = 2'
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
before_save :format_phone_number, :if => :phone_number_changed?
|
|
57
|
+
|
|
58
|
+
before_save :set_verifier,
|
|
59
|
+
:if => :is_verified?,
|
|
60
|
+
:unless => :is_verified_was
|
|
61
|
+
|
|
62
|
+
before_save :nullify_verifier,
|
|
63
|
+
:unless => :is_verified?,
|
|
64
|
+
:if => :is_verified_was
|
|
65
|
+
|
|
66
|
+
attr_accessor :current_user
|
|
67
|
+
|
|
68
|
+
# Returns description
|
|
69
|
+
def to_s
|
|
70
|
+
phone_number
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Returns boolean of comparison
|
|
74
|
+
# true only if is_valid == 2 or 999
|
|
75
|
+
# Beware of strings from forms
|
|
76
|
+
# Rails SHOULD convert incoming string params to integer.
|
|
77
|
+
def is_not_valid?
|
|
78
|
+
# [2,999].include?(is_valid.to_i)
|
|
79
|
+
[2,999].include?(is_valid)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
protected
|
|
83
|
+
|
|
84
|
+
# Set verified time and user if given
|
|
85
|
+
def set_verifier
|
|
86
|
+
self.verified_on = Time.now
|
|
87
|
+
self.verified_by_uid = current_user.try(:uid)||''
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Unset verified time and user
|
|
91
|
+
def nullify_verifier
|
|
92
|
+
self.verified_on = nil
|
|
93
|
+
self.verified_by_uid = nil
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Formats phone numer with () and -
|
|
97
|
+
def format_phone_number
|
|
98
|
+
unless self.phone_number.nil?
|
|
99
|
+
old = self.phone_number.gsub(/\D/,'')
|
|
100
|
+
new_phone = "(#{old[0..2]}) #{old[3..5]}-#{old[6..9]}"
|
|
101
|
+
self.phone_number = new_phone
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# == requires
|
|
2
|
+
# * key ( unique )
|
|
3
|
+
# * description ( unique and > 3 chars )
|
|
4
|
+
class Project < ActiveRecordShared
|
|
5
|
+
|
|
6
|
+
acts_as_list
|
|
7
|
+
default_scope :order => :position
|
|
8
|
+
|
|
9
|
+
acts_like_a_hash
|
|
10
|
+
|
|
11
|
+
# has_many :operational_event_types
|
|
12
|
+
has_many :instrument_types
|
|
13
|
+
has_many :enrollments
|
|
14
|
+
has_many :samples
|
|
15
|
+
has_many :gift_cards
|
|
16
|
+
has_many :study_subjects, :through => :enrollments
|
|
17
|
+
has_many :instruments
|
|
18
|
+
|
|
19
|
+
validates_complete_date_for :began_on, :allow_nil => true
|
|
20
|
+
validates_complete_date_for :ended_on, :allow_nil => true
|
|
21
|
+
validates_length_of :eligibility_criteria, :maximum => 65000, :allow_blank => true
|
|
22
|
+
|
|
23
|
+
# TODO perhaps move this into study_subject where is clearly belongs, but will need a RIGHT JOIN or something?
|
|
24
|
+
# Returns all projects for which the study_subject
|
|
25
|
+
# does not have an enrollment
|
|
26
|
+
def self.unenrolled_projects(study_subject)
|
|
27
|
+
Project.all(
|
|
28
|
+
:joins => "LEFT JOIN enrollments ON " <<
|
|
29
|
+
"projects.id = enrollments.project_id AND " <<
|
|
30
|
+
"enrollments.study_subject_id = #{study_subject.id}",
|
|
31
|
+
:conditions => [ "enrollments.study_subject_id IS NULL" ])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Returns description
|
|
35
|
+
def to_s
|
|
36
|
+
description
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class ProjectOutcome < ActiveRecordShared
|
|
2
|
+
|
|
3
|
+
acts_as_list
|
|
4
|
+
default_scope :order => :position
|
|
5
|
+
|
|
6
|
+
acts_like_a_hash
|
|
7
|
+
|
|
8
|
+
has_many :enrollments
|
|
9
|
+
|
|
10
|
+
# validates_presence_of :code
|
|
11
|
+
# validates_uniqueness_of :code
|
|
12
|
+
# validates_length_of :code, :maximum => 250, :allow_blank => true
|
|
13
|
+
|
|
14
|
+
# Returns description
|
|
15
|
+
def to_s
|
|
16
|
+
description
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|