def _get_all_occurrences(self, room_ids, form, flexible_days=0, reservation_id=None): start_dt = form.start_dt.data end_dt = form.end_dt.data repeat_frequency = form.repeat_frequency.data repeat_interval = form.repeat_interval.data day_start_dt = datetime.combine(start_dt.date(), time()) day_end_dt = datetime.combine(end_dt.date(), time(23, 59)) today_start_dt = datetime.combine(date.today(), time()) flexible_start_dt = day_start_dt - timedelta(days=flexible_days) if not session.user.isAdmin(): flexible_start_dt = max(today_start_dt, flexible_start_dt) flexible_end_dt = day_end_dt + timedelta(days=flexible_days) occurrences = ReservationOccurrence.find_all( Reservation.room_id.in_(room_ids), Reservation.id != reservation_id, ReservationOccurrence.start_dt >= flexible_start_dt, ReservationOccurrence.end_dt <= flexible_end_dt, ReservationOccurrence.is_valid, _join=Reservation, _eager=ReservationOccurrence.reservation ) candidates = {} for days in xrange(-flexible_days, flexible_days + 1): offset = timedelta(days=days) series_start = start_dt + offset series_end = end_dt + offset if series_start < flexible_start_dt: continue candidates[series_start, series_end] = ReservationOccurrence.create_series(series_start, series_end, (repeat_frequency, repeat_interval)) return occurrences, candidates
def test_filter_overlap(create_occurrence, overlapping_combination_from_2am_to_4am): start_hour, end_hour, expected = overlapping_combination_from_2am_to_4am() occ1 = create_occurrence(start_dt=date.today() + relativedelta(hour=2), end_dt=date.today() + relativedelta(hour=4)) occ2 = ReservationOccurrence(start_dt=date.today() + relativedelta(hour=start_hour), end_dt=date.today() + relativedelta(hour=end_hour)) overlap_filter = ReservationOccurrence.filter_overlap([occ2]) assert (occ1 in ReservationOccurrence.find_all(overlap_filter)) == expected
def _process(self): occurrences = ReservationOccurrence.find_all( Reservation.room_id == self._room.id, ReservationOccurrence.start_dt >= self._calendar_start, ReservationOccurrence.end_dt <= self._calendar_end, ReservationOccurrence.is_valid, _join=Reservation, _eager=ReservationOccurrence.reservation ) return self._get_view(room=self._room, start_dt=self._calendar_start, end_dt=self._calendar_end, occurrences=occurrences).display()
def _process(self): occurrences = ReservationOccurrence.find_all( Reservation.room_id == self._room.id, ReservationOccurrence.start_dt >= self._calendar_start, ReservationOccurrence.end_dt <= self._calendar_end, ReservationOccurrence.is_valid, _join=Reservation, _eager=ReservationOccurrence.reservation) return self._get_view(room=self._room, start_dt=self._calendar_start, end_dt=self._calendar_end, occurrences=occurrences).display()
def approve(self, notify_blocker=True): """Approve the room blocking, rejecting all colliding reservations/occurrences.""" self.state = BlockedRoomState.accepted # Get colliding reservations start_dt = datetime.combine(self.blocking.start_date, time()) end_dt = datetime.combine(self.blocking.end_date, time(23, 59, 59)) reservation_criteria = [ Reservation.room_id == self.room_id, ~Reservation.is_rejected, ~Reservation.is_cancelled ] # Whole reservations to reject reservations = Reservation.find_all( Reservation.start_dt >= start_dt, Reservation.end_dt <= end_dt, *reservation_criteria ) # Single occurrences to reject occurrences = ReservationOccurrence.find_all( ReservationOccurrence.start_dt >= start_dt, ReservationOccurrence.end_dt <= end_dt, ReservationOccurrence.is_valid, ~ReservationOccurrence.reservation_id.in_(map(attrgetter('id'), reservations)) if reservations else True, *reservation_criteria, _join=Reservation ) reason = f'Conflict with blocking {self.blocking.id}: {self.blocking.reason}' for reservation in reservations: if self.blocking.can_override(reservation.created_by_user, room=reservation.room): continue reservation.reject(self.blocking.created_by_user, reason) for occurrence in occurrences: reservation = occurrence.reservation if self.blocking.can_override(reservation.created_by_user, room=reservation.room): continue occurrence.reject(self.blocking.created_by_user, reason) if notify_blocker: # We only need to notify the blocking creator if the blocked room wasn't approved yet. # This is the case if it's a new blocking for a room managed by the creator notify_request_response(self)
def approve(self, notify_blocker=True): """Approve the room blocking, rejecting all colliding reservations/occurrences.""" self.state = BlockedRoomState.accepted # Get colliding reservations start_dt = datetime.combine(self.blocking.start_date, time()) end_dt = datetime.combine(self.blocking.end_date, time(23, 59, 59)) reservation_criteria = [ Reservation.room_id == self.room_id, ~Reservation.is_rejected, ~Reservation.is_cancelled ] # Whole reservations to reject reservations = Reservation.find_all( Reservation.start_dt >= start_dt, Reservation.end_dt <= end_dt, *reservation_criteria ) # Single occurrences to reject occurrences = ReservationOccurrence.find_all( ReservationOccurrence.start_dt >= start_dt, ReservationOccurrence.end_dt <= end_dt, ReservationOccurrence.is_valid, ~ReservationOccurrence.reservation_id.in_(map(attrgetter('id'), reservations)) if reservations else True, *reservation_criteria, _join=Reservation ) reason = 'Conflict with blocking {}: {}'.format(self.blocking.id, self.blocking.reason) for reservation in reservations: if self.blocking.can_be_overridden(reservation.created_by_user, reservation.room): continue reservation.reject(self.blocking.created_by_user, reason) for occurrence in occurrences: reservation = occurrence.reservation if self.blocking.can_be_overridden(reservation.created_by_user, reservation.room): continue occurrence.reject(self.blocking.created_by_user, reason) if notify_blocker: # We only need to notify the blocking creator if the blocked room wasn't approved yet. # This is the case if it's a new blocking for a room managed by the creator notify_request_response(self)
def _process(self): if self._overload: rooms = [] occurrences = [] else: rooms = Room.find_all(is_active=True) occurrences = ReservationOccurrence.find_all( Reservation.room_id.in_(room.id for room in rooms), ReservationOccurrence.start_dt >= self.start_dt, ReservationOccurrence.end_dt <= self.end_dt, ReservationOccurrence.is_valid, _join=Reservation, _eager=ReservationOccurrence.reservation ) return WPRoomBookingCalendar(self, rooms=rooms, occurrences=occurrences, start_dt=self.start_dt, end_dt=self.end_dt, overload=self._overload, max_days=self.MAX_DAYS).display()
def _process(self): if self._overload: rooms = [] occurrences = [] else: rooms = Room.find_all(is_active=True) occurrences = ReservationOccurrence.find_all( Reservation.room_id.in_(room.id for room in rooms), ReservationOccurrence.start_dt >= self.start_dt, ReservationOccurrence.end_dt <= self.end_dt, ReservationOccurrence.is_valid, _join=Reservation, _eager=ReservationOccurrence.reservation) return WPRoomBookingCalendar(self, rooms=rooms, occurrences=occurrences, start_dt=self.start_dt, end_dt=self.end_dt, overload=self._overload, max_days=self.MAX_DAYS).display()
def _get_all_occurrences(self, room_ids, form, flexible_days=0, reservation_id=None): start_dt = form.start_dt.data end_dt = form.end_dt.data repeat_frequency = form.repeat_frequency.data repeat_interval = form.repeat_interval.data day_start_dt = datetime.combine(start_dt.date(), time()) day_end_dt = datetime.combine(end_dt.date(), time(23, 59)) today_start_dt = datetime.combine(date.today(), time()) flexible_start_dt = day_start_dt - timedelta(days=flexible_days) if not session.user.isAdmin(): flexible_start_dt = max(today_start_dt, flexible_start_dt) flexible_end_dt = day_end_dt + timedelta(days=flexible_days) occurrences = ReservationOccurrence.find_all( Reservation.room_id.in_(room_ids), Reservation.id != reservation_id, ReservationOccurrence.start_dt >= flexible_start_dt, ReservationOccurrence.end_dt <= flexible_end_dt, ReservationOccurrence.is_valid, _join=Reservation, _eager=ReservationOccurrence.reservation) candidates = {} for days in xrange(-flexible_days, flexible_days + 1): offset = timedelta(days=days) series_start = start_dt + offset series_end = end_dt + offset if series_start < flexible_start_dt: continue candidates[series_start, series_end] = ReservationOccurrence.create_series( series_start, series_end, (repeat_frequency, repeat_interval)) return occurrences, candidates