Source code for org.forms.payments
from __future__ import annotations
from onegov.core.utils import normalize_for_url
from onegov.form.core import Form
from onegov.form.fields import ChosenSelectField, TranslatedSelectField
from onegov.form.validators import StrictOptional
from onegov.org import _
from onegov.ticket import handlers as ticket_handlers
from operator import itemgetter
from wtforms import DateField
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from onegov.core.request import CoreRequest
from onegov.pay import PaymentCollection
from onegov.ticket import TicketCollection, TicketInvoiceCollection
from wtforms.fields.choices import _Choice
[docs]
def coerce_optional_bool(choice: str | bool | None) -> bool | None:
if isinstance(choice, str):
match choice.lower():
case 'true':
return True
case 'false':
return False
case _:
return None
return choice
[docs]
def get_ticket_group_choices(request: CoreRequest) -> list[_Choice]:
tickets: TicketCollection | None
# NOTE: This is a little bit expensive, but since we don't use the
# same ticket collection class in every application this is
# easier than overwriting these forms in every application
tickets = request.resolve_path('/tickets/ALL/all')
if tickets is None:
return []
handlers: list[tuple[str, str]] = []
groups = dict(tickets.groups_by_handler_code())
for handler_code in groups:
if handler_code not in ticket_handlers.registry:
continue
handler = ticket_handlers.get(handler_code)
assert hasattr(handler, 'handler_title')
handlers.append(
(handler_code, request.translate(handler.handler_title))
)
handlers.sort(key=itemgetter(1))
choices: list[_Choice] = []
for handler_code, title in handlers:
handler_groups = groups[handler_code]
handler_groups.sort(key=normalize_for_url)
choices.append((
handler_code,
title,
{
'class': f'{handler_code}-link'
f'{" is-parent" if handler_groups else ""}'
}
))
choices.extend(
(
f'{handler_code}-{group}',
group,
{'class': f'{handler_code}-sub-link ticket-group-filter'}
)
for group in handler_groups
)
choices.insert(0, (
'',
request.translate(_('All Tickets')),
{'class': 'ALL-link'}
))
return choices
[docs]
class TicketInvoiceSearchForm(Form):
[docs]
invoiced = TranslatedSelectField(
label=_('Status'),
fieldset=_('Filter Invoices'),
choices=[
('None', _('All')),
('False', _('Uninvoiced')),
('True', _('Invoiced')),
],
coerce=coerce_optional_bool,
default=None,
)
[docs]
ticket_group = ChosenSelectField(
label=_('Ticket category'),
fieldset=_('Filter Invoices'),
choices=[],
default='ALL',
)
[docs]
ticket_start_date = DateField(
label=_('Ticket created from date'),
fieldset=_('Filter by Ticket Date'),
description=_('Filters payments by the creation date of their '
'associated ticket.'),
validators=[StrictOptional()]
)
[docs]
ticket_end_date = DateField(
label=_('Ticket created to date'),
fieldset=_('Filter by Ticket Date'),
description=_('Filters payments by the creation date of their '
'associated ticket.'),
validators=[StrictOptional()]
)
[docs]
reservation_start_date = DateField(
label=_('From reservation date'),
fieldset=_('Filter by Reservation Date'),
validators=[StrictOptional()]
)
[docs]
reservation_end_date = DateField(
label=_('To reservation date'),
fieldset=_('Filter by Reservation Date'),
validators=[StrictOptional()]
)
[docs]
def on_request(self) -> None:
self.ticket_group.choices = get_ticket_group_choices(self.request)
[docs]
def apply_model(self, model: TicketInvoiceCollection) -> None:
"""Populate the form fields from the model's filter values."""
self.invoiced.data = model.invoiced
self.ticket_group.data = model.ticket_group or ''
self.ticket_start_date.data = model.ticket_start
self.ticket_end_date.data = model.ticket_end
self.reservation_start_date.data = model.reservation_start
self.reservation_end_date.data = model.reservation_end
[docs]
def update_model(self, model: TicketInvoiceCollection) -> None:
"""Update the model's filter values from the form's data."""
model.invoiced = self.invoiced.data
model.ticket_group = self.ticket_group.data or None
model.ticket_start = self.ticket_start_date.data
model.ticket_end = self.ticket_end_date.data
model.reservation_start = self.reservation_start_date.data
model.reservation_end = self.reservation_end_date.data
# Reset to the first page when filters change
model.page = 0
[docs]
class PaymentSearchForm(Form):
[docs]
status = TranslatedSelectField(
label=_('Status'),
fieldset=_('Filter Payments'),
choices=[
('', _('All')),
('open', _('Open')),
('paid', _('Paid')),
('invoiced', _('Invoiced'))
],
default='',
)
[docs]
payment_type = TranslatedSelectField(
label=_('Payment Type'),
fieldset=_('Filter Payments'),
choices=[
('', _('All')),
('manual', _('Manual')),
('provider', _('Payment Provider'))
],
default='',
)
[docs]
ticket_group = ChosenSelectField(
label=_('Ticket category'),
fieldset=_('Filter Payments'),
choices=[],
default='ALL',
)
[docs]
ticket_start_date = DateField(
label=_('Ticket created from date'),
fieldset=_('Filter by Ticket Date'),
description=_('Filters payments by the creation date of their '
'associated ticket.'),
validators=[StrictOptional()]
)
[docs]
ticket_end_date = DateField(
label=_('Ticket created to date'),
fieldset=_('Filter by Ticket Date'),
description=_('Filters payments by the creation date of their '
'associated ticket.'),
validators=[StrictOptional()]
)
[docs]
reservation_start_date = DateField(
label=_('From reservation date'),
fieldset=_('Filter by Reservation Date'),
validators=[StrictOptional()]
)
[docs]
reservation_end_date = DateField(
label=_('To reservation date'),
fieldset=_('Filter by Reservation Date'),
validators=[StrictOptional()]
)
[docs]
def apply_model(self, model: PaymentCollection) -> None:
"""Populate the form fields from the model's filter values."""
self.reservation_start_date.data = model.reservation_start
self.reservation_end_date.data = model.reservation_end
self.status.data = model.status or ''
self.ticket_group.data = model.ticket_group
self.ticket_start_date.data = model.ticket_start
self.ticket_end_date.data = model.ticket_end
self.payment_type.data = model.payment_type or ''
[docs]
def update_model(self, model: PaymentCollection) -> None:
"""Update the model's filter values from the form's data."""
model.reservation_start = self.reservation_start_date.data
model.reservation_end = self.reservation_end_date.data
model.status = self.status.data or None
model.ticket_group = self.ticket_group.data or None
model.ticket_start = self.ticket_start_date.data
model.ticket_end = self.ticket_end_date.data
model.payment_type = self.payment_type.data or None
# Reset to the first page when filters change
model.page = 0
[docs]
def on_request(self) -> None:
self.ticket_group.choices = get_ticket_group_choices(self.request)