Beispiel #1
0
 def _process(self):
     form = RequestListFilterForm(request.args, csrf_enabled=False)
     results = None
     if form.validate_on_submit():
         reverse = form.direction.data == 'desc'
         from_dt = as_utc(get_day_start(
             form.start_date.data)) if form.start_date.data else None
         to_dt = as_utc(get_day_end(
             form.end_date.data)) if form.end_date.data else None
         results = find_requests(from_dt=from_dt, to_dt=to_dt)
         results = [(req, req.event, req.event.start_dt, contribs,
                     session_blocks)
                    for req, contribs, session_blocks in results]
         results = group_list(results,
                              lambda x: x[2].date(),
                              itemgetter(2),
                              sort_reverse=reverse)
         results = OrderedDict(
             sorted(results.viewitems(), key=itemgetter(0),
                    reverse=reverse))
     return WPVCAssistance.render_template(
         'request_list.html',
         form=form,
         results=results,
         action=url_for('.request_list'),
         vc_capable_rooms=get_vc_capable_rooms(),
         within_working_hours=start_time_within_working_hours)
Beispiel #2
0
    def _process(self):
        form = RequestListFilterForm(request.args, csrf_enabled=False)
        results = None
        if request.args and form.validate():
            reverse = form.direction.data == 'desc'
            talks = form.granularity.data == 'talks'
            from_dt = as_utc(get_day_start(
                form.start_date.data)) if form.start_date.data else None
            to_dt = as_utc(get_day_end(
                form.end_date.data)) if form.end_date.data else None
            states = {form.state.data} if form.state.data is not None else None
            results = find_requests(talks=talks,
                                    from_dt=from_dt,
                                    to_dt=to_dt,
                                    states=states)
            if not talks:
                results = [(req, req.event, req.event.start_dt)
                           for req in results]
            results = group_list(results,
                                 lambda x: x[2].date(),
                                 itemgetter(2),
                                 sort_reverse=reverse)
            results = OrderedDict(
                sorted(results.viewitems(), key=itemgetter(0),
                       reverse=reverse))

        return WPAudiovisualManagers.render_template('request_list.html',
                                                     form=form,
                                                     results=results)
Beispiel #3
0
def find_next_start_dt(duration, obj, day=None):
    """Find the next most convenient start date fitting a duration within an object.

    :param duration: Duration to fit into the event/session-block.
    :param obj: The :class:`Event` or :class:`SessionBlock` the duration needs to
                fit into.
    :param day: The local event date where to fit the duration in case the object is
                an event.
    :return: The end datetime of the latest scheduled entry in the object if the
              duration fits then. It it doesn't, the latest datetime that fits it.
              ``None`` if the duration cannot fit in the object.
    """
    if isinstance(obj, Event):
        if day is None:
            raise ValueError("No day specified for event.")
        if not (obj.start_dt_local.date() <= day <= obj.end_dt_local.date()):
            raise ValueError("Day out of event bounds.")
        earliest_dt = obj.start_dt if obj.start_dt_local.date() == day else obj.start_dt.replace(hour=8, minute=0)
        latest_dt = obj.end_dt if obj.start_dt.date() == day else get_day_end(day, tzinfo=obj.tzinfo)
    elif isinstance(obj, SessionBlock):
        if day is not None:
            raise ValueError("Day specified for session block.")
        earliest_dt = obj.timetable_entry.start_dt
        latest_dt = obj.timetable_entry.end_dt
    else:
        raise ValueError("Invalid object type {}".format(type(obj)))
    max_duration = latest_dt - earliest_dt
    if duration > max_duration:
        return None
    start_dt = find_latest_entry_end_dt(obj, day=day) or earliest_dt
    end_dt = start_dt + duration
    if end_dt > latest_dt:
        start_dt = latest_dt - duration
    return start_dt
Beispiel #4
0
def test_filter_available(
    dummy_room,
    create_reservation,
    create_blocking,
    has_booking,
    has_blocking,
    has_pre_booking,
    include_pre_bookings,
    has_pending_blocking,
    include_pending_blockings,
    filtered,
):
    if has_booking:
        create_reservation(
            start_dt=datetime.combine(date.today(), time(8)), end_dt=datetime.combine(date.today(), time(10))
        )
    if has_pre_booking:
        create_reservation(
            start_dt=datetime.combine(date.today(), time(10)),
            end_dt=datetime.combine(date.today(), time(12)),
            is_accepted=False,
        )
    if has_blocking:
        create_blocking(state=BlockedRoom.State.accepted)
    if has_pending_blocking:
        create_blocking(state=BlockedRoom.State.pending)
    availabilty_filter = Room.filter_available(
        get_day_start(date.today()),
        get_day_end(date.today()),
        (RepeatFrequency.NEVER, 0),
        include_pre_bookings=include_pre_bookings,
        include_pending_blockings=include_pending_blockings,
    )
    assert set(Room.find_all(availabilty_filter)) == (set() if filtered else {dummy_room})
