Files
chatwoot/app/models/leave.rb
T

109 lines
3.1 KiB
Ruby

# frozen_string_literal: true
# == Schema Information
#
# Table name: leaves
#
# id :bigint not null, primary key
# approved_at :datetime
# end_date :date not null
# leave_type :integer default("vacation"), not null
# reason :text
# start_date :date not null
# status :integer default("pending"), not null
# created_at :datetime not null
# updated_at :datetime not null
# account_id :bigint not null
# account_user_id :bigint not null
# approved_by_id :bigint
#
# Indexes
#
# index_leaves_on_account_and_status (account_id,status)
# index_leaves_on_account_id (account_id)
# index_leaves_on_account_user_and_dates (account_user_id,start_date,end_date)
# index_leaves_on_account_user_id (account_user_id)
# index_leaves_on_approved_by_id (approved_by_id)
# index_leaves_on_end_date (end_date)
# index_leaves_on_start_date (start_date)
# index_leaves_on_status (status)
#
class Leave < ApplicationRecord
belongs_to :account
belongs_to :account_user
belongs_to :approved_by, class_name: 'User', optional: true
has_one :user, through: :account_user
enum leave_type: {
vacation: 0,
sick: 1,
personal: 2,
maternity: 3,
paternity: 4,
bereavement: 5,
unpaid: 6
}
enum status: {
pending: 0,
approved: 1,
rejected: 2,
cancelled: 3
}
validates :start_date, presence: true
validates :end_date, presence: true
validates :leave_type, presence: true
validates :status, presence: true
validate :end_date_after_start_date
validate :no_overlapping_leaves, if: :approved?
scope :active, -> { approved.where('start_date <= ? AND end_date >= ?', Date.current, Date.current) }
scope :upcoming, -> { approved.where('start_date > ?', Date.current) }
scope :past, -> { where('end_date < ?', Date.current) }
scope :by_date_range, ->(start_date, end_date) { where('start_date <= ? AND end_date >= ?', end_date, start_date) }
before_update :set_approved_at, if: -> { status_changed? && approved? }
def active?
approved? && start_date <= Date.current && end_date >= Date.current
end
def days_count
return 0 unless start_date && end_date
(end_date - start_date).to_i + 1
end
def overlaps_with?(other_leave)
return false if other_leave == self
start_date <= other_leave.end_date && end_date >= other_leave.start_date
end
private
def end_date_after_start_date
return unless start_date && end_date
errors.add(:end_date, 'must be after or equal to start date') if end_date < start_date
end
def no_overlapping_leaves
overlapping_leaves = account_user.leaves
.approved
.where.not(id: id)
.by_date_range(start_date, end_date)
return unless overlapping_leaves.exists?
errors.add(:base, 'Leave dates overlap with an existing approved leave')
end
def set_approved_at
self.approved_at = Time.current
end
end