Class: WorkSchedule
Overview
== Schema Information
Table name: work_schedules
Database name: primary
id :bigint not null, primary key
amount :decimal(, )
approved_by :integer
approved_on :date
created_by :integer
effective_date :date
expiry_date :date
notes :text
state :string default("pending"), not null
created_at :datetime not null
updated_at :datetime not null
employee_id :integer
Indexes
index_work_schedules_on_approved_by (approved_by)
index_work_schedules_on_approved_on (approved_on)
index_work_schedules_on_created_by (created_by)
index_work_schedules_on_effective_date (effective_date)
index_work_schedules_on_employee_id (employee_id)
index_work_schedules_on_expiry_date (expiry_date)
index_work_schedules_on_state (state)
Foreign Keys
fk_rails_... (approved_by => parties.id)
fk_rails_... (created_by => parties.id)
Constant Summary
Models::Auditable::ALWAYS_IGNORED
Instance Attribute Summary collapse
#updater
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
#publish_event
Instance Attribute Details
#amount ⇒ Object
44
|
# File 'app/models/work_schedule.rb', line 44
validates :amount, numericality: { greater_than: 0 }, presence: true
|
#effective_date ⇒ Object
43
|
# File 'app/models/work_schedule.rb', line 43
validates :employee_id, :effective_date, presence: true
|
#employee_id ⇒ Object
43
|
# File 'app/models/work_schedule.rb', line 43
validates :employee_id, :effective_date, presence: true
|
#skip_approval ⇒ Object
validate :validate_approved_schedules_limit, on: :create
53
54
55
|
# File 'app/models/work_schedule.rb', line 53
def skip_approval
@skip_approval
end
|
Class Method Details
.effective_now ⇒ ActiveRecord::Relation<WorkSchedule>
A relation of WorkSchedules that are effective now. Active Record Scope
59
60
61
62
63
64
65
66
67
|
# File 'app/models/work_schedule.rb', line 59
scope :effective_now, ->(exclude_schedule_id = nil) {
where(
state: 'approved',
effective_date: ..Date.current,
expiry_date: [nil, Date.current..]
)
.where.not(id: exclude_schedule_id)
.order(effective_date: :desc)
}
|
.effective_on ⇒ ActiveRecord::Relation<WorkSchedule>
A relation of WorkSchedules that are effective on. Active Record Scope
68
69
70
|
# File 'app/models/work_schedule.rb', line 68
scope :effective_on, ->(date) {
where('effective_date <= ? AND (expiry_date IS NULL OR expiry_date >= ?)', date, date).where(state: 'approved')
}
|
Instance Method Details
#after_approved_schedule_tasks ⇒ Object
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
# File 'app/models/work_schedule.rb', line 142
def after_approved_schedule_tasks
if effective_date >= Date.today
current_schedule = employee.work_schedules.effective_now(id).first
if current_schedule.present?
current_schedule.update(expiry_date: effective_date)
if current_schedule.expiry_date == Date.today
current_schedule.expire!
end
end
end
send_approved_email
end
|
#auto_assign_time_off_policy ⇒ Object
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
|
# File 'app/models/work_schedule.rb', line 165
def auto_assign_time_off_policy
total_hours = amount
applicable_policies = TimeOffPolicy.where(hours_per_week: total_hours)
if applicable_policies.empty?
errors.add(:base, "No time-off policy created for #{total_hours} hours per week. Please contact HW Team or HR to create a new Policy for this work schedule.")
raise ActiveRecord::RecordInvalid, self
end
tenure = ((effective_date - employee.employee_record.hire_date) / 365.25).floor
selected_policy = applicable_policies.find do |policy|
tenure >= policy.min_tenure && (policy.max_tenure.nil? || tenure < policy.max_tenure)
end
unless selected_policy
errors.add(:base, "No time-off policy matches the tenure criteria for #{total_hours} hours per week.")
raise ActiveRecord::RecordInvalid, self
end
existing_assignment = employee.time_off_policy_assignments.find_by(
time_off_policy_id: selected_policy.id,
)
return if existing_assignment
employee.time_off_policy_assignments.create!(
time_off_policy: selected_policy,
work_schedule_id: id,
accrual_start_date: effective_date
)
end
|
#before_approved_schedule_tasks ⇒ Object
def send_udpate_email
InternalMailer.update_work_schedule(self).deliver_now
end
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
# File 'app/models/work_schedule.rb', line 126
def before_approved_schedule_tasks
ActiveRecord::Base.transaction do
self.approved_on = Date.today
auto_assign_time_off_policy
return true
rescue ActiveRecord::RecordInvalid => e
errors.add(:base, "Time-off policy assignment failed: #{e.message}")
false rescue StandardError => e
errors.add(:base, "Unexpected error during approval: #{e.message}")
false end
end
|
#changes_summary ⇒ Object
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
|
# File 'app/models/work_schedule.rb', line 222
def changes_summary
summary = {}
saved_changes.each do |attribute, values|
old_value, new_value = values
summary[attribute] = { old: old_value, new: new_value }
end
work_schedule_days.each do |day|
day_changes = {}
day.saved_changes.each do |attribute, values|
old_value, new_value = values
day_changes[attribute] = { old: old_value, new: new_value }
end
summary[day] = day_changes unless day_changes.empty?
end
summary
end
|
#check_approval_requirement ⇒ Object
110
111
112
113
114
115
116
|
# File 'app/models/work_schedule.rb', line 110
def check_approval_requirement
if skip_approval.to_b
approve
else
send_create_email
end
end
|
38
|
# File 'app/models/work_schedule.rb', line 38
belongs_to :creator, class_name: 'Employee', foreign_key: 'created_by'
|
37
|
# File 'app/models/work_schedule.rb', line 37
belongs_to :employee
|
#is_current? ⇒ Boolean
161
162
163
|
# File 'app/models/work_schedule.rb', line 161
def is_current?
approved? && effective_date <= Date.today && (expiry_date.nil? || expiry_date > Date.today)
end
|
#parent ⇒ Object
106
107
108
|
# File 'app/models/work_schedule.rb', line 106
def parent
employee
end
|
#send_approved_email ⇒ Object
#send_create_email ⇒ Object
41
|
# File 'app/models/work_schedule.rb', line 41
has_one :time_off_policy, through: :time_off_policy_assignment
|
40
|
# File 'app/models/work_schedule.rb', line 40
has_one :time_off_policy_assignment, dependent: :destroy
|
#to_detailed_json ⇒ Object
243
244
245
246
247
248
249
250
251
252
253
|
# File 'app/models/work_schedule.rb', line 243
def to_detailed_json
as_json(
only: [:id, :employee_id, :amount, :effective_date, :expiry_date, :state, :notes],
include: {
work_schedule_days: {
only: [:day_of_week, :hours],
methods: [:day_name, :formatted_start_time, :formatted_end_time, :formatted_lunch_times]
}
}
)
end
|
#update_policy_assignment ⇒ Object
206
207
208
209
210
211
212
213
214
215
216
|
# File 'app/models/work_schedule.rb', line 206
def update_policy_assignment
if saved_change_to_effective_date? || work_schedule_days_changed?
employee.time_off_policy_assignments.find_by(work_schedule_id: id)&.destroy
auto_assign_time_off_policy
end
end
|
#work_schedule_days ⇒ ActiveRecord::Relation<WorkScheduleDay>
39
|
# File 'app/models/work_schedule.rb', line 39
has_many :work_schedule_days, dependent: :destroy
|
#work_schedule_days_changed? ⇒ Boolean
218
219
220
|
# File 'app/models/work_schedule.rb', line 218
def work_schedule_days_changed?
work_schedule_days.any? { |day| day.saved_changes.present? }
end
|