Ejemplo n.º 1
0
def get_rooms_availability(rooms, start_dt, end_dt, repeat_frequency, repeat_interval):
    availability = OrderedDict()
    candidates = ReservationOccurrence.create_series(start_dt, end_dt, (repeat_frequency, repeat_interval))
    date_range = sorted(set(cand.start_dt.date() for cand in candidates))
    occurrences = get_existing_rooms_occurrences(rooms, start_dt.replace(hour=0, minute=0),
                                                 end_dt.replace(hour=23, minute=59), repeat_frequency, repeat_interval)
    blocked_rooms = get_rooms_blockings(rooms, start_dt.date(), end_dt.date())
    unbookable_hours = get_rooms_unbookable_hours(rooms)
    nonbookable_periods = get_rooms_nonbookable_periods(rooms, start_dt, end_dt)
    conflicts, pre_conflicts = get_rooms_conflicts(rooms, start_dt.replace(tzinfo=None), end_dt.replace(tzinfo=None),
                                                   repeat_frequency, repeat_interval, blocked_rooms,
                                                   nonbookable_periods, unbookable_hours)
    dates = list(candidate.start_dt.date() for candidate in candidates)
    for room in rooms:
        room_occurrences = occurrences.get(room.id, [])
        room_conflicts = conflicts.get(room.id, [])
        pre_room_conflicts = pre_conflicts.get(room.id, [])
        pre_bookings = [occ for occ in room_occurrences if not occ.reservation.is_accepted]
        existing_bookings = [occ for occ in room_occurrences if occ.reservation.is_accepted]
        room_blocked_rooms = blocked_rooms.get(room.id, [])
        room_nonbookable_periods = nonbookable_periods.get(room.id, [])
        room_unbookable_hours = unbookable_hours.get(room.id, [])
        availability[room.id] = {'room_id': room.id,
                                 'candidates': group_by_occurrence_date(candidates),
                                 'pre_bookings': group_by_occurrence_date(pre_bookings),
                                 'bookings': group_by_occurrence_date(existing_bookings),
                                 'conflicts': group_by_occurrence_date(room_conflicts),
                                 'pre_conflicts': group_by_occurrence_date(pre_room_conflicts),
                                 'blockings': group_blockings(room_blocked_rooms, dates),
                                 'nonbookable_periods': group_nonbookable_periods(room_nonbookable_periods, dates),
                                 'unbookable_hours': room_unbookable_hours}
    return date_range, availability
Ejemplo n.º 2
0
def get_room_calendar(start_date, end_date, room_ids, **filters):
    start_dt = datetime.combine(start_date, time(hour=0, minute=0))
    end_dt = datetime.combine(end_date, time(hour=23, minute=59))
    query = _bookings_query(dict(filters, **{'start_date': start_dt, 'end_date': end_dt, 'room_ids': room_ids}))
    query = query.order_by(db.func.indico.natsort(Room.full_name))
    rooms = (Room.query
             .filter(Room.is_active, Room.id.in_(room_ids) if room_ids else True)
             .options(joinedload('location'))
             .order_by(db.func.indico.natsort(Room.full_name))
             .all())

    unbookable_hours = get_rooms_unbookable_hours(rooms)
    nonbookable_periods = get_rooms_nonbookable_periods(rooms, start_dt, end_dt)
    occurrences_by_room = groupby(query, attrgetter('reservation.room_id'))
    blocked_rooms = get_rooms_blockings(rooms, start_dt, end_dt)

    dates = [d.date() for d in iterdays(start_dt, end_dt)]

    calendar = OrderedDict((room.id, {
        'room_id': room.id,
        'nonbookable_periods': group_nonbookable_periods(nonbookable_periods.get(room.id, []), dates),
        'unbookable_hours': unbookable_hours.get(room.id, []),
        'blockings': group_blockings(blocked_rooms.get(room.id, []), dates),
    }) for room in rooms)

    for room_id, occurrences in occurrences_by_room:
        occurrences = list(occurrences)
        pre_bookings = [occ for occ in occurrences if not occ.reservation.is_accepted]
        existing_bookings = [occ for occ in occurrences if occ.reservation.is_accepted]

        calendar[room_id].update({
            'bookings': group_by_occurrence_date(existing_bookings),
            'pre_bookings': group_by_occurrence_date(pre_bookings)
        })
    return calendar
