Ejemplo n.º 1
0
def rb_merge_users(new_id, old_id):
    """Updates RB data after an Avatar merge

    :param new_id: Target user
    :param old_id: Source user (being deleted in the merge)
    """
    from indico.modules.rb import settings as rb_settings
    from indico.modules.rb.models.blocking_principals import BlockingPrincipal
    from indico.modules.rb.models.blockings import Blocking
    from indico.modules.rb.models.reservations import Reservation
    from indico.modules.rb.models.rooms import Room

    old_user = User.get(int(old_id))
    new_user = User.get(int(new_id))
    for bp in BlockingPrincipal.find():
        if bp.principal == old_user:
            bp.principal = new_user
    Blocking.find(created_by_id=old_id).update({'created_by_id': new_id})
    Reservation.find(created_by_id=old_id).update({'created_by_id': new_id})
    Reservation.find(booked_for_id=old_id).update({'booked_for_id': new_id})
    Room.find(owner_id=old_id).update({'owner_id': new_id})
    for key in ('authorized_principals', 'admin_principals'):
        principals = rb_settings.get(key)
        principals = principals_merge_users(principals, new_id, old_id)
        rb_settings.set(key, principals)
Ejemplo n.º 2
0
def _merge_users(target, source, **kwargs):
    BlockingPrincipal.merge_users(target, source, 'blocking')
    Blocking.find(created_by_id=source.id).update({Blocking.created_by_id: target.id})
    Reservation.find(created_by_id=source.id).update({Reservation.created_by_id: target.id})
    Reservation.find(booked_for_id=source.id).update({Reservation.booked_for_id: target.id})
    Room.find(owner_id=source.id).update({Room.owner_id: target.id})
    rb_settings.acls.merge_users(target, source)
Ejemplo n.º 3
0
def rb_merge_users(new_id, old_id):
    """Updates RB data after an Avatar merge

    :param new_id: Target user
    :param old_id: Source user (being deleted in the merge)
    """
    from indico.modules.rb import settings as rb_settings
    from indico.modules.rb.models.blocking_principals import BlockingPrincipal
    from indico.modules.rb.models.blockings import Blocking
    from indico.modules.rb.models.reservations import Reservation
    from indico.modules.rb.models.rooms import Room

    old_user = User.get(int(old_id))
    new_user = User.get(int(new_id))
    for bp in BlockingPrincipal.find():
        if bp.principal == old_user:
            bp.principal = new_user
    Blocking.find(created_by_id=old_id).update({'created_by_id': new_id})
    Reservation.find(created_by_id=old_id).update({'created_by_id': new_id})
    Reservation.find(booked_for_id=old_id).update({'booked_for_id': new_id})
    Room.find(owner_id=old_id).update({'owner_id': new_id})
    for key in ('authorized_principals', 'admin_principals'):
        principals = rb_settings.get(key)
        principals = principals_merge_users(principals, new_id, old_id)
        rb_settings.set(key, principals)
Ejemplo n.º 4
0
def test_find_overlapping_with_is_not_valid(overlapping_reservation, dummy_user):
    reservation, occurrence = overlapping_reservation
    assert reservation in Reservation.find_overlapping_with(room=reservation.room,
                                                            occurrences=[occurrence]).all()
    reservation.cancel(dummy_user, silent=True)
    assert reservation not in Reservation.find_overlapping_with(room=reservation.room,
                                                                occurrences=[occurrence]).all()
Ejemplo n.º 5
0
def _merge_users(target, source, **kwargs):
    BlockingPrincipal.merge_users(target, source, 'blocking')
    Blocking.find(created_by_id=source.id).update({Blocking.created_by_id: target.id})
    Reservation.find(created_by_id=source.id).update({Reservation.created_by_id: target.id})
    Reservation.find(booked_for_id=source.id).update({Reservation.booked_for_id: target.id})
    Room.find(owner_id=source.id).update({Room.owner_id: target.id})
    rb_settings.acls.merge_users(target, source)
Ejemplo n.º 6
0
def test_find_overlapping_with_different_room(overlapping_reservation,
                                              create_room):
    reservation, occurrence = overlapping_reservation
    assert reservation in Reservation.find_overlapping_with(
        room=reservation.room, occurrences=[occurrence]).all()
    assert reservation not in Reservation.find_overlapping_with(
        room=create_room(), occurrences=[occurrence]).all()
Ejemplo n.º 7
0
    def _process(self, args):
        room = Room.get_one(args.pop('room_id'))
        user_id = args.pop('user_id', None)
        booked_for = User.get_one(user_id) if user_id else session.user
        is_prebooking = args.pop('is_prebooking')

        # Check that the booking is not longer than allowed
        booking_limit_days = room.booking_limit_days or rb_settings.get(
            'booking_limit')
        if not self._validate_room_booking_limit(
                args['start_dt'], args['end_dt'], booking_limit_days):
            msg = (
                _('Bookings for the room "{}" may not be longer than {} days'
                  ).format(room.name, booking_limit_days))
            return jsonify(success=False, msg=msg)

        try:
            Reservation.create_from_data(room,
                                         dict(args,
                                              booked_for_user=booked_for),
                                         session.user,
                                         prebook=is_prebooking)
            db.session.flush()
        except NoReportError as e:
            db.session.rollback()
            return jsonify(success=False, msg=unicode(e))
        return jsonify(success=True, is_prebooking=is_prebooking)
Ejemplo n.º 8
0
def test_find_overlapping_with_is_not_valid(overlapping_reservation, dummy_user):
    reservation, occurrence = overlapping_reservation
    assert reservation in Reservation.find_overlapping_with(room=reservation.room,
                                                            occurrences=[occurrence]).all()
    reservation.cancel(dummy_user, silent=True)
    assert reservation not in Reservation.find_overlapping_with(room=reservation.room,
                                                                occurrences=[occurrence]).all()
Ejemplo n.º 9
0
def test_find_overlapping_with_skip_reservation(overlapping_reservation):
    reservation, occurrence = overlapping_reservation
    assert reservation in Reservation.find_overlapping_with(
        room=reservation.room, occurrences=[occurrence]).all()
    assert reservation not in Reservation.find_overlapping_with(
        room=reservation.room,
        occurrences=[occurrence],
        skip_reservation_id=reservation.id).all()
Ejemplo n.º 10
0
def test_find_overlapping_with_is_not_valid(overlapping_reservation, dummy_user, freeze_time):
    freeze_time(datetime.combine(date.today(), time(1)))
    reservation, occurrence = overlapping_reservation
    assert reservation in Reservation.find_overlapping_with(room=reservation.room,
                                                            occurrences=[occurrence]).all()
    reservation.cancel(dummy_user, silent=True)
    assert reservation not in Reservation.find_overlapping_with(room=reservation.room,
                                                                occurrences=[occurrence]).all()
