From 366d8d1e2ea18c30b3a2645f0ff9796d0b21597a Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Sat, 24 Mar 2018 01:50:30 +0100 Subject: [PATCH 4/5] notifications: allow notifications without an end_timestamp (#22732) Those notifications will disappear only with an action of the user. --- .../migrations/0005_auto_20180324_0025.py | 20 ++++++++ combo/apps/notifications/models.py | 9 ++-- tests/test_notification.py | 57 ++++++++++++++++++++++ 3 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 combo/apps/notifications/migrations/0005_auto_20180324_0025.py diff --git a/combo/apps/notifications/migrations/0005_auto_20180324_0025.py b/combo/apps/notifications/migrations/0005_auto_20180324_0025.py new file mode 100644 index 0000000..445f861 --- /dev/null +++ b/combo/apps/notifications/migrations/0005_auto_20180324_0025.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.11 on 2018-03-24 00:25 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('notifications', '0004_auto_20180316_1026'), + ] + + operations = [ + migrations.AlterField( + model_name='notification', + name='end_timestamp', + field=models.DateTimeField(null=True, verbose_name='End date and time'), + ), + ] diff --git a/combo/apps/notifications/models.py b/combo/apps/notifications/models.py index 4b805a1..bc6d120 100644 --- a/combo/apps/notifications/models.py +++ b/combo/apps/notifications/models.py @@ -49,7 +49,7 @@ class NotificationQuerySet(QuerySet): if user: qs = qs.filter(user=user) n = n or now() - qs = qs.filter(start_timestamp__lte=n, end_timestamp__gt=n) + qs = qs.filter(Q(start_timestamp__lte=n) & (Q(end_timestamp__isnull=True)|Q(end_timestamp__gte=n))) return qs.order_by('-start_timestamp') def new(self): @@ -72,11 +72,10 @@ class Notification(models.Model): url = models.URLField(_('URL'), default='', blank=True) origin = models.CharField(_('Origin'), max_length=100, blank=True) start_timestamp = models.DateTimeField(_('Start date and time')) - end_timestamp = models.DateTimeField(_('End date and time')) + end_timestamp = models.DateTimeField(_('End date and time'), null=True) acked = models.BooleanField(_('Acked'), default=False) external_id = models.SlugField(_('External identifier'), null=True) - class Meta: verbose_name = _('Notification') unique_together = ( @@ -104,7 +103,9 @@ class Notification(models.Model): ''' start_timestamp = start_timestamp or now() - if duration: + if duration == 0: + end_timestamp = None + elif duration: if not isinstance(duration, timedelta): duration = timedelta(seconds=duration) end_timestamp = start_timestamp + duration diff --git a/tests/test_notification.py b/tests/test_notification.py index 2f62b56..1e63929 100644 --- a/tests/test_notification.py +++ b/tests/test_notification.py @@ -3,6 +3,7 @@ import json import mock import pytest from decimal import Decimal +from datetime import timedelta as timedelta from django.test.client import RequestFactory from django.utils.timezone import timedelta, now @@ -348,3 +349,59 @@ def test_notify_remote_items(mock_get, app, john_doe, jane_doe, regie, freezer): # be sure the are no more reminders created regie.notify_new_remote_invoices() assert Notification.objects.count() == 4 + + +def test_notification_never_expire(app, freezer, rf, john_doe): + start = freezer() + + app.authorization = ('Basic', (john_doe.username, john_doe.username)) + app.post_json(reverse('api-notification-add'), params={ + 'summary': 'notibar', + 'url': 'http://www.example.net', + 'body': 'foobar', + 'origin': 'blah', + 'duration': 0, + }) + app.post_json(reverse('api-notification-add'), params={ + 'summary': 'notifoo', + 'url': 'http://www.example.net', + 'body': 'foobar', + 'origin': 'blah', + 'duration': 86400 * 2, # 2 days + }) + page = Page.objects.create(title='notif', slug='test_notification_cell', template_name='standard') + cell = NotificationsCell(page=page, placeholder='content', order=0) + + request = rf.get('/') + request.user = john_doe + context = {'request': request} + + freezer.move_to(start - timedelta(seconds=10)) + assert Notification.objects.visible(john_doe).count() == 0 + content = cell.render(context) + assert 'notibar' not in content + assert 'notifoo' not in content + + freezer.move_to(start + timedelta(seconds=10)) + assert Notification.objects.visible(john_doe).count() == 2 + content = cell.render(context) + assert 'notibar' in content + assert 'notifoo' in content + + freezer.move_to(start + timedelta(days=1)) + content = cell.render(context) + assert Notification.objects.visible(john_doe).count() == 2 + assert 'notibar' in content + assert 'notifoo' in content + + freezer.move_to(start + timedelta(days=3)) + content = cell.render(context) + assert Notification.objects.visible(john_doe).count() == 1 + assert 'notibar' in content + assert 'notifoo' not in content + + freezer.move_to(start + timedelta(days=365)) + content = cell.render(context) + assert Notification.objects.visible(john_doe).count() == 1 + assert 'notibar' in content + assert 'notifoo' not in content -- 2.14.2