Created
December 7, 2015 18:52
-
-
Save davidimoore/3dd0ac6ea0c29f3d007e to your computer and use it in GitHub Desktop.
User
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # == Schema Information | |
| # | |
| # Table name: users | |
| # | |
| # id :integer not null, primary key | |
| # email :string(255) default(""), not null | |
| # encrypted_password :string(255) default(""), not null | |
| # reset_password_token :string(255) | |
| # reset_password_sent_at :datetime | |
| # remember_created_at :datetime | |
| # sign_in_count :integer default(0), not null | |
| # current_sign_in_at :datetime | |
| # last_sign_in_at :datetime | |
| # current_sign_in_ip :string(255) | |
| # last_sign_in_ip :string(255) | |
| # gender :string(255) default("U") | |
| # first_name :string(255) | |
| # last_name :string(255) | |
| # join_me_username :string(255) | |
| # join_me_password :string(255) | |
| # skype_login :string(255) | |
| # skype_password :string(255) | |
| # oms_password :string(255) | |
| # notes :string(255) | |
| # call_number :string(255) | |
| # sms_number :string(255) | |
| # emulating_student :boolean default(FALSE) | |
| # archived :boolean default(FALSE) | |
| # roles :text default([]), is an Array | |
| # created_at :datetime | |
| # updated_at :datetime | |
| # modal_states :json default({}) | |
| # speaks_spanish :boolean default(FALSE) | |
| # tutored_previously :boolean default(FALSE) | |
| # accepts_tutor_agreement_guidelines :boolean default(FALSE) | |
| # cleared_background_check :boolean default(FALSE) | |
| # student_city :string(255) | |
| # tutor_city :string(255) | |
| # address1 :string(255) | |
| # address2 :string(255) | |
| # city :string(255) | |
| # state :string(255) | |
| # zipcode :string(255) | |
| # test :boolean default(FALSE) | |
| # completed_tutor_training :boolean default(FALSE) | |
| # completed_teacher_training :boolean default(FALSE) | |
| # view_promotion :boolean default(TRUE) | |
| # token :string | |
| # profile :json default({}) | |
| # permissions :json default({}) | |
| # reading_stage :integer | |
| # student_password :string default("1234") | |
| # reading_stage_updated_at :datetime | |
| # program_access :string | |
| # oms_id :integer | |
| # initial_reading_stage :integer default(1) | |
| # initial_reading_stage_updated_at :datetime | |
| # oms_login :string | |
| # | |
| class User < ActiveRecord::Base | |
| include Roles | |
| attr_accessor :description, :tutor_registration, :tutor_group_id | |
| # Include default devise modules. Others available are: | |
| # :confirmable, :lockable, :omniauthable, :timeoutable | |
| devise :database_authenticatable, :recoverable, :rememberable, :registerable, | |
| :trackable, :validatable, :async | |
| with_options if: "tutor_registration?" do |tutor_registration| | |
| tutor_registration.validates :first_name, presence: true | |
| tutor_registration.validates :last_name, presence: true | |
| tutor_registration.validates :call_number, presence: true | |
| tutor_registration.validates :accepts_tutor_agreement_guidelines, acceptance: { accept: true } | |
| tutor_registration.validate :validate_tutor_group | |
| end | |
| has_many :classroom_users | |
| has_many :classrooms, through: :classroom_users | |
| has_many :school_users | |
| has_many :schools, through: :school_users | |
| has_many :area_users | |
| has_many :areas, through: :area_users | |
| has_many :district_users | |
| has_many :districts, through: :district_users | |
| has_many :user_reading_stages, class_name: "UserReadingStage", foreign_key: :student_id | |
| has_many :assessed_user_reading_stages, class_name: "UserReadingStage", foreign_key: :assessor_id | |
| has_many :student_assignments, class_name: "TutorAssignment", foreign_key: :student_id | |
| has_many :tutors, through: :student_assignments, source: :tutor | |
| has_many :tutor_assignments, class_name: "TutorAssignment", foreign_key: :tutor_id | |
| has_many :students, through: :tutor_assignments, source: :student | |
| has_many :tutor_sessions, through: :tutor_assignments | |
| has_many :tutor_session_feedbacks, foreign_key: :author_id | |
| has_many :organization_users | |
| has_many :organizations, through: :organization_users | |
| has_many :tutor_group_users | |
| has_many :tutor_groups, through: :tutor_group_users | |
| has_many :meeting_users | |
| has_many :meetings, through: :meeting_users | |
| has_many :meeting_reservations | |
| has_many :meetings_to_attend, through: :meeting_reservations, source: :meeting | |
| has_many :tutor_events, class_name: "TutorEvent", foreign_key: :author_id | |
| has_many :user_messages | |
| has_many :messages, through: :user_messages | |
| has_many :sent_messages, class_name: "Message", foreign_key: :author_id | |
| has_many :authored_notes, class_name: "Note", foreign_key: :author_id | |
| has_many :notes | |
| has_many :evaluations | |
| has_many :chat_transcripts | |
| has_many :task_confirmations | |
| has_many :reports | |
| has_many :stimuli | |
| has_many :conference_users | |
| has_many :conferences, through: :conference_users | |
| has_many :conference_sessions | |
| has_many :user_previous_classrooms | |
| has_many :previous_classrooms, through: :user_previous_classrooms, source: :classroom | |
| has_many :client_errors | |
| has_many :activity_logs, as: :loggable | |
| default_scope { order("LOWER(last_name) ASC, LOWER(first_name) ASC") } | |
| scope :with_one_of_roles, ->(*roles) { where.overlap(roles: roles) } | |
| scope :active, -> { where(archived: false, test: false) } | |
| scope :non_roles, -> { where("'user' = ANY (roles)").order(last_name: :asc) } | |
| scope :teachers, -> { where("'#{Roles::TEACHER}' = ANY (roles)").order(last_name: :asc) } | |
| scope :tutors, -> { where("'#{Roles::TUTOR}' = ANY (roles)").order(last_name: :asc) } | |
| scope :test_tutors, -> { where(test: true).where("'#{Roles::TUTOR}' = ANY (roles)").order(last_name: :asc) } | |
| scope :non_students, -> { where("'#{Roles::TUTOR}' = ANY (roles) OR '#{Roles::TEACHER}' = ANY (roles) OR '#{Roles::ADMIN}' = ANY (roles) OR '#{Roles::STAFF}' = ANY (roles)").order(last_name: :asc) } | |
| scope :students, -> { where("'#{Roles::STUDENT}' = ANY (roles)").order(last_name: :asc) } | |
| scope :staff, -> { where("'#{Roles::STAFF}' = ANY (roles)").order(last_name: :asc) } | |
| scope :admins, -> { where("'#{Roles::ADMIN}' = ANY (roles)").order(last_name: :asc) } | |
| scope :archived, -> { where(archived: true) } | |
| scope :test, -> { where(test: true) } | |
| scope :assigned_teachers, -> { joins(:classroom_users).where("'#{Roles::TEACHER}' = ANY (roles)").active.order(last_name: :asc) } | |
| scope :autocomplete_tutor, -> (tutor_query) { tutors.active.where("first_name ilike ? or last_name ilike ?", "#{tutor_query}%", "#{tutor_query}%").includes(:tutor_groups).order(last_name: :asc, first_name: :asc) } | |
| scope :autocomplete_student, -> (student_query) { students.active.where("first_name ilike ? or last_name ilike ?", "#{student_query}%", "%#{student_query}%").includes(:classrooms).order(last_name: :asc, first_name: :asc) } | |
| scope :autocomplete, -> (user_query) { active.where("first_name ilike ? or last_name ilike ?", "#{user_query}%", "#{user_query}%").order(last_name: :asc, first_name: :asc) } | |
| after_create :set_oms_login | |
| after_create :set_default_role | |
| after_create :set_reading_stage | |
| after_create :update_profile | |
| after_create :update_permissions | |
| after_update :update_conferences | |
| def generate_token! | |
| self.token = SecureRandom.hex | |
| save! | |
| end | |
| def description | |
| @description | |
| end | |
| def full_name_with_desc | |
| title = description || roles[0].capitalize | |
| "#{full_name} (#{title})" | |
| end | |
| def full_name | |
| "#{first_name} #{last_name}".gsub(/\b('?[a-z])/) { $1.capitalize }.strip | |
| end | |
| alias_method :name, :full_name | |
| def full_name_abbreviated(last_name_length = 7) | |
| first_name_abbrev = first_name.gsub(/\b('?[a-z])/) { $1.capitalize }.strip.slice(0, 1) | |
| last_name_abbrev = last_name.gsub(/\b('?[a-z])/) { $1.capitalize }.strip.slice(0, last_name_length) | |
| "#{first_name_abbrev}. #{last_name_abbrev}" | |
| end | |
| def student_name_abbreviated(first_name_length = 7) | |
| first_name_abbrev = first_name.gsub(/\b('?[a-z])/) { $1.capitalize }.strip.slice(0, first_name_length) | |
| last_name_abbrev = last_name.gsub(/\b('?[a-z])/) { $1.capitalize }.strip.slice(0, 1) | |
| "#{first_name_abbrev} #{last_name_abbrev}." | |
| end | |
| def active_admin_access? | |
| roles.any? { |role| Roles.system_roles.include?(role) } | |
| end | |
| def active_for_authentication? | |
| super && !self.archived? | |
| end | |
| def user_role? | |
| roles.any? { |role| Roles.user_roles.include?(role) } | |
| end | |
| def is?(role) | |
| roles.include? role | |
| end | |
| def is_not?(role) | |
| !roles.include? role | |
| end | |
| def roles_contain_one_of?(allowed_roles) | |
| roles.any? do |role| | |
| allowed_roles.include? role | |
| end | |
| end | |
| def set_default_role | |
| update_attribute :roles, ["user"] if roles.empty? | |
| end | |
| def admin? | |
| is? Roles::ADMIN | |
| end | |
| def staff? | |
| is?(Roles::ADMIN) || is?(Roles::STAFF) | |
| end | |
| def archived? | |
| archived | |
| end | |
| def active? | |
| ((archived == false || archived.nil?) && (test == false || test.nil?)) | |
| end | |
| def activity_role | |
| emulating_student || is_not?(Roles::TUTOR) ? Roles::STUDENT : Roles::TUTOR | |
| end | |
| def active_admin_access? | |
| roles.any? { |role| Roles.active_admin_roles.include?(role) } | |
| end | |
| def primary_tutor_assignment | |
| tutor_assignments.active.first | |
| rescue | |
| nil | |
| end | |
| def primary_teaching_classroom | |
| classrooms.where(classroom_users: { role: [ClassroomRoles::PRIMARY_TEACHER, ClassroomRoles::TEACHER] }).first | |
| rescue | |
| nil | |
| end | |
| def primary_classroom | |
| primary_tutor_assignment.classroom | |
| rescue | |
| nil | |
| end | |
| def primary_student | |
| tutor_assignments.active.first.student | |
| rescue | |
| nil | |
| end | |
| def primary_student_assignment | |
| student_assignments.active.first | |
| rescue | |
| nil | |
| end | |
| def primary_tutor | |
| student_assignments.where(archived: false).first.tutor | |
| rescue | |
| nil | |
| end | |
| def primary_district | |
| districts.first | |
| end | |
| def primary_channel_open? | |
| primary_tutor_assignment.present? && primary_tutor_assignment.tutor_channels.present? && primary_tutor_assignment.tutor_channels.first.open? | |
| end | |
| def active_tutor_session | |
| return nil unless primary_tutor_assignment.present? | |
| primary_tutor_assignment.tutor_sessions.where(end_time: nil).first | |
| end | |
| def flashcard_assessments | |
| evaluation = evaluations.find_by evaluation_type: EvaluationTypes::TUTORMATE_FLASHCARD | |
| evaluation ? evaluation.assessments : nil | |
| end | |
| def latest_reading_stage(assessor_role = "overall", context = ReadingStageContexts::CLASSROOM) | |
| case assessor_role | |
| when "teacher" | |
| assessment = UserReadingStage.latest_by_teacher(self) | |
| when "other" | |
| assessment = UserReadingStage.latest_by_non_teacher(self, context) | |
| else | |
| assessment = UserReadingStage.latest_overall(self) | |
| end | |
| assessment ? assessment.reading_stage : ReadingStages::ONE | |
| end | |
| def primary_school | |
| primary_classroom.try(:school) | |
| end | |
| def primary_area | |
| primary_school.try(:area) | |
| end | |
| def primary_district | |
| primary_area.try(:district) | |
| end | |
| def self.update_profiles | |
| tutors.each{ |user| user.create_update_profile_job } | |
| end | |
| def create_update_profile_job | |
| UserUpdateProfileWorker.perform_async(id) | |
| end | |
| def update_profile | |
| data = { | |
| user_id: id, | |
| name: full_name, | |
| email: email, | |
| classroom_id: primary_classroom.try(:id) || 0, | |
| classroom_name: primary_classroom.try(:abbreviation) || "No Classroom", | |
| classroom_phone_number: primary_classroom.try(:call_number) || "No Classroom Phone Number", | |
| school_name: primary_school.try(:abbreviation) || "No School", | |
| area_name: primary_area.try(:name) || "No Area", | |
| tutor_group_id: tutor_groups.try(:first).try(:id) || 0, | |
| tutor_group_name: tutor_groups.try(:first).try(:name) || "No Tutor Group", | |
| tutor_assignment_id: primary_tutor_assignment.try(:id) || 0, | |
| student_name: primary_student.try(:student_name_abbreviated, 15) || "No Student" | |
| } | |
| update_attribute(:profile, data) | |
| end | |
| def json_chat_profile | |
| { | |
| user_id: id, | |
| name: full_name, | |
| email: email, | |
| classroom_id: profile["classroom_id"] || 0, | |
| classroom_name: profile["classroom_name"] || "No Classroom", | |
| classroom_phone_number: profile["classroom_phone_number"] || "No Classroom Phone Number", | |
| school_name: profile["school_name"] || "No School", | |
| area_name: profile["area_name"] || "No Area", | |
| tutor_assignment_id: profile["tutor_assignment_id"] || 0, | |
| tutor_group_id: profile["tutor_group_id"] || 0, | |
| tutor_group_name: profile["tutor_group_name"] || "No Tutor Group", | |
| student_name: profile["student_name"] || "No Student" | |
| }.as_json | |
| end | |
| def archive | |
| update_attribute(:archived, true) | |
| self.student_assignments.each{ |assignment| assignment.archive } if self.is?(Roles::STUDENT) | |
| self.tutor_assignments.each{ |assignment| assignment.archive } if self.is?(Roles::TUTOR) | |
| self.tutor_events.each{ |event| event.destroy } if self.is?(Roles::TUTOR) | |
| self.meeting_reservations.each{ |reservation| reservation.destroy } if self.is?(Roles::TUTOR) | |
| self.conferences.of_user.each{ |conference| conference.update_attribute(:archived, true) } | |
| self.conference_users.of_groups.destroy_all | |
| end | |
| def unarchive | |
| update_attribute(:archived, false) | |
| self.conferences.of_user.each{ |conference| conference.update_attribute(archived: false) } | |
| end | |
| def primary_tutor_group | |
| tutor_groups.first | |
| rescue | |
| nil | |
| end | |
| def needs_alt_chat? | |
| primary_tutor_group.present? && primary_tutor_group.blocks_chat? | |
| end | |
| def qualified? | |
| cleared_background_check == true && accepts_tutor_agreement_guidelines == true && completed_tutor_training == true | |
| end | |
| def self.update_users_permissions(model_name) | |
| users = model_name.constantize.for_permissions.map{ |model_user| model_user.user } | |
| users.each{|user| UserUpdatePermissionsWorker.perform_async(user.id) } | |
| end | |
| def update_permissions | |
| case | |
| when staff? | |
| dis = District.all.order(abbreviation: :asc) | |
| ars = Area.all.includes(:district).order(abbreviation: :asc) | |
| scs = School.all.includes(:area).order(abbreviation: :asc) | |
| crs = Classroom.all.includes(:school).order(abbreviation: :asc) | |
| orgs = Organization.all.order(name: :asc).order(abbreviation: :asc) | |
| tgs = TutorGroup.all.includes(:organization).order(abbreviation: :asc) | |
| when (orgs = organizations.includes(:tutor_groups).order(abbreviation: :asc).with_reporting_rights).any? | |
| tgs = orgs.map{ |organization| organization.tutor_groups.order(abbreviation: :asc) }.flatten | |
| when (tgs = tutor_groups.order(abbreviation: :asc).with_reporting_rights).any? | |
| when (dis = districts.includes(:areas, :schools, :classrooms).order(abbreviation: :asc).with_reporting_rights).any? | |
| ars = dis.map{ |district| district.areas.order(abbreviation: :asc) }.flatten | |
| scs = dis.map{ |district| district.schools.order(abbreviation: :asc) }.flatten | |
| crs = dis.map{ |district| district.classrooms.order(abbreviation: :asc) }.flatten | |
| when (ars = areas.includes(:schools, :classrooms).order(abbreviation: :asc).with_reporting_rights).any? | |
| scs = ars.map{ |area| area.schools.order(abbreviation: :asc) }.flatten | |
| crs = ars.map{ |area| area.classrooms.order(abbreviation: :asc) }.flatten | |
| when (scs = schools.includes(:classrooms).order(abbreviation: :asc).with_reporting_rights).any? | |
| crs = scs.map{ |school| school.classrooms.order(abbreviation: :asc) }.flatten | |
| when (crs = classrooms.order(abbreviation: :asc).with_reporting_rights).any? | |
| end | |
| data = { districts: dis ||= [], areas: ars ||= [], schools: scs ||= [], classrooms: crs ||= [], organizations: orgs ||= [], tutor_groups: tgs ||= [] } | |
| update_attribute(:permissions, data) | |
| end | |
| def highest_permission | |
| permission = case | |
| when staff? | |
| { entity: "any" } | |
| when is?(Roles::STUDENT) | |
| { entity: "none" } | |
| when permissions["organizations"].any? | |
| { entity: "organization", id: permissions["organizations"][0]["id"] } | |
| when permissions["tutor_groups"].any? | |
| { entity: "tutor_group", id: permissions["tutor_groups"][0]["id"] } | |
| when permissions["districts"].any? | |
| { entity: "district", id: permissions["districts"][0]["id"] } | |
| when permissions["areas"].any? | |
| { entity: "area", id: permissions["areas"][0]["id"] } | |
| when permissions["schools"].any? | |
| { entity: "school", id: permissions["schools"][0]["id"] } | |
| when permissions["classrooms"].any? | |
| { entity: "classroom", id: permissions["classrooms"][0]["id"] } | |
| else | |
| { entity: "none" } | |
| end | |
| end | |
| def has_permission?(permission) | |
| return true if self.staff? | |
| permits = self.permissions[permission[:entity].pluralize] | |
| if permits.present? | |
| allowed_permit = permits.select{ |permit| permission[:id].to_i == permit["id"].to_i } | |
| return allowed_permit.present? | |
| else | |
| return false | |
| end | |
| end | |
| def pubnub_uuid | |
| case | |
| when staff? | |
| "support_#{id}" | |
| when is?(Roles::TEACHER) | |
| "student_#{id}" | |
| when is?(Roles::TUTOR) | |
| "tutor_#{id}" | |
| else | |
| "user_#{id}" | |
| end | |
| end | |
| def available_reports | |
| if admin? | |
| ReportTypes.allowed_for_staff | |
| elsif is? Roles::TEACHER | |
| ReportTypes.allowed_for_teachers | |
| elsif is? Roles::TUTOR | |
| ReportTypes.allowed_for_tutors | |
| else | |
| ReportTypes.allowed_for_tutors | |
| end | |
| end | |
| def previous_classroom(school_year = SchoolYears::FALL_2014) | |
| user_previous_classrooms.where(school_year: school_year).try(:first).try(:classroom) | |
| end | |
| def user_conferences | |
| conferences.of_users | |
| end | |
| def oms_username | |
| if self.is?(Roles::STUDENT) | |
| "#{self.first_name}_#{self.id}" | |
| else | |
| end | |
| end | |
| def sync_create_student_on_oms | |
| OmsCreateStudentWorker.perform_async(self.id) if self.is?(Roles::STUDENT) | |
| end | |
| def sync_update_student_on_oms | |
| OmsUpdateStudentWorker.perform_async(self.id) if self.is?(Roles::STUDENT) | |
| end | |
| private | |
| def update_conferences | |
| if archived | |
| conference_users.includes(:conference).each do |conference_user| | |
| conference_user.destroy if conference_user.conference.conference_type == ConferenceTypes::GROUP | |
| conference_user.conference.update_attribute(:archived, true) if conference_user.conference.conference_type == ConferenceTypes::USER | |
| end | |
| end | |
| end | |
| def set_reading_stage | |
| if self.is?(Roles::STUDENT) | |
| self.reading_stage = read_attribute(:reading_stage) || ReadingStages::ONE | |
| self.reading_stage_updated_at = read_attribute(:reading_stage_updated_at) || Time.now | |
| self.save | |
| end | |
| end | |
| def tutor_registration? | |
| !!self.tutor_registration | |
| end | |
| def validate_tutor_group | |
| self.errors.add(:base, "Tutor group must be present") and return unless self.tutor_group_id.present? | |
| tutor_group = TutorGroup.where(id: self.tutor_group_id).includes(:organization).first | |
| organization = tutor_group.organization | |
| return unless organization.requires_domain_validation? | |
| email_domain = self.email.split("@").last | |
| return if organization.domains.include?(email_domain) | |
| self.errors.add(:base, "The email is not valid for the selected tutor group") | |
| end | |
| def set_oms_login | |
| update_column(:oms_login, "#{first_name}_#{id}") | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment