Skip to content

Commit e3076b7

Browse files
authored
Org: Makes resource notification delivery time configurable
TYPE: Feature LINK: ogc-3205
1 parent 0d67186 commit e3076b7

10 files changed

Lines changed: 400 additions & 126 deletions

File tree

src/onegov/org/cronjobs.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,10 +542,11 @@ def send_monthly_ticket_statistics(request: OrgRequest) -> None:
542542
)
543543

544544

545-
@OrgApp.cronjob(hour=6, minute=5, timezone='Europe/Zurich')
545+
@OrgApp.cronjob(hour='*', minute='*/5', timezone='Europe/Zurich')
546546
def send_daily_resource_usage_overview(request: OrgRequest) -> None:
547547
today = to_timezone(utcnow(), 'Europe/Zurich')
548548
weekday = WEEKDAYS[today.weekday()]
549+
current_time = f'{today.hour:02d}:{today.minute:02d}'
549550

550551
# get all recipients which require an e-mail today
551552
recipients_q = (
@@ -561,11 +562,13 @@ def send_daily_resource_usage_overview(request: OrgRequest) -> None:
561562

562563
# If the key 'daily_reservations' doesn't exist, the recipient was
563564
# created before anything else was an option, therefore it must be true
565+
# Legacy recipients without 'daily_reservations_times' default to 06:00.
564566
recipients = [
565567
(address, content['resources'])
566568
for address, content in recipients_q
567569
if content.get('daily_reservations', True)
568570
and weekday in content['send_on']
571+
and current_time in content.get('daily_reservations_times', ['06:00'])
569572
]
570573

571574
if not recipients:

src/onegov/org/forms/resource_recipient.py

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from __future__ import annotations
22

3+
import re
4+
35
from onegov.form import Form
4-
from onegov.form.fields import MultiCheckboxField
6+
from onegov.form.fields import MultiCheckboxField, TagsField
57
from onegov.org import _
68
from onegov.reservation import Resource, ResourceCollection
79
from wtforms.fields import EmailField
@@ -15,6 +17,8 @@
1517
from onegov.org.request import OrgRequest
1618

1719

20+
_TIME_RE = re.compile(r'^([01]\d|2[0-3]):([0-5]\d)$')
21+
1822
WEEKDAYS = (
1923
('MO', _('Mo')),
2024
('TU', _('Tu')),
@@ -56,8 +60,8 @@ class ResourceRecipientForm(Form):
5660
label=_('Daily Reservations'),
5761
fieldset=_('Notifications *'),
5862
description=_("On each day selected below, a notification with the "
59-
"day's reservations will be sent to the recipient above "
60-
"at 06:00."),
63+
"day's reservations will be sent to the recipient "
64+
"above."),
6165
)
6266

6367
customer_messages = BooleanField(
@@ -93,13 +97,47 @@ class ResourceRecipientForm(Form):
9397
render_kw={'prefix_label': False, 'class_': 'oneline-checkboxes'}
9498
)
9599

100+
daily_reservations_times = TagsField(
101+
label=_('Delivery Times'),
102+
fieldset='Tage und Ressourcen',
103+
description=_('e.g. 07:05'),
104+
depends_on=('daily_reservations', 'y'),
105+
)
106+
96107
resources = MultiCheckboxField(
97108
label=_('Resources'),
98109
fieldset='Tage und Ressourcen',
99110
validators=[InputRequired()],
100111
choices=None
101112
)
102113

114+
def ensure_valid_delivery_times(self) -> bool | None:
115+
if not self.daily_reservations.data:
116+
return None
117+
118+
times = self.daily_reservations_times.data
119+
if not times:
120+
self.daily_reservations_times.errors.append( # type: ignore[attr-defined]
121+
_('Please enter at least one delivery time.')
122+
)
123+
return False
124+
125+
for t in times:
126+
m = _TIME_RE.match(t)
127+
if not m:
128+
self.daily_reservations_times.errors.append( # type: ignore[attr-defined]
129+
_('Invalid time "${time}". Use HH:MM format (e.g. 06:00).',
130+
mapping={'time': t})
131+
)
132+
return False
133+
if int(m.group(2)) % 5 != 0:
134+
self.daily_reservations_times.errors.append( # type: ignore[attr-defined]
135+
_('Minutes must be a multiple of 5 (e.g. 06:10, 16:35).')
136+
)
137+
return False
138+
139+
return None
140+
103141
def ensure_at_least_one_notification(self) -> bool | None:
104142
if not (
105143
self.new_reservations.data
@@ -113,6 +151,9 @@ def ensure_at_least_one_notification(self) -> bool | None:
113151
return None
114152

115153
def on_request(self) -> None:
154+
if not self.request.POST and not self.daily_reservations_times.data:
155+
self.daily_reservations_times.data = ['06:00'] # legacy default
156+
116157
default_group = self.request.translate(_('General'))
117158

118159
self.resources.choices = [

src/onegov/org/locale/de_CH/LC_MESSAGES/onegov.org.po

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
msgid ""
33
msgstr ""
44
"Project-Id-Version: PACKAGE 1.0\n"
5-
"POT-Creation-Date: 2026-06-11 11:12+0200\n"
5+
"POT-Creation-Date: 2026-06-19 09:20+0200\n"
66
"PO-Revision-Date: 2022-03-15 10:21+0100\n"
77
"Last-Translator: Marc Sommerhalder <marc.sommerhalder@seantis.ch>\n"
88
"Language-Team: German\n"
@@ -1975,11 +1975,10 @@ msgstr "Tägliche Reservationen"
19751975

19761976
msgid ""
19771977
"On each day selected below, a notification with the day's reservations will "
1978-
"be sent to the recipient above at 06:00."
1978+
"be sent to the recipient above."
19791979
msgstr ""
19801980
"An jedem unten ausgewählten Tag wird eine Benachrichtigung mit den "
1981-
"Reservierungen des Tages um 06:00 Uhr an den oben genannten Empfänger "
1982-
"gesendet."
1981+
"Reservierungen des Tages an den oben genannten Empfänger gesendet."
19831982

19841983
msgid "Customer Messages"
19851984
msgstr "Kunden Nachrichten"
@@ -1992,9 +1991,6 @@ msgstr ""
19921991
"Reservierung hinzufügt, wird eine eine Benachrichtigung an den oben "
19931992
"genannten Empfänger gesendet."
19941993

1995-
msgid "Internal Comments"
1996-
msgstr "Internes Kommentarfeld"
1997-
19981994
msgid "Internal Notes"
19991995
msgstr "Interne Notizen"
20001996

@@ -2019,6 +2015,26 @@ msgstr ""
20192015
msgid "Send on"
20202016
msgstr "Senden am"
20212017

2018+
msgid "Delivery Times"
2019+
msgstr "Zustellungszeiten"
2020+
2021+
msgid "e.g. 07:05"
2022+
msgstr "z.B. 07:05"
2023+
2024+
#. type: ignore[attr-defined]
2025+
msgid "Please enter at least one delivery time."
2026+
msgstr "Bitte mindestens eine Zustellungszeit eingeben."
2027+
2028+
#. type: ignore[attr-defined]
2029+
#, python-format
2030+
msgid "Invalid time \"${time}\". Use HH:MM format (e.g. 06:00)."
2031+
msgstr ""
2032+
"Ungültige Zeit \"${time}\". Bitte im Format HH:MM eingeben (z.B. 06:00)."
2033+
2034+
#. type: ignore[attr-defined]
2035+
msgid "Minutes must be a multiple of 5 (e.g. 06:10, 16:35)."
2036+
msgstr "Minuten müssen ein Vielfaches von 5 sein (z.B. 06:10, 16:35)."
2037+
20222038
msgid "Please add at least one notification."
20232039
msgstr "Bitte wählen sie mindestens eine Benachrichtigung."
20242040

@@ -3735,9 +3751,6 @@ msgstr "Der Eintrag wurde übernommen"
37353751
msgid "The entry is not valid, please adjust it"
37363752
msgstr "Der Eintrag ist nicht gültig, bitte korrigieren"
37373753

3738-
msgid "An entry with this name already exists"
3739-
msgstr "Ein Eintrag mit diesem Namen existiert bereits"
3740-
37413754
msgid "Your directory submission has been adopted"
37423755
msgstr "Ihr Verzeichniseintrag wurde übernommen"
37433756

@@ -3907,6 +3920,12 @@ msgstr ""
39073920
msgid "Delete content"
39083921
msgstr "Inhalt löschen"
39093922

3923+
msgid "Internal Comments"
3924+
msgstr "Internes Kommentarfeld"
3925+
3926+
msgid "Administrative"
3927+
msgstr "Administrativ"
3928+
39103929
msgid "Photo album"
39113930
msgstr "Fotoalbum"
39123931

@@ -6523,9 +6542,6 @@ msgstr "Kunden-Login bestätigen"
65236542
msgid "A link was added to the clipboard"
65246543
msgstr "Ein Verweis wurde in die Zwischenablage kopiert"
65256544

6526-
msgid "Administrative"
6527-
msgstr "Administrativ"
6528-
65296545
msgid "Added a new directory"
65306546
msgstr "Ein neues Verzeichnis wurde hinzugefügt"
65316547

@@ -8029,6 +8045,15 @@ msgstr "Der Benutzer wurde erfolgreich erstellt"
80298045
msgid "Please enter your e-mail address in order to continue"
80308046
msgstr "Bitte geben Sie ihre E-Mail Adresse ein um fortzufahren"
80318047

8048+
#~ msgid "e.g. 07:00 or 07:00, 14:30"
8049+
#~ msgstr "z.B. 07:00 oder 07:00, 14:30"
8050+
8051+
#~ msgid "Minutes must be a multiple of 5 (e.g. 06:00, 06:30)."
8052+
#~ msgstr "Minuten müssen ein Vielfaches von 5 sein (z.B. 06:00, 06:30)."
8053+
8054+
#~ msgid "An entry with this name already exists"
8055+
#~ msgstr "Ein Eintrag mit diesem Namen existiert bereits"
8056+
80328057
#~ msgid "Back"
80338058
#~ msgstr "Zurück"
80348059

src/onegov/org/locale/fr_CH/LC_MESSAGES/onegov.org.po

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
msgid ""
33
msgstr ""
44
"Project-Id-Version: PACKAGE 1.0\n"
5-
"POT-Creation-Date: 2026-06-11 11:12+0200\n"
5+
"POT-Creation-Date: 2026-06-19 09:20+0200\n"
66
"PO-Revision-Date: 2022-03-15 10:50+0100\n"
77
"Last-Translator: Marc Sommerhalder <marc.sommerhalder@seantis.ch>\n"
88
"Language-Team: French\n"
@@ -1979,10 +1979,10 @@ msgstr "Réservations quotidiennes"
19791979

19801980
msgid ""
19811981
"On each day selected below, a notification with the day's reservations will "
1982-
"be sent to the recipient above at 06:00."
1982+
"be sent to the recipient above."
19831983
msgstr ""
19841984
"Pour chaque jour sélectionné ci-dessous, une notification avec les "
1985-
"réservations du jour sera envoyée au destinataire ci-dessus à 6h00.."
1985+
"réservations du jour sera envoyée au destinataire ci-dessus."
19861986

19871987
msgid "Customer Messages"
19881988
msgstr "Messages des clients"
@@ -1994,9 +1994,6 @@ msgstr ""
19941994
"Chaque fois qu'un client ajoute un message au ticket pour une réservation, "
19951995
"une notification est envoyée au destinataire ci-dessus."
19961996

1997-
msgid "Internal Comments"
1998-
msgstr "Commentaires internes"
1999-
20001997
msgid "Internal Notes"
20011998
msgstr "Notes internes"
20021999

@@ -2020,6 +2017,25 @@ msgstr ""
20202017
msgid "Send on"
20212018
msgstr "Envoyer sur"
20222019

2020+
msgid "Delivery Times"
2021+
msgstr "Heures d'envoi"
2022+
2023+
msgid "e.g. 07:05"
2024+
msgstr "p.ex. 07:05"
2025+
2026+
#. type: ignore[attr-defined]
2027+
msgid "Please enter at least one delivery time."
2028+
msgstr "Veuillez saisir au moins une heure d'envoi."
2029+
2030+
#. type: ignore[attr-defined]
2031+
#, python-format
2032+
msgid "Invalid time \"${time}\". Use HH:MM format (e.g. 06:00)."
2033+
msgstr "Heure invalide \"${time}\". Utiliser le format HH:MM (p.ex. 06:00)."
2034+
2035+
#. type: ignore[attr-defined]
2036+
msgid "Minutes must be a multiple of 5 (e.g. 06:10, 16:35)."
2037+
msgstr "Les minutes doivent être un multiple de 5 (p.ex. 06:10, 16:35)."
2038+
20232039
msgid "Please add at least one notification."
20242040
msgstr "Veuillez ajouter au moins une notification."
20252041

@@ -3743,9 +3759,6 @@ msgstr "La proposition a été adoptée"
37433759
msgid "The entry is not valid, please adjust it"
37443760
msgstr "L'entrée n'est pas valide, veuillez la rectifier"
37453761

3746-
msgid "An entry with this name already exists"
3747-
msgstr "Une entrée du même nom existe déjà"
3748-
37493762
msgid "Your directory submission has been adopted"
37503763
msgstr "Votre proposition de répertoire a été adoptée"
37513764

@@ -3915,6 +3928,12 @@ msgstr ""
39153928
msgid "Delete content"
39163929
msgstr "Supprimer le contenu"
39173930

3931+
msgid "Internal Comments"
3932+
msgstr "Commentaires internes"
3933+
3934+
msgid "Administrative"
3935+
msgstr "Administratif"
3936+
39183937
msgid "Photo album"
39193938
msgstr "Album photo"
39203939

@@ -6538,9 +6557,6 @@ msgstr "Confirmer la connexion du client"
65386557
msgid "A link was added to the clipboard"
65396558
msgstr "Un lien a été ajouté au presse-papiers"
65406559

6541-
msgid "Administrative"
6542-
msgstr "Administratif"
6543-
65446560
msgid "Added a new directory"
65456561
msgstr "Ajout d'un nouveau dossier"
65466562

@@ -8040,6 +8056,15 @@ msgstr "L'utilisateur a bien été créé"
80408056
msgid "Please enter your e-mail address in order to continue"
80418057
msgstr "Veuillez saisir votre adresse e-mail pour continuer"
80428058

8059+
#~ msgid "e.g. 07:00 or 07:00, 14:30"
8060+
#~ msgstr "p.ex. 07:00 ou 07:00, 14:30"
8061+
8062+
#~ msgid "Minutes must be a multiple of 5 (e.g. 06:00, 06:30)."
8063+
#~ msgstr "Les minutes doivent être un multiple de 5 (p.ex. 06:00, 06:30)."
8064+
8065+
#~ msgid "An entry with this name already exists"
8066+
#~ msgstr "Une entrée du même nom existe déjà"
8067+
80438068
#~ msgid "Back"
80448069
#~ msgstr "Retour"
80458070

0 commit comments

Comments
 (0)