Class: PayrollPeriod

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

Constant Summary collapse

STAGES =
{
  IN_PROGRESS: '01'
}

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ApplicationRecord

define_decrypted_attribute, define_decrypted_attributes, #errors_in_bullet_points, primary_connection, special_connection

Class Method Details

.format_period(period_no, start_date, end_date, revision_no = 1) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'app/models/payroll_period.rb', line 14

def format_period(period_no, start_date, end_date, revision_no = 1)
  if start_date.year == end_date.year
    formatted_start_date = I18n.l(start_date, format: :short)
    formatted_end_date = I18n.l(end_date, format: :long)
  else
    formatted_start_date = I18n.l(start_date, format: :long)
    formatted_end_date = I18n.l(end_date, format: :long)
  end

  if revision_no > 1
    "##{period_no}-#{revision_no}: #{formatted_start_date} - #{formatted_end_date}"
  else
    "##{period_no}: #{formatted_start_date} - #{formatted_end_date}"
  end
end

.years_for_company(company_id:) ⇒ Object



10
11
12
# File 'app/models/payroll_period.rb', line 10

def years_for_company(company_id:)
  PayrollPeriod.where(company_id: company_id).select(:year).distinct.pluck(:year)
end

Instance Method Details

#clone_timesheets(from_payroll_period_id:, create_default_hours_per_week:, create_employees_default_hours_per_week:, default_hours_per_week:, user_name:) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'app/models/payroll_period.rb', line 155

def clone_timesheets(
  from_payroll_period_id:,
  create_default_hours_per_week:,
  create_employees_default_hours_per_week:,
  default_hours_per_week:,
  user_name:
)
  option = if create_default_hours_per_week
             '02'
           elsif create_employees_default_hours_per_week
             '03'
           else
             '01'
           end
  ActiveRecord::Base.execute_procedure(
    'pr_clone_time_sheet',
    company_id,
    from_payroll_period_id,
    payroll_period_id,
    user_name,
    option,
    default_hours_per_week
  )[0]
end

#create_transaction(scheduled_deposit_date:, user_name:, start_date: Time.now, deposit_date: nil, completed_date: nil) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'app/models/payroll_period.rb', line 130

def create_transaction(
  scheduled_deposit_date:,
  user_name:,
  start_date: Time.now,
  deposit_date: nil,
  completed_date: nil
)
  if scheduled_deposit_date > latest_deposit_date || scheduled_deposit_date < Date.today.beginning_of_day
    raise ActiveRecord::RecordInvalid.new(
      self,
      'Invalid scheduled deposit date.'
    )
  end
  create_transaction_header(
    company_id: company_id,
    payroll_period_id: payroll_period_id,
    start_date: start_date,
    completed_date: completed_date,
    scheduled_deposit_date: scheduled_deposit_date,
    deposit_date: deposit_date,
    stage: STAGES[:IN_PROGRESS],
    user_name: user_name
  )
end

#current?Boolean

Returns:

  • (Boolean)


126
127
128
# File 'app/models/payroll_period.rb', line 126

def current?
  Time.zone.now.between?(start_date, end_date)
end

#days_countObject



94
95
96
# File 'app/models/payroll_period.rb', line 94

def days_count
  duration.in_days.to_f.ceil + 1
end

#durationObject



68
69
70
# File 'app/models/payroll_period.rb', line 68

def duration
  (end_date - start_date).seconds
end

#duration_spentObject



72
73
74
75
76
# File 'app/models/payroll_period.rb', line 72

def duration_spent
  return nil if Time.zone.now > end_date

  (Time.zone.now - start_date).seconds
end

#formattedObject



57
58
59
# File 'app/models/payroll_period.rb', line 57

def formatted
  PayrollPeriod.format_period(period_no, start_date, end_date)
end

#formatted_end_dateObject



108
109
110
# File 'app/models/payroll_period.rb', line 108

def formatted_end_date
  I18n.l(end_date, format: :long)
end

#formatted_start_dateObject



104
105
106
# File 'app/models/payroll_period.rb', line 104

def formatted_start_date
  I18n.l(start_date, format: :long)
end

#has_employee_without_bank_account?Boolean

Returns:

  • (Boolean)


