Class: HrLite::LeaveBalance

Inherits:
ApplicationRecord show all
Defined in:
app/models/hr_lite/leave_balance.rb

Overview

Hybrid balance: only carry-in and manual adjustments are stored; entitlement accrues as a pure function of the policy and used is recomputed live from approved requests — so a holiday added after an approval self-heals both the quota and payroll.

year is a LeaveYear key (calendar year by default; with config.leave_year_start_month = 7, key 2026 = Jul 2026 – Jun 2027). Entitlement prorates from the joining date, Keka-style: joined on or before the 15th → that month counts; after the 15th → from next month.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.for(user, leave_type, year) ⇒ Object



18
19
20
# File 'app/models/hr_lite/leave_balance.rb', line 18

def self.for(user, leave_type, year)
  find_or_initialize_by(user_id: user.id, leave_type: leave_type, year: year)
end

Instance Method Details

#available(as_of: Date.current) ⇒ Object



36
37
38
# File 'app/models/hr_lite/leave_balance.rb', line 36

def available(as_of: Date.current)
  entitled(as_of: as_of) - used
end

#entitled(as_of: Date.current) ⇒ Object



22
23
24
25
26
# File 'app/models/hr_lite/leave_balance.rb', line 22

def entitled(as_of: Date.current)
  return Float::INFINITY if leave_type.unlimited?

  (accrued_base(as_of) + carried_forward + adjustment).round(1)
end

#usedObject



28
29
30
31
32
33
34
# File 'app/models/hr_lite/leave_balance.rb', line 28

def used
  range = LeaveYear.range(year)
  requests = LeaveRequest.approved
                         .where(user_id: user_id, leave_type_id: leave_type_id)
                         .where(start_date: range)
  requests.sum { |request| LeaveDayCounter.count(request) }
end