Example #1
0
 def is_parallel(self, in_session=False):
     siblings = self.siblings if not in_session else self.session_siblings
     for sibling in siblings:
         if overlaps((self.start_dt, self.end_dt),
                     (sibling.start_dt, sibling.end_dt)):
             return True
     return False
Example #2
0
 def overlaps(self, occurrence, skip_self=False):
     if self.reservation and occurrence.reservation and self.reservation.room_id != occurrence.reservation.room_id:
         raise ValueError(
             'ReservationOccurrence objects of different rooms')
     if skip_self and self.reservation and occurrence.reservation and self.reservation == occurrence.reservation:
         return False
     return date_time.overlaps((self.start_dt, self.end_dt),
                               (occurrence.start_dt, occurrence.end_dt))
Example #3
0
def find_requests(talks=False,
                  from_dt=None,
                  to_dt=None,
                  services=None,
                  states=None):
    """Finds requests matching certain criteria.

    :param talks: if True, yield ``(request, contrib, start_dt)`` tuples
                  instead of just requests, i.e. the same request may be
                  yielded multiple times
    :param from_dt: earliest event/contribution to include
    :param to_dt: latest event/contribution to include
    :param states: acceptable request states (by default anything but withdrawn)
    :param services: set of services that must have been requested
    """
    from indico_audiovisual.definition import AVRequest
    query = Request.query.filter_by(type=AVRequest.name)
    if states is not None:
        query = query.filter(Request.state.in_(states))
    else:
        query = query.filter(Request.state != RequestState.withdrawn)

    if from_dt is not None or to_dt is not None:
        query = query.join(Event).filter(Event.happens_between(from_dt, to_dt))

    # We only want the latest one for each event
    query = limit_groups(query, Request, Request.event_id,
                         Request.created_dt.desc(), 1)
    query = query.options(joinedload('event'))
    for req in query:
        event = req.event
        # Skip requests which do not have the requested services or are outside the date range
        if services and not (set(req.data['services']) & services):
            continue
        elif to_dt is not None and event.start_dt > to_dt:
            continue
        if not talks:
            yield req
            continue

        # Lectures don't have contributions so we use the event info directly
        if event.type == 'lecture':
            yield req, event, event.start_dt
            continue

        contribs = [x[0] for x in get_selected_contributions(req)]
        for contrib in contribs:
            contrib_start = _get_start_date(contrib)
            contrib_end = _get_end_date(contrib)
            if from_dt is not None and to_dt is not None and not overlaps(
                (contrib_start, contrib_end), (from_dt, to_dt)):
                continue
            elif from_dt and _get_start_date(contrib) < from_dt:
                continue
            elif to_dt and _get_end_date(contrib) > to_dt:
                continue
            yield req, contrib, _get_start_date(contrib)
Example #4
0
 def happens_between(self, from_dt=None, to_dt=None):
     """Check whether the event takes place within two dates"""
     if from_dt is not None and to_dt is not None:
         # any event that takes place during the specified range
         return overlaps((self.start_dt, self.end_dt), (from_dt, to_dt), inclusive=True)
     elif from_dt is not None:
         # any event that starts on/after the specified date
         return self.start_dt >= from_dt
     elif to_dt is not None:
         # any event that ends on/before the specifed date
         return self.end_dt <= to_dt
     else:
         return True
Example #5
0
 def happens_between(self, from_dt=None, to_dt=None):
     """Check whether the event takes place within two dates."""
     if from_dt is not None and to_dt is not None:
         # any event that takes place during the specified range
         return overlaps((self.start_dt, self.end_dt), (from_dt, to_dt), inclusive=True)
     elif from_dt is not None:
         # any event that starts on/after the specified date
         return self.start_dt >= from_dt
     elif to_dt is not None:
         # any event that ends on/before the specifed date
         return self.end_dt <= to_dt
     else:
         return True
Example #6
0
    def _produce_candidate_bars(self):
        blocked_rooms_by_room = MultiDict((br.room_id, br) for br in self.blocked_rooms)

        for room in self.rooms:
            blocked_rooms = blocked_rooms_by_room.getlist(room.id)
            for (start_dt, end_dt), candidates in self.candidates.iteritems():
                # Check if there's a blocking
                for blocked_room in blocked_rooms:
                    blocking = blocked_room.blocking
                    if overlaps((start_dt.date(), end_dt.date()), (blocking.start_date, blocking.end_date),
                                inclusive=True):
                        break
                else:
                    # In case we didn't break the loop due to a match
                    blocking = None
                for cand in candidates:
                    bar = Bar.from_candidate(cand, room.id, start_dt, end_dt, blocking)
                    self.bars.append(bar)
Example #7
0
    def _produce_candidate_bars(self):
        blocked_rooms_by_room = MultiDict((br.room_id, br) for br in self.blocked_rooms)

        for room in self.rooms:
            blocked_rooms = blocked_rooms_by_room.getlist(room.id)
            for (start_dt, end_dt), candidates in self.candidates.iteritems():
                # Check if there's a blocking
                for blocked_room in blocked_rooms:
                    blocking = blocked_room.blocking
                    if overlaps((start_dt.date(), end_dt.date()), (blocking.start_date, blocking.end_date),
                                inclusive=True):
                        break
                else:
                    # In case we didn't break the loop due to a match
                    blocking = None
                for cand in candidates:
                    bar = Bar.from_candidate(cand, room.id, start_dt, end_dt, blocking)
                    self.bars.append(bar)
