Class: TimeOffPartialDay
- Inherits:
-
Object
- Object
- TimeOffPartialDay
- Defined in:
- app/services/time_off_partial_day.rb
Overview
Shared rules for hour-based partial-day PTO (aligned with Crm::ManagerScheduleGridSlot).
Used by Employee#day_status_employee_event / #capacity_ratio and Daily Focus prompts.
Constant Summary collapse
- HOURS_EPSILON =
0.001
Class Method Summary collapse
-
.hour_unit_partial_day?(time_off_request_date:, schedule_day_hours:, time_off_request:) ⇒ Boolean
Hour-unit request with some PTO hours taken but less than a full scheduled day (grid partial-day mode).
-
.net_work_hours_from_planned(planned) ⇒ Float?
Net working hours inside the planned window (subtracts lunch overlap unless skip_lunch).
- .parse_hhmm(str) ⇒ Object
-
.partial_day_hour_pto?(time_off_request_date:, working_hours_on_date:, time_off_request:) ⇒ Boolean
Approved calendar row: positive hour PTO and not a full day off (matches manager schedule grid).
-
.planned_inner_hash(time_off_request_date) ⇒ Object
Inner "planned" hash from TimeOffRequestDate#planned_work_day JSON (start/end/lunch HH:MM).
Class Method Details
.hour_unit_partial_day?(time_off_request_date:, schedule_day_hours:, time_off_request:) ⇒ Boolean
Hour-unit request with some PTO hours taken but less than a full scheduled day (grid partial-day mode).
18 19 20 21 22 23 24 |
# File 'app/services/time_off_partial_day.rb', line 18 def self.hour_unit_partial_day?(time_off_request_date:, schedule_day_hours:, time_off_request:) return false if time_off_request_date.blank? || time_off_request.blank? return false unless time_off_request.time_off_type&.unit == 'hour' return false if schedule_day_hours.blank? time_off_request_date.amount.to_d < schedule_day_hours.to_d - HOURS_EPSILON end |
.net_work_hours_from_planned(planned) ⇒ Float?
Net working hours inside the planned window (subtracts lunch overlap unless skip_lunch).
40 41 42 43 44 45 46 47 48 49 50 |
# File 'app/services/time_off_partial_day.rb', line 40 def self.net_work_hours_from_planned(planned) planned = planned.with_indifferent_access ws = parse_hhmm(planned[:start_time]) we = parse_hhmm(planned[:end_time]) return nil unless ws && we && we > ws dur = we - ws return dur.round(4) if ActiveModel::Type::Boolean.new.cast(planned[:skip_lunch]) apply_planned_lunch_subtraction(dur, planned, ws, we).round(4) end |
.parse_hhmm(str) ⇒ Object
63 64 65 66 67 68 69 70 |
# File 'app/services/time_off_partial_day.rb', line 63 def self.parse_hhmm(str) return if str.blank? t = Time.zone.parse("2000-01-01 #{str}") t.hour + (t.min / 60.0) rescue ArgumentError, TypeError nil end |
.partial_day_hour_pto?(time_off_request_date:, working_hours_on_date:, time_off_request:) ⇒ Boolean
Approved calendar row: positive hour PTO and not a full day off (matches manager schedule grid).
27 28 29 30 31 32 33 34 35 36 |
# File 'app/services/time_off_partial_day.rb', line 27 def self.partial_day_hour_pto?(time_off_request_date:, working_hours_on_date:, time_off_request:) return false unless working_hours_on_date.to_f.positive? return false unless time_off_request_date.amount.to_d.positive? hour_unit_partial_day?( time_off_request_date: time_off_request_date, schedule_day_hours: working_hours_on_date, time_off_request: time_off_request ) end |
.planned_inner_hash(time_off_request_date) ⇒ Object
Inner "planned" hash from TimeOffRequestDate#planned_work_day JSON (start/end/lunch HH:MM).
9 10 11 12 13 14 15 |
# File 'app/services/time_off_partial_day.rb', line 9 def self.planned_inner_hash(time_off_request_date) raw = time_off_request_date&.planned_work_day return {} unless raw.is_a?(Hash) p = raw.with_indifferent_access[:planned] p.is_a?(Hash) ? p.with_indifferent_access : {} end |