Ejemplo n.º 3
0
def get_rooms_availability(rooms, start_dt, end_dt, repeat_frequency,
                           repeat_interval, flexibility):
    period_days = (end_dt - start_dt).days
    availability = OrderedDict()
    candidates = ReservationOccurrence.create_series(
        start_dt, end_dt, (repeat_frequency, repeat_interval))
    date_range = sorted(set(cand.start_dt.date() for cand in candidates))
    occurrences = get_existing_rooms_occurrences(
        rooms, start_dt.replace(hour=0, minute=0),
        end_dt.replace(hour=23, minute=59), repeat_frequency, repeat_interval)
    blocked_rooms = get_rooms_blockings(rooms, start_dt.date(), end_dt.date())
    unbookable_hours = get_rooms_unbookable_hours(rooms)
    nonbookable_periods = get_rooms_nonbookable_periods(
        rooms, start_dt, end_dt)
    conflicts, pre_conflicts = get_rooms_conflicts(
        rooms, start_dt.replace(tzinfo=None), end_dt.replace(tzinfo=None),
        repeat_frequency, repeat_interval, blocked_rooms, nonbookable_periods,
        unbookable_hours)
    dates = list(candidate.start_dt.date() for candidate in candidates)
    for room in rooms:
        booking_limit_days = room.booking_limit_days or rb_settings.get(
            'booking_limit')
        if period_days > booking_limit_days:
            continue

        start_dt = start_dt + timedelta(days=flexibility)
        end_dt = end_dt + timedelta(days=flexibility)
        room_occurrences = occurrences.get(room.id, [])
        room_conflicts = conflicts.get(room.id, [])
        pre_room_conflicts = pre_conflicts.get(room.id, [])
        pre_bookings = [
            occ for occ in room_occurrences if not occ.reservation.is_accepted
        ]
        existing_bookings = [
            occ for occ in room_occurrences if occ.reservation.is_accepted
        ]
        room_blocked_rooms = blocked_rooms.get(room.id, [])
        room_nonbookable_periods = nonbookable_periods.get(room.id, [])
        room_unbookable_hours = unbookable_hours.get(room.id, [])
        availability[room.id] = {
            'room':
            room,
            'candidates':
            group_by_occurrence_date(candidates),
            'pre_bookings':
            group_by_occurrence_date(pre_bookings),
            'bookings':
            group_by_occurrence_date(existing_bookings),
            'conflicts':
            group_by_occurrence_date(room_conflicts),
            'pre_conflicts':
            group_by_occurrence_date(pre_room_conflicts),
            'blockings':
            group_blockings(room_blocked_rooms, dates),
            'nonbookable_periods':
            group_nonbookable_periods(room_nonbookable_periods, dates),
            'unbookable_hours':
            room_unbookable_hours
        }
    return date_range, availability
Ejemplo n.º 4
0
def get_room_calendar(start_date, end_date, room_ids):
    start_dt = datetime.combine(start_date, time(hour=0, minute=0))
    end_dt = datetime.combine(end_date, time(hour=23, minute=59))
    reservation_strategy = contains_eager('reservation')
    reservation_strategy.noload('room')
    reservation_strategy.noload('booked_for_user')
    reservation_strategy.noload('created_by_user')
    query = (ReservationOccurrence.query.filter(
        ReservationOccurrence.is_valid).filter(
            ReservationOccurrence.start_dt >= start_dt,
            ReservationOccurrence.end_dt <=
            end_dt).join(Reservation).join(Room).filter(
                Room.is_active,
                Room.id.in_(room_ids) if room_ids else True).order_by(
                    db.func.indico.natsort(
                        Room.full_name)).options(reservation_strategy))

    rooms = (Room.query.filter(
        Room.is_active,
        Room.id.in_(room_ids) if room_ids else True).options(
            joinedload('location')).order_by(
                db.func.indico.natsort(Room.full_name)).all())

    unbookable_hours = get_rooms_unbookable_hours(rooms)
    nonbookable_periods = get_rooms_nonbookable_periods(
        rooms, start_dt, end_dt)
    occurrences_by_room = groupby(query, attrgetter('reservation.room_id'))
    blocked_rooms = get_rooms_blockings(rooms, start_dt, end_dt)

    dates = [d.date() for d in iterdays(start_dt, end_dt)]

    calendar = OrderedDict((room.id, {
        'room_id':
        room.id,
        'nonbookable_periods':
        group_nonbookable_periods(nonbookable_periods.get(room.id, []), dates),
        'unbookable_hours':
        unbookable_hours.get(room.id, []),
        'blockings':
        group_blockings(blocked_rooms.get(room.id, []), dates),
    }) for room in rooms)

    for room_id, occurrences in occurrences_by_room:
        occurrences = list(occurrences)
        pre_bookings = [
            occ for occ in occurrences if not occ.reservation.is_accepted
        ]
        existing_bookings = [
            occ for occ in occurrences if occ.reservation.is_accepted
        ]

        calendar[room_id].update({
            'bookings':
            group_by_occurrence_date(existing_bookings),
            'pre_bookings':
            group_by_occurrence_date(pre_bookings)
        })
    return calendar
