def validate_occurrences(self, field): for req_dt in field.data: if not isinstance(req_dt, datetime): raise ValidationError(_('You have to explicitly specify the time for the assistance request')) is_in_working_hours = WORKING_TIME_PERIOD[0] <= req_dt.time() <= WORKING_TIME_PERIOD[1] if not is_in_working_hours: raise ValidationError(_('One of the specified times is not within the working hours'))
class RoomAssistanceForm(IndicoForm): _fieldsets = [ ('Startup assistance emails', [ 'room_assistance_recipients', 'rooms_with_assistance', 'room_assistance_support' ]), ] room_assistance_recipients = EmailListField( _('Recipients'), description=_('Notifications about room assistance requests are sent ' 'to these email addresses (one per line)')) rooms_with_assistance = IndicoQuerySelectMultipleField( 'Rooms', query_factory=lambda: Room.query, description=_('Rooms for which users can request startup ' 'assistance'), get_label='full_name', collection_class=set, render_kw={'size': 20}, modify_object_list=_order_func) room_assistance_support = PrincipalListField( _('Room assistance support'), groups=True, description=_('List of users who can view the list of events with ' 'room startup assistance.'))
def _on_event_update(self, event, **kwargs): changes = kwargs['changes'] if not changes.viewkeys() & {'location_data', 'start_dt', 'end_dt'}: return request = Request.find_latest_for_event(event, RoomAssistanceRequest.name) if not request or request.state != RequestState.accepted: return if 'location_data' in changes and not event_has_room_with_support_attached( event): request.definition.reject( request, { 'comment': render_plugin_template('auto_reject_no_supported_room.txt') }, User.get_system_user()) request.data = dict(request.data, occurrences=[]) flash( _("The new event location is not in the list of the rooms supported by the room assistance team. " "Room assistance request has been rejected and support will not be provided." ), 'warning') if changes.viewkeys() & {'start_dt', 'end_dt'}: tz = pytz.timezone(config.DEFAULT_TIMEZONE) occurrences = { dateutil.parser.parse(occ).astimezone(tz) for occ in request.data['occurrences'] } req_dates = {occ.date() for occ in occurrences} event_dates = set(event.iter_days()) old_dates = req_dates - event_dates has_overlapping_dates = req_dates & event_dates if not has_overlapping_dates: request.definition.reject( request, { 'comment': render_plugin_template( 'auto_reject_no_overlapping_dates.txt') }, User.get_system_user()) request.data = dict(request.data, occurrences=[]) flash( _("The new event dates don't overlap with the existing room assistance request for this event. " "Room assistance request has been rejected and support will not be provided." ), 'warning') elif old_dates and has_overlapping_dates: new_data = dict(request.data) new_data['occurrences'] = [ occ.astimezone(pytz.utc).isoformat() for occ in occurrences if occ.date() in req_dates & event_dates ] request.data = new_data flash( _("Room assistance had been requested for days that are not between the updated start/end " "dates. Support will not be provided on these days anymore." ), 'warning')
class RoomAssistanceRequestForm(RequestFormBase): start_dt = IndicoDateTimeField( _('When'), [DataRequired(), DateTimeRange(earliest=now_utc())], description=_('When do you need the assistance?')) reason = TextAreaField(_('Reason'), [DataRequired()], description=_('Why are you requesting assistance?')) def validate_start_dt(self, field): localized_time = field.data.astimezone(session.tzinfo).time() is_in_working_hours = WORKING_TIME_PERIOD[ 0] <= localized_time <= WORKING_TIME_PERIOD[1] if not is_in_working_hours: raise ValidationError( 'Specified datetime is not within the working hours')
class RoomAssistanceRequestForm(RequestFormBase): occurrences = _RequestOccurrencesField(_('When'), [DataRequired()], description=_('When do you need the assistance?')) reason = TextAreaField(_('Reason'), [DataRequired()], description=_('Why are you requesting assistance?')) def __init__(self, *args, **kwargs): super(RoomAssistanceRequestForm, self).__init__(*args, **kwargs) self.occurrences.event = kwargs['event'] def validate_occurrences(self, field): for req_dt in field.data: if not isinstance(req_dt, datetime): raise ValidationError(_('You have to explicitly specify the time for the assistance request')) is_in_working_hours = WORKING_TIME_PERIOD[0] <= req_dt.time() <= WORKING_TIME_PERIOD[1] if not is_in_working_hours: raise ValidationError(_('One of the specified times is not within the working hours'))
def _extend_services_menu(self, reservation, **kwargs): if not session.user or not is_room_assistance_support(session.user): return return TopMenuItem('services-cern-room-assistance', _('Room assistance'), url_for_plugin('room_assistance.request_list'), section='services')
def validate_occurrences(self, field): for req_dt in field.data: is_in_working_hours = WORKING_TIME_PERIOD[0] <= req_dt.time( ) <= WORKING_TIME_PERIOD[1] if not is_in_working_hours: raise ValidationError( _('One of the specified times is not within the working hours' ))
class RequestListFilterForm(IndicoForm): direction = SelectField(_('Sort direction'), [DataRequired()], choices=[('asc', _('Ascending')), ('desc', _('Descending'))]) abs_start_date = IndicoDateField( _('Start Date'), [Optional(), Exclusive('rel_start_date')]) abs_end_date = IndicoDateField( _('End Date'), [Optional(), Exclusive('rel_end_date')]) rel_start_date = IntegerField( _('Days in the past'), [Optional(), Exclusive('abs_start_date'), NumberRange(min=0)]) rel_end_date = IntegerField( _('Days in the future'), [Optional(), Exclusive('abs_end_date'), NumberRange(min=0)]) def is_submitted(self): return bool(request.args) @generated_data def start_date(self): if self.abs_start_date.data is None and self.rel_start_date.data is None: return None return self.abs_start_date.data or ( date.today() - timedelta(days=self.rel_start_date.data)) @generated_data def end_date(self): if self.abs_end_date.data is None and self.rel_end_date.data is None: return None return self.abs_end_date.data or ( date.today() + timedelta(days=self.rel_end_date.data))
class RoomAssistanceRequest(RequestDefinitionBase): name = 'room-assistance' title = _('Room assistance') form = RoomAssistanceRequestForm @classmethod def render_form(cls, event, **kwargs): kwargs['event_has_room_attached'] = event.room is not None kwargs['room_allows_assistance'] = event.room in cls.plugin.settings.get('rooms_with_assistance') return super(RoomAssistanceRequest, cls).render_form(event, **kwargs) @classmethod def create_form(cls, event, existing_request=None): form_data = {'occurrences': None} if existing_request: tz = pytz.timezone(config.DEFAULT_TIMEZONE) form_data = dict(existing_request.data) form_data['occurrences'] = [dateutil.parser.parse(occ).astimezone(tz) for occ in form_data['occurrences']] with plugin_context(cls.plugin): return cls.form(prefix='request-', obj=FormDefaults(form_data), event=event, request=existing_request) @classmethod def can_be_managed(cls, user): return False @classmethod def send(cls, req, data): room = req.event.room if room is None or room not in cls.plugin.settings.get('rooms_with_assistance'): raise Forbidden is_new = req.id is None req.state = RequestState.accepted old_data = {} if is_new else req.data data['occurrences'] = [occ.astimezone(pytz.utc).isoformat() for occ in data['occurrences']] super(RoomAssistanceRequest, cls).send(req, data) with plugin_context(cls.plugin): if is_new: notify_about_new_request(req) else: changes = {} if data['reason'] != old_data['reason']: changes['reason'] = {'old': old_data['reason'], 'new': data['reason']} if data['occurrences'] != old_data['occurrences']: changes['occurrences'] = [dateutil.parser.parse(occ) for occ in data['occurrences']] if changes: notify_about_request_modification(req, changes) @classmethod def withdraw(cls, req, notify_event_managers=True): super(RoomAssistanceRequest, cls).withdraw(req, notify_event_managers) with plugin_context(cls.plugin): notify_about_withdrawn_request(req)
class RoomAssistanceRequest(RequestDefinitionBase): name = 'room-assistance' title = _('Room assistance') form = RoomAssistanceRequestForm @classmethod def render_form(cls, event, **kwargs): kwargs['event_has_room_attached'] = event.room is not None kwargs[ 'room_allows_assistance'] = event.room in cls.plugin.settings.get( 'rooms_with_assistance') return super(RoomAssistanceRequest, cls).render_form(event, **kwargs) @classmethod def create_form(cls, event, existing_request=None): form_data = {'start_dt': event.start_dt_local - timedelta(minutes=30)} if existing_request: form_data = dict(existing_request.data) if form_data['start_dt']: form_data['start_dt'] = dateutil.parser.parse( form_data['start_dt']) with plugin_context(cls.plugin): return cls.form(prefix='request-', obj=FormDefaults(form_data), event=event, request=existing_request) @classmethod def can_be_managed(cls, user): return False @classmethod def send(cls, req, data): room = req.event.room if room is None or room not in cls.plugin.settings.get( 'rooms_with_assistance'): raise Forbidden data['start_dt'] = data['start_dt'].isoformat() is_new = req.id is None req.state = RequestState.accepted old_data = {} if is_new else req.data super(RoomAssistanceRequest, cls).send(req, data) with plugin_context(cls.plugin): if is_new: notify_about_new_request(req) else: changes = {} if data['reason'] != old_data['reason']: changes['reason'] = { 'old': old_data['reason'], 'new': data['reason'] } if data['start_dt'] != old_data['start_dt']: changes['start_dt'] = { 'old': dateutil.parser.parse(old_data['start_dt']), 'new': dateutil.parser.parse(data['start_dt']) } if changes: notify_about_request_modification(req, changes) @classmethod def withdraw(cls, req, notify_event_managers=True): super(RoomAssistanceRequest, cls).withdraw(req, notify_event_managers) with plugin_context(cls.plugin): notify_about_withdrawn_request(req)
def _get_breadcrumbs(self): return render_breadcrumbs(_('Room assistance'))