Ejemplo n.º 11
0
def test_find_overlapping_with_skip_reservation(overlapping_reservation):
    reservation, occurrence = overlapping_reservation
    assert reservation in Reservation.find_overlapping_with(room=reservation.room, occurrences=[occurrence]).all()
    assert (
        reservation
        not in Reservation.find_overlapping_with(
            room=reservation.room, occurrences=[occurrence], skip_reservation_id=reservation.id
        ).all()
    )
Ejemplo n.º 12
0
def _merge_users(target, source, **kwargs):
    source_principals = set(source.in_blocking_acls.options(joinedload(BlockingPrincipal.blocking)))
    target_blockings = {x.blocking for x in target.in_blocking_acls.options(joinedload(BlockingPrincipal.blocking))}
    for principal in source_principals:
        if principal.blocking not in target_blockings:
            principal.user_id = target.id
        else:
            db.session.delete(principal)
    Blocking.find(created_by_id=source.id).update({Blocking.created_by_id: target.id})
    Reservation.find(created_by_id=source.id).update({Reservation.created_by_id: target.id})
    Reservation.find(booked_for_id=source.id).update({Reservation.booked_for_id: target.id})
    Room.find(owner_id=source.id).update({Room.owner_id: target.id})
    settings.acls.merge_users(target, source)
Ejemplo n.º 13
0
 def _create_reservation(**params):
     params.setdefault('start_dt', date.today() + relativedelta(hour=8, minute=30))
     params.setdefault('end_dt', date.today() + relativedelta(hour=17, minute=30))
     params.setdefault('repeat_frequency', RepeatFrequency.NEVER)
     params.setdefault('repeat_interval', int(params['repeat_frequency'] != RepeatFrequency.NEVER))
     params.setdefault('booking_reason', u'Testing')
     params.setdefault('room', dummy_room)
     params.setdefault('booked_for_user', dummy_user)
     params.setdefault('created_by_user', dummy_user)
     reservation = Reservation(**params)
     reservation.create_occurrences(skip_conflicts=False)
     db.session.add(reservation)
     db.session.flush()
     return reservation
Ejemplo n.º 14
0
 def _create_reservation(**params):
     params.setdefault('start_dt', date.today() + relativedelta(hour=8, minute=30))
     params.setdefault('end_dt', date.today() + relativedelta(hour=17, minute=30))
     params.setdefault('repeat_frequency', RepeatFrequency.NEVER)
     params.setdefault('repeat_interval', int(params['repeat_frequency'] != RepeatFrequency.NEVER))
     params.setdefault('contact_email', dummy_avatar.email)
     params.setdefault('is_accepted', True)
     params.setdefault('booking_reason', u'Testing')
     params.setdefault('room', dummy_room)
     params.setdefault('booked_for_user', dummy_avatar.user)
     params.setdefault('created_by_user', dummy_avatar.user)
     reservation = Reservation(**params)
     reservation.create_occurrences(skip_conflicts=False)
     db.session.add(reservation)
     db.session.flush()
     return reservation
Ejemplo n.º 15
0
    def _process(self):
        args = self.args
        args.setdefault('booked_for_user', session.user)

        if not is_booking_start_within_grace_period(args['start_dt'], session.user, args['admin_override_enabled']):
            raise ExpectedError(_('You cannot create a booking which starts in the past'))

        # Check that the booking is not longer than allowed
        booking_limit_days = self.room.booking_limit_days or rb_settings.get('booking_limit')
        if not self._validate_room_booking_limit(args['start_dt'], args['end_dt'], booking_limit_days):
            msg = (_('Bookings for the room "{}" may not be longer than {} days')
                   .format(self.room.name, booking_limit_days))
            raise ExpectedError(msg)

        try:
            resv = Reservation.create_from_data(self.room, args, session.user, prebook=self.prebook)
            if args.get('link_type') is not None and args.get('link_id') is not None:
                self._link_booking(resv, args['link_type'], args['link_id'], args['link_back'])
            db.session.flush()
        except NoReportError as e:
            db.session.rollback()
            raise ExpectedError(unicode(e))

        serialized_occurrences = serialize_occurrences(group_by_occurrence_date(resv.occurrences.all()))
        if self.prebook:
            data = {'pre_bookings': serialized_occurrences}
        else:
            data = {'bookings': serialized_occurrences}
        return jsonify(room_id=self.room.id, booking=reservation_details_schema.dump(resv), calendar_data=data)
Ejemplo n.º 16
0
def compose_rooms_stats(rooms):
    reservations = Reservation.find(
        Reservation.room_id.in_(r.id for r in rooms))
    return {
        'active': {
            'valid':
            reservations.filter(Reservation.is_accepted,
                                ~Reservation.is_archived).count(),
            'pending':
            reservations.filter(Reservation.is_pending,
                                ~Reservation.is_archived).count(),
            'cancelled':
            reservations.filter(Reservation.is_cancelled,
                                ~Reservation.is_archived).count(),
            'rejected':
            reservations.filter(Reservation.is_rejected,
                                ~Reservation.is_archived).count(),
        },
        'archived': {
            'valid':
            reservations.filter(Reservation.is_accepted,
                                Reservation.is_archived).count(),
            'pending':
            reservations.filter(Reservation.is_pending,
                                Reservation.is_archived).count(),
            'cancelled':
            reservations.filter(Reservation.is_cancelled,
                                Reservation.is_archived).count(),
            'rejected':
            reservations.filter(Reservation.is_rejected,
                                Reservation.is_archived).count()
        }
    }
