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'))
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)
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)
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)
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)
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)
def _serialize_availability(availability): for data in availability.viewvalues(): data['blockings'] = serialize_blockings(data.get('blockings', {})) data['nonbookable_periods'] = serialize_nonbookable_periods(data.get('nonbookable_periods', {})) data['unbookable_hours'] = serialize_unbookable_hours(data.get('unbookable_hours', {})) data.update({k: serialize_occurrences(data[k]) if k in data else {} for k in ['candidates', 'pre_bookings', 'bookings', 'conflicts', 'pre_conflicts']}) return availability
def _serialize_availability(availability): for data in availability.viewvalues(): data['blockings'] = serialize_blockings(data['blockings']) data['nonbookable_periods'] = serialize_nonbookable_periods(data['nonbookable_periods']) data['unbookable_hours'] = serialize_unbookable_hours(data['unbookable_hours']) data.update({k: serialize_occurrences(data[k]) if k in data else [] for k in ['candidates', 'pre_bookings', 'bookings', 'conflicts', 'pre_conflicts']}) return availability
def _serialize_availability(availability): for data in availability.viewvalues(): data['blockings'] = serialize_blockings(data.get('blockings', {})) data['nonbookable_periods'] = serialize_nonbookable_periods(data.get('nonbookable_periods', {})) data['unbookable_hours'] = serialize_unbookable_hours(data.get('unbookable_hours', {})) data.update({k: serialize_occurrences(data[k]) if k in data else {} for k in ('candidates', 'conflicting_candidates', 'pre_bookings', 'bookings', 'conflicts', 'pre_conflicts', 'rejections', 'cancellations')}) return availability
def _process(self, room_ids, start_dt, last_reservation_id, my_bookings, limit): start_dt = start_dt or datetime.combine(date.today(), time(0, 0)) booked_for_user = session.user if my_bookings else None bookings, rows_left = get_active_bookings(limit=limit, start_dt=start_dt, last_reservation_id=last_reservation_id, room_ids=room_ids, booked_for_user=booked_for_user) return jsonify(bookings=serialize_occurrences(bookings), rows_left=rows_left)
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))
def _process(self, args): rooms = Room.query.filter(Room.is_active, Room.id.in_(args.pop('room_ids'))) date_range, availability = get_rooms_availability(rooms, **args) date_range = [dt.isoformat() for dt in date_range] for room_id in availability: data = availability[room_id] data['room'] = rooms_schema.dump(data['room'], many=False).data data.update({ k: serialize_occurrences(data[k]) for k in [ 'candidates', 'pre_bookings', 'bookings', 'conflicts', 'pre_conflicts' ] }) return jsonify_data(flash=False, availability=availability, date_range=date_range)
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'))
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'))
def _process(self, args): query = search_for_rooms(args, only_available=True) if 'limit' in args: query = query.limit(args.pop('limit')) rooms = query.all() if 'additional_room_ids' in args: rooms.extend( Room.query.filter(Room.is_active, Room.id.in_( args.pop('additional_room_ids')))) date_range, availability = get_rooms_availability( rooms, args['start_dt'], args['end_dt'], args['repeat_frequency'], args['repeat_interval'], flexibility=0) date_range = [dt.isoformat() for dt in date_range] for room_id in availability: data = availability[room_id] data['room'] = rooms_schema.dump(data['room'], many=False).data data.update({ k: serialize_occurrences(data[k]) for k in [ 'candidates', 'pre_bookings', 'bookings', 'conflicts', 'pre_conflicts' ] }) data.update({ 'num_days_available': len(date_range) - len(data['conflicts']), 'all_days_available': not data['conflicts'] }) return jsonify_data(flash=False, availability=availability, date_range=date_range)
def get_booking_edit_calendar_data(booking, booking_changes): """Return calendar-related data for the booking edit modal.""" room = booking.room booking_details = serialize_booking_details(booking) old_date_range = booking_details['date_range'] booking_availability = dict(booking_details['occurrences'], candidates={}, conflicts={}, conflicting_candidates={}, pre_bookings={}, pre_conflicts={}, pending_cancellations={}, num_days_available=None, num_conflicts=None) response = { 'will_be_split': False, 'calendars': [{ 'date_range': old_date_range, 'data': booking_availability }] } if should_split_booking(booking, booking_changes): future_occurrences = [ occ for occ in sorted(booking.occurrences, key=attrgetter('start_dt')) if occ.start_dt >= datetime.now() ] new_booking_start_dt = datetime.combine( future_occurrences[0].start_dt.date(), booking_changes['start_dt'].time()) availability_filters = dict(booking_changes, start_dt=new_booking_start_dt) new_date_range, data = get_rooms_availability( [room], skip_conflicts_with=[booking.id], **availability_filters) for occ in booking.occurrences: serialized = serialize_occurrences({occ.start_dt.date(): [occ]}) if occ in future_occurrences: booking_availability['pending_cancellations'].update( serialized) elif not occ.is_rejected and not occ.is_cancelled: booking_availability['bookings'].update(serialized) response['will_be_split'] = True elif not has_same_dates(booking, booking_changes): new_date_range, data = get_rooms_availability( [room], skip_conflicts_with=[booking.id], **booking_changes) else: return response room_availability = data[room.id] room_availability['cancellations'] = {} room_availability['rejections'] = {} other_bookings = { dt: filter(lambda x: x.reservation.id != booking.id, other) for dt, other in room_availability['bookings'].iteritems() } cancelled_dates = [ occ.start_dt.date() for occ in booking.occurrences if occ.is_cancelled ] rejected_dates = [ occ.start_dt.date() for occ in booking.occurrences if occ.is_rejected ] candidates = room_availability['candidates'] for dt, dt_candidates in candidates.iteritems(): if dt in cancelled_dates: candidates[dt] = [] room_availability['cancellations'].update({dt: dt_candidates}) elif dt in rejected_dates: candidates[dt] = [] room_availability['rejections'].update({dt: dt_candidates}) room_availability['num_days_available'] = len(new_date_range) - len( room_availability['conflicts']) room_availability['num_conflicts'] = len(room_availability['conflicts']) room_availability['bookings'] = {} room_availability['other'] = serialize_occurrences(other_bookings) room_availability['pending_cancellations'] = {} response['calendars'].append({ 'date_range': new_date_range, 'data': serialize_availability(data)[room.id] }) return response