Source code for org.views.form_registration_window

from collections import defaultdict
from onegov.core.security import Private
from onegov.form import CompleteFormSubmission
from onegov.form import FormDefinition
from onegov.form import FormRegistrationWindow
from onegov.form import FormSubmission
from onegov.org import OrgApp, _
from onegov.org.cli import close_ticket
from onegov.org.forms import FormRegistrationWindowForm
from onegov.org.forms.form_registration import FormRegistrationMessageForm
from onegov.org.layout import FormSubmissionLayout
from onegov.core.elements import Link, LinkGroup, Confirm, Intercooler, Block

from onegov.org.models import TicketNote
from onegov.org.views.form_submission import handle_submission_action
from onegov.org.mail import send_transactional_html_mail
from onegov.org.views.ticket import accept_ticket, send_email_if_enabled
from onegov.ticket import TicketCollection, Ticket


from typing import Any, Literal, TYPE_CHECKING
if TYPE_CHECKING:
    from email.headerregistry import Address
    from onegov.core.types import RenderData, SequenceOrScalar
    from onegov.org.request import OrgRequest
    from webob import Response


@OrgApp.form(
    model=FormDefinition,
    name='new-registration-window',
    permission=Private,
    form=FormRegistrationWindowForm,
    template='form.pt'
)
[docs] def handle_new_registration_form( self: FormDefinition, request: 'OrgRequest', form: FormRegistrationWindowForm, layout: FormSubmissionLayout | None = None ) -> 'RenderData | Response': title = _('New Registration Window') layout = layout or FormSubmissionLayout(self, request) layout.editbar_links = None layout.breadcrumbs.append(Link(title, '#')) if form.submitted(request): assert form.start.data is not None assert form.end.data is not None form.populate_obj(self.add_registration_window( form.start.data, form.end.data )) request.success(_('The registration window was added successfully')) return request.redirect(request.link(self)) return { 'layout': layout, 'title': title, 'form': form, 'helptext': _( 'Registration windows limit forms to a set number of submissions ' 'and a specific time-range.' ) }
[docs] def send_form_registration_email( request: 'OrgRequest', receivers: 'SequenceOrScalar[Address | str]', content: dict[str, Any], action: Literal['general-message'] ) -> None: if action == 'general-message': subject = _('General Message') else: raise NotImplementedError send_transactional_html_mail( request=request, template='mail_registration_message.pt', subject=subject, receivers=receivers, content=content )
[docs] def ticket_linkable( request: 'OrgRequest', ticket: Ticket | None ) -> Ticket | None: if ticket is None: return None if not request.link(ticket): return None return ticket
@OrgApp.form( model=FormRegistrationWindow, permission=Private, name='send-message', template='form.pt', form=FormRegistrationMessageForm )
[docs] def view_send_form_registration_message( self: FormRegistrationWindow, request: 'OrgRequest', form: FormRegistrationMessageForm, layout: FormSubmissionLayout | None = None, ) -> 'RenderData | Response': if form.submitted(request): count = 0 tickets = TicketCollection(request.session) for email, submission in form.receivers.items(): if not form.message.data: continue ticket = tickets.by_handler_id(submission.id.hex) # be extra safe and check for missing ticket of submission ticket = ticket_linkable(request, ticket) if ticket is not None: TicketNote.create(ticket, request, ( request.translate(_( 'New e-mail: ${message}', mapping={'message': form.message.data.strip()} )) )) send_form_registration_email( request=request, receivers=(email,), action='general-message', content={ 'model': submission, 'action': 'general-message', 'message': form.message.data.strip(), } ) count += 1 request.success( _('Successfully sent ${count} emails', mapping={'count': count}) ) return request.redirect(request.link(self)) layout = layout or FormSubmissionLayout(self.form, request) layout.breadcrumbs.append( Link(_('Registration Window'), request.link(self)) ) layout.editbar_links = [] return { 'title': _('Send E-Mail to attendees'), 'layout': layout, 'form': form }
@OrgApp.html( model=FormRegistrationWindow, permission=Private, template='registration_window.pt' )
[docs] def view_registration_window( self: FormRegistrationWindow, request: 'OrgRequest', layout: FormSubmissionLayout | None = None ) -> 'RenderData': layout = layout or FormSubmissionLayout(self.form, request) title = layout.format_date_range(self.start, self.end) layout.breadcrumbs.append(Link(title, '#')) registrations = defaultdict(list) q = request.session.query(FormSubmission) q = q.filter_by(registration_window_id=self.id) q = q.filter_by(state='complete') # ogc-1345 order after family name first q = q.order_by( FormSubmission.data['nachname'], FormSubmission.data['name'], FormSubmission.data['vorname'], ) has_pending_or_confirmed = False for submission in q: if not submission.registration_state: continue registrations[submission.registration_state].append(submission) if submission.registration_state != 'cancelled': has_pending_or_confirmed = True editbar_links: list[Link | LinkGroup] = [ Link( text=_('Edit'), url=request.link(self, 'edit'), attrs={'class': 'edit-link'} ) ] if registrations: editbar_links.append( Link( text=_('Email attendees'), url=request.link(self, name='send-message'), attrs={'class': 'manage-recipients'} ) ) editbar_links.append( Link( text=_('Cancel Registration Window'), url=layout.csrf_protected_url( request.link(self, name='cancel')), attrs={'class': 'cancel'}, traits=( Confirm( _('You really want to cancel all confirmed and ' 'deny all open submissions for this ' 'registration window?'), _('Each attendee will receive a ticket email ' 'unless ticket messages are not muted.'), _('Cancel Registration Window'), _('Cancel'), ), Intercooler( request_method='POST', redirect_after=request.link(self) ) ) ), ) editbar_links.append( Link( text=_('Delete'), url=layout.csrf_protected_url(request.link(self)), attrs={'class': 'delete-link'}, traits=( Confirm( _( 'Do you really want to delete ' 'this registration window?' ), _('Existing submissions will be disassociated.'), _('Delete registration window'), _('Cancel') ), Intercooler( request_method='DELETE', redirect_after=request.link(self.form) ) ) if not has_pending_or_confirmed else ( Block( _("This registration window can't be deleted."), _('There are confirmed or open submissions associated ' 'with it. Cancel the registration window first.'), _('Cancel') ) ) ) ) layout.editbar_links = editbar_links tickets = TicketCollection(request.session) def ticket_link(subm: FormSubmission) -> str | None: ticket = tickets.by_handler_id(subm.id.hex) return ticket and request.link(ticket) or None return { 'layout': layout, 'title': title, 'model': self, 'registrations': registrations, 'groups': ( (_('Open'), 'open'), (_('Confirmed'), 'confirmed'), (_('Cancelled'), 'cancelled'), ), 'ticket_link': ticket_link }
@OrgApp.form( model=FormRegistrationWindow, permission=Private, form=FormRegistrationWindowForm, template='form.pt', name='edit' )
[docs] def handle_edit_registration_form( self: FormRegistrationWindow, request: 'OrgRequest', form: FormRegistrationWindowForm, layout: FormSubmissionLayout | None = None ) -> 'RenderData | Response': title = _('Edit Registration Window') layout = layout or FormSubmissionLayout(self.form, request) layout.breadcrumbs.append(Link(title, '#')) layout.editbar_links = [] if form.submitted(request): form.populate_obj(self) request.success(_('Your changes were saved')) return request.redirect(request.link(self.form)) elif not request.POST: form.process(obj=self) return { 'layout': layout, 'title': title, 'form': form }
@OrgApp.view( model=FormRegistrationWindow, permission=Private, name='cancel', request_method='POST' )
[docs] def view_cancel_submissions_for_registration_window( self: FormRegistrationWindow, request: 'OrgRequest' ) -> None: """ Cancels a bunch of submissions either open ones or already accepted ones. If there is a corresponding ticket, it is accepted before denying the submission. """ request.assert_valid_csrf_token() count = 0 action: Literal['cancelled', 'denied'] for submission in self.submissions: if submission.registration_state == 'confirmed': action = 'cancelled' elif submission.registration_state == 'open': action = 'denied' else: continue ticket = TicketCollection(request.session).by_handler_id( submission.id.hex) if ticket and ticket.state == 'open': accept_ticket(ticket, request) if ticket: # if there is a ticket then the submission is complete assert isinstance(submission, CompleteFormSubmission) handle_submission_action( submission, request, action, ignore_csrf=True, raises=True, no_messages=True, force_email=ticket.muted ) assert request.current_user is not None close_ticket(ticket, request.current_user, request) # same behaviour as when closing ticket normally # to disable mail on ticket close, there is a ticket-setting send_email_if_enabled( ticket=ticket, request=request, template='mail_ticket_closed.pt', subject=_('Your request has been closed.') ) count += 1 if count: request.success( _('${count} submissions cancelled / denied over the ticket system', mapping={'count': count}))
@OrgApp.view( model=FormRegistrationWindow, permission=Private, request_method='DELETE' )
[docs] def delete_registration_window( self: FormRegistrationWindow, request: 'OrgRequest' ) -> None: request.assert_valid_csrf_token() self.disassociate() request.session.delete(self) request.success(_('The registration window was deleted'))