Ejemplo n.º 5
0
def get_room_details_availability(room, start_dt, end_dt):
    dates = [d.date() for d in iterdays(start_dt, end_dt)]

    occurrences = get_existing_room_occurrences(room, start_dt, end_dt,
                                                RepeatFrequency.DAY, 1)
    pre_bookings = [
        occ for occ in occurrences if not occ.reservation.is_accepted
    ]
    bookings = [occ for occ in occurrences if occ.reservation.is_accepted]
    blocked_rooms = get_rooms_blockings([room], start_dt.date(), end_dt.date())
    nonoverridable_blocked_rooms = group_blocked_rooms(
        filter_blocked_rooms(blocked_rooms,
                             nonoverridable_only=True,
                             explicit=True)).get(room.id, [])
    overridable_blocked_rooms = group_blocked_rooms(
        filter_blocked_rooms(blocked_rooms,
                             overridable_only=True,
                             explicit=True)).get(room.id, [])
    unbookable_hours = get_rooms_unbookable_hours([room]).get(room.id, [])
    nonbookable_periods = get_rooms_nonbookable_periods([room], start_dt,
                                                        end_dt).get(
                                                            room.id, [])

    availability = []
    for day in dates:
        iso_day = day.isoformat()
        nb_periods = serialize_nonbookable_periods(
            group_nonbookable_periods(nonbookable_periods, dates)).get(iso_day)
        availability.append({
            'bookings':
            serialize_occurrences(
                group_by_occurrence_date(bookings)).get(iso_day),
            'pre_bookings':
            serialize_occurrences(
                group_by_occurrence_date(pre_bookings)).get(iso_day),
            'blockings':
            serialize_blockings(
                group_blockings(nonoverridable_blocked_rooms,
                                dates)).get(iso_day),
            'overridable_blockings': (serialize_blockings(
                group_blockings(overridable_blocked_rooms,
                                dates)).get(iso_day)),
            'nonbookable_periods':
            nb_periods,
            'unbookable_hours':
            serialize_unbookable_hours(unbookable_hours),
            'day':
            iso_day,
        })
    return sorted(availability, key=itemgetter('day'))
Ejemplo n.º 6
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.º 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))
            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.º 8
0
def get_recurring_booking_suggestions(rooms, start_dt, end_dt, repeat_frequency, repeat_interval, limit=None):
    data = []
    booking_days = end_dt - start_dt
    booking_length = booking_days.days + 1
    candidates = ReservationOccurrence.create_series(start_dt, end_dt, (repeat_frequency, repeat_interval))
    blocked_rooms = get_rooms_blockings(rooms, start_dt.date(), end_dt.date())
    unbookable_hours = get_rooms_unbookable_hours(rooms)
    nonbookable_periods = get_rooms_nonbookable_periods(rooms, start_dt, end_dt)
    conflicts = get_rooms_conflicts(rooms, start_dt, end_dt, repeat_frequency, repeat_interval, blocked_rooms,
                                    nonbookable_periods, unbookable_hours)[0]
    for room in rooms:
        if limit and len(data) == limit:
            break

        suggestions = {}
        booking_limit = room.booking_limit_days or rb_settings.get('booking_limit')
        limit_exceeded = booking_limit is not None and booking_limit < booking_length
        if limit_exceeded:
            excess_days = booking_length - booking_limit
            suggestions['shorten'] = excess_days

        if not limit_exceeded:
            number_of_conflicting_days = len(group_by_occurrence_date(conflicts.get(room.id, [])))
            if number_of_conflicting_days and number_of_conflicting_days < len(candidates):
                suggestions['skip'] = number_of_conflicting_days
        if suggestions:
            data.append({'room': room, 'suggestions': suggestions})
    return data