Ejemplo n.º 17
0
def split_booking(booking, new_booking_data):
    is_ongoing_booking = booking.start_dt.date() < date.today() < booking.end_dt.date()
    if not is_ongoing_booking:
        return

    room = booking.room
    occurrences = sorted(booking.occurrences, key=attrgetter('start_dt'))
    cancelled_dates = [occ.start_dt.date() for occ in occurrences if occ.is_cancelled]
    rejected_occs = {occ.start_dt.date(): occ.rejection_reason for occ in occurrences if occ.is_rejected}
    occurrences_to_cancel = [occ for occ in occurrences if occ.start_dt >= datetime.now()]
    new_start_dt = datetime.combine(occurrences_to_cancel[0].start_dt.date(), new_booking_data['start_dt'].time())
    for occurrence_to_cancel in occurrences_to_cancel:
        occurrence_to_cancel.cancel(session.user, silent=True)

    new_end_dt = [occ for occ in occurrences if occ.start_dt < datetime.now()][-1].end_dt
    old_booking_data = {
        'booking_reason': booking.booking_reason,
        'booked_for_user': booking.booked_for_user,
        'start_dt': booking.start_dt,
        'end_dt': new_end_dt,
        'repeat_frequency': booking.repeat_frequency,
        'repeat_interval': booking.repeat_interval,
    }

    booking.modify(old_booking_data, session.user)
    prebook = not room.can_book(session.user, allow_admin=False) and room.can_prebook(session.user, allow_admin=False)
    resv = Reservation.create_from_data(room, dict(new_booking_data, start_dt=new_start_dt), session.user,
                                        prebook=prebook)
    for new_occ in resv.occurrences:
        new_occ_start = new_occ.start_dt.date()
        if new_occ_start in cancelled_dates:
            new_occ.cancel(None, silent=True)
        if new_occ_start in rejected_occs:
            new_occ.reject(None, rejected_occs[new_occ_start], silent=True)
    return resv
Ejemplo n.º 18
0
def _event_deleted(event, user, **kwargs):
    reservations = Reservation.find(Reservation.event_id == int(event.id),
                                    ~Reservation.is_cancelled,
                                    ~Reservation.is_rejected)
    for resv in reservations:
        resv.event_id = None
        resv.cancel(user or session.user, 'Associated event was deleted')
Ejemplo n.º 19
0
 def _process(self):
     rooms = sorted(self._location.rooms,
                    key=lambda r: natural_sort_key(r.full_name))
     kpi = {}
     if self._with_kpi:
         kpi['occupancy'] = calculate_rooms_occupancy(self._location.rooms)
         kpi['total_rooms'] = len(self._location.rooms)
         kpi['active_rooms'] = sum(1 for room in self._location.rooms
                                   if room.is_active)
         kpi['reservable_rooms'] = sum(1 for room in self._location.rooms
                                       if room.is_reservable)
         kpi['reservable_capacity'] = sum(room.capacity or 0
                                          for room in self._location.rooms
                                          if room.is_reservable)
         kpi['reservable_surface'] = sum(room.surface_area or 0
                                         for room in self._location.rooms
                                         if room.is_reservable)
         kpi['booking_stats'] = compose_rooms_stats(self._location.rooms)
         kpi['booking_count'] = Reservation.find(
             Reservation.room.has(Room.location == self._location)).count()
     return WPRoomBookingAdminLocation(
         self,
         'rb-rooms',
         location=self._location,
         rooms=rooms,
         action_succeeded=self._actionSucceeded,
         equipment_types=self._location.equipment_types.all(),
         attributes=self._location.attributes.all(),
         kpi=kpi).display()
Ejemplo n.º 20
0
def calculate_rooms_booked_time(rooms, start_date=None, end_date=None):
    if end_date is None:
        end_date = date.today() - relativedelta(days=1)
    if start_date is None:
        start_date = end_date - relativedelta(days=29)
    # Reservations on working days
    reservations = Reservation.find(Reservation.room_id.in_(r.id for r in rooms),
                                    db.extract('dow', ReservationOccurrence.start_dt).between(1, 5),
                                    db.cast(ReservationOccurrence.start_dt, db.Date) >= start_date,
                                    db.cast(ReservationOccurrence.end_dt, db.Date) <= end_date,
                                    ReservationOccurrence.is_valid,
                                    _join=ReservationOccurrence)

    rsv_start = db.cast(ReservationOccurrence.start_dt, db.TIME)
    rsv_end = db.cast(ReservationOccurrence.end_dt, db.TIME)
    slots = ((db.cast(start, db.TIME), db.cast(end, db.TIME)) for start, end in WORKING_TIME_PERIODS)

    # this basically handles all possible ways an occurrence overlaps with each one of the working time slots
    overlaps = sum(db.case([
                ((rsv_start < start) & (rsv_end > end), db.extract('epoch', end - start)),
                ((rsv_start < start) & (rsv_end > start) & (rsv_end <= end), db.extract('epoch', rsv_end - start)),
                ((rsv_start >= start) & (rsv_start < end) & (rsv_end > end), db.extract('epoch', end - rsv_start)),
                ((rsv_start >= start) & (rsv_end <= end), db.extract('epoch', rsv_end - rsv_start))
            ], else_=0) for start, end in slots)

    return reservations.with_entities(db.func.sum(overlaps)).scalar() or 0
Ejemplo n.º 21
0
 def _process(self):
     rooms = sorted(self._location.rooms,
                    key=lambda r: natural_sort_key(r.full_name))
     kpi = {}
     if self._with_kpi:
         kpi['occupancy'] = calculate_rooms_occupancy(
             self._location.rooms.all())
         kpi['total_rooms'] = self._location.rooms.count()
         kpi['active_rooms'] = self._location.rooms.filter_by(
             is_active=True).count()
         kpi['reservable_rooms'] = self._location.rooms.filter_by(
             is_reservable=True).count()
         kpi['reservable_capacity'] = (self._location.rooms.with_entities(
             func.sum(
                 Room.capacity)).filter_by(is_reservable=True).scalar())
         kpi['reservable_surface'] = (self._location.rooms.with_entities(
             func.sum(
                 Room.surface_area)).filter_by(is_reservable=True).scalar())
         kpi['booking_stats'] = compose_rooms_stats(
             self._location.rooms.all())
         kpi['booking_count'] = Reservation.find(
             Reservation.room_id.in_(
                 r.id for r in self._location.rooms)).count()
     return WPRoomBookingAdminLocation(
         self,
         location=self._location,
         rooms=rooms,
         action_succeeded=self._actionSucceeded,
         equipment_types=self._location.equipment_types.all(),
         attributes=self._location.attributes.all(),
         kpi=kpi).display()
