diff --git a/drivers/place/area_management.cr b/drivers/place/area_management.cr index 160a80d1a8..359ec23f21 100644 --- a/drivers/place/area_management.cr +++ b/drivers/place/area_management.cr @@ -470,6 +470,28 @@ class Place::AreaManagement < PlaceOS::Driver desk_checked_in: desk_checked_in, } + # Group upcoming desk bookings by desk ID for frontend tooltip support + desk_bookings_map = Hash(String, Array(Hash(String, JSON::Any))).new { |h, k| h[k] = [] of Hash(String, JSON::Any) } + upcoming = location_service.upcoming_bookings(level_id).get.as_a + upcoming.each do |loc| + next unless loc["location"]?.try(&.as_s) == "booking" && loc["type"]?.try(&.as_s) == "desk" + desk_id = loc["map_id"]?.try(&.as_s) || loc["asset_id"]?.try(&.as_s) + next unless desk_id + + entry = {} of String => JSON::Any + {"booking_id", "started_at", "ends_at", "duration", "staff_name", "staff_email", "checked_in"}.each do |key| + if val = loc[key]? + entry[key] = val + end + end + desk_bookings_map[desk_id] << entry + end + + # Sort bookings per desk by start time + desk_bookings_map.each_value(&.sort_by! { |b| b["started_at"]?.try(&.as_i64) || 0_i64 }) + + self["#{level_id}:desk_bookings"] = desk_bookings_map + # we need to know the map dimensions to be able to count people in areas map_width = 100.0 map_height = 100.0 diff --git a/drivers/place/desk_bookings_locations.cr b/drivers/place/desk_bookings_locations.cr index 425d14ad06..4b23076ab0 100644 --- a/drivers/place/desk_bookings_locations.cr +++ b/drivers/place/desk_bookings_locations.cr @@ -96,8 +96,8 @@ class Place::DeskBookingsLocations < PlaceOS::Driver case event.action when "create" - return unless event.in_progress? - # Check if this event is happening now + # Include future bookings for today so "Free until..." can see upcoming bookings + return unless event.booking_end > Time.utc.to_unix logger.debug { "adding new booking" } @bookings[event.user_email] << event when "cancelled", "rejected" @@ -109,9 +109,9 @@ class Place::DeskBookingsLocations < PlaceOS::Driver return unless event.in_progress? @bookings[event.user_email].each { |booking| booking.checked_in = true if booking.id == event.id } when "changed" - # Check if this booking is for today and update as required + # Keep future bookings for today so "Free until..." can see upcoming bookings @bookings[event.user_email].reject! { |booking| booking.id == event.id } - @bookings[event.user_email] << event if event.in_progress? + @bookings[event.user_email] << event if event.booking_end > Time.utc.to_unix else # ignore the update (approve) logger.debug { "booking event was ignored" } @@ -155,6 +155,17 @@ class Place::DeskBookingsLocations < PlaceOS::Driver logger.debug { "searching devices in zone #{zone_id}" } return [] of Nil if location && location != "booking" + bookings = [] of Booking + @bookings.each_value(&.each { |booking| + next unless zone_id.in?(booking.zones) + next unless booking.in_progress? + bookings << booking + }) + map_bookings(bookings) + end + + def upcoming_bookings(zone_id : String) + logger.debug { "fetching upcoming bookings in zone #{zone_id}" } bookings = [] of Booking @bookings.each_value(&.each { |booking| next unless zone_id.in?(booking.zones) @@ -237,10 +248,12 @@ class Place::DeskBookingsLocations < PlaceOS::Driver @known_users : Hash(String, Tuple(String, String)) = Hash(String, Tuple(String, String)).new def query_desk_bookings : Nil + period_end = (Time.utc + 24.hours).to_unix + ids = Set(Int64).new bookings = [] of JSON::Any zones.each do |zone| - bookings.concat staff_api.query_bookings(type: @booking_type, zones: {zone}).get.as_a + bookings.concat staff_api.query_bookings(type: @booking_type, period_end: period_end, zones: {zone}).get.as_a rescue error logger.warn(exception: error) { "failed to query bookings in zone: #{zone}" } end diff --git a/drivers/place/desk_bookings_locations_spec.cr b/drivers/place/desk_bookings_locations_spec.cr index 7c83616fd1..10c8bc4315 100644 --- a/drivers/place/desk_bookings_locations_spec.cr +++ b/drivers/place/desk_bookings_locations_spec.cr @@ -25,7 +25,7 @@ end # :nodoc: class StaffAPIMock < DriverSpecs::MockDriver - def query_bookings(type : String, zones : Array(String)) + def query_bookings(type : String, zones : Array(String) = [] of String, period_start : Int64? = nil, period_end : Int64? = nil) logger.debug { "Querying desk bookings!" } now = Time.local