Ejemplo n.º 9
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.º 10
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.º 11
0
    def _process(self):
        room_details = room_details_schema.dump(self.room).data
        start_dt = date.today()
        end_dt = start_dt + timedelta(days=4)
        last_bookings = group_by_occurrence_date(
            get_existing_room_occurrences(self.room,
                                          start_dt,
                                          end_dt,
                                          only_accepted=True))
        range_bookings = {
            day.date(): last_bookings.get(day.date())
            for day in iterdays(start_dt, end_dt)
        }
        bookings = [{
            'availability': {
                'usage': bookings or []
            },
            'label': dt,
            'conflictIndicator': False,
            'id': dt
        } for dt, bookings in serialize_occurrences(
            range_bookings).iteritems()]

        room_details['bookings'] = sorted(bookings, key=itemgetter('id'))
        return jsonify(room_details)
Ejemplo n.º 12
0
def get_number_of_skipped_days_for_rooms(rooms,
                                         start_dt,
                                         end_dt,
                                         repeat_frequency,
                                         repeat_interval,
                                         limit=None):
    data = []
    candidates = ReservationOccurrence.create_series(
        start_dt, end_dt, (repeat_frequency, repeat_interval))
    blocked_rooms = get_rooms_blockings(rooms, start_dt.date(), end_dt.date())
    unbookable_hours = get_rooms_unbookable_hours(rooms)
    nonbookable_periods = get_rooms_nonbookable_periods(
        rooms, start_dt, end_dt)
    conflicts, _ = get_rooms_conflicts(rooms, start_dt, end_dt,
                                       repeat_frequency, repeat_interval,
                                       blocked_rooms, nonbookable_periods,
                                       unbookable_hours)
    for room in rooms:
        if limit and len(data) == limit:
            break

        number_of_conflicting_days = len(
            group_by_occurrence_date(conflicts.get(room.id, [])))
        if number_of_conflicting_days and number_of_conflicting_days < len(
                candidates):
            data.append({
                'room': room,
                'suggestions': {
                    'skip': number_of_conflicting_days
                }
            })
    return sorted(data, key=lambda item: item['suggestions']['skip'])
Ejemplo n.º 13
0
def get_room_calendar(day, room_ids):
    start_dt = datetime.combine(day, time(hour=0, minute=0))
    end_dt = datetime.combine(day, time(hour=23, minute=59))
    reservation_strategy = contains_eager('reservation')
    reservation_strategy.noload('room')
    reservation_strategy.noload('booked_for_user')
    reservation_strategy.noload('created_by_user')
    query = (ReservationOccurrence.query
             .filter(ReservationOccurrence.is_valid)
             .filter(ReservationOccurrence.start_dt >= start_dt, ReservationOccurrence.end_dt <= end_dt)
             .join(Reservation)
             .join(Room)
             .filter(Room.is_active, Room.id.in_(room_ids) if room_ids else True)
             .order_by(db.func.indico.natsort(Room.full_name))
             .options(reservation_strategy))

    rooms = (Room.query
             .filter(Room.is_active, Room.id.in_(room_ids) if room_ids else True)
             .options(joinedload('location'))
             .order_by(db.func.indico.natsort(Room.full_name))
             .all())

    unbookable_hours = get_rooms_unbookable_hours(rooms)
    nonbookable_periods = get_rooms_nonbookable_periods(rooms, start_dt, end_dt)
    occurrences_by_room = groupby(query, attrgetter('reservation.room_id'))
    blocked_rooms = get_rooms_blockings(rooms, start_dt, end_dt)

    dates = [d.date() for d in iterdays(start_dt, end_dt)]

    calendar = OrderedDict((room.id, {
        'room_id': room.id,
        'nonbookable_periods': group_nonbookable_periods(nonbookable_periods.get(room.id, []), dates),
        'unbookable_hours': unbookable_hours.get(room.id, []),
        'blockings': group_blockings(blocked_rooms.get(room.id, []), dates),
    }) for room in rooms)

    for room_id, occurrences in occurrences_by_room:
        occurrences = list(occurrences)
        pre_bookings = [occ for occ in occurrences if not occ.reservation.is_accepted]
        existing_bookings = [occ for occ in occurrences if occ.reservation.is_accepted]

        calendar[room_id].update({
            'bookings': group_by_occurrence_date(existing_bookings),
            'pre_bookings': group_by_occurrence_date(pre_bookings)
        })
    return calendar