Ejemplo n.º 22
0
def _export_reservations(hook, limit_per_room, include_rooms, extra_filters=None):
    """Exports reservations.

    :param hook: The HTTPAPIHook instance
    :param limit_per_room: Should the limit/offset be applied per room
    :param include_rooms: Should reservations include room information
    """
    filters = list(extra_filters) if extra_filters else []
    if hook._fromDT and hook._toDT:
        filters.append(cast(Reservation.start_dt, Date) <= hook._toDT.date())
        filters.append(cast(Reservation.end_dt, Date) >= hook._fromDT.date())
        filters.append(cast(Reservation.start_dt, Time) <= hook._toDT.time())
        filters.append(cast(Reservation.end_dt, Time) >= hook._fromDT.time())
    elif hook._toDT:
        filters.append(cast(Reservation.end_dt, Date) <= hook._toDT.date())
        filters.append(cast(Reservation.end_dt, Time) <= hook._toDT.time())
    elif hook._fromDT:
        filters.append(cast(Reservation.start_dt, Date) >= hook._fromDT.date())
        filters.append(cast(Reservation.start_dt, Time) >= hook._fromDT.time())
    filters += _get_reservation_state_filter(hook._queryParams)
    occurs = [datetime.strptime(x, '%Y-%m-%d').date()
              for x in filter(None, get_query_parameter(hook._queryParams, ['occurs'], '').split(','))]
    data = []
    if hook._occurrences:
        data.append('occurrences')
    order = {
        'start': Reservation.start_dt,
        'end': Reservation.end_dt
    }.get(hook._orderBy, Reservation.start_dt)
    if hook._descending:
        order = order.desc()
    reservations_data = Reservation.get_with_data(*data, filters=filters, limit=hook._limit, offset=hook._offset,
                                                  order=order, limit_per_room=limit_per_room, occurs_on=occurs)
    for result in reservations_data:
        yield result['reservation'].room_id, _serializable_reservation(result, include_rooms)
Ejemplo n.º 23
0
    def _process(self):
        args = self.args
        args.setdefault('booked_for_user', session.user)

        if not is_booking_start_within_grace_period(args['start_dt'], session.user, args['admin_override_enabled']):
            raise ExpectedError(_('You cannot create a booking which starts in the past'))

        # Check that the booking is not longer than allowed
        booking_limit_days = self.room.booking_limit_days or rb_settings.get('booking_limit')
        if not self._validate_room_booking_limit(args['start_dt'], args['end_dt'], booking_limit_days):
            msg = (_('Bookings for the room "{}" may not be longer than {} days')
                   .format(self.room.name, booking_limit_days))
            raise ExpectedError(msg)

        try:
            resv = Reservation.create_from_data(self.room, args, session.user, prebook=self.prebook)
            if args.get('link_type') is not None and args.get('link_id') is not None:
                self._link_booking(resv, args['link_type'], args['link_id'], args['link_back'])
            db.session.flush()
        except NoReportError as e:
            db.session.rollback()
            raise ExpectedError(unicode(e))

        serialized_occurrences = serialize_occurrences(group_by_occurrence_date(resv.occurrences.all()))
        if self.prebook:
            data = {'pre_bookings': serialized_occurrences}
        else:
            data = {'bookings': serialized_occurrences}
        return jsonify(room_id=self.room.id, booking=reservation_details_schema.dump(resv), calendar_data=data)
Ejemplo n.º 24
0
def test_is_pending(create_reservation, is_accepted, is_rejected, is_cancelled,
                    expected):
    reservation = create_reservation(is_accepted=is_accepted,
                                     is_rejected=is_rejected,
                                     is_cancelled=is_cancelled)
    assert reservation.is_pending == expected
    assert Reservation.find_first(is_pending=expected) == reservation
Ejemplo n.º 25
0
    def _process(self, args):
        room = Room.get_one(args.pop('room_id'))
        user_id = args.pop('user_id', None)
        booked_for = User.get_one(user_id) if user_id else session.user
        is_prebooking = args.pop('is_prebooking')

        # Check that the booking is not longer than allowed
        booking_limit_days = room.booking_limit_days or rb_settings.get('booking_limit')
        if not self._validate_room_booking_limit(args['start_dt'], args['end_dt'], booking_limit_days):
            msg = (_('Bookings for the room "{}" may not be longer than {} days')
                   .format(room.name, booking_limit_days))
            raise ExpectedError(msg)

        try:
            resv = Reservation.create_from_data(room, dict(args, booked_for_user=booked_for), session.user,
                                                prebook=is_prebooking)
            db.session.flush()
        except NoReportError as e:
            db.session.rollback()
            raise ExpectedError(unicode(e))

        serialized_occurrences = serialize_occurrences(group_by_occurrence_date(resv.occurrences.all()))
        if is_prebooking:
            data = {'pre_bookings': serialized_occurrences}
        else:
            data = {'bookings': serialized_occurrences}
        return jsonify(room_id=room.id, **data)
