diff --git a/backend/hitas/migrations/0017_alter_aparmentdocument_modified_at_and_more.py b/backend/hitas/migrations/0017_alter_aparmentdocument_modified_at_and_more.py new file mode 100644 index 000000000..604687f9e --- /dev/null +++ b/backend/hitas/migrations/0017_alter_aparmentdocument_modified_at_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.16 on 2025-01-24 11:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('hitas', '0016_external_report_view'), + ] + + operations = [ + migrations.AlterField( + model_name='aparmentdocument', + name='modified_at', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='housingcompanydocument', + name='modified_at', + field=models.DateTimeField(auto_now_add=True), + ), + ] diff --git a/backend/hitas/models/document.py b/backend/hitas/models/document.py index df876392a..840e9e95a 100644 --- a/backend/hitas/models/document.py +++ b/backend/hitas/models/document.py @@ -33,7 +33,9 @@ class BaseDocument(ExternalSafeDeleteHitasModel): display_name = models.CharField(max_length=1024) original_filename = models.CharField(max_length=255) created_at = models.DateTimeField(auto_now_add=True) - modified_at = models.DateTimeField(auto_now=True) + # This field is using `auto_now_add=True` instead of `auto_now=True` because + # we want to set the `modified_at` using custom logic for example when the file is updated. + modified_at = models.DateTimeField(auto_now_add=True) class Meta: abstract = True diff --git a/backend/hitas/tests/apis/test_api_document.py b/backend/hitas/tests/apis/test_api_document.py index 7685a1e7f..d886cbad4 100644 --- a/backend/hitas/tests/apis/test_api_document.py +++ b/backend/hitas/tests/apis/test_api_document.py @@ -1,6 +1,9 @@ +from datetime import timedelta + import pytest from django.core.files.uploadedfile import SimpleUploadedFile from django.urls import reverse +from django.utils import timezone from rest_framework import status from hitas.models import ( @@ -176,6 +179,57 @@ def test__api__housingcompany__document__update__file(api_client: HitasAPIClient assert not document.file.storage.exists(old_filename), "Old file should be deleted from storage" +@pytest.mark.django_db +def test__api__document__modified_at(api_client: HitasAPIClient): + apartment = ApartmentFactory() + document = AparmentDocument.objects.create( + apartment=apartment, display_name="Test document", original_filename="testfile.txt" + ) + response = api_client.put( + reverse( + "hitas:document-detail", args=[apartment.housing_company.uuid.hex, apartment.uuid.hex, document.uuid.hex] + ), + data={ + "display_name": "Test document", + "file_content": SimpleUploadedFile("testfile.txt", b"test file content 1", content_type="text/plain"), + }, + ) + assert response.status_code == status.HTTP_200_OK + document.refresh_from_db() + + # Pretend document was created 2 days ago + document.created_at = timezone.now() - timedelta(days=2) + document.modified_at = timezone.now() - timedelta(days=2) + document.save() + initial_modified_at = document.modified_at + + # Update display_name + response = api_client.put( + reverse( + "hitas:document-detail", args=[apartment.housing_company.uuid.hex, apartment.uuid.hex, document.uuid.hex] + ), + data={ + "display_name": "New name", + }, + ) + assert response.status_code == status.HTTP_200_OK + document.refresh_from_db() + assert document.modified_at == initial_modified_at, "modified_at should not change when updating display_name only" + + response = api_client.put( + reverse( + "hitas:document-detail", args=[apartment.housing_company.uuid.hex, apartment.uuid.hex, document.uuid.hex] + ), + data={ + "display_name": "New name", + "file_content": SimpleUploadedFile("testfile.txt", b"test file content 2", content_type="text/plain"), + }, + ) + assert response.status_code == status.HTTP_200_OK + document.refresh_from_db() + assert document.modified_at > initial_modified_at, "modified_at should change when updating file" + + @pytest.mark.django_db def test__api__apartment__document__redirect(api_client: HitasAPIClient): apartment = ApartmentFactory() diff --git a/backend/hitas/views/document.py b/backend/hitas/views/document.py index a754cba05..0f91c1bf1 100644 --- a/backend/hitas/views/document.py +++ b/backend/hitas/views/document.py @@ -1,4 +1,5 @@ from django.shortcuts import redirect +from django.utils import timezone from rest_framework import serializers from rest_framework.decorators import action from rest_framework.parsers import JSONParser, MultiPartParser @@ -45,6 +46,7 @@ def update(self, instance, validated_data): file = validated_data.get("file") if file: validated_data["original_filename"] = file.name + validated_data["modified_at"] = timezone.now() return super().update(instance, validated_data)