53
54
55
# File 'app/models/payroll_period.rb', line 53

def has_employee_without_bank_account?
  employees.any? { |employee| employee.bank_accounts.blank? }
end

#has_timesheets?Boolean

Returns:

  • (Boolean)


122
123
124
# File 'app/models/payroll_period.rb', line 122

def has_timesheets?
  employee_timesheets.exists?
end

#latest_deposit_dateObject



112
113
114
115
116
# File 'app/models/payroll_period.rb', line 112

def latest_deposit_date
  return nil unless end_date.present?

  [4.business_days.after(end_date), 4.business_days.after(Date.today)].max
end

#locked?Boolean

Returns:

  • (Boolean)


45
46
47
# File 'app/models/payroll_period.rb', line 45

def locked?
  payroll_transaction_header.present? && payroll_transaction_header.locked?
end

#payroll_frequency_descriptionObject



61
62
63
64
65
66
# File 'app/models/payroll_period.rb', line 61

def payroll_frequency_description
  TypesMaster
    .payroll_frequencies
    .find_by(type: frequency)
    .type_description
end

#payroll_transaction_headerObject



37
38
39
# File 'app/models/payroll_period.rb', line 37

def payroll_transaction_header
  payroll_transaction_headers.last
end

#payroll_transaction_header_idObject



41
42
43
# File 'app/models/payroll_period.rb', line 41

def payroll_transaction_header_id
  payroll_transaction_header_ids.first
end

#remaining_days_countObject



98
99
100
101
102
# File 'app/models/payroll_period.rb', line 98

def remaining_days_count
  return nil if Time.zone.now > end_date

  (end_date - Time.zone.now).to_i / 86_400
end

#remaining_duration_to_run_payrollObject



78
79
80
81
82
# File 'app/models/payroll_period.rb', line 78

def remaining_duration_to_run_payroll
  return nil if Time.zone.now > run_payroll_deadline

  (run_payroll_deadline - Time.zone.now).seconds
end

#run_payroll_deadlineObject



84
85
86
# File 'app/models/payroll_period.rb', line 84

def run_payroll_deadline
  1.business_day.after(end_date) + 17.hours # the payroll should be run before 5 PM, the business day after the end date
end

#run_payroll_deadline_passed?Boolean

Returns:

  • (Boolean)


88
89
90
91
92
# File 'app/models/payroll_period.rb', line 88

def run_payroll_deadline_passed?
  return false if run_payroll_deadline.nil?

  Time.zone.now > run_payroll_deadline
end

#stats(gross_salary:, net_salary:, deductions:, employer_contribution:) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'app/models/payroll_period.rb', line 180

def stats(
  gross_salary:,
  net_salary:,
  deductions:,
  employer_contribution:
)
  record = as_json(
    methods: %i[payroll_frequency_description formatted payroll_transaction_header_id]
  )

  {
    payroll_period: record,
    gross_salary: gross_salary&.abs,
    net_salary: net_salary&.abs,
    deductions: deductions&.abs,
    employer_contribution: employer_contribution&.abs
  }.compact
end

#timesheets_countObject



118
119
120
# File 'app/models/payroll_period.rb', line 118

def timesheets_count
  employee_timesheets.count
end

#unlocked?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'app/models/payroll_period.rb', line 49

def unlocked?
  !locked?
end

#wizard_info(option:) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'app/models/payroll_period.rb', line 207

def wizard_info(option:)
  info = as_json(
    methods: %i[
      latest_deposit_date
      has_timesheets?
      formatted
      payroll_period_id
    ],
    only: []
  )

  option_label = if option == 'open_period'
                   wizard_open_period_label
                 elsif option == 'next_period'
                   wizard_next_period_label
                 end

  info.merge!(
    option_label: option_label
  )

  info
end

#wizard_next_period_labelObject



203
204
205
# File 'app/models/payroll_period.rb', line 203

def wizard_next_period_label
  "#{I18n.t('payroll.payroll_run.run.new')} #{formatted}"
end

#wizard_open_period_labelObject



199
200
201
# File 'app/models/payroll_period.rb', line 199

def wizard_open_period_label
  "#{I18n.t('payroll.payroll_run.run.resume')} #{formatted}"
end