Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get availability for a bookable #22

Open
chrisedington opened this issue Feb 28, 2017 · 4 comments
Open

Get availability for a bookable #22

chrisedington opened this issue Feb 28, 2017 · 4 comments

Comments

@chrisedington
Copy link

chrisedington commented Feb 28, 2017

Hi,

I was wondering if there is a way I can get the available times for a specific bookable.

My bookable at the moment is created like this:

session = Session.new
session.capacity = 5
session.schedule = IceCube::Schedule.new(iteration.date, duration: 90.minutes)
session.schedule.add_recurrence_rule IceCube::Rule.daily.hour_of_day(9,10, 11, 12, 14, 15, 16, 17)
session.save!

So ideally I would like to display a list of "available times" which can be reserved, based on current availability. I don't want to show a full list of the slots mentioned in the snippet above, rather only the available ones.

I would imagine doingsession.availability(which doesn't exist) and getting back a list.

Any advice on how I can achieve this?

@Chosko
Copy link
Collaborator

Chosko commented Mar 1, 2017

The availability of a bookable is calculated at runtime, given an hash of options. This hash of options must provide all the condition requested by a booking instance, included the time (or interval) at which you want to book the resource (if :time_type != :none).

As you can see in the source code, there are complex calculations to understand if the bookable is really available, and it's not possible to have a list of availabilities without making those calculations for each possible time.
A way to get a real list of availabilities would require to iterate over all the possible 'slots' (WARNING: you can have an infinite number of slots!) and call check_availability! with a temporary hash of options for each slot....

I imagine a feasible similar feature. It would be a function "bookable.get_availabilities(from: start_time, to: end_time)" that iterates over the slots of the schedule, but limiting the calculation between the given interval.

PRs or suggestions are appreciated

@colemerrick
Copy link

@Chosko I'm interested in this as well and can help. Would it depend on the schedule you assign to the bookable? For example, if a bookable is available daily for a day at a time, could you loop through the bookings, create an array of the days the bookable is booked, and subtract it from an array that reflects the days of the month. Obviously a simple use case, but maybe it can be applied to some more complicated ones - with the idea being to limit the infinite number of slots such that one can define how far in advance you want to print out the available ones.

@micksabox
Copy link

micksabox commented Mar 3, 2017

I'm interested in a solution and am also available to help.
One requirement I have is that not only do I need the availability for 1 specific Bookable instance, I need ALL available time slots among N number of Bookables of same class, within a maximum day time frame.

I also need the algorithm to be efficient, because I'm planning on having 15 min schedule intervals per Bookable. So worst case, that is 96 intervals per day multiplied by 8 = 768, where N is equal to 8.

I'm not sure how schedule is serialized as :text, but maybe there needs to be a separate DB construct to model availability more efficiently?

@zernie
Copy link

zernie commented Jun 4, 2021

I know that this is an old issue, but ...has anyone been able to implement this ?

My dumb implementation is not working correctly:)

  # only works for time_type=range
  def availability(time_start, time_end, amount: 1, duration: nil)
        overlapped = ActsAsBookable::Booking.overlapped(self, time_start: time_start, time_end: time_end).to_a

        self.schedule.occurrences_between(time_start, time_end).select do |occurrence|
          time_end = if duration
                       occurrence.start_time + duration
                     else
                       occurrence.end_time
                     end
          self.check_availability(time_start: occurrence.start_time, time_end: time_end, scope: overlapped, amount: amount)
        end
      end

##
# Real capacity check (calculated with overlapped bookings)
#
overlapped = if opts[:scope]
                       opts[:scope]
                     else
                       ActsAsBookable::Booking.overlapped(self, opts)
                     end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants