module ActiveBookings::Bookable::Core::InstanceMethods
Public Instance Methods
Accept a booking by a booker. This is an alias method, equivalent to @booker.book!(@bookable, opts)
@param booker The booker model @param opts The booking options
Example:
@room.book!(@user, from: Date.today, to: Date.tomorrow, amount: 2)
# File lib/active_bookings/bookable/core.rb, line 279 def book!(booker, opts={}) booker.book!(self, opts) end
# File lib/active_bookings/bookable/core.rb, line 293 def booker? self.class.booker? end
Check availability of current bookable
@param opts The booking options @return true if the bookable is available for given options, otherwise return false
Example:
@room.check_availability!(from: Date.today, to: Date.tomorrow, amount: 2)
# File lib/active_bookings/bookable/core.rb, line 262 def check_availability(opts) begin check_availability!(opts) rescue ActiveBookings::AvailabilityError false end end
Check availability of current bookable, raising an error if the bookable is not available
@param opts The booking options @return true if the bookable is available for given options @raise ActiveBookings::AvailabilityError
if the bookable is not available for given options
Example:
@room.check_availability!(from: Date.today, to: Date.tomorrow, amount: 2)
# File lib/active_bookings/bookable/core.rb, line 164 def check_availability!(opts) # validates options self.validate_booking_options!(opts) # Capacity check (done first because it doesn't require additional queries) if self.booking_opts[:capacity_type] != :none # Amount > capacity if opts[:amount] > self.capacity error = I18n.t('.active_bookings.availability.amount_gt_capacity', model: self.class.to_s) raise ActiveBookings::AvailabilityError.new error end end ## # Time check # if self.booking_opts[:time_type] == :range time_check_ok = true # If it's bookable across recurrences, just check start time and end time if self.booking_opts[:bookable_across_occurrences] # Check start time if !(ActiveBookings::TimeUtils.time_in_schedule?(self.schedule, opts[:time_start])) time_check_ok = false end # Check end time if !(ActiveBookings::TimeUtils.time_in_schedule?(self.schedule, opts[:time_end])) time_check_ok = false end # If it's not bookable across recurrences, check if the whole interval is included in an occurrence else # Check the whole interval if !(ActiveBookings::TimeUtils.interval_in_schedule?(self.schedule, opts[:time_start], opts[:time_end])) time_check_ok = false end end # If something went wrong unless time_check_ok error = I18n.t('.active_bookings.availability.unavailable_interval', model: self.class.to_s, time_start: opts[:time_start], time_end: opts[:time_end]) raise ActiveBookings::AvailabilityError.new error end end if self.booking_opts[:time_type] == :fixed if !(ActiveBookings::TimeUtils.time_in_schedule?(self.schedule, opts[:time])) error = I18n.t('.active_bookings.availability.unavailable_time', model: self.class.to_s, time: opts[:time]) raise ActiveBookings::AvailabilityError.new error end end ## # Real capacity check (calculated with overlapped bookings) # overlapped = ActiveBookings::Booking.overlapped(self, opts) # If capacity_type is :closed cannot book if already booked (no matter if amount < capacity) if (self.booking_opts[:capacity_type] == :closed && !overlapped.empty?) error = I18n.t('.active_bookings.availability.already_booked', model: self.class.to_s) raise ActiveBookings::AvailabilityError.new error end # if capacity_type is :open, check if amount <= maximum amount of overlapped booking if (self.booking_opts[:capacity_type] == :open && !overlapped.empty?) # if time_type is :range, split in sub-intervals and check the maximum sum of amounts against capacity for each sub-interval if (self.booking_opts[:time_type] == :range) # Map overlapped bookings to a set of intervals with amount intervals = overlapped.map { |e| {time_start: e.time_start, time_end: e.time_end, amount: e.amount} } # Make subintervals from overlapped bookings and check capacity for each of them ActiveBookings::TimeUtils.subintervals(intervals) do |a,b,op| case op when :open res = {amount: a[:amount] + b[:amount]} when :close res = {amount: a[:amount] - b[:amount]} end if (res[:amount] >= self.capacity) error = I18n.t('.active_bookings.availability.already_booked', model: self.class.to_s) raise ActiveBookings::AvailabilityError.new error end res end # else, just sum the amounts (fixed times are not intervals and they overlap if are the same) else if(overlapped.sum(:amount) + opts[:amount] > self.capacity) error = I18n.t('.active_bookings.availability.already_booked', model: self.class.to_s) raise ActiveBookings::AvailabilityError.new error end end end true end
Check if options passed for booking this Bookable
are valid
@raise ActiveBookings::OptionsInvalid
if options are not valid @param opts The booking options
# File lib/active_bookings/bookable/core.rb, line 289 def validate_booking_options!(opts) self.class.validate_booking_options!(opts) end