Beispiel #5
0
def get_default_booking_interval(duration=90, precision=15, force_today=False):
    """Get the default booking interval for a room.

    Returns the default booking interval for a room as a tuple containing
    the start and end times as `datetime` objects.

    The start time is the default working start time or the current time (if the
    working start time is in the past); rounded up to the given precision in
    minutes (15 by default).

    The end time corresponds to the start time plus the given duration in
    minutes. If the booking ends after the end of work time, it is
    automatically moved to the next day.

    :param duration: int -- The duration of a booking in minutes (must be
        greater than 1)
    :param precision: int -- The number of minutes by which to round up the
        current time for the start time of a booking. Negative values are
        allowed but will round the time down and create a booking starting in
        the past.
    :param force_today: Forces a booking to be for today, even if it past the
        end of work time. This is ignored if the current time is either after
        23:50 or within the amount of minutes of the precision from midnight.
        For example with a precision of 30 minutes, if the current time is 23:42
        then the meeting will be the following day.
    :returns: (datetime, datetime, bool) -- A tuple with the start and end times
        of the booking and a boolean which is `True` if the date was changed
        from today and `False` otherwise.
    :raises: ValueError if the duration is less than 1 minute
    """
    if duration < 1:
        raise ValueError(
            "The duration must be strictly positive (got {} min)".format(
                duration))

    date_changed = False
    work_start = datetime.combine(date.today(),
                                  Location.working_time_periods[0][0])
    work_end = datetime.combine(date.today(),
                                Location.working_time_periods[-1][1])
    start_dt = max(work_start,
                   round_up_to_minutes(datetime.now(), precision=precision))

    end_dt = start_dt + timedelta(minutes=duration)
    if end_dt.date() > start_dt.date():
        end_dt = get_day_end(start_dt.date())

    if ((not force_today and start_dt > work_end)
            or start_dt.date() > date.today()
            or end_dt - start_dt < timedelta(minutes=10)):
        date_changed = True
        start_dt = work_start + timedelta(days=1)
        end_dt = start_dt + timedelta(minutes=duration)
    return start_dt, end_dt, date_changed
Beispiel #6
0
 def validate_start_dt(self, field):
     event = self.contrib.event
     day = self.contrib.start_dt.astimezone(event.tzinfo).date()
     if day == event.end_dt_local.date():
         latest_dt = event.end_dt
         error_msg = _("With this time, the contribution would exceed the event end time.")
     else:
         latest_dt = get_day_end(day, tzinfo=event.tzinfo)
         error_msg = _("With this time, the contribution would exceed the current day.")
     if field.data + self.contrib.duration > latest_dt:
         raise ValidationError(error_msg)
Beispiel #7
0
 def validate_start_dt(self, field):
     event = self.contrib.event
     day = self.contrib.start_dt.astimezone(event.tzinfo).date()
     if day == event.end_dt_local.date():
         latest_dt = event.end_dt
         error_msg = _("With this time, the contribution would exceed the event end time.")
     else:
         latest_dt = get_day_end(day, tzinfo=event.tzinfo)
         error_msg = _("With this time, the contribution would exceed the current day.")
     if field.data + self.contrib.duration > latest_dt:
         raise ValidationError(error_msg)
 def _process(self):
     form = RequestListFilterForm(request.args)
     results = None
     if form.validate_on_submit():
         reverse = form.direction.data == 'desc'
         from_dt = as_utc(get_day_start(form.start_date.data)) if form.start_date.data else None
         to_dt = as_utc(get_day_end(form.end_date.data)) if form.end_date.data else None
         results = _find_requests(from_dt=from_dt, to_dt=to_dt)
         results = group_list(results, lambda req: dateutil.parser.parse(req['requested_at']).date(),
                              sort_reverse=reverse)
         results = OrderedDict(sorted(results.viewitems(), reverse=reverse))
     return WPRoomAssistance.render_template('request_list.html', form=form, results=results,
                                             parse_dt=dateutil.parser.parse)
Beispiel #9
0
 def validate_duration(self, field):
     if field.errors:
         return
     if self.contrib.is_scheduled:
         event = self.contrib.event
         day = self.contrib.start_dt.astimezone(event.tzinfo).date()
         if day == event.end_dt_local.date():
             latest_dt = event.end_dt
             error_msg = _("With this duration, the contribution would exceed the event end time.")
         else:
             latest_dt = get_day_end(day, tzinfo=event.tzinfo)
             error_msg = _("With this duration, the contribution would exceed the current day.")
         if self.contrib.start_dt + field.data > latest_dt:
             raise ValidationError(error_msg)
Beispiel #10
0
 def validate_duration(self, field):
     if field.errors:
         return
     if self.contrib.is_scheduled:
         event = self.contrib.event
         day = self.contrib.start_dt.astimezone(event.tzinfo).date()
         if day == event.end_dt_local.date():
             latest_dt = event.end_dt
             error_msg = _("With this duration, the contribution would exceed the event end time.")
         else:
             latest_dt = get_day_end(day, tzinfo=event.tzinfo)
             error_msg = _("With this duration, the contribution would exceed the current day.")
         if self.contrib.start_dt + field.data > latest_dt:
             raise ValidationError(error_msg)
