diff --git a/backend/trcustoms/common/management/commands/fix_denormalized_data.py b/backend/trcustoms/common/management/commands/fix_denormalized_data.py index fe8f76f9..51a3c4e3 100644 --- a/backend/trcustoms/common/management/commands/fix_denormalized_data.py +++ b/backend/trcustoms/common/management/commands/fix_denormalized_data.py @@ -49,9 +49,12 @@ def handle(self, *args, **options): def fix_levels(self) -> None: with tqdm(desc="Levels", total=Level.objects.count()) as progress: for level in Level.objects.iterator(): - level.update_last_file() - level.update_review_count() - level.update_rating_count() + level.update_rating_count(save=False) + level.update_review_count(save=False) + level.update_download_count(save=False) + level.update_last_file(save=False) + level.update_last_user_content_updated(save=False) + level.save() progress.update() def fix_users(self) -> None: diff --git a/backend/trcustoms/levels/models.py b/backend/trcustoms/levels/models.py index e74619bf..b59f0a55 100644 --- a/backend/trcustoms/levels/models.py +++ b/backend/trcustoms/levels/models.py @@ -154,31 +154,44 @@ class Meta: def __str__(self) -> str: return f"{self.name} (id={self.pk})" - def update_rating_count(self) -> None: + def update_rating_count(self, save: bool = True) -> None: rating_count = self.ratings.count() if rating_count != self.rating_count: self.rating_count = rating_count - self.save(update_fields=["rating_count"]) + if save: + self.save(update_fields=["rating_count"]) - def update_review_count(self) -> None: + def update_review_count(self, save: bool = True) -> None: review_count = self.reviews.count() if review_count != self.review_count: self.review_count = review_count - self.save(update_fields=["review_count"]) + if save: + self.save(update_fields=["review_count"]) - def update_download_count(self) -> None: + def update_download_count(self, save: bool = True) -> None: download_count = sum( list(self.files.values_list("download_count", flat=True)) + [0] ) if download_count != self.download_count: self.download_count = download_count - self.save(update_fields=["download_count"]) + if save: + self.save(update_fields=["download_count"]) - def update_last_file(self) -> None: + def update_last_file(self, save: bool = True) -> None: last_file = self.files.active().order_by("-version").first() if last_file != self.last_file: self.last_file = last_file - self.save() + if save: + self.save() + + def update_last_user_content_updated(self, save: bool = True) -> None: + self.last_user_content_updated = ( + max(self.files.values_list("created", flat=True)) + if self.files.count() > 1 + else None + ) + if save: + self.save(update_fields=["last_user_content_updated"]) class LevelScreenshot(DatesInfo): diff --git a/backend/trcustoms/levels/serializers.py b/backend/trcustoms/levels/serializers.py index 850742d2..7f1f0e4f 100644 --- a/backend/trcustoms/levels/serializers.py +++ b/backend/trcustoms/levels/serializers.py @@ -361,13 +361,7 @@ def handle_m2m(self, level_factory, validated_data): if file is not None and ( not level.last_file or file != level.last_file.file ): - level_file = LevelFile.objects.create(level=level, file=file) - level.last_user_content_updated = ( - max(level_file.created, level_file.created) - if level.files.count() > 1 - else None - ) - level.save(update_fields=["last_user_content_updated"]) + LevelFile.objects.create(level=level, file=file) return level diff --git a/backend/trcustoms/levels/signals.py b/backend/trcustoms/levels/signals.py index 72c898e4..4820526f 100644 --- a/backend/trcustoms/levels/signals.py +++ b/backend/trcustoms/levels/signals.py @@ -40,6 +40,12 @@ def update_level_author_info_on_level_change(sender, instance, **kwargs): author.update_authored_level_count() +@receiver(post_save, sender=LevelFile) +@receiver(post_delete, sender=LevelFile) +def update_level_update_date_on_files_change(sender, instance, **kwargs): + instance.level.update_last_user_content_updated() + + @receiver(m2m_changed, sender=Level.authors.through) def update_level_author_info_on_authors_change( sender, instance, pk_set, **kwargs diff --git a/backend/trcustoms/levels/tests/test_signals.py b/backend/trcustoms/levels/tests/test_signals.py new file mode 100644 index 00000000..2fb1607a --- /dev/null +++ b/backend/trcustoms/levels/tests/test_signals.py @@ -0,0 +1,22 @@ +from datetime import datetime + +import pytest + +from trcustoms.levels.tests.factories import LevelFactory, LevelFileFactory + + +@pytest.mark.django_db +def test_deleting_files_updates_last_user_content_updated() -> None: + level = LevelFactory() + + file1 = LevelFileFactory(level=level, created=datetime(2022, 1, 1)) + file2 = LevelFileFactory(level=level, created=datetime(2023, 2, 3)) + level.refresh_from_db() + + assert file1.created != file2.created + assert level.last_user_content_updated == file2.created + + file2.delete() + level.refresh_from_db() + + assert level.last_user_content_updated is None