Coverage for baibu/metrics/forms.py: 100%
29 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-10-06 13:07 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-10-06 13:07 +0000
1from datetime import timedelta
3from django import forms
4from django.conf import settings
5from django.utils import timezone
6from django.utils.translation import gettext_lazy as _
8from .report import COLUMNS
10DEFAULT_RANGE_DAYS = 30
13class RangeForm(forms.Form):
14 """The days to show (inclusive) and the figure to chart."""
16 start = forms.DateField(
17 label=_("From"), required=False, widget=forms.DateInput(attrs={"type": "date"}, format="%Y-%m-%d")
18 )
19 end = forms.DateField(
20 label=_("To"), required=False, widget=forms.DateInput(attrs={"type": "date"}, format="%Y-%m-%d")
21 )
22 chart = forms.ChoiceField(
23 label=_("Chart"), required=False, choices=[(column.key, column.label) for column in COLUMNS]
24 )
26 @staticmethod
27 def defaults() -> dict:
28 end = timezone.localdate() - timedelta(days=1)
29 return {"start": end - timedelta(days=DEFAULT_RANGE_DAYS - 1), "end": end, "chart": "active_users"}
31 def clean(self):
32 data = super().clean()
33 defaults = self.defaults()
34 end = data.get("end") or defaults["end"]
35 start = data.get("start") or end - timedelta(days=DEFAULT_RANGE_DAYS - 1)
36 if end > timezone.localdate():
37 self.add_error("end", _("Choose a day that is not in the future."))
38 if start > end:
39 self.add_error("start", _("The first day must not be after the last day."))
40 elif (end - start).days + 1 > settings.METRICS_MAX_RANGE_DAYS:
41 self.add_error(
42 None,
43 _("Choose at most %(days)s days.") % {"days": settings.METRICS_MAX_RANGE_DAYS},
44 )
45 return {"start": start, "end": end, "chart": data.get("chart") or defaults["chart"]}
47 def range(self) -> dict:
48 """The chosen range if the form is valid, otherwise the default."""
49 return self.cleaned_data if self.is_valid() else self.defaults()