Ejemplo n.º 14
0
def get_room_bookings(room, start_dt, end_dt, skip_booking_id=None):
    bookings = get_existing_room_occurrences(room,
                                             start_dt,
                                             end_dt,
                                             RepeatFrequency.DAY,
                                             1,
                                             only_accepted=True,
                                             skip_booking_id=skip_booking_id)
    return serialize_occurrences(group_by_occurrence_date(bookings))
Ejemplo n.º 15
0
def get_active_bookings(limit, start_dt, last_reservation_id=None, **filters):
    criteria = [ReservationOccurrence.start_dt > start_dt]
    if last_reservation_id is not None:
        criteria.append(db.and_(db.cast(ReservationOccurrence.start_dt, db.Date) >= start_dt,
                                ReservationOccurrence.reservation_id > last_reservation_id))

    query = (_bookings_query(filters)
             .filter(db.or_(*criteria))
             .order_by(ReservationOccurrence.start_dt,
                       ReservationOccurrence.reservation_id,
                       db.func.indico.natsort(Room.full_name))
             .limit(limit))

    bookings, total = with_total_rows(query)
    rows_left = total - limit if total > limit else total
    return group_by_occurrence_date(query, sort_by=lambda obj: (obj.start_dt, obj.reservation_id)), rows_left
Ejemplo n.º 16
0
def get_number_of_skipped_days_for_rooms(rooms, start_dt, end_dt, repeat_frequency, repeat_interval, limit=None):
    data = []
    candidates = ReservationOccurrence.create_series(start_dt, end_dt, (repeat_frequency, repeat_interval))
    blocked_rooms = get_rooms_blockings(rooms, start_dt.date(), end_dt.date())
    unbookable_hours = get_rooms_unbookable_hours(rooms)
    nonbookable_periods = get_rooms_nonbookable_periods(rooms, start_dt, end_dt)
    conflicts, _ = get_rooms_conflicts(rooms, start_dt, end_dt, repeat_frequency, repeat_interval, blocked_rooms,
                                       nonbookable_periods, unbookable_hours)
    for room in rooms:
        if limit and len(data) == limit:
            break

        number_of_conflicting_days = len(group_by_occurrence_date(conflicts.get(room.id, [])))
        if number_of_conflicting_days and number_of_conflicting_days < len(candidates):
            data.append({'room': room, 'suggestions': {'skip': number_of_conflicting_days}})
    return sorted(data, key=lambda item: item['suggestions']['skip'])
Ejemplo n.º 17
0
def get_active_bookings(limit, start_dt, last_reservation_id=None, **filters):
    criteria = [ReservationOccurrence.start_dt > start_dt]
    if last_reservation_id is not None:
        criteria.append(
            db.and_(
                db.cast(ReservationOccurrence.start_dt, db.Date) >= start_dt,
                ReservationOccurrence.reservation_id > last_reservation_id))

    query = (_bookings_query(filters).filter(db.or_(*criteria)).order_by(
        ReservationOccurrence.start_dt, ReservationOccurrence.reservation_id,
        db.func.indico.natsort(Room.full_name)).limit(limit))

    bookings, total = with_total_rows(query)
    rows_left = total - limit if total > limit else total
    return group_by_occurrence_date(
        query, sort_by=lambda obj:
        (obj.start_dt, obj.reservation_id)), rows_left
Ejemplo n.º 18
0
def get_room_details_availability(room, start_dt, end_dt):
    dates = [d.date() for d in iterdays(start_dt, end_dt)]

    bookings = get_existing_room_occurrences(room, start_dt, end_dt, RepeatFrequency.DAY, 1, only_accepted=True)
    blockings = get_rooms_blockings([room], start_dt.date(), end_dt.date()).get(room.id, [])
    unbookable_hours = get_rooms_unbookable_hours([room]).get(room.id, [])
    nonbookable_periods = get_rooms_nonbookable_periods([room], start_dt, end_dt).get(room.id, [])

    availability = []
    for day in dates:
        iso_day = day.isoformat()
        availability.append({
            'bookings': serialize_occurrences(group_by_occurrence_date(bookings)).get(iso_day),
            'blockings': serialize_blockings(group_blockings(blockings, dates)).get(iso_day),
            'nonbookable_periods': serialize_nonbookable_periods(
                group_nonbookable_periods(nonbookable_periods, dates)).get(iso_day),
            'unbookable_hours': serialize_unbookable_hours(unbookable_hours),
            'day': iso_day,
        })
    return sorted(availability, key=itemgetter('day'))