Example #8
0
def get_duration_suggestion(occurrences, from_, to):
    old_duration = (to - from_).total_seconds() / 60
    duration = old_duration
    all_occurrences_overlap = all(overlaps((from_, to), occ) for occ in occurrences)

    # Don't calculate duration suggestion, if there are at least
    # two existing bookings conflicting with the specified dates
    if all_occurrences_overlap and len(occurrences) > 1:
        return

    for (start, end) in occurrences:
        if start <= from_:
            continue
        if from_ < end < to:
            if start > from_:
                continue
            duration -= (end - from_).total_seconds() / 60
        if from_ < start < to:
            if end < to:
                continue
            duration -= (to - start).total_seconds() / 60
    return abs(duration - old_duration) if old_duration != duration else None
Example #9
0
def get_duration_suggestion(occurrences, from_, to):
    old_duration = (to - from_).total_seconds() / 60
    duration = old_duration
    all_occurrences_overlap = all(overlaps((from_, to), occ) for occ in occurrences)

    # Don't calculate duration suggestion, if there are at least
    # two existing bookings conflicting with the specified dates
    if all_occurrences_overlap and len(occurrences) > 1:
        return

    for (start, end) in occurrences:
        if start <= from_:
            continue
        if from_ < end < to:
            if start > from_:
                continue
            duration -= (end - from_).total_seconds() / 60
        if from_ < start < to:
            if end < to:
                continue
            duration -= (to - start).total_seconds() / 60
    return abs(duration - old_duration) if old_duration != duration else None
Example #10
0
def check_room_available(room, start_dt, end_dt):
    occurrences = get_existing_room_occurrences(room,
                                                start_dt,
                                                end_dt,
                                                allow_overlapping=True)
    prebookings = [
        occ for occ in occurrences if not occ.reservation.is_accepted
    ]
    bookings = [occ for occ in occurrences if occ.reservation.is_accepted]
    unbookable_hours = get_rooms_unbookable_hours([room])
    hours_overlap = any(
        hours for hours in unbookable_hours
        if overlaps((start_dt.time(), end_dt.time()), (hours.start_time,
                                                       hours.end_time)))
    nonbookable_periods = any(
        get_rooms_nonbookable_periods([room], start_dt, end_dt))
    blockings = get_rooms_blockings([room], start_dt, end_dt).get(room.id, [])
    blocked_for_user = any(blocking for blocking in blockings
                           if not blocking.blocking.can_be_overridden(
                               session.user, room, explicit_only=True))
    user_booking = any(booking for booking in bookings
                       if booking.reservation.booked_for_id == session.user.id)
    user_prebooking = any(
        prebooking for prebooking in prebookings
        if prebooking.reservation.booked_for_id == session.user.id)

    return {
        'can_book': room.can_book(session.user, allow_admin=False),
        'can_prebook': room.can_prebook(session.user, allow_admin=False),
        'conflict_booking': any(bookings),
        'conflict_prebooking': any(prebookings),
        'unbookable': (hours_overlap or nonbookable_periods
                       or blocked_for_user),
        'user_booking': user_booking,
        'user_prebooking': user_prebooking,
    }
Example #11
0
def check_room_available(room, start_dt, end_dt):
    occurrences = get_existing_room_occurrences(room, start_dt, end_dt, allow_overlapping=True)
    prebookings = [occ for occ in occurrences if not occ.reservation.is_accepted]
    bookings = [occ for occ in occurrences if occ.reservation.is_accepted]
    unbookable_hours = get_rooms_unbookable_hours([room])
    hours_overlap = any(hours for hours in unbookable_hours
                        if overlaps((start_dt.time(), end_dt.time()), (hours.start_time, hours.end_time)))
    nonbookable_periods = any(get_rooms_nonbookable_periods([room], start_dt, end_dt))
    blocked_rooms = get_rooms_blockings([room], start_dt, end_dt)
    nonoverridable_blocked_rooms = filter_blocked_rooms(blocked_rooms, nonoverridable_only=True, explicit=True)
    blocked_for_user = any(nonoverridable_blocked_rooms)
    user_booking = any(booking for booking in bookings if booking.reservation.booked_for_id == session.user.id)
    user_prebooking = any(prebooking for prebooking in prebookings
                          if prebooking.reservation.booked_for_id == session.user.id)

    return {
        'can_book': room.can_book(session.user, allow_admin=False),
        'can_prebook': room.can_prebook(session.user, allow_admin=False),
        'conflict_booking': any(bookings),
        'conflict_prebooking': any(prebookings),
        'unbookable': (hours_overlap or nonbookable_periods or blocked_for_user),
        'user_booking': user_booking,
        'user_prebooking': user_prebooking,
    }
 def overlaps(self, occurrence, skip_self=False):
     if self.reservation and occurrence.reservation and self.reservation.room_id != occurrence.reservation.room_id:
         raise ValueError('ReservationOccurrence objects of different rooms')
     if skip_self and self.reservation and occurrence.reservation and self.reservation == occurrence.reservation:
         return False
     return date_time.overlaps((self.start_dt, self.end_dt), (occurrence.start_dt, occurrence.end_dt))
Example #13
0
 def is_parallel(self, in_session=False):
     siblings = self.siblings if not in_session else self.session_siblings
     for sibling in siblings:
         if overlaps((self.start_dt, self.end_dt), (sibling.start_dt, sibling.end_dt)):
             return True
     return False