From 21c54cf9c5a76bda1f63763032931bfdce1f5e9f Mon Sep 17 00:00:00 2001 From: Dmytro Trotsko Date: Thu, 20 Jun 2024 17:18:10 +0300 Subject: [PATCH] OKRS24-223 Fixed Celery taks to get weekly based dates properly. Added 'Available Since', 'Available Until', 'Available for at least' filters. --- src/base/admin.py | 2 +- src/signals/filters.py | 6 +++++ src/signals/forms.py | 11 +++++++- .../0020_signal_signal_availability_days.py | 18 +++++++++++++ src/signals/models.py | 6 +++++ src/signals/tools.py | 13 ++++++---- src/signals/views.py | 3 +++ src/templates/signals/signals.html | 26 +++++++++++++++++++ 8 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 src/signals/migrations/0020_signal_signal_availability_days.py diff --git a/src/base/admin.py b/src/base/admin.py index d850462..dcf1cf8 100644 --- a/src/base/admin.py +++ b/src/base/admin.py @@ -12,7 +12,7 @@ class DescriptedFilterFieldInline(admin.TabularInline): model = DescriptedFilterField - fields = ('description',) + fields = ('description', 'filter_field') extra = 0 can_create = False diff --git a/src/signals/filters.py b/src/signals/filters.py index 0b38d96..d9269c7 100644 --- a/src/signals/filters.py +++ b/src/signals/filters.py @@ -52,6 +52,9 @@ class SignalFilter(django_filters.FilterSet): field_name="source_id__external_name", to_field_name='external_name') time_type = django_filters.MultipleChoiceFilter(choices=TimeTypeChoices.choices) + from_date = django_filters.DateFilter(field_name='from_date', lookup_expr='gte') + to_date = django_filters.DateFilter(field_name='to_date', lookup_expr='lte') + signal_availability_days = django_filters.NumberFilter(field_name='signal_availability_days', lookup_expr='gte') def __init__(self, data, *args, **kwargs): data = data.copy() @@ -74,6 +77,9 @@ class Meta: 'geographic_scope', 'source', 'time_type', + 'from_date', + 'to_date', + 'signal_availability_days', ] def filter_search(self, queryset, name, value) -> Any: diff --git a/src/signals/forms.py b/src/signals/forms.py index 25e94c8..b6b9f82 100644 --- a/src/signals/forms.py +++ b/src/signals/forms.py @@ -36,6 +36,10 @@ class SignalFilterForm(forms.ModelForm): geographic_scope = forms.ModelMultipleChoiceField(queryset=GeographicScope.objects.all(), widget=forms.CheckboxSelectMultiple()) severenity_pyramid_rungs = forms.ChoiceField(choices=SeverityPyramidRungsChoices.choices, widget=forms.CheckboxSelectMultiple()) + from_date = forms.DateField(widget=forms.DateInput(attrs={'type': 'date'}), required=False) + to_date = forms.DateField(widget=forms.DateInput(attrs={'type': 'date'}), required=False) + signal_availability_days = forms.IntegerField(required=False) + class Meta: model = Signal fields: list[str] = [ @@ -49,6 +53,9 @@ class Meta: 'source', 'time_type', 'geographic_scope', + 'from_date', + 'to_date', + 'signal_availability_days', ] widgets = { @@ -68,7 +75,6 @@ class Meta: 'data-bs-toggle': 'tooltip', 'data-bs-placement': 'bottom', }), - } def __init__(self, *args, **kwargs) -> None: @@ -87,3 +93,6 @@ def __init__(self, *args, **kwargs) -> None: field.required = False field.help_text = '' field.label = '' + self.fields['from_date'].label = _('Available Since') + self.fields['to_date'].label = _('Available Until') + self.fields['signal_availability_days'].label = _('Available for at least (days)') diff --git a/src/signals/migrations/0020_signal_signal_availability_days.py b/src/signals/migrations/0020_signal_signal_availability_days.py new file mode 100644 index 0000000..9f5557f --- /dev/null +++ b/src/signals/migrations/0020_signal_signal_availability_days.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.10 on 2024-06-20 06:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('signals', '0019_alter_signal_severenity_pyramid_rungs'), + ] + + operations = [ + migrations.AddField( + model_name='signal', + name='signal_availability_days', + field=models.IntegerField(blank=True, help_text='Number of days the signal is available for', null=True), + ), + ] diff --git a/src/signals/models.py b/src/signals/models.py index 3700ea6..24337c3 100644 --- a/src/signals/models.py +++ b/src/signals/models.py @@ -518,6 +518,12 @@ class Signal(TimeStampedModel): blank=True ) + signal_availability_days: models.IntegerField = models.IntegerField( + help_text=_('Number of days the signal is available for'), + null=True, + blank=True + ) + temporal_scope_start: models.CharField = models.CharField( help_text=_('Temporal Scope Start'), null=True, diff --git a/src/signals/tools.py b/src/signals/tools.py index e505778..545d290 100644 --- a/src/signals/tools.py +++ b/src/signals/tools.py @@ -10,7 +10,7 @@ class SignalLastUpdatedParser: def __init__(self, covidcast_meta_data: list) -> None: self.covidcast_meta_data = covidcast_meta_data - self.year_month_date_format = '%Y%m' + self.year_week_date_format = '%Y-%W-%w' self.year_month_day_date_format = '%Y%m%d' def format_date(self, date: str,) -> datetime: @@ -23,7 +23,9 @@ def format_date(self, date: str,) -> datetime: """ formated_date: datetime if len(date) == 6: - formated_date = datetime.strptime(date, self.year_month_date_format) + year, week = date[:4], date[4:] + logger.info(f"Date: {date}, year: {year}, week: {int(week)-1}") + formated_date = datetime.strptime(f"{int(year)}-{int(week)-1}-1", self.year_week_date_format) elif len(date) == 8: formated_date = datetime.strptime(date, self.year_month_day_date_format) return formated_date @@ -36,14 +38,15 @@ def set_data(self) -> None: for db_source in self.covidcast_meta_data: for signal_data in db_source['signals']: try: - signal = Signal.objects.get(name=signal_data['signal_basename'], source__name=signal_data['source']) + signal = Signal.objects.get(name=signal_data['signal'], source__name=signal_data['source']) except Signal.DoesNotExist: logger.warning( - f"Signal {signal_data['signal_basename']} not found in db. Update failed." + f"Signal {signal_data['signal']} not found in db. Update failed." ) continue signal.last_updated = self.format_date(str(signal_data['max_issue'])) signal.from_date = self.format_date(str(signal_data['min_time'])) signal.to_date = self.format_date(str(signal_data['max_time'])) + signal.signal_availability_days = abs((signal.to_date - signal.from_date).days) signal.save() - logger.info(f"Signal {signal_data['signal_basename']} successfully updated.") + logger.info(f"Signal {signal_data['signal']} successfully updated.") diff --git a/src/signals/views.py b/src/signals/views.py index a1acb29..a411a9f 100644 --- a/src/signals/views.py +++ b/src/signals/views.py @@ -57,6 +57,9 @@ def get_url_params(self): else None, "source": [el for el in self.request.GET.getlist("source")], "time_type": [el for el in self.request.GET.getlist("time_type")], + "from_date": self.request.GET.get("from_date"), + "to_date": self.request.GET.get("to_date"), + "signal_availability_days": self.request.GET.get("signal_availability_days"), } url_params_str = "" for param_name, param_value in url_params_dict.items(): diff --git a/src/templates/signals/signals.html b/src/templates/signals/signals.html index dc34b24..a3bcd63 100644 --- a/src/templates/signals/signals.html +++ b/src/templates/signals/signals.html @@ -189,6 +189,32 @@

+
+

+ +

+ {% if form.from_date.value or form.to_date.value or form.signal_availability_days.value %} +
+ {% else %} +
+ {% endif %} +
+ {{ form.from_date|as_crispy_field }} + {{ form.to_date|as_crispy_field }} + {{ form.signal_availability_days|as_crispy_field }} +
+
+