From dac52db434e6b51c42cca414c491c364fba46dde Mon Sep 17 00:00:00 2001 From: imperosol Date: Mon, 29 Sep 2025 15:03:34 +0200 Subject: [PATCH] forbid past dates for product actions --- counter/forms.py | 5 +++-- counter/models.py | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/counter/forms.py b/counter/forms.py index 990d4afe..9b1a9ab6 100644 --- a/counter/forms.py +++ b/counter/forms.py @@ -13,6 +13,7 @@ from phonenumber_field.widgets import RegionalPhoneNumberWidget from club.widgets.ajax_select import AutoCompleteSelectClub from core.models import User from core.views.forms import ( + FutureDateTimeField, NFCTextInput, SelectDate, SelectDateTime, @@ -185,7 +186,7 @@ class ScheduledProductActionForm(forms.ModelForm): labels = {"task": _("Action")} help_texts = {"task": ""} - trigger_at = forms.DateTimeField( + trigger_at = FutureDateTimeField( label=_("Date and time of action"), widget=SelectDateTime ) counters = forms.ModelMultipleChoiceField( @@ -206,7 +207,7 @@ class ScheduledProductActionForm(forms.ModelForm): ) def clean(self): - if not self.changed_data: + if not self.changed_data or "trigger_at" in self.errors: return super().clean() if "trigger_at" in self.changed_data: if not self.instance.clocked_id: diff --git a/counter/models.py b/counter/models.py index d7bc3b4e..685071c3 100644 --- a/counter/models.py +++ b/counter/models.py @@ -1385,3 +1385,13 @@ class ScheduledProductAction(PeriodicTask): def full_clean(self, *args, **kwargs): self.one_off = True # A product action should occur one time only return super().full_clean(*args, **kwargs) + + def clean_clocked(self): + if not self.clocked: + raise ValidationError(_("Product actions must declare a clocked schedule.")) + + def validate_unique(self, *args, **kwargs): + # The checks done in PeriodicTask.validate_unique aren't + # adapted in the case of scheduled product action, + # so we skip it and execute directly Model.validate_unique + return super(PeriodicTask, self).validate_unique(*args, **kwargs)