Class: HrLite::RegularizationRequest
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- HrLite::RegularizationRequest
- Defined in:
- app/models/hr_lite/regularization_request.rb
Overview
"I forgot to punch — please fix that day." The employee proposes the times; an admin approves, which applies them to the attendance record with the full regularization audit trail (same fields the manual admin fix writes), or rejects with a note.
Defined Under Namespace
Classes: InvalidMerge
Constant Summary collapse
- STATUSES =
%w[pending approved rejected cancelled].freeze
Instance Method Summary collapse
-
#approve!(actor:, note: nil) ⇒ Object
Applies the proposed times to the day's record (creating it if the person never punched at all).
- #cancel!(actor:) ⇒ Object
-
#punch ⇒ Object
Current punch state for the approver's context.
- #reject!(actor:, note:) ⇒ Object
- #times_label ⇒ Object
Instance Method Details
#approve!(actor:, note: nil) ⇒ Object
Applies the proposed times to the day's record (creating it if the person never punched at all). Only the provided times overwrite — a forgot-checkout ticket keeps the genuine GPS check-in untouched. A merge that would produce a nonsense record (checkout before the existing check-in, or a checkout with no check-in at all) raises InvalidMerge with the real story so the admin knows what to fix.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'app/models/hr_lite/regularization_request.rb', line 50 def approve!(actor:, note: nil) transition!("approved", actor, note) do # Re-checked at approval, not only at create: leave can be approved for # that day while the ticket waits in the queue, and DayStatus ranks # full-day leave above any punch — so the "fix" would write a record # nothing reads while telling everyone attendance had been corrected. if LeaveRequest.active_on(date).where(user_id: user_id, half_day: false).exists? raise InvalidMerge, "the day is now covered by approved leave — cancel the leave first" end record = AttendanceRecord.find_or_initialize_by(user_id: user_id, date: date) record.check_in_at = check_in_at if check_in_at record.check_out_at = check_out_at if check_out_at if record.check_in_at.nil? raise InvalidMerge, "the day has no check-in — the ticket needs a check-in time too" end record.status = "present" if record.status.blank? record.regularized_by_id = actor.id record.regularized_at = Time.current record.regularization_note = "Ticket ##{id}: #{reason}" raise InvalidMerge, record.errors..to_sentence unless record.valid? record.save! AuditLog.create!( actor: actor, action: "regularize", subject_type: record.class.name, subject_id: record.id, audited_changes: { "date" => record.date.to_s, "ticket" => id, "note" => reason } ) end Notifications.publish( "regularization.approved", title: "Attendance fixed for #{date.strftime('%d %b')} (#{times_label})", body: decision_note.presence, path: "/regularization_requests", bell_to: [ user ], email_to: [ user ] ) true end |
#cancel!(actor:) ⇒ Object
103 104 105 106 107 108 109 110 111 112 |
# File 'app/models/hr_lite/regularization_request.rb', line 103 def cancel!(actor:) transition!("cancelled", actor, nil) Notifications.publish( "regularization.cancelled", title: "#{HrLite.display_name(user)} cancelled a regularization ticket (#{date.strftime('%d %b')})", path: "/admin/regularization_requests", bell_to: HrLite.admin_users ) true end |
#punch ⇒ Object
Current punch state for the approver's context.
38 39 40 |
# File 'app/models/hr_lite/regularization_request.rb', line 38 def punch AttendanceRecord.find_by(user_id: user_id, date: date) end |
#reject!(actor:, note:) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 |
# File 'app/models/hr_lite/regularization_request.rb', line 91 def reject!(actor:, note:) transition!("rejected", actor, note) Notifications.publish( "regularization.rejected", title: "Regularization rejected — #{date.strftime('%d %b')}", body: decision_note.presence, path: "/regularization_requests", bell_to: [ user ], email_to: [ user ] ) true end |
#times_label ⇒ Object
33 34 35 |
# File 'app/models/hr_lite/regularization_request.rb', line 33 def times_label [ check_in_at&.strftime("%H:%M"), check_out_at&.strftime("%H:%M") ].compact.join(" – ").presence || "—" end |