Beispiel #11
0
def get_default_booking_interval(duration=90, precision=15, force_today=False):
    """Get the default booking interval for a room.

    Returns the default booking interval for a room as a tuple containing
    the start and end times as `datetime` objects.

    The start time is the default working start time or the current time (if the
    working start time is in the past); rounded up to the given precision in
    minutes (15 by default).

    The end time corresponds to the start time plus the given duration in
    minutes. If the booking ends after the end of work time, it is
    automatically moved to the next day.

    :param duration: int -- The duration of a booking in minutes (must be
        greater than 1)
    :param precision: int -- The number of minutes by which to round up the
        current time for the start time of a booking. Negative values are
        allowed but will round the time down and create a booking starting in
        the past.
    :param force_today: Forces a booking to be for today, even if it past the
        end of work time. This is ignored if the current time is either after
        23:50 or within the amount of minutes of the precision from midnight.
        For example with a precision of 30 minutes, if the current time is 23:42
        then the meeting will be the following day.
    :returns: (datetime, datetime, bool) -- A tuple with the start and end times
        of the booking and a boolean which is `True` if the date was changed
        from today and `False` otherwise.
    :raises: ValueError if the duration is less than 1 minute
    """
    if duration < 1:
        raise ValueError("The duration must be strictly positive (got {} min)".format(duration))

    date_changed = False
    work_start = datetime.combine(date.today(), Location.working_time_periods[0][0])
    work_end = datetime.combine(date.today(), Location.working_time_periods[-1][1])
    start_dt = max(work_start, round_up_to_minutes(datetime.now(), precision=precision))

    end_dt = start_dt + timedelta(minutes=duration)
    if end_dt.date() > start_dt.date():
        end_dt = get_day_end(start_dt.date())

    if ((not force_today and start_dt > work_end) or
            start_dt.date() > date.today() or
            end_dt - start_dt < timedelta(minutes=10)):
        date_changed = True
        start_dt = work_start + timedelta(days=1)
        end_dt = start_dt + timedelta(minutes=duration)
    return start_dt, end_dt, date_changed
Beispiel #12
0
 def _process(self):
     form = VCRoomListFilterForm(request.args, csrf_enabled=False)
     results = None
     if request.args and form.validate():
         reverse = form.direction.data == 'desc'
         from_dt = as_utc(get_day_start(form.start_date.data)) if form.start_date.data else None
         to_dt = as_utc(get_day_end(form.end_date.data)) if form.end_date.data else None
         results = find_event_vc_rooms(from_dt=from_dt, to_dt=to_dt, distinct=True)
         results = group_list((r for r in results if r.event_new),
                              key=lambda r: r.event_new.start_dt.date(),
                              sort_by=lambda r: r.event_new.start_dt,
                              sort_reverse=reverse)
         results = OrderedDict(sorted(results.viewitems(), key=itemgetter(0), reverse=reverse))
     return WPVCService.render_template('vc_room_list.html', form=form, results=results,
                                        action=url_for('.vc_room_list'))
Beispiel #13
0
 def _process(self):
     form = VCRoomListFilterForm(request.args)
     results = None
     if request.args and form.validate():
         reverse = form.direction.data == 'desc'
         from_dt = as_utc(get_day_start(form.start_date.data)) if form.start_date.data else None
         to_dt = as_utc(get_day_end(form.end_date.data)) if form.end_date.data else None
         results = find_event_vc_rooms(from_dt=from_dt, to_dt=to_dt, distinct=True)
         results = group_list((r for r in results if r.event),
                              key=lambda r: r.event.getStartDate().date(),
                              sort_by=lambda r: r.event.getStartDate(),
                              sort_reverse=reverse)
         results = OrderedDict(sorted(results.viewitems(), key=itemgetter(0), reverse=reverse))
     return WPVCService.render_template('vc_room_list.html', form=form, results=results,
                                        action=url_for('.vc_room_list'))
Beispiel #14
0
def test_filter_available(dummy_room, create_reservation, create_blocking,
                          has_booking, has_blocking,
                          has_pre_booking, include_pre_bookings,
                          has_pending_blocking, include_pending_blockings, filtered):
    if has_booking:
        create_reservation(start_dt=datetime.combine(date.today(), time(8)),
                           end_dt=datetime.combine(date.today(), time(10)))
    if has_pre_booking:
        create_reservation(start_dt=datetime.combine(date.today(), time(10)),
                           end_dt=datetime.combine(date.today(), time(12)),
                           state=ReservationState.pending)
    if has_blocking:
        create_blocking(state=BlockedRoom.State.accepted)
    if has_pending_blocking:
        create_blocking(state=BlockedRoom.State.pending)
    availabilty_filter = Room.filter_available(get_day_start(date.today()), get_day_end(date.today()),
                                               (RepeatFrequency.NEVER, 0),
                                               include_pre_bookings=include_pre_bookings,
                                               include_pending_blockings=include_pending_blockings)
    assert set(Room.find_all(availabilty_filter)) == (set() if filtered else {dummy_room})