-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathresource_recipient.py
More file actions
169 lines (141 loc) · 5.39 KB
/
Copy pathresource_recipient.py
File metadata and controls
169 lines (141 loc) · 5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
from __future__ import annotations
import re
from onegov.form import Form
from onegov.form.fields import MultiCheckboxField, TagsField
from onegov.org import _
from onegov.reservation import Resource, ResourceCollection
from wtforms.fields import EmailField
from wtforms.fields import StringField
from wtforms.fields import BooleanField
from wtforms.validators import InputRequired, Email
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from onegov.org.request import OrgRequest
_TIME_RE = re.compile(r'^([01]\d|2[0-3]):([0-5]\d)$')
WEEKDAYS = (
('MO', _('Mo')),
('TU', _('Tu')),
('WE', _('We')),
('TH', _('Th')),
('FR', _('Fr')),
('SA', _('Sa')),
('SU', _('Su')),
)
class ResourceRecipientForm(Form):
if TYPE_CHECKING:
request: OrgRequest
name = StringField(
label=_('Name'),
fieldset='Empfänger',
description='Peter Muster',
validators=[InputRequired()]
)
address = EmailField(
label=_('E-Mail'),
fieldset='Empfänger',
description='peter.muster@example.org',
validators=[InputRequired(), Email()]
)
new_reservations = BooleanField(
label=_('New Reservations'),
fieldset=_('Notifications *'),
description=_('For each new reservation, a notification will be sent '
'to the above recipient.'),
)
daily_reservations = BooleanField(
label=_('Daily Reservations'),
fieldset=_('Notifications *'),
description=_("On each day selected below, a notification with the "
"day's reservations will be sent to the recipient "
"above."),
)
customer_messages = BooleanField(
label=_('Customer Messages'),
fieldset=_('Notifications *'),
description=_('Each time a customer adds a message to the ticket for '
'a reservation, a notification is sent to the recipient '
'above.'),
)
internal_notes = BooleanField(
label=_('Internal Notes'),
fieldset=_('Notifications *'),
description=_('Each time a new note is added to the ticket for a '
'reservation, a notification is sent to the recipient '
'above.'),
)
rejected_reservations = BooleanField(
label=_('Rejected Reservations'),
fieldset=_('Notifications *'),
description=_('If a reservation is cancelled, a notification will '
'be sent to the above recipient.'),
)
send_on = MultiCheckboxField(
label=_('Send on'),
fieldset='Tage und Ressourcen',
choices=WEEKDAYS,
default=[key for key, value in WEEKDAYS],
validators=[InputRequired()],
depends_on=('daily_reservations', 'y'),
render_kw={'prefix_label': False, 'class_': 'oneline-checkboxes'}
)
daily_reservations_times = TagsField(
label=_('Delivery Times'),
fieldset='Tage und Ressourcen',
description=_('e.g. 07:00 or 07:00, 14:30'),
depends_on=('daily_reservations', 'y'),
)
resources = MultiCheckboxField(
label=_('Resources'),
fieldset='Tage und Ressourcen',
validators=[InputRequired()],
choices=None
)
def ensure_valid_delivery_times(self) -> bool | None:
if not self.daily_reservations.data:
return None
times = self.daily_reservations_times.data
if isinstance(times, str):
times = [t.strip() for t in times.split(',') if t.strip()]
if not times:
self.daily_reservations_times.errors.append( # type: ignore[attr-defined]
_('Please enter at least one delivery time.')
)
return False
for t in times:
m = _TIME_RE.match(t)
if not m:
self.daily_reservations_times.errors.append( # type: ignore[attr-defined]
_('Invalid time "${time}". Use HH:MM format (e.g. 06:00).',
mapping={'time': t})
)
return False
if int(m.group(2)) % 5 != 0:
self.daily_reservations_times.errors.append( # type: ignore[attr-defined]
_('Minutes must be a multiple of 5 (e.g. 06:00, 06:30).')
)
return False
return None
def ensure_at_least_one_notification(self) -> bool | None:
if not (
self.new_reservations.data
or self.daily_reservations.data
or self.customer_messages.data
or self.internal_notes.data
or self.rejected_reservations.data
):
self.request.alert(_('Please add at least one notification.'))
return False
return None
def on_request(self) -> None:
if not self.request.POST and not self.daily_reservations_times.data:
self.daily_reservations_times.data = ['06:00'] # legacy default
default_group = self.request.translate(_('General'))
self.resources.choices = [
(resource_id.hex, f'{group or default_group} - {title}')
for group, title, resource_id in (
ResourceCollection(self.request.app.libres_context).query()
.with_entities(Resource.group, Resource.title, Resource.id)
.order_by(Resource.group, Resource.name)
.tuples()
)
]