Repository: zestedesavoir/zds-site

Issue:
Les notifications ne sont pas supprimées à la suppression d'un MP
Hello,

Suite à la réception de nombreux MP automatiques pour la mise à jour de mes articles, je les ai supprimés sans les ouvrir étant donné que j'en connaissais déjà la teneur.
Problème : les notifications sont restées, et impossible de les supprimer. Un clic dessus mène à une 404, et la notification ne disparaît pas :-/



Discussion:
Ah, bien vu ! Je n'avais pas prévu ce cas de figure.

Si quelqu'un corrige le bug avant moi : il suffit d'envoyer le signal qui marque un MP comme lu quand on quitte un MP.

Du coup, il faudra peut-être voir pour supprimer les notifications rémanentes, je ne sais pas trop comment vous pourrez faire ça :-/

Tout à fait, il faut penser à développer un script de migration pour détecter toutes les notifications plus nécessaires.

J'ai un souci avec cette issue.

Après quelques tests en local, je ne suis pas parvenu à reproduire le bug. J'ai créé un message privé avec des participants et quand j'ai supprimé les MP (sans les lires) du côté des participants, la notification a disparu. J'ai fais la même chose en supprimant plusieurs messages privés d'un coup.

J'ai aussi vérifié si j'avais pensé à ce cas. Contrairement à ce que j'ai dis plus haut, j'avais bien prévu le coup. Quand la liste des participants est éditée, j'ai un `receiver` qui réagit et qui met à jour les notifications en conséquence.

Par contre, en écrivant ce message je me suis posé la question : "Mais si je suis seul dans le MP et que je supprime le MP sans lire la notification, que se passe-t-il sachant qu'il n'y a plus de participant ?". Dans ce cas là, ma notification persiste.

Donc, @Deuchnord est-ce que tu me confirmes que tu étais seul dans les MPs ?

Je confirme, c'était des messages automatiques de Clem, à chaque fois j'étais seul dans les conversations


Resolving patch:
diff --git a/zds/notification/management/commands/delete_useless_notif.py b/zds/notification/management/commands/delete_useless_notif.py
new file mode 100644
--- /dev/null
+++ b/zds/notification/management/commands/delete_useless_notif.py
@@ -0,0 +1,21 @@
+# coding: utf-8
+from django.contrib.contenttypes.models import ContentType
+from django.core.management import BaseCommand
+
+from zds.member.models import Profile
+from zds.notification.models import Notification
+
+
+class Command(BaseCommand):
+    help = 'Remove useless notifications for private topics.'
+
+    def handle(self, *args, **options):
+        for profile in Profile.objects.all():
+            self.stdout.write(u'Remove all useless notifications of {}...'.format(profile.user.username))
+            content_type = ContentType.objects.get(model='privatepost')
+            for notification in Notification.objects\
+                    .filter(is_read=False, content_type=content_type, subscription__user=profile.user):
+                if notification.content_object is None:
+                    notification.is_read = True
+                    notification.save()
+                    self.stdout.write(u'Notification #{} marked as read.'.format(notification.id))
diff --git a/zds/notification/receivers.py b/zds/notification/receivers.py
--- a/zds/notification/receivers.py
+++ b/zds/notification/receivers.py
@@ -232,6 +232,17 @@ def add_participant_topic_event(sender, **kwargs):
                     subscription.deactivate()
 
 
+@receiver(pre_delete, sender=PrivateTopic)
+def delete_private_topic_event(sender, instance, **kwargs):
+    """
+    A private topic is deleted when there is nobody in this private topic.
+    """
+    subscriptions = PrivateTopicAnswerSubscription.objects.get_subscriptions(content_object=instance, is_active=True)
+    for subscription in subscriptions:
+        subscription.mark_notification_read()
+        subscription.deactivate()
+
+
 @receiver(pre_delete, sender=User)
 def delete_notifications(sender, instance, **kwargs):
     """


Test patch:
diff --git a/zds/notification/tests.py b/zds/notification/tests.py
--- a/zds/notification/tests.py
+++ b/zds/notification/tests.py
@@ -451,17 +451,20 @@ def test_remove_notifications_when_a_user_leave_private_topic(self):
         self.assertIsNotNone(notifications.first())
         self.assertEqual(topic.last_message, notifications.first().content_object)
 
-        self.assertIsNotNone(
-            PrivateTopicAnswerSubscription.objects.get_existing(self.user2, topic, is_active=True))
+        self.assertIsNotNone(PrivateTopicAnswerSubscription.objects.get_existing(self.user2, topic, is_active=True))
 
+        send_message_mp(self.user2, topic, "Test")
         topic.participants.remove(self.user2)
         topic.save()
 
-        notifications = Notification.objects.get_unread_notifications_of(self.user2)
-        self.assertEqual(0, len(notifications))
+        self.assertEqual(0, len(Notification.objects.get_unread_notifications_of(self.user2)))
+        self.assertIsNotNone(PrivateTopicAnswerSubscription.objects.get_existing(self.user2, topic, is_active=False))
+
+        self.assertEqual(1, len(Notification.objects.get_unread_notifications_of(self.user1)))
 
-        self.assertIsNotNone(
-            PrivateTopicAnswerSubscription.objects.get_existing(self.user2, topic, is_active=False))
+        response = self.client.post(reverse('mp-delete', args=[topic.pk, topic.slug]), follow=True)
+        self.assertEqual(200, response.status_code)
+        self.assertEqual(0, len(Notification.objects.get_unread_notifications_of(self.user1)))
 
     def test_send_an_email_when_we_specify_it(self):
         """