From 308364f74c3307e4cfad8c1dc49dc22dfe3b3cec Mon Sep 17 00:00:00 2001 From: Karl Engelhardt Date: Wed, 9 Nov 2022 15:12:58 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Rename=20FoiRequest.first?= =?UTF-8?q?=5Fmessage=20to=20created=5Fat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 4 +-- froide/account/views.py | 4 +-- froide/foirequest/admin.py | 8 +++--- froide/foirequest/api_views.py | 10 +++----- froide/foirequest/documents.py | 2 +- froide/foirequest/feeds.py | 4 +-- froide/foirequest/filters.py | 14 +++++------ froide/foirequest/forms/message.py | 2 +- ...emove_foirequest_first_message_and_more.py | 25 +++++++++++++++++++ froide/foirequest/models/request.py | 21 +++++++++++----- froide/foirequest/services.py | 6 ++--- .../foirequest/emails/overdue_reply.txt | 2 +- .../templates/foirequest/header/info-box.html | 2 +- .../foirequest/publicbody_upload.html | 2 +- froide/foirequest/tests/factories.py | 2 +- froide/foirequest/tests/test_mail.py | 2 +- froide/foirequest/tests/test_request.py | 4 +-- froide/foirequest/utils.py | 2 +- froide/organization/views.py | 2 +- froide/tests/live/test_request.py | 4 +-- 20 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 froide/foirequest/migrations/0058_remove_foirequest_first_message_and_more.py diff --git a/docker-compose.yml b/docker-compose.yml index 7f542b22d..466156ba4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: POSTGRES_DB: froide POSTGRES_PASSWORD: froide ports: - - "127.0.0.1:5432:5432" + - "127.0.0.1:5433:5432" elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.15.0 volumes: @@ -23,7 +23,7 @@ services: - "cluster.routing.allocation.disk.watermark.high=2gb" - "cluster.routing.allocation.disk.watermark.flood_stage=1gb" ports: - - "127.0.0.1:9200:9200" + - "127.0.0.1:9201:9200" volumes: es-data: {} diff --git a/froide/account/views.py b/froide/account/views.py index 416eb2501..462b02535 100644 --- a/froide/account/views.py +++ b/froide/account/views.py @@ -198,7 +198,7 @@ def get_context_data(self, **kwargs): aggregates = foirequests.aggregate( count=models.Count("id"), - first_date=models.Min("first_message"), + first_date=models.Min("created_at"), successful=models.Count( "id", filter=models.Q( @@ -251,7 +251,7 @@ def get_context_data(self, **kwargs): ctx.update( { - "foirequests": foirequests.order_by("-first_message")[:10], + "foirequests": foirequests.order_by("-created_at")[:10], "aggregates": aggregates, "campaigns": campaigns, "top_followers": top_followers, diff --git a/froide/foirequest/admin.py b/froide/foirequest/admin.py index 17f5e21ab..099019337 100644 --- a/froide/foirequest/admin.py +++ b/froide/foirequest/admin.py @@ -163,7 +163,7 @@ class FoiRequestAdmin(admin.ModelAdmin): ] list_display = ( "title", - "first_message", + "created_at", "secret_address", "request_page", "public_body", @@ -173,7 +173,7 @@ class FoiRequestAdmin(admin.ModelAdmin): ) list_filter = ( "jurisdiction", - "first_message", + "created_at", "last_message", "status", "resolution", @@ -195,7 +195,7 @@ class FoiRequestAdmin(admin.ModelAdmin): ) search_fields = ["title", "description", "secret_address", "reference"] ordering = ("-last_message",) - date_hierarchy = "first_message" + date_hierarchy = "created_at" actions = [ "mark_checked", @@ -409,7 +409,7 @@ def unblock_request(self, request, queryset): mes.timestamp = timezone.now() if req.law: req.due_date = req.law.calculate_due_date() - req.first_message = mes.timestamp + req.created_at = mes.timestamp req.is_blocked = False req.save() diff --git a/froide/foirequest/api_views.py b/froide/foirequest/api_views.py index 5edf3b88b..a88554a3d 100644 --- a/froide/foirequest/api_views.py +++ b/froide/foirequest/api_views.py @@ -313,7 +313,7 @@ class Meta: "due_date", "resolved_on", "last_message", - "first_message", + "created_at", "status", "public_body", "resolution", @@ -397,12 +397,8 @@ class FoiRequestFilter(filters.FilterSet): lookup_expr="isnull", method="campaign_filter", ) - first_message_after = filters.DateFilter( - field_name="first_message", lookup_expr="gte" - ) - first_message_before = filters.DateFilter( - field_name="first_message", lookup_expr="lt" - ) + created_at_after = filters.DateFilter(field_name="created_at", lookup_expr="gte") + created_at_before = filters.DateFilter(field_name="created_at", lookup_expr="lt") has_same = filters.BooleanFilter( field_name="same_as", lookup_expr="isnull", exclude=True ) diff --git a/froide/foirequest/documents.py b/froide/foirequest/documents.py index d7790b303..d86455de9 100644 --- a/froide/foirequest/documents.py +++ b/froide/foirequest/documents.py @@ -40,7 +40,7 @@ class FoiRequestDocument(Document): campaign = fields.IntegerField() due_date = fields.DateField() - first_message = fields.DateField() + created_at = fields.DateField() last_message = fields.DateField() publicbody = fields.IntegerField(attr="public_body_id") diff --git a/froide/foirequest/feeds.py b/froide/foirequest/feeds.py index 009e5e221..1d8caa7c2 100644 --- a/froide/foirequest/feeds.py +++ b/froide/foirequest/feeds.py @@ -74,7 +74,7 @@ def link(self): return self.make_url(self.url_name) def items(self): - return self.items.order_by("-first_message")[:15] + return self.items.order_by("-created_at")[:15] @clean_feed_output def item_title(self, item): @@ -92,7 +92,7 @@ def item_description(self, item): return linebreaksbr(item.get_description()) def item_pubdate(self, item): - return item.first_message + return item.created_at class LatestFoiRequestsFeedAtom(LatestFoiRequestsFeed): diff --git a/froide/foirequest/filters.py b/froide/foirequest/filters.py index 96dd0c123..000b44863 100644 --- a/froide/foirequest/filters.py +++ b/froide/foirequest/filters.py @@ -228,8 +228,8 @@ class BaseFoiRequestFilterSet(BaseSearchFilterSet): widget=forms.HiddenInput(), ) - first = django_filters.DateFromToRangeFilter( - method="filter_first", + created = django_filters.DateFromToRangeFilter( + method="filter_created", widget=DateRangeWidget, ) last = django_filters.DateFromToRangeFilter( @@ -239,8 +239,8 @@ class BaseFoiRequestFilterSet(BaseSearchFilterSet): choices=[ ("-last", _("last message (newest first)")), ("last", _("last message (oldest first)")), - ("-first", _("request date (newest first)")), - ("first", _("request date (oldest first)")), + ("-created", _("request date (newest first)")), + ("created", _("request date (oldest first)")), ], label=_("sort"), empty_label=_("default sort"), @@ -259,7 +259,7 @@ class Meta: "classification", "tag", "publicbody", - "first", + "created", ] def __init__(self, *args, **kwargs): @@ -303,14 +303,14 @@ def filter_organization(self, qs, name, value): filtered_qs = qs.filter(user=all_members) return filtered_qs - def filter_first(self, qs, name, value): + def filter_created(self, qs, name, value): range_kwargs = {} if value.start is not None: range_kwargs["gte"] = value.start if value.stop is not None: range_kwargs["lte"] = value.stop - return qs.filter(Q("range", first_message=range_kwargs)) + return qs.filter(Q("range", created_at=range_kwargs)) def filter_last(self, qs, name, value): range_kwargs = {} diff --git a/froide/foirequest/forms/message.py b/froide/foirequest/forms/message.py index 5bd4c8124..3a2c07da2 100644 --- a/froide/foirequest/forms/message.py +++ b/froide/foirequest/forms/message.py @@ -510,7 +510,7 @@ def clean_date(self): raise forms.ValidationError( _("Your reply date is in the future, that is not possible.") ) - if date < self.foirequest.first_message.date(): + if date < self.foirequest.created_at.date(): raise forms.ValidationError( _( "Your reply date is before the request was made, " diff --git a/froide/foirequest/migrations/0058_remove_foirequest_first_message_and_more.py b/froide/foirequest/migrations/0058_remove_foirequest_first_message_and_more.py new file mode 100644 index 000000000..36d12fbb2 --- /dev/null +++ b/froide/foirequest/migrations/0058_remove_foirequest_first_message_and_more.py @@ -0,0 +1,25 @@ +# Generated by Django 4.0.7 on 2022-11-09 13:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("foirequest", "0057_foimessage_redacted_content_anon_and_more"), + ] + + operations = [ + migrations.RenameField( + model_name="foirequest", + old_name="first_message", + new_name="created_at", + ), + migrations.AlterField( + model_name="foirequest", + name="created_at", + field=models.DateTimeField( + blank=True, null=True, verbose_name="Created at" + ), + ), + ] diff --git a/froide/foirequest/models/request.py b/froide/foirequest/models/request.py index a818351cb..de37ee40a 100644 --- a/froide/foirequest/models/request.py +++ b/froide/foirequest/models/request.py @@ -2,6 +2,7 @@ import re from collections import namedtuple from datetime import timedelta +from typing import TYPE_CHECKING, Optional import django.dispatch from django.conf import settings @@ -26,6 +27,9 @@ from .project import FoiProject +if TYPE_CHECKING: + from .message import FoiMessage + MODERATOR_CLASSIFICATION_OFFSET = timedelta(days=31) @@ -76,7 +80,7 @@ def get_unclassified_for_moderation(self): def get_throttle_filter(self, qs, user, extra_filters=None): qs = qs.filter(user=user) - return qs, "first_message" + return qs, "created_at" def delete_private_requests(self, user): if not user: @@ -320,9 +324,7 @@ class FoiRequest(models.Model): Team, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_("Team") ) - first_message = models.DateTimeField( - _("Date of first message"), blank=True, null=True - ) + created_at = models.DateTimeField(_("Created at"), blank=True, null=True) last_message = models.DateTimeField( _("Date of last message"), blank=True, null=True ) @@ -856,14 +858,21 @@ def days_to_resolution(self): break if final is None or mes is None: return None - return (mes.timestamp - self.first_message).days + return (mes.timestamp - self.created_at).days @property - def first_outgoing_message(self): + def first_outgoing_message(self) -> Optional["FoiMessage"]: sent_msg = self.sent_messages() if sent_msg: return sent_msg[0] + @property + def first_message(self): + if self.first_outgoing_message: + return self.first_outgoing_message.timestamp + else: + return self.created_at + def get_absolute_short_url(pk): return reverse("foirequest-shortlink", kwargs={"obj_id": pk}) diff --git a/froide/foirequest/services.py b/froide/foirequest/services.py index 4d5f1e94a..1e4f74527 100644 --- a/froide/foirequest/services.py +++ b/froide/foirequest/services.py @@ -175,7 +175,7 @@ def create_request(self, publicbody, sequence=0): language=data.get("language", ""), site=Site.objects.get_current(), reference=data.get("reference", ""), - first_message=now, + created_at=now, last_message=now, project=data.get("project"), project_order=data.get("project_order"), @@ -381,12 +381,12 @@ def process(self, request=None): message.timestamp = timezone.now() else: if email.date < foirequest.first_message: - # Mail timestamp is earlier than first message due to bad time on mail server + # Mail timestamp is earlier than first outgoing message due to bad time on mail server message.timestamp = timezone.now() else: message.timestamp = email.date - # if the message timestamp is still before or equal request start + # if the message timestamp is still before or equal first outgoing message if message.timestamp <= foirequest.first_message: # bump it by one second message.timestamp = foirequest.first_message + timedelta(seconds=1) diff --git a/froide/foirequest/templates/foirequest/emails/overdue_reply.txt b/froide/foirequest/templates/foirequest/emails/overdue_reply.txt index 3a7a92a3c..718f867ba 100644 --- a/froide/foirequest/templates/foirequest/emails/overdue_reply.txt +++ b/froide/foirequest/templates/foirequest/emails/overdue_reply.txt @@ -1,4 +1,4 @@ -{% load i18n %}{% autoescape off %}{% blocktrans with title=foirequest.title name=foirequest.user.get_full_name due=due date=foirequest.first_message|date:"SHORT_DATE_FORMAT" num=foirequest.pk %}Dear Sir or Madam, +{% load i18n %}{% autoescape off %}{% blocktrans with title=foirequest.title name=foirequest.user.get_full_name due=due date=foirequest.created_at|date:"SHORT_DATE_FORMAT" num=foirequest.pk %}Dear Sir or Madam, My Freedom of Information request "{{ title }}" ({{ date }}, #{{ num }}) was not answered in the time defined by law and is now {{ due }} late. Please update me on the status of my request as soon as possible. diff --git a/froide/foirequest/templates/foirequest/header/info-box.html b/froide/foirequest/templates/foirequest/header/info-box.html index d834d04e8..5577cd472 100644 --- a/froide/foirequest/templates/foirequest/header/info-box.html +++ b/froide/foirequest/templates/foirequest/header/info-box.html @@ -93,7 +93,7 @@

{{ object.readable_status }}

{# date #}
  • {% blocktrans %}Date{% endblocktrans %}
    -
    {{ object.first_message|date:"j. F Y" }}
    +
    {{ object.created_at|date:"j. F Y" }}
  • {# due date #} diff --git a/froide/foirequest/templates/foirequest/publicbody_upload.html b/froide/foirequest/templates/foirequest/publicbody_upload.html index 84bf0fee0..8436923b4 100644 --- a/froide/foirequest/templates/foirequest/publicbody_upload.html +++ b/froide/foirequest/templates/foirequest/publicbody_upload.html @@ -46,7 +46,7 @@

    {% else %}
    {% trans "Request" %}
    -
    “{{ foirequest.title }}” [#{{ foirequest.id }}] ({{ foirequest.first_message|date:"SHORT_DATE_FORMAT" }})
    +
    “{{ foirequest.title }}” [#{{ foirequest.id }}] ({{ foirequest.created_at|date:"SHORT_DATE_FORMAT" }})
    {% trans "Requester" %}
    {{ foirequest.user.get_full_name }} <{{ foirequest.secret_address }}>
    {% trans "File transfer" %}
    diff --git a/froide/foirequest/tests/factories.py b/froide/foirequest/tests/factories.py index 910372689..daeddcadf 100644 --- a/froide/foirequest/tests/factories.py +++ b/froide/foirequest/tests/factories.py @@ -54,7 +54,7 @@ class Meta: status = "" visibility = 2 user = factory.LazyAttribute(lambda o: UserFactory()) - first_message = timezone.now() - timedelta(days=14) + created_at = timezone.now() - timedelta(days=14) last_message = timezone.now() - timedelta(days=2) resolved_on = None due_date = timezone.now() + timedelta(days=14) diff --git a/froide/foirequest/tests/test_mail.py b/froide/foirequest/tests/test_mail.py index ad5048c2e..872469cc8 100644 --- a/froide/foirequest/tests/test_mail.py +++ b/froide/foirequest/tests/test_mail.py @@ -31,7 +31,7 @@ def foirequest_with_msg(world): req = factories.FoiRequestFactory.create( site=world, secret_address=secret_address, - first_message=date, + created_at=date, last_message=date, ) factories.FoiMessageFactory.create(request=req, timestamp=date) diff --git a/froide/foirequest/tests/test_request.py b/froide/foirequest/tests/test_request.py index bd1346225..2c2408554 100644 --- a/froide/foirequest/tests/test_request.py +++ b/froide/foirequest/tests/test_request.py @@ -647,7 +647,7 @@ def test_postal_reply(world, client, pb): message = req.foimessage_set.all()[0] message.timestamp = datetime(2011, 1, 1, 0, 0, 0, tzinfo=timezone.utc) message.save() - req.first_message = message.timestamp + req.created_at = message.timestamp req.save() file_size = os.path.getsize(factories.TEST_PDF_PATH) @@ -1546,7 +1546,7 @@ def test_resolution(world, client): assert req.costs == 0.0 assert req.status == FoiRequest.STATUS.RESOLVED assert req.resolution == FoiRequest.RESOLUTION.SUCCESSFUL - assert req.days_to_resolution() == (mes.timestamp - req.first_message).days + assert req.days_to_resolution() == (mes.timestamp - req.created_at).days @pytest.mark.django_db diff --git a/froide/foirequest/utils.py b/froide/foirequest/utils.py index 5c6ef0f2c..88fbe8618 100644 --- a/froide/foirequest/utils.py +++ b/froide/foirequest/utils.py @@ -45,7 +45,7 @@ def get_label(self): return self.label if self.label is not None else self.name -def throttle(qs, throttle_config, date_param="first_message"): +def throttle(qs, throttle_config, date_param="created_at"): if throttle_config is None: return False diff --git a/froide/organization/views.py b/froide/organization/views.py index 445c9b247..909521096 100644 --- a/froide/organization/views.py +++ b/froide/organization/views.py @@ -53,7 +53,7 @@ def _get_last_foirequests(self, organization: Organization): user__private=False ).values_list("user_id", flat=True) foirequests = FoiRequest.published.filter(user__in=public_members) - return foirequests.order_by("-first_message")[:10] + return foirequests.order_by("-created_at")[:10] def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) diff --git a/froide/tests/live/test_request.py b/froide/tests/live/test_request.py index 22a6476c3..d949ff193 100644 --- a/froide/tests/live/test_request.py +++ b/froide/tests/live/test_request.py @@ -162,7 +162,7 @@ def test_make_logged_in_request_too_many( for _i in range(5): req = foi_request_factory( user=dummy_user, - first_message=timezone.now(), + created_at=timezone.now(), ) foi_message_factory(request=req, is_response=False, sender_user=dummy_user) do_login(page, live_server) @@ -244,7 +244,7 @@ def test_set_status( user = User.objects.get(username="dummy") req = foi_request_factory( user=user, - first_message=timezone.now(), + created_at=timezone.now(), status="resolved", resolution=from_resolution, )