Ejemplo n.º 26
0
def create_booking_for_event(room_id, event):
    try:
        room = Room.get_one(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 = "Event '{}'".format(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
Ejemplo n.º 27
0
    def _process(self):
        args = self.args
        user_id = args.pop('user_id', None)
        booked_for = User.get_one(user_id, is_deleted=False) if user_id else session.user

        # Check that the booking is not longer than allowed
        booking_limit_days = self.room.booking_limit_days or rb_settings.get('booking_limit')
        if not self._validate_room_booking_limit(args['start_dt'], args['end_dt'], booking_limit_days):
            msg = (_('Bookings for the room "{}" may not be longer than {} days')
                   .format(self.room.name, booking_limit_days))
            raise ExpectedError(msg)

        try:
            resv = Reservation.create_from_data(self.room, dict(args, booked_for_user=booked_for), session.user,
                                                prebook=self.prebook)
            if args.get('link_type') is not None and args.get('link_id') is not None:
                self._link_booking(resv, args['link_type'], args['link_id'], args['link_back'])
            db.session.flush()
        except NoReportError as e:
            db.session.rollback()
            raise ExpectedError(unicode(e))

        serialized_occurrences = serialize_occurrences(group_by_occurrence_date(resv.occurrences.all()))
        if self.prebook:
            data = {'pre_bookings': serialized_occurrences}
        else:
            data = {'bookings': serialized_occurrences}
        return jsonify(room_id=self.room.id, booking=reservation_details_schema.dump(resv).data, calendar_data=data)
Ejemplo n.º 28
0
    def _process(self, args):
        room = Room.get_one(args.pop('room_id'))
        user_id = args.pop('user_id', None)
        booked_for = User.get_one(user_id) if user_id else session.user
        is_prebooking = args.pop('is_prebooking')

        # Check that the booking is not longer than allowed
        booking_limit_days = room.booking_limit_days or rb_settings.get('booking_limit')
        if not self._validate_room_booking_limit(args['start_dt'], args['end_dt'], booking_limit_days):
            msg = (_('Bookings for the room "{}" may not be longer than {} days')
                   .format(room.name, booking_limit_days))
            raise ExpectedError(msg)

        try:
            resv = Reservation.create_from_data(room, dict(args, booked_for_user=booked_for), session.user,
                                                prebook=is_prebooking)
            db.session.flush()
        except NoReportError as e:
            db.session.rollback()
            raise ExpectedError(unicode(e))

        serialized_occurrences = serialize_occurrences(group_by_occurrence_date(resv.occurrences.all()))
        if is_prebooking:
            data = {'pre_bookings': serialized_occurrences}
        else:
            data = {'bookings': serialized_occurrences}
        return jsonify(room_id=room.id, booking=reservation_details_schema.dump(resv).data, calendar_data=data)
Ejemplo n.º 29
0
def calculate_rooms_booked_time(rooms, start_date=None, end_date=None):
    if end_date is None:
        end_date = date.today() - relativedelta(days=1)
    if start_date is None:
        start_date = end_date - relativedelta(days=29)
    # Reservations on working days
    reservations = Reservation.find(
        Reservation.room_id.in_(r.id for r in rooms),
        db.extract('dow', ReservationOccurrence.start_dt).between(1, 5),
        db.cast(ReservationOccurrence.start_dt, db.Date) >= start_date,
        db.cast(ReservationOccurrence.end_dt, db.Date) <= end_date,
        ReservationOccurrence.is_valid,
        _join=ReservationOccurrence)

    rsv_start = db.cast(ReservationOccurrence.start_dt, db.TIME)
    rsv_end = db.cast(ReservationOccurrence.end_dt, db.TIME)
    slots = ((db.cast(start, db.TIME), db.cast(end, db.TIME))
             for start, end in Location.working_time_periods)

    # this basically handles all possible ways an occurrence overlaps with each one of the working time slots
    overlaps = sum(
        db.case([((rsv_start < start) & (rsv_end > end),
                  db.extract('epoch', end - start)),
                 ((rsv_start < start) & (rsv_end > start) & (rsv_end <= end),
                  db.extract('epoch', rsv_end - start)),
                 ((rsv_start >= start) & (rsv_start < end) & (rsv_end > end),
                  db.extract('epoch', end - rsv_start)),
                 ((rsv_start >= start) & (rsv_end <= end),
                  db.extract('epoch', rsv_end - rsv_start))],
                else_=0) for start, end in slots)

    return reservations.with_entities(db.func.sum(overlaps)).scalar() or 0
Ejemplo n.º 30
0
def _export_reservations(hook, limit_per_room, include_rooms, extra_filters=None):
    """Exports reservations.

    :param hook: The HTTPAPIHook instance
    :param limit_per_room: Should the limit/offset be applied per room
    :param include_rooms: Should reservations include room information
    """
    filters = list(extra_filters) if extra_filters else []
    if hook._fromDT and hook._toDT:
        filters.append(cast(Reservation.start_dt, Date) <= hook._toDT.date())
        filters.append(cast(Reservation.end_dt, Date) >= hook._fromDT.date())
        filters.append(cast(Reservation.start_dt, Time) <= hook._toDT.time())
        filters.append(cast(Reservation.end_dt, Time) >= hook._fromDT.time())
    elif hook._toDT:
        filters.append(cast(Reservation.end_dt, Date) <= hook._toDT.date())
        filters.append(cast(Reservation.end_dt, Time) <= hook._toDT.time())
    elif hook._fromDT:
        filters.append(cast(Reservation.start_dt, Date) >= hook._fromDT.date())
        filters.append(cast(Reservation.start_dt, Time) >= hook._fromDT.time())
    filters += _get_reservation_state_filter(hook._queryParams)
    data = ['vc_equipment']
    if hook._occurrences:
        data.append('occurrences')
    order = {
        'start': Reservation.start_dt,
        'end': Reservation.end_dt
    }.get(hook._orderBy, Reservation.start_dt)
    if hook._descending:
        order = order.desc()
    reservations_data = Reservation.get_with_data(*data, filters=filters, limit=hook._limit, offset=hook._offset,
                                                  order=order, limit_per_room=limit_per_room)
    for result in reservations_data:
        yield result['reservation'].room_id, _serializable_reservation(result, include_rooms)
Ejemplo n.º 31
0
 def _process(self):
     reservations = Reservation.find_all(event_id=self.event_id)
     if not reservations:
         self._redirect(url_for('event_mgmt.rooms_choose_event',
                                self.event))
         return
     return WPRoomBookingEventBookingList(
         self, self.event, reservations=reservations).display()
Ejemplo n.º 32
0
 def _createTabCtrl(self):
     self._tabCtrl = TabControl()
     self._tabExistBookings = self._tabCtrl.newTab('existing', 'Existing Bookings',
                                                   url_for('event_mgmt.rooms_booking_list', self._conf))
     self._tabNewBooking = self._tabCtrl.newTab('new', 'New Booking',
                                                url_for('event_mgmt.rooms_choose_event', self._conf))
     if not Reservation.find(event_id=self._conf.getId()).count():
         self._tabExistBookings.setEnabled(False)
     self._setActiveTab()
Ejemplo n.º 33
0
 def _createTabCtrl(self):
     self._tabCtrl = TabControl()
     self._tabExistBookings = self._tabCtrl.newTab('existing', 'Existing Bookings',
                                                   url_for('event_mgmt.rooms_booking_list', self._conf))
     self._tabNewBooking = self._tabCtrl.newTab('new', 'New Booking',
                                                url_for('event_mgmt.rooms_choose_event', self._conf))
     if not Reservation.find(event_id=self._conf.getId()).count():
         self._tabExistBookings.setEnabled(False)
     self._setActiveTab()
Ejemplo n.º 34
0
 def _create_booking(self, form, room):
     if 'submit_book' in form and 'submit_prebook' in form:
         # Admins have the choice
         prebook = form.submit_prebook.data
     else:
         # Otherwise the existence of the book submit button means the user can book
         prebook = 'submit_book' not in form
     reservation = Reservation.create_from_data(room, form.data, session.user, prebook)
     db.session.add(reservation)
     db.session.flush()
     return reservation
Ejemplo n.º 35
0
 def _create_booking(self, form, room):
     if 'submit_book' in form and 'submit_prebook' in form:
         # Admins have the choice
         prebook = form.submit_prebook.data
     else:
         # Otherwise the existence of the book submit button means the user can book
         prebook = 'submit_book' not in form
     reservation = Reservation.create_from_data(room, form.data, session.user, prebook)
     db.session.add(reservation)
     db.session.flush()
     return reservation
Ejemplo n.º 36
0
def rb_merge_users(new_id, old_id):
    """Updates RB data after an Avatar merge

    :param new_id: Target user
    :param old_id: Source user (being deleted in the merge)
    """
    from indico.modules.rb import settings
    from indico.modules.rb.models.blocking_principals import BlockingPrincipal
    from indico.modules.rb.models.blockings import Blocking
    from indico.modules.rb.models.reservations import Reservation
    from indico.modules.rb.models.rooms import Room

    BlockingPrincipal.find(entity_type='Avatar', entity_id=old_id).update({'entity_id': new_id})
    Blocking.find(created_by_id=old_id).update({'created_by_id': new_id})
    Reservation.find(created_by_id=old_id).update({'created_by_id': new_id})
    Reservation.find(booked_for_id=old_id).update({'booked_for_id': new_id})
    Room.find(owner_id=old_id).update({'owner_id': new_id})
    for key in ('authorized_principals', 'admin_principals'):
        principals = settings.get(key, [])
        principals = principals_merge_users(principals, new_id, old_id)
        settings.set(key, principals)
Ejemplo n.º 37
0
def split_booking(booking, new_booking_data):
    is_ongoing_booking = booking.start_dt.date() < date.today() < booking.end_dt.date()
    if not is_ongoing_booking:
        return

    cancelled_dates = []
    rejected_occs = {}
    room = booking.room
    occurrences = sorted(booking.occurrences, key=attrgetter('start_dt'))
    old_frequency = booking.repeat_frequency
    occurrences_to_cancel = [occ for occ in occurrences if occ.start_dt >= datetime.now() and occ.is_valid]

    if old_frequency != RepeatFrequency.NEVER and new_booking_data['repeat_frequency'] == RepeatFrequency.NEVER:
        new_start_dt = new_booking_data['start_dt']
    else:
        new_start_dt = datetime.combine(occurrences_to_cancel[0].start_dt.date(), new_booking_data['start_dt'].time())
        cancelled_dates = [occ.start_dt.date() for occ in occurrences if occ.is_cancelled]
        rejected_occs = {occ.start_dt.date(): occ.rejection_reason for occ in occurrences if occ.is_rejected}

        new_end_dt = [occ for occ in occurrences if occ.start_dt < datetime.now()][-1].end_dt
        old_booking_data = {
            'booking_reason': booking.booking_reason,
            'booked_for_user': booking.booked_for_user,
            'start_dt': booking.start_dt,
            'end_dt': new_end_dt,
            'repeat_frequency': booking.repeat_frequency,
            'repeat_interval': booking.repeat_interval,
        }

        booking.modify(old_booking_data, session.user)

    for occurrence_to_cancel in occurrences_to_cancel:
        occurrence_to_cancel.cancel(session.user, silent=True)

    prebook = not room.can_book(session.user, allow_admin=False) and room.can_prebook(session.user, allow_admin=False)
    resv = Reservation.create_from_data(room, dict(new_booking_data, start_dt=new_start_dt), session.user,
                                        prebook=prebook, ignore_admin=True)
    for new_occ in resv.occurrences:
        new_occ_start = new_occ.start_dt.date()
        if new_occ_start in cancelled_dates:
            new_occ.cancel(None, silent=True)
        if new_occ_start in rejected_occs:
            new_occ.reject(None, rejected_occs[new_occ_start], silent=True)

    booking.edit_logs.append(ReservationEditLog(user_name=session.user.full_name, info=[
        'Split into a new booking',
        f'booking_link:{resv.id}'
    ]))
    resv.edit_logs.append(ReservationEditLog(user_name=session.user.full_name, info=[
        'Split from another booking',
        f'booking_link:{booking.id}'
    ]))
    return resv
Ejemplo n.º 38
0
def create_booking_for_event(room_id, event):
    try:
        room = Room.get_one(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 = "Event '%s'" % (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)
        resv = Reservation.create_from_data(room, data, session.user, ignore_admin=True)
        return resv
    except NoReportError:
        flash(_("Booking could not be created. Probably somebody else booked the room in the meantime."), 'error')
Ejemplo n.º 39
0
def rb_merge_users(new_id, old_id):
    """Updates RB data after an Avatar merge

    :param new_id: Target user
    :param old_id: Source user (being deleted in the merge)
    """
    from indico.modules.rb import settings
    from indico.modules.rb.models.blocking_principals import BlockingPrincipal
    from indico.modules.rb.models.blockings import Blocking
    from indico.modules.rb.models.reservations import Reservation
    from indico.modules.rb.models.rooms import Room

    BlockingPrincipal.find(entity_type='Avatar',
                           entity_id=old_id).update({'entity_id': new_id})
    Blocking.find(created_by_id=old_id).update({'created_by_id': new_id})
    Reservation.find(created_by_id=old_id).update({'created_by_id': new_id})
    Reservation.find(booked_for_id=old_id).update({'booked_for_id': new_id})
    Room.find(owner_id=old_id).update({'owner_id': new_id})
    for key in ('authorized_principals', 'admin_principals'):
        principals = settings.get(key, [])
        principals = principals_merge_users(principals, new_id, old_id)
        settings.set(key, principals)
Ejemplo n.º 40
0
    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
Ejemplo n.º 41
0
    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)
Ejemplo n.º 42
0
    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)
Ejemplo n.º 43
0
def compose_rooms_stats(rooms):
    reservations = Reservation.find(Reservation.room_id.in_(r.id for r in rooms))
    return {
        'active': {
            'valid': reservations.filter(Reservation.is_valid, ~Reservation.is_archived).count(),
            'pending': reservations.filter(Reservation.is_pending, ~Reservation.is_archived).count(),
            'cancelled': reservations.filter(Reservation.is_cancelled, ~Reservation.is_archived).count(),
            'rejected': reservations.filter(Reservation.is_rejected, ~Reservation.is_archived).count(),
        },
        'archived': {
            'valid': reservations.filter(Reservation.is_valid, Reservation.is_archived).count(),
            'pending': reservations.filter(Reservation.is_pending, Reservation.is_archived).count(),
            'cancelled': reservations.filter(Reservation.is_cancelled, Reservation.is_archived).count(),
            'rejected': reservations.filter(Reservation.is_rejected, Reservation.is_archived).count()
        }
    }
Ejemplo n.º 44
0
def calculate_rooms_booked_time(rooms, start_date=None, end_date=None):
    if end_date is None:
        end_date = date.today() - relativedelta(days=1)
    if start_date is None:
        start_date = end_date - relativedelta(days=29)
    # Reservations on working days
    reservations = Reservation.find(Reservation.room_id.in_(r.id for r in rooms),
                                    extract('dow', ReservationOccurrence.start_dt).between(1, 5),
                                    ReservationOccurrence.start_dt >= start_date,
                                    ReservationOccurrence.end_dt <= end_date,
                                    ReservationOccurrence.is_valid,
                                    _join=ReservationOccurrence)
    # Take into account only working hours
    earliest_time = greatest(cast(ReservationOccurrence.start_dt, TIME), Location.working_time_start)
    latest_time = least(cast(ReservationOccurrence.end_dt, TIME), Location.working_time_end)
    booked_time = reservations.with_entities(func.sum(latest_time - earliest_time)).scalar()
    return (booked_time or timedelta()).total_seconds()
Ejemplo n.º 45
0
def split_booking(booking, new_booking_data):
    is_ongoing_booking = booking.start_dt.date() < date.today(
    ) < booking.end_dt.date()
    if not is_ongoing_booking:
        return

    room = booking.room
    occurrences = sorted(booking.occurrences, key=attrgetter('start_dt'))
    occurrences_to_cancel = [
        occ for occ in occurrences if occ.start_dt.date() >= date.today()
    ]
    new_start_dt = datetime.combine(occurrences_to_cancel[0].start_dt.date(),
                                    new_booking_data['start_dt'].time())
    for occurrence_to_cancel in occurrences_to_cancel:
        occurrence_to_cancel.cancel(session.user, silent=True)

    new_end_dt = [
        occ for occ in occurrences if occ.start_dt.date() < date.today()
    ][-1].end_dt
    old_booking_data = {
        'booking_reason':
        booking.booking_reason,
        'room_usage':
        'current_user'
        if booking.booked_for_user == session.user else 'someone',
        'booked_for_user':
        booking.booked_for_user,
        'start_dt':
        booking.start_dt,
        'end_dt':
        new_end_dt,
        'repeat_frequency':
        booking.repeat_frequency,
        'repeat_interval':
        booking.repeat_interval,
    }

    booking.modify(old_booking_data, session.user)
    prebook = not room.can_book(session.user,
                                allow_admin=False) and room.can_prebook(
                                    session.user, allow_admin=False)
    return Reservation.create_from_data(room,
                                        dict(new_booking_data,
                                             start_dt=new_start_dt),
                                        session.user,
                                        prebook=prebook)
Ejemplo n.º 46
0
 def api_roomBooking(self, user):
     data = MultiDict({
         'start_dt': self._params['from'],
         'end_dt': self._params['to'],
         'repeat_frequency': RepeatFrequency.NEVER,
         'repeat_interval': 0,
         'room_id': self._room.id,
         'booked_for_user': self._params['booked_for'],
         'booking_reason': self._params['reason']
     })
     try:
         reservation = Reservation.create_from_data(self._room, data, user)
     except ConflictingOccurrences:
         raise HTTPAPIError('Failed to create the booking due to conflicts with other bookings')
     except IndicoError as e:
         raise HTTPAPIError('Failed to create the booking: {}'.format(e))
     db.session.add(reservation)
     db.session.flush()
     return {'reservationID': reservation.id}
Ejemplo n.º 47
0
Archivo: api.py Proyecto: indico/indico
 def api_roomBooking(self, user):
     data = MultiDict({
         'start_dt': self._params['from'],
         'end_dt': self._params['to'],
         'repeat_frequency': RepeatFrequency.NEVER,
         'repeat_interval': 0,
         'room_id': self._room.id,
         'booked_for_user': self._params['booked_for'],
         'booking_reason': self._params['reason']
     })
     try:
         reservation = Reservation.create_from_data(self._room, data, user)
     except ConflictingOccurrences:
         raise HTTPAPIError('Failed to create the booking due to conflicts with other bookings')
     except IndicoError as e:
         raise HTTPAPIError('Failed to create the booking: {}'.format(e))
     db.session.add(reservation)
     db.session.flush()
     return {'reservationID': reservation.id}
Ejemplo n.º 48
0
def calculate_rooms_booked_time(rooms, start_date=None, end_date=None):
    if end_date is None:
        end_date = date.today() - relativedelta(days=1)
    if start_date is None:
        start_date = end_date - relativedelta(days=29)
    # Reservations on working days
    reservations = Reservation.find(Reservation.room_id.in_(r.id for r in rooms),
                                    extract('dow', ReservationOccurrence.start_dt).between(1, 5),
                                    ReservationOccurrence.start_dt >= start_date,
                                    ReservationOccurrence.end_dt <= end_date,
                                    ReservationOccurrence.is_valid,
                                    _join=ReservationOccurrence)
    # Take into account only working hours
    earliest_time = least(greatest(cast(ReservationOccurrence.start_dt, TIME), Location.working_time_start),
                          Location.working_time_end)
    latest_time = greatest(least(cast(ReservationOccurrence.end_dt, TIME), Location.working_time_end),
                           Location.working_time_start)
    booked_time = reservations.with_entities(func.sum(latest_time - earliest_time)).scalar()
    return (booked_time or timedelta()).total_seconds()
Ejemplo n.º 49
0
 def _process(self):
     rooms = sorted(self._location.rooms, key=lambda r: natural_sort_key(r.full_name))
     kpi = {}
     if self._with_kpi:
         kpi['occupancy'] = calculate_rooms_occupancy(self._location.rooms)
         kpi['total_rooms'] = len(self._location.rooms)
         kpi['active_rooms'] = sum(1 for room in self._location.rooms if room.is_active)
         kpi['reservable_rooms'] = sum(1 for room in self._location.rooms if room.is_reservable)
         kpi['reservable_capacity'] = sum(room.capacity or 0 for room in self._location.rooms if room.is_reservable)
         kpi['reservable_surface'] = sum(room.surface_area or 0 for room in self._location.rooms
                                         if room.is_reservable)
         kpi['booking_stats'] = compose_rooms_stats(self._location.rooms)
         kpi['booking_count'] = Reservation.find(Reservation.room.has(Room.location == self._location)).count()
     return WPRoomBookingAdminLocation(self, 'rb-rooms',
                                       location=self._location,
                                       rooms=rooms,
                                       action_succeeded=self._actionSucceeded,
                                       equipment_types=self._location.equipment_types.all(),
                                       attributes=self._location.attributes.all(),
                                       kpi=kpi).display()
Ejemplo n.º 50
0
 def _process(self):
     rooms = sorted(self._location.rooms, key=lambda r: natural_sort_key(r.full_name))
     kpi = {}
     if self._with_kpi:
         kpi['occupancy'] = calculate_rooms_occupancy(self._location.rooms.all())
         kpi['total_rooms'] = self._location.rooms.count()
         kpi['active_rooms'] = self._location.rooms.filter_by(is_active=True).count()
         kpi['reservable_rooms'] = self._location.rooms.filter_by(is_reservable=True).count()
         kpi['reservable_capacity'] = (self._location.rooms.with_entities(func.sum(Room.capacity))
                                                           .filter_by(is_reservable=True).scalar())
         kpi['reservable_surface'] = (self._location.rooms.with_entities(func.sum(Room.surface_area))
                                                          .filter_by(is_reservable=True).scalar())
         kpi['booking_stats'] = compose_rooms_stats(self._location.rooms.all())
         kpi['booking_count'] = Reservation.find(Reservation.room_id.in_(r.id for r in self._location.rooms)).count()
     return WPRoomBookingAdminLocation(self,
                                       location=self._location,
                                       rooms=rooms,
                                       action_succeeded=self._actionSucceeded,
                                       equipment_types=self._location.equipment_types.all(),
                                       attributes=self._location.attributes.all(),
                                       kpi=kpi).display()
Ejemplo n.º 51
0
 def _checkParams(self):
     resv_id = request.view_args.get("resvID")
     self._reservation = Reservation.get(request.view_args["resvID"])
     if not self._reservation:
         raise IndicoError("No booking with id: {}".format(resv_id))
Ejemplo n.º 52
0
 def _process_args(self):
     self.booking = Reservation.get_one(request.view_args['booking_id'])
Ejemplo n.º 53
0
def test_find_overlapping_with_different_room(overlapping_reservation, create_room):
    reservation, occurrence = overlapping_reservation
    assert reservation in Reservation.find_overlapping_with(room=reservation.room, occurrences=[occurrence]).all()
    assert reservation not in Reservation.find_overlapping_with(room=create_room(), occurrences=[occurrence]).all()
Ejemplo n.º 54
0
 def _process_args(self):
     self._reservation = Reservation.get_one(request.view_args['resvID'])
Ejemplo n.º 55
0
 def _checkParams(self):
     resv_id = request.view_args['resvID']
     self._reservation = Reservation.get(resv_id)
     if not self._reservation:
         raise NoReportError('No booking with id: {}'.format(resv_id))
Ejemplo n.º 56
0
def test_is_pending(create_reservation, is_accepted, is_rejected, is_cancelled, expected):
    reservation = create_reservation(is_accepted=is_accepted, is_rejected=is_rejected, is_cancelled=is_cancelled)
    assert reservation.is_pending == expected
    assert Reservation.find_first(is_pending=expected) == reservation
Ejemplo n.º 57
0
 def _process(self):
     reservations = Reservation.find_all(event_id=self.event_id)
     if not reservations:
         self._redirect(url_for('event_mgmt.rooms_choose_event', self.event))
         return
     return WPRoomBookingEventBookingList(self, self.event, reservations=reservations).display()
Ejemplo n.º 58
0
    def migrate_reservations(self):
        print cformat("%{white!}migrating reservations")
        i = 1
        for rid, v in self.rb_root["Reservations"].iteritems():
            room = Room.get(v.room.id)
            if room is None:
                print cformat("  %{red!}skipping resv for dead room {0.room.id}: {0.id} ({0._utcCreatedDT})").format(v)
                continue

            repeat_frequency, repeat_interval = RepeatMapping.convert_legacy_repeatability(v.repeatability)
            booked_for_id = getattr(v, "bookedForId", None)

            r = Reservation(
                id=v.id,
                created_dt=as_utc(v._utcCreatedDT),
                start_dt=utc_to_local(v._utcStartDT),
                end_dt=utc_to_local(v._utcEndDT),
                booked_for_id=self.merged_avatars.get(booked_for_id, booked_for_id) or None,
                booked_for_name=convert_to_unicode(v.bookedForName),
                contact_email=convert_to_unicode(v.contactEmail),
                contact_phone=convert_to_unicode(getattr(v, "contactPhone", None)),
                created_by_id=self.merged_avatars.get(v.createdBy, v.createdBy) or None,
                is_cancelled=v.isCancelled,
                is_accepted=v.isConfirmed,
                is_rejected=v.isRejected,
                booking_reason=convert_to_unicode(v.reason),
                rejection_reason=convert_to_unicode(getattr(v, "rejectionReason", None)),
                repeat_frequency=repeat_frequency,
                repeat_interval=repeat_interval,
                uses_vc=getattr(v, "usesAVC", False),
                needs_vc_assistance=getattr(v, "needsAVCSupport", False),
                needs_assistance=getattr(v, "needsAssistance", False),
            )

            for eq_name in getattr(v, "useVC", []):
                eq = room.location.get_equipment_by_name(eq_name)
                if eq:
                    r.used_equipment.append(eq)

            occurrence_rejection_reasons = {}
            if getattr(v, "resvHistory", None):
                for h in reversed(v.resvHistory._entries):
                    ts = as_utc(parse_dt_string(h._timestamp))

                    if len(h._info) == 2:
                        possible_rejection_date, possible_rejection_reason = h._info
                        m = re.match(
                            r"Booking occurrence of the (\d{1,2} \w{3} \d{4}) rejected", possible_rejection_reason
                        )
                        if m:
                            d = datetime.strptime(m.group(1), "%d %b %Y")
                            occurrence_rejection_reasons[d] = possible_rejection_reason[9:].strip("'")

                    el = ReservationEditLog(
                        timestamp=ts, user_name=h._responsibleUser, info=map(convert_to_unicode, h._info)
                    )
                    r.edit_logs.append(el)

            notifications = getattr(v, "startEndNotification", []) or []
            excluded_days = getattr(v, "_excludedDays", []) or []
            ReservationOccurrence.create_series_for_reservation(r)
            for occ in r.occurrences:
                occ.notification_sent = occ.date in notifications
                occ.is_rejected = r.is_rejected
                occ.is_cancelled = r.is_cancelled or occ.date in excluded_days
                occ.rejection_reason = (
                    convert_to_unicode(occurrence_rejection_reasons[occ.date])
                    if occ.date in occurrence_rejection_reasons
                    else None
                )

            event_id = getattr(v, "_ReservationBase__owner", None)
            if hasattr(event_id, "_Impersistant__obj"):  # Impersistant object
                event_id = event_id._Impersistant__obj
            if event_id is not None:
                event = self.zodb_root["conferences"].get(event_id)
                if event:
                    # For some stupid reason there are bookings in the database which have a completely unrelated parent
                    guids = getattr(event, "_Conference__roomBookingGuids", [])
                    if any(int(x.id) == v.id for x in guids if x.id is not None):
                        r.event_id = int(event_id)
                    else:
                        print cformat("  %{red}event {} does not contain booking {}").format(event_id, v.id)

            print cformat("- [%{cyan}{}%{reset}/%{green!}{}%{reset}]  %{grey!}{}%{reset}  {}").format(
                room.location_name, room.name, r.id, r.created_dt.date()
            )

            room.reservations.append(r)
            db.session.add(room)
            i = (i + 1) % 1000
            if not i:
                db.session.commit()
        db.session.commit()