Class: EmployeeRecord
Overview
== Schema Information
Table name: employee_records(Employee profile and role flags used for rep classification.)
Database name: primary
id :integer not null, primary key
activities_per_day :integer
activities_per_day_priority_tiers :integer
author_bio :text
author_page :boolean default(FALSE), not null
bereavement_days :integer
calendly_link :string
call_block_a :string
call_block_b :string
certifications :text
default_dashboard :string(255)
department(Department label used for organizational filtering and analytics.) :string(30)
disable_self_assign :boolean default(FALSE)
disable_special_events_alerts :boolean default(FALSE), not null
employment_end_date :date
employment_start_date :date
full_bio :text
heatwave_preferences :json
hide_signature_call_text_me_directly :boolean default(FALSE)
hide_signature_pbx_extension :boolean default(FALSE)
hire_date :date
interesting_fact :text
is_visa_holder :boolean
job_description :text
job_title :string(100)
jury_duty_days :integer
kpi_activities :integer
kpi_live_chat :integer
kpi_outbound_calls :integer
kpi_sms :integer
kpi_support_cases :integer
local_sales_rep :boolean default(FALSE), not null
mba_inventory :string default([]), is an Array
menus :string is an Array
monitor_group_sms_numbers :boolean default(FALSE)
monitor_unlinked_extensions :boolean default(FALSE), not null
next_birthday :date
next_work_anniversary :date
payroll_identifier :string
primary_sales_rep(True when employee is classified as a primary sales rep.) :boolean default(FALSE), not null
process_voicemails :boolean default(TRUE), not null
pto_backup1 :string
pto_backup2 :string
pto_backup3 :string
release_date :date
scheduler_link_type :string default("hidden")
secondary_sales_rep :boolean default(FALSE), not null
show_calendly_link :boolean default(FALSE)
show_signature_photo :boolean default(FALSE)
signature :text
slug :string
std_days :integer
vacation_days :integer
visa_end_date :date
visa_start_date :date
visa_type :string
voicemail_email_notifications :boolean default(FALSE), not null
watch_list_ids :integer default([]), is an Array
watch_list_role_ids :integer default([]), is an Array
created_at :datetime not null
updated_at :datetime not null
backup_rep_id :integer
commission_structure_id :integer
creator_id :integer
party_id :integer not null
print_node_computer_id :integer
profile_picture_id :integer
signature_picture_id :integer
updater_id :integer
Indexes
employee_records_profile_picture_id_idx (profile_picture_id)
employee_records_signature_picture_id_idx (signature_picture_id)
idx_party_secondary_sales_rep (party_id,secondary_sales_rep)
index_employee_records_on_call_block_a (call_block_a)
index_employee_records_on_call_block_b (call_block_b)
index_employee_records_on_employment_end_date (employment_end_date)
index_employee_records_on_employment_start_date (employment_start_date)
index_employee_records_on_is_visa_holder (is_visa_holder)
index_employee_records_on_slug (slug) UNIQUE
index_employee_records_on_visa_end_date (visa_end_date)
index_employee_records_on_visa_start_date (visa_start_date)
index_employee_records_on_visa_type (visa_type)
Foreign Keys
fk_rails_... (party_id => parties.id) ON DELETE => cascade
fk_rails_... (profile_picture_id => digital_assets.id)
fk_rails_... (signature_picture_id => digital_assets.id)
Constant Summary
collapse
- DEFAULT_ACTIVITIES_PER_DAY_PRIORITY_TIERS =
Default activities per day priority tiers.
90
- DEFAULT_ACTIVITIES_PER_DAY =
Default activities per day.
40
- MANAGER_SQL =
<<-EOS
exists(select 1 from accounts a
inner join accounts_roles ar on ar.account_id = a.id
inner join roles r on r.id = ar.role_id
inner join parties e on e.id = a.party_id and e.type = 'Employee'
where e.id = employee_records.party_id
and (r.name ILIKE '%manager%' or r.name ILIKE '%director%')
and e.inactive = false)
or exists(select 1 from employee_records er
where er.id = employee_records.id and er.party_id IN (select distinct e.parent_id
from parties e
where e.parent_id is not null))
EOS
- SALES_REP_SQL =
<<-EOS
exists(select 1 from accounts a
inner join accounts_roles ar on ar.account_id = a.id
inner join roles r on r.id = ar.role_id
inner join parties e on e.id = a.party_id and e.type = 'Employee'
where e.id = employee_records.party_id
and (r.name ILIKE '%sales%')
and e.inactive = false)
or exists(select 1 from employee_records er
where er.id = employee_records.id and er.party_id IN (select distinct e.parent_id
from parties e
where e.parent_id is not null))
EOS
- CALL_BLOCK_OPTIONS =
Available call block options.
[%w[None none], %w[Morning morning], %w[Afternoon afternoon]].freeze
- TYPES_OF_VISA =
[
['F-1 (Foreign academic student)', 'F-1 (Foreign academic student)'],
['H-1B (Temporary worker)', 'H-1B (Temporary worker)'],
['H-3 (Temporary worker)', 'H-3 (Temporary worker)'],
['J-1 (Exchange visitor)', 'J-1 (Exchange visitor)'],
['K-1 (Fiancé of a U.S. citizen)', 'K-1 (Fiancé of a U.S. citizen)']
].freeze
- SCHEDULER_LINK_TYPES =
Recognised scheduler link types.
%w[hidden external heatwave].freeze
Models::Auditable::ALWAYS_IGNORED
Constants included
from Schedulable
Schedulable::SIMPLE_FORM_OPTIONS
Instance Attribute Summary collapse
#creator, #updater
Delegated Instance Attributes
collapse
Class Method Summary
collapse
Instance Method Summary
collapse
#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
config
#after_commit
#publish_event
Instance Attribute Details
#activities_per_day ⇒ Object
166
|
# File 'app/models/employee_record.rb', line 166
validates :activities_per_day, numericality: { greater_than_or_equal_to: 0 }
|
#activities_per_day_priority_tiers ⇒ Object
167
|
# File 'app/models/employee_record.rb', line 167
validates :activities_per_day_priority_tiers, numericality: { greater_than_or_equal_to: 0 }
|
#scheduler_link_type ⇒ Object
190
|
# File 'app/models/employee_record.rb', line 190
validates :scheduler_link_type, inclusion: { in: SCHEDULER_LINK_TYPES }, allow_nil: true
|
Class Method Details
.active_employees ⇒ ActiveRecord::Relation<EmployeeRecord>
A relation of EmployeeRecords that are active employees. Active Record Scope
177
|
# File 'app/models/employee_record.rb', line 177
scope :active_employees, -> { joins(:party).merge(Employee.active_employees) }
|
.active_employees_in_department(department) ⇒ Object
257
258
259
|
# File 'app/models/employee_record.rb', line 257
def self.active_employees_in_department(department)
active_employees.includes(:party).where(EmployeeRecord[:department].matches(department))
end
|
.department_select_options ⇒ Object
334
335
336
|
# File 'app/models/employee_record.rb', line 334
def self.department_select_options
where.not(department: nil).order(:department).distinct.pluck(:department)
end
|
.employees_and_departments_hybrid_for_select ⇒ Object
247
248
249
250
251
252
253
254
255
|
# File 'app/models/employee_record.rb', line 247
def self.employees_and_departments_hybrid_for_select
collection = []
collection << ["\u221e Everyone", '*']
active_employees.includes(:party).order(:department).group_by(&:department).each do |department, employee_records|
collection << ["\u272a #{department}", "D|#{department}", { class: 'department-select-option' }]
collection += employee_records.sort_by { |er| er.party.full_name }.map { |er| [er.party.full_name, "EID|#{er.party.id}", { class: 'employee-select-option' }] }
end
collection
end
|
.employees_grouped_by_department ⇒ Object
235
236
237
238
239
240
241
242
243
244
245
|
# File 'app/models/employee_record.rb', line 235
def self.employees_grouped_by_department
options = active_employees.includes(:party).order(:department).group_by(&:department)
options.each do |department, employee_records|
options[department] = (begin
employee_records.map { |s| [s.party.full_name, s.party.id] }
rescue StandardError
nil
end) || []
end
options
end
|
.job_title_select_options ⇒ Object
330
331
332
|
# File 'app/models/employee_record.rb', line 330
def self.job_title_select_options
where.not(job_title: nil).order(:job_title).distinct.pluck(:job_title)
end
|
.managed_by ⇒ ActiveRecord::Relation<EmployeeRecord>
A relation of EmployeeRecords that are managed by. Active Record Scope
179
|
# File 'app/models/employee_record.rb', line 179
scope :managed_by, ->(manager_party_id) { joins(:party).where(party_id: Employee.descendants_ids(manager_party_id)) }
|
.managers ⇒ ActiveRecord::Relation<EmployeeRecord>
A relation of EmployeeRecords that are managers. Active Record Scope
175
|
# File 'app/models/employee_record.rb', line 175
scope :managers, -> { where(MANAGER_SQL) }
|
.managers_select_options ⇒ Object
326
327
328
|
# File 'app/models/employee_record.rb', line 326
def self.managers_select_options
managers.joins(:party).order('parties.full_name').pluck('parties.full_name', :id) end
|
.mba_inventory_for_select ⇒ Object
318
319
320
|
# File 'app/models/employee_record.rb', line 318
def self.mba_inventory_for_select
['Receiving Gifts', 'Quality Time', 'Words of Affirmation', 'Acts of Service', 'Physical Touch']
end
|
222
223
224
225
226
227
228
229
230
231
232
233
|
# File 'app/models/employee_record.rb', line 222
def self.
res = %w[activities articles catalogs communications customers customers_training quotes orders engineering ap ar ledger employee_training items logistics marketing reports tech phone it].sort
res.insert(0, 'home') hsh = res.index_with { |m| m.humanize.titleize }
hsh['ap'] = 'A/P'
hsh['ar'] = 'A/R'
hsh['it'] = 'Information Technology'
hsh['image_profiles'] = 'Image Profile Manager'
hsh.invert
end
|
.primary_sales_rep_for_select ⇒ Object
261
262
263
264
265
|
# File 'app/models/employee_record.rb', line 261
def self.primary_sales_rep_for_select
EmployeeRecord.joins(:party)
.includes(:party)
.merge(Employee.primary_sales_reps.active_employees).map { |er| [er.employee_name, er.id] }
end
|
.sales_reps ⇒ ActiveRecord::Relation<EmployeeRecord>
A relation of EmployeeRecords that are sales reps. Active Record Scope
176
|
# File 'app/models/employee_record.rb', line 176
scope :sales_reps, -> { where(SALES_REP_SQL) }
|
.select_options(scope = nil) ⇒ Object
.with_author_page ⇒ ActiveRecord::Relation<EmployeeRecord>
A relation of EmployeeRecords that are with author page. Active Record Scope
198
|
# File 'app/models/employee_record.rb', line 198
scope :with_author_page, -> { where(author_page: true) }
|
.without_an_open_review ⇒ ActiveRecord::Relation<EmployeeRecord>
A relation of EmployeeRecords that are without an open review. Active Record Scope
178
|
# File 'app/models/employee_record.rb', line 178
scope :without_an_open_review, -> { active_employees.where("not exists(select 1 from employee_reviews er where er.employee_record_id = employee_records.id and er.state in ('pending'))") }
|
Instance Method Details
#active? ⇒ Object
183
|
# File 'app/models/employee_record.rb', line 183
delegate :full_name, :inactive?, :active?, to: :party
|
#anniversary_date ⇒ Object
307
308
309
310
311
|
# File 'app/models/employee_record.rb', line 307
def anniversary_date
return unless hire_date
hire_date.strftime("%B #{hire_date.day.ordinalize}")
end
|
#appraisals ⇒ ActiveRecord::Relation<Appraisal>
163
|
# File 'app/models/employee_record.rb', line 163
has_many :appraisals
|
#author_slug_source ⇒ Object
200
201
202
|
# File 'app/models/employee_record.rb', line 200
def author_slug_source
party&.full_name
end
|
151
|
# File 'app/models/employee_record.rb', line 151
belongs_to :backup_rep, class_name: 'Employee', optional: true
|
#clifton_strengths ⇒ ActiveRecord::Relation<CliftonStrength>
159
|
# File 'app/models/employee_record.rb', line 159
has_many :clifton_strengths, -> { order('strength_themes.priority') }, through: :strength_themes
|
152
|
# File 'app/models/employee_record.rb', line 152
belongs_to :commission_structure, optional: true
|
#days_until_next_anniversary ⇒ Object
301
302
303
304
305
|
# File 'app/models/employee_record.rb', line 301
def days_until_next_anniversary
return unless next_work_anniversary
(next_work_anniversary - Date.current).to_i
end
|
#effective_scheduler_link ⇒ Object
279
280
281
282
283
284
285
286
287
|
# File 'app/models/employee_record.rb', line 279
def effective_scheduler_link
case scheduler_link_type
when 'heatwave'
slug = party&.scheduler_profile&.slug
slug.present? ? "#{WEB_URL}/en-US/meet/#{slug}" : nil
when 'external'
calendly_link
end
end
|
#employee ⇒ Object
208
209
210
|
# File 'app/models/employee_record.rb', line 208
def employee
party
end
|
#employee_goals ⇒ ActiveRecord::Relation<EmployeeGoal>
162
|
# File 'app/models/employee_record.rb', line 162
has_many :employee_goals, through: :employee_reviews
|
#employee_name ⇒ Object
212
213
214
|
# File 'app/models/employee_record.rb', line 212
def employee_name
party&.full_name
end
|
#employee_reviewed ⇒ ActiveRecord::Relation<EmployeeReview>
161
|
# File 'app/models/employee_record.rb', line 161
has_many :employee_reviewed, class_name: 'EmployeeReview', foreign_key: 'reviewer_id', inverse_of: :reviewer
|
#employee_reviews ⇒ ActiveRecord::Relation<EmployeeReview>
160
|
# File 'app/models/employee_record.rb', line 160
has_many :employee_reviews, inverse_of: :employee_record
|
#full_name ⇒ Object
Alias for Party#full_name
183
|
# File 'app/models/employee_record.rb', line 183
delegate :full_name, :inactive?, :active?, to: :party
|
#inactive? ⇒ Object
Alias for Party#inactive?
183
|
# File 'app/models/employee_record.rb', line 183
delegate :full_name, :inactive?, :active?, to: :party
|
#is_manager? ⇒ Boolean
267
268
269
|
# File 'app/models/employee_record.rb', line 267
def is_manager?
self.class.managers.where(id:).present?
end
|
#managers_select_options ⇒ Object
322
323
324
|
# File 'app/models/employee_record.rb', line 322
def managers_select_options
self.class.managers_select_options.reject { |v| v[1] == id }
end
|
#manages ⇒ Object
271
272
273
|
# File 'app/models/employee_record.rb', line 271
def manages
self.class.active_employees.managed_by(party_id)
end
|
#manages_employee_record_ids ⇒ Object
275
276
277
|
# File 'app/models/employee_record.rb', line 275
def manages_employee_record_ids
manages.ids
end
|
#mba_inventory_1 ⇒ Object
338
339
340
|
# File 'app/models/employee_record.rb', line 338
def mba_inventory_1
mba_inventory&.dig(0)
end
|
#mba_inventory_1=(val) ⇒ Object
342
343
344
345
|
# File 'app/models/employee_record.rb', line 342
def mba_inventory_1=(val)
self.mba_inventory ||= Array.new(3)
self.mba_inventory[0] = val
end
|
#mba_inventory_2 ⇒ Object
347
348
349
|
# File 'app/models/employee_record.rb', line 347
def mba_inventory_2
mba_inventory&.dig(1)
end
|
#mba_inventory_2=(val) ⇒ Object
351
352
353
354
|
# File 'app/models/employee_record.rb', line 351
def mba_inventory_2=(val)
self.mba_inventory ||= Array.new(3)
self.mba_inventory[1] = val
end
|
#mba_inventory_3 ⇒ Object
356
357
358
|
# File 'app/models/employee_record.rb', line 356
def mba_inventory_3
mba_inventory&.dig(2)
end
|
#mba_inventory_3=(val) ⇒ Object
360
361
362
363
|
# File 'app/models/employee_record.rb', line 360
def mba_inventory_3=(val)
self.mba_inventory ||= Array.new(3)
self.mba_inventory[2] = val
end
|
attr_accessible :title, :body
150
|
# File 'app/models/employee_record.rb', line 150
belongs_to :party, optional: true, touch: true
|
#praises ⇒ ActiveRecord::Relation<Praise>
164
|
# File 'app/models/employee_record.rb', line 164
has_many :praises, through: :appraisals
|
#profile_picture ⇒ Image
153
|
# File 'app/models/employee_record.rb', line 153
belongs_to :profile_picture, class_name: 'Image', optional: true
|
216
217
218
219
220
|
# File 'app/models/employee_record.rb', line 216
def
res = self.class..invert
res = res.select { |k, _v| k.in?( || []) } if .present?
res
end
|
#set_first_anniversary ⇒ Object
374
375
376
377
378
379
380
381
382
|
# File 'app/models/employee_record.rb', line 374
def set_first_anniversary
return if hire_date.blank?
return unless hire_date_changed? || next_work_anniversary.nil? || next_work_anniversary < Date.current
na = hire_date.dup.change(year: Date.current.year)
na += 1.year if na < Date.current
self.next_work_anniversary = na
end
|
#set_first_birthday ⇒ Object
365
366
367
368
369
370
371
372
|
# File 'app/models/employee_record.rb', line 365
def set_first_birthday
return if next_birthday.present? && next_birthday > Date.current
return if employee.dob.blank?
nb = employee.dob.dup.change(year: Date.current.year)
nb += 1.year if nb < Date.current
self.next_birthday = nb
end
|
#should_generate_new_friendly_id? ⇒ Boolean
204
205
206
|
# File 'app/models/employee_record.rb', line 204
def should_generate_new_friendly_id?
slug.blank? || will_save_change_to_party_id?
end
|
#signature_picture ⇒ Image
154
|
# File 'app/models/employee_record.rb', line 154
belongs_to :signature_picture, class_name: 'Image', optional: true
|
#signature_picture_small ⇒ Object
289
290
291
292
293
|
# File 'app/models/employee_record.rb', line 289
def signature_picture_small
return nil if signature_picture.nil?
signature_picture.image_url(width: 80)
end
|
#strength_themes ⇒ ActiveRecord::Relation<StrengthTheme>
158
|
# File 'app/models/employee_record.rb', line 158
has_many :strength_themes, -> { order(:priority) }
|
#sync_profile_picture_to_party ⇒ Object
Sync profile_picture_id to Party.profile_image_id
This keeps the legacy employee_record.profile_picture_id in sync with the
consolidated Party.profile_image_id column
387
388
389
390
391
|
# File 'app/models/employee_record.rb', line 387
def sync_profile_picture_to_party
return unless profile_picture_id_changed? && party.present?
party.update_column(:profile_image_id, profile_picture_id)
end
|
#visa_duration_months ⇒ Object
393
394
395
396
397
398
399
|
# File 'app/models/employee_record.rb', line 393
def visa_duration_months
return 0 if visa_start_date.blank? || visa_end_date.blank?
months = ((visa_end_date.year * 12) + visa_end_date.month) - ((visa_start_date.year * 12) + visa_start_date.month)
months -= 1 if visa_end_date.day < visa_start_date.day
[months, 0].max
end
|
#years_at_work ⇒ Object
295
296
297
298
299
|
# File 'app/models/employee_record.rb', line 295
def years_at_work
return unless hire_date
((Date.current - hire_date) / 365).floor
end
|