def get_rooms_conflicts(rooms, start_dt, end_dt, repeat_frequency, repeat_interval, blocked_rooms, nonbookable_periods, unbookable_hours, skip_conflicts_with=None, allow_admin=False, skip_past_conflicts=False): rooms_conflicts = defaultdict(set) rooms_pre_conflicts = defaultdict(set) rooms_conflicting_candidates = defaultdict(set) skip_conflicts_with = skip_conflicts_with or [] candidates = ReservationOccurrence.create_series(start_dt, end_dt, (repeat_frequency, repeat_interval)) room_ids = [room.id for room in rooms] query = (ReservationOccurrence.query .filter(Reservation.room_id.in_(room_ids), ReservationOccurrence.is_valid, ReservationOccurrence.filter_overlap(candidates)) .join(ReservationOccurrence.reservation) .options(ReservationOccurrence.NO_RESERVATION_USER_STRATEGY, contains_eager(ReservationOccurrence.reservation))) if skip_conflicts_with: query = query.filter(~Reservation.id.in_(skip_conflicts_with)) if skip_past_conflicts: query = query.filter(ReservationOccurrence.start_dt > datetime.now()) overlapping_occurrences = group_list(query, key=lambda obj: obj.reservation.room.id, sort_by=lambda obj: obj.reservation.room.id) for room_id, occurrences in overlapping_occurrences.items(): conflicts = get_room_bookings_conflicts(candidates, occurrences, skip_conflicts_with) rooms_conflicts[room_id], rooms_pre_conflicts[room_id], rooms_conflicting_candidates[room_id] = conflicts for room_id, occurrences in blocked_rooms.items(): conflicts, conflicting_candidates = get_room_blockings_conflicts(room_id, candidates, occurrences, allow_admin=allow_admin) rooms_conflicts[room_id] |= conflicts rooms_conflicting_candidates[room_id] |= conflicting_candidates if not (allow_admin and rb_is_admin(session.user)): for room_id, occurrences in nonbookable_periods.items(): room = Room.get_or_404(room_id) if not room.can_override(session.user, allow_admin=allow_admin): conflicts, conflicting_candidates = get_room_nonbookable_periods_conflicts(candidates, occurrences) rooms_conflicts[room_id] |= conflicts rooms_conflicting_candidates[room_id] |= conflicting_candidates for room_id, occurrences in unbookable_hours.items(): room = Room.get_or_404(room_id) if not room.can_override(session.user, allow_admin=allow_admin): conflicts, conflicting_candidates = get_room_unbookable_hours_conflicts(candidates, occurrences) rooms_conflicts[room_id] |= conflicts rooms_conflicting_candidates[room_id] |= conflicting_candidates rooms_conflicting_candidates = defaultdict(list, ((k, list(v)) for k, v in rooms_conflicting_candidates.items())) return rooms_conflicts, rooms_pre_conflicts, rooms_conflicting_candidates
def create_booking_for_event(room_id, event): try: room = Room.get_or_404(room_id) default_timezone = timezone(config.DEFAULT_TIMEZONE) start_dt = event.start_dt.astimezone(default_timezone).replace( tzinfo=None) end_dt = event.end_dt.astimezone(default_timezone).replace(tzinfo=None) booking_reason = f"Event '{event.title}'" data = dict(start_dt=start_dt, end_dt=end_dt, booked_for_user=event.creator, booking_reason=booking_reason, repeat_frequency=RepeatFrequency.NEVER, event_id=event.id) booking = Reservation.create_from_data(room, data, session.user, ignore_admin=True) booking.linked_object = event return booking except NoReportError: flash( _("Booking could not be created. Probably somebody else booked the room in the meantime." ), 'error') return None
def _checkSplitRooms(self, room, occs): if room in self.splitmap: for ri in self.splitmap[room]: oroom = Room.get_or_404(ri, is_deleted=False) overlap = Reservation.find_overlapping_with(oroom, occs).all() if overlap: raise ExpectedError( 'Overlaps with other reservations in {}.'.format( oroom.name)) else: for ri, splits in self.splitmap.items(): if room in splits: oroom = Room.get_or_404(ri, is_deleted=False) overlap = Reservation.find_overlapping_with(oroom, occs).all() if overlap: raise ExpectedError( 'Overlaps with other reservations in {}.'.format( oroom.name)) break
def _process_args(self): self.room = None if 'room_id' in request.view_args: self.room = Room.get_or_404(request.view_args['room_id'], is_deleted=False)
def _process_args(self, args): self.args = args self.prebook = args.pop('is_prebooking') self.room = Room.get_or_404(self.args.pop('room_id'), is_deleted=False)