Ejemplo n.º 19
0
def get_room_details_availability(room, start_dt, end_dt):
    dates = [d.date() for d in iterdays(start_dt, end_dt)]

    bookings = get_existing_room_occurrences(room, start_dt, end_dt, RepeatFrequency.DAY, 1, only_accepted=True)
    blockings = get_rooms_blockings([room], start_dt.date(), end_dt.date()).get(room.id, [])
    unbookable_hours = get_rooms_unbookable_hours([room]).get(room.id, [])
    nonbookable_periods = get_rooms_nonbookable_periods([room], start_dt, end_dt).get(room.id, [])

    availability = []
    for day in dates:
        iso_day = day.isoformat()
        nb_periods = serialize_nonbookable_periods(group_nonbookable_periods(nonbookable_periods, dates)).get(iso_day)
        availability.append({
            'bookings': serialize_occurrences(group_by_occurrence_date(bookings)).get(iso_day),
            'blockings': serialize_blockings(group_blockings(blockings, dates)).get(iso_day),
            'nonbookable_periods': nb_periods,
            'unbookable_hours': serialize_unbookable_hours(unbookable_hours),
            'day': iso_day,
        })
    return sorted(availability, key=itemgetter('day'))
Ejemplo n.º 20
0
def get_room_bookings(room, start_dt, end_dt, skip_booking_id=None):
    bookings = get_existing_room_occurrences(room, start_dt, end_dt, RepeatFrequency.DAY, 1, only_accepted=True,
                                             skip_booking_id=skip_booking_id)
    return serialize_occurrences(group_by_occurrence_date(bookings))
Ejemplo n.º 21
0
def get_booking_occurrences(booking):
    date_range = sorted(
        set(cand.start_dt.date() for cand in booking.occurrences))
    occurrences = group_by_occurrence_date(booking.occurrences)
    return date_range, occurrences
Ejemplo n.º 22
0
def get_room_calendar(start_date,
                      end_date,
                      room_ids,
                      include_inactive=False,
                      **filters):
    start_dt = datetime.combine(start_date, time(hour=0, minute=0))
    end_dt = datetime.combine(end_date, time(hour=23, minute=59))
    query = _bookings_query(
        dict(filters,
             start_dt=start_dt,
             end_dt=end_dt,
             room_ids=room_ids,
             include_inactive=include_inactive))
    query = query.order_by(db.func.indico.natsort(Room.full_name))
    rooms = (Room.query.filter(
        Room.is_active,
        Room.id.in_(room_ids) if room_ids else True).options(
            joinedload('location')).order_by(
                db.func.indico.natsort(Room.full_name)).all())

    unbookable_hours = get_rooms_unbookable_hours(rooms)
    nonbookable_periods = get_rooms_nonbookable_periods(
        rooms, start_dt, end_dt)
    occurrences_by_room = groupby(query, attrgetter('reservation.room_id'))
    blocked_rooms = get_rooms_blockings(rooms, start_dt, end_dt)

    dates = [d.date() for d in iterdays(start_dt, end_dt)]

    calendar = OrderedDict((room.id, {
        'room_id':
        room.id,
        'nonbookable_periods':
        group_nonbookable_periods(nonbookable_periods.get(room.id, []), dates),
        'unbookable_hours':
        unbookable_hours.get(room.id, []),
        'blockings':
        group_blockings(blocked_rooms.get(room.id, []), dates),
    }) for room in rooms)

    for room_id, occurrences in occurrences_by_room:
        occurrences = list(occurrences)
        pre_bookings = [
            occ for occ in occurrences if occ.reservation.is_pending
        ]
        existing_bookings = [
            occ for occ in occurrences
            if not occ.reservation.is_pending and occ.is_valid
        ]

        additional_data = {
            'bookings': group_by_occurrence_date(existing_bookings),
            'pre_bookings': group_by_occurrence_date(pre_bookings)
        }

        if include_inactive:
            additional_data.update({
                'cancellations':
                group_by_occurrence_date(occ for occ in occurrences
                                         if occ.is_cancelled),
                'rejections':
                group_by_occurrence_date(occ for occ in occurrences
                                         if occ.is_rejected)
            })

        calendar[room_id].update(additional_data)
    return calendar
