Class: SchedulerAvailabilityService

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

Constant Summary collapse

SLOT_INCREMENT_MINUTES =
15

Instance Method Summary collapse

Constructor Details

#initialize(booking_page, date, guest_timezone: 'America/Chicago', employee: nil, prefetched_gcal_busy: nil) ⇒ SchedulerAvailabilityService

prefetched_gcal_busy: optional Hash { employee_id => { Date => [end:] } }
When provided, skips per-day Google Calendar API calls (used by available_dates batch).



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

def initialize(booking_page, date, guest_timezone: 'America/Chicago', employee: nil, prefetched_gcal_busy: nil)
  @booking_page = booking_page
  @date = date.is_a?(Date) ? date : Date.parse(date.to_s)
  @guest_timezone = guest_timezone
  @duration = booking_page.duration_minutes
  @buffer_before = booking_page.buffer_before_minutes
  @buffer_after = booking_page.buffer_after_minutes
  @prefetched_gcal_busy = prefetched_gcal_busy

  @employees = if employee
                 [employee]
               else
                 booking_page.active_hosts.includes(:employee).map(&:employee)
               end
end

Instance Method Details

#assign_host(eligible_employee_ids) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
# File 'app/services/scheduler_availability_service.rb', line 71

def assign_host(eligible_employee_ids)
  return eligible_employee_ids.first if eligible_employee_ids.size == 1

  booking_counts = SchedulerBooking.confirmed
                                   .where(scheduler_booking_page: @booking_page)
                                   .where(employee_id: eligible_employee_ids)
                                   .group(:employee_id)
                                   .count

  eligible_employee_ids.min_by { |id| booking_counts[id] || 0 }
end

#available_slotsObject



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'app/services/scheduler_availability_service.rb', line 32

def available_slots
  return [] if @employees.empty?
  return [] if @date < Date.current
  return [] if @date > Date.current + @booking_page.max_days_ahead.days

  all_slots = {}

  @employees.each do |employee|
    slots = slots_for_employee(employee)
    slots.each do |slot_start|
      key = slot_start.to_i
      all_slots[key] ||= { starts_at: slot_start, employee_ids: [] }
      all_slots[key][:employee_ids] << employee.id
    end
  end

  all_slots.values
           .sort_by { |s| s[:starts_at] }
           .map do |slot|
             guest_time = slot[:starts_at].in_time_zone(@guest_timezone)
             {
               time: guest_time.strftime('%-l:%M %p'),
               starts_at: slot[:starts_at].iso8601,
               employee_ids: slot[:employee_ids]
             }
           end
end

#has_availability?Boolean

Returns:

  • (Boolean)


24
25
26
27
28
29
30
# File 'app/services/scheduler_availability_service.rb', line 24

def has_availability?
  return false if @employees.empty?
  return false if @date < Date.current
  return false if @date > Date.current + @booking_page.max_days_ahead.days

  @employees.any? { |employee| slots_for_employee(employee).any? }
end

#verify_slot(starts_at) ⇒ Object



60
61
62
63
64
65
66
67
68
69
# File 'app/services/scheduler_availability_service.rb', line 60

def verify_slot(starts_at)
  starts_at = Time.zone.parse(starts_at) if starts_at.is_a?(String)
  ends_at = starts_at + @duration.minutes

  @employees.filter_map do |employee|
    next unless slot_available_for_employee?(employee, starts_at, ends_at)

    employee.id
  end
end