Class: TimeOffBalanceCalculator

Inherits:
Object
  • Object
show all
Defined in:
app/services/time_off_balance_calculator.rb

Overview

Service object: time off balance calculator.

Instance Method Summary collapse

Constructor Details

#initialize(employee:, date: Date.current, time_off_type: nil, excluding_request_id: nil) ⇒ TimeOffBalanceCalculator

The calculator looks at the past balance first and then calculates future data based on requests.



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'app/services/time_off_balance_calculator.rb', line 6

def initialize(employee:, date: Date.current, time_off_type: nil, excluding_request_id: nil)
  @employee = employee
  # Coerce nil to today: the keyword default only applies when the kwarg is
  # omitted, but callers (e.g. Crm::TimeOffRequestsController#create) pass an
  # explicit `date: time_off_request.start_date`, which is nil when the form
  # is submitted without a start date — and used to crash at the
  # `@date <= Date.today` comparison below.
  @date = date || Date.current
  @time_off_type = time_off_type
  # When the employee is EDITING an existing time-off request, that
  # request's hours are already counted in `calculate_time_used` /
  # `calculate_time_pending`. Without excluding it, the projected-
  # balance check double-counts: validates the edited amount against
  # a balance that already deducted the original amount, producing
  # bogus "you're requesting more than your projected balance" errors
  # on edits that don't actually change the total.
  @excluding_request_id = excluding_request_id
  @vacation_time_off_type = TimeOffType.find(TimeOffType::VACATION_ID)
end

Instance Method Details

#callObject



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'app/services/time_off_balance_calculator.rb', line 26

def call
  balances = {}
  time_off_types = @time_off_type ? [@time_off_type] : TimeOffType.order(:id)

  time_off_types.each do |type|
    balances[type.name] = if type.id == TimeOffType::VACATION_ID
                            # This Vacation type is the main type of the PTO module. Needs to be treated differently since there are more calculations
                            calculate_vacation_balance
                          else
                            calculate_balance_for_type(type)
                          end
  end

  balances
end

#formatted_balancesObject



42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'app/services/time_off_balance_calculator.rb', line 42

def formatted_balances
  calculate.transform_values do |data|
    result = {
      time_used: format_number(data[:time_used]),
      unit: data[:unit],
      time_available: format_number(data[:time_available]),
      max_available: format_number(data[:max_available]),
      breakdown: data[:breakdown] || {}
    }
    result[:time_planned] = format_number(data[:time_planned]) if data[:time_planned].present?
    result
  end
end

#vacation_summaryObject



56
57
58
# File 'app/services/time_off_balance_calculator.rb', line 56

def vacation_summary
  calculate_vacation_summary
end