Ejemplo n.º 23
0
def get_rooms_availability(rooms,
                           start_dt,
                           end_dt,
                           repeat_frequency,
                           repeat_interval,
                           skip_conflicts_with=None,
                           admin_override_enabled=False):
    availability = OrderedDict()
    candidates = ReservationOccurrence.create_series(
        start_dt, end_dt, (repeat_frequency, repeat_interval))
    date_range = sorted(set(cand.start_dt.date() for cand in candidates))
    occurrences = get_existing_rooms_occurrences(
        rooms, start_dt.replace(hour=0, minute=0),
        end_dt.replace(hour=23, minute=59), repeat_frequency, repeat_interval)
    blocked_rooms = get_rooms_blockings(rooms, start_dt.date(), end_dt.date())
    nonoverridable_blocked_rooms = group_blocked_rooms(
        filter_blocked_rooms(blocked_rooms,
                             nonoverridable_only=True,
                             explicit=True))
    overridable_blocked_rooms = group_blocked_rooms(
        filter_blocked_rooms(blocked_rooms,
                             overridable_only=True,
                             explicit=True))
    unbookable_hours = get_rooms_unbookable_hours(rooms)
    nonbookable_periods = get_rooms_nonbookable_periods(
        rooms, start_dt, end_dt)
    conflicts, pre_conflicts, conflicting_candidates = get_rooms_conflicts(
        rooms,
        start_dt.replace(tzinfo=None),
        end_dt.replace(tzinfo=None),
        repeat_frequency,
        repeat_interval,
        nonoverridable_blocked_rooms,
        nonbookable_periods,
        unbookable_hours,
        skip_conflicts_with,
        allow_admin=admin_override_enabled)
    dates = list(candidate.start_dt.date() for candidate in candidates)
    for room in rooms:
        room_occurrences = occurrences.get(room.id, [])
        room_conflicting_candidates = conflicting_candidates.get(room.id, [])
        room_conflicts = conflicts.get(room.id, [])
        pre_room_conflicts = pre_conflicts.get(room.id, [])
        pre_bookings = [
            occ for occ in room_occurrences if not occ.reservation.is_accepted
        ]
        existing_bookings = [
            occ for occ in room_occurrences if occ.reservation.is_accepted
        ]
        room_nonoverridable_blocked_rooms = nonoverridable_blocked_rooms.get(
            room.id, [])
        room_overridable_blocked_rooms = overridable_blocked_rooms.get(
            room.id, [])
        room_nonbookable_periods = nonbookable_periods.get(room.id, [])
        room_unbookable_hours = unbookable_hours.get(room.id, [])

        room_candidates = get_room_candidates(candidates, room_conflicts,
                                              pre_room_conflicts)
        availability[room.id] = {
            'room_id':
            room.id,
            'candidates':
            group_by_occurrence_date(room_candidates),
            'conflicting_candidates':
            group_by_occurrence_date(room_conflicting_candidates),
            'pre_bookings':
            group_by_occurrence_date(pre_bookings),
            'bookings':
            group_by_occurrence_date(existing_bookings),
            'conflicts':
            group_by_occurrence_date(room_conflicts),
            'pre_conflicts':
            group_by_occurrence_date(pre_room_conflicts),
            'blockings':
            group_blockings(room_nonoverridable_blocked_rooms, dates),
            'overridable_blockings':
            group_blockings(room_overridable_blocked_rooms, dates),
            'nonbookable_periods':
            group_nonbookable_periods(room_nonbookable_periods, dates),
            'unbookable_hours':
            room_unbookable_hours
        }
    return date_range, availability
Ejemplo n.º 24
0
def get_booking_occurrences(booking):
    date_range = sorted(set(cand.start_dt.date() for cand in booking.occurrences))
    occurrences = group_by_occurrence_date(booking.occurrences)
    return date_range, occurrences