diff --git a/bluebottle/activities/messages.py b/bluebottle/activities/messages.py index f1d2e2c1b4..258456410a 100644 --- a/bluebottle/activities/messages.py +++ b/bluebottle/activities/messages.py @@ -509,6 +509,26 @@ def get_recipients(self): return members +class PublishActivityReminderNotification(TransitionMessage): + subject = pgettext('email', 'Publish your activity "{title}"') + template = 'messages/publish_activity_reminder' + send_once = True + + context = { + 'title': 'title', + } + + @property + def action_link(self): + return self.obj.get_absolute_url() + + action_title = pgettext('email', 'Publish your activity') + + def get_recipients(self): + """activity owner""" + return [self.obj.owner] + + class DoGoodHoursReminderQ1Notification(BaseDoGoodHoursReminderNotification): subject = pgettext('email', "It’s a new year, let's make some impact!") template = 'messages/do-good-hours/reminder-q1' diff --git a/bluebottle/activities/periodic_tasks.py b/bluebottle/activities/periodic_tasks.py new file mode 100644 index 0000000000..db3f7938f1 --- /dev/null +++ b/bluebottle/activities/periodic_tasks.py @@ -0,0 +1,31 @@ +from datetime import timedelta + +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ + +from bluebottle.activities.messages import PublishActivityReminderNotification +from bluebottle.activities.models import Activity +from bluebottle.fsm.periodic_tasks import ModelPeriodicTask +from bluebottle.notifications.effects import NotificationEffect + + +class UnpublishedActivitiesReminderTask(ModelPeriodicTask): + def get_queryset(self): + return Activity.objects.filter( + polymorphic_ctype__model__in=('dateactivity', 'deed'), + polymorphic_ctype__app_label__in=('time_based', 'deeds'), + created__lte=timezone.now() - timedelta(days=3), + created__gte=timezone.now() - timedelta(days=4), + status__in=['draft', 'needs_work'] + ) + + effects = [ + NotificationEffect( + PublishActivityReminderNotification + ), + ] + + def __str__(self): + return str( + _("Send a reminder whe activities are unpublished for more then 3 days") + ) diff --git a/bluebottle/activities/templates/mails/messages/publish_activity_reminder.html b/bluebottle/activities/templates/mails/messages/publish_activity_reminder.html new file mode 100644 index 0000000000..1a11ae8dc9 --- /dev/null +++ b/bluebottle/activities/templates/mails/messages/publish_activity_reminder.html @@ -0,0 +1,11 @@ +{% extends "mails/messages/activity_base.html" %} +{% load i18n %} +{% block message %} +

+ {% blocktrans context 'email' %}You have created the activity {{title}} but have not published it yet. This means no one will be able to find your activity and join it.{% endblocktrans %} +

+

+ {% blocktrans context 'email' %}You can publish your activity from your activity detail page.{% endblocktrans %} +

+{% endblock %} + diff --git a/bluebottle/deeds/periodic_tasks.py b/bluebottle/deeds/periodic_tasks.py index 1f37f9ebe1..f767f73874 100644 --- a/bluebottle/deeds/periodic_tasks.py +++ b/bluebottle/deeds/periodic_tasks.py @@ -2,6 +2,7 @@ from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ +from bluebottle.activities.periodic_tasks import UnpublishedActivitiesReminderTask from bluebottle.deeds.messages import DeedReminderNotification from bluebottle.deeds.models import ( @@ -71,5 +72,5 @@ def __str__(self): Deed.periodic_tasks = [ - DeedStartedTask, DeedFinishedTask, DeedReminderTask + DeedStartedTask, DeedFinishedTask, DeedReminderTask, UnpublishedActivitiesReminderTask ] diff --git a/bluebottle/deeds/tests/test_periodic_tasks.py b/bluebottle/deeds/tests/test_periodic_tasks.py index 8afd5635fe..6f51203ae5 100644 --- a/bluebottle/deeds/tests/test_periodic_tasks.py +++ b/bluebottle/deeds/tests/test_periodic_tasks.py @@ -1,9 +1,11 @@ -from datetime import timedelta, date +from datetime import timedelta, date, datetime import mock from django.core import mail from django.db import connection +from django.utils.timezone import now, get_current_timezone +from bluebottle.activities.periodic_tasks import timezone from bluebottle.clients.utils import LocalTenant from bluebottle.deeds.tasks import deed_tasks from bluebottle.deeds.tests.factories import ( @@ -33,9 +35,14 @@ def setUp(self): def run_tasks(self, when): with mock.patch('bluebottle.deeds.periodic_tasks.date') as mock_date: - mock_date.today.return_value = when - mock_date.side_effect = lambda *args, **kw: date(*args, **kw) - deed_tasks() + now_return_value = datetime.combine( + when, datetime.min.time() + ).astimezone(get_current_timezone()) + + with mock.patch.object(timezone, 'now', return_value=now_return_value): + mock_date.today.return_value = when + mock_date.side_effect = lambda *args, **kw: date(*args, **kw) + deed_tasks() def test_nothing(self): self.assertEqual(self.activity.status, 'open') @@ -115,3 +122,33 @@ def test_reminder(self): self.assertEqual(len(mail.outbox), 0) self.run_tasks(self.activity.start - timedelta(days=1)) self.assertEqual(len(mail.outbox), 0, 'Should not send reminder mail again.') + + def test_reminder_unpublished(self): + self.activity.created = now() + self.activity.status = 'draft' + self.activity.save() + + mail.outbox = [] + self.run_tasks(now() + timedelta(days=2)) + self.assertEqual(len(mail.outbox), 0, 'activities need to be older then 3 days') + + self.run_tasks(now() + timedelta(days=4)) + + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].to[0], self.activity.owner.email) + self.assertEqual(mail.outbox[0].subject, f'Publish your activity "{self.activity.title}"') + + mail.outbox = [] + self.run_tasks(now() + timedelta(days=4)) + self.assertEqual(len(mail.outbox), 0, 'Should not send reminder mail again.') + + def test_reminder_unpublished_not_draft(self): + self.activity.created = now() + self.activity.status = 'open' + self.activity.save() + + mail.outbox = [] + + self.run_tasks(now() + timedelta(days=4)) + + self.assertEqual(len(mail.outbox), 0) diff --git a/bluebottle/time_based/periodic_tasks.py b/bluebottle/time_based/periodic_tasks.py index adfc2cc6dc..b4d055e621 100644 --- a/bluebottle/time_based/periodic_tasks.py +++ b/bluebottle/time_based/periodic_tasks.py @@ -3,6 +3,7 @@ from django.db.models import DateTimeField, ExpressionWrapper, F, Q from django.utils import timezone from django.utils.translation import gettext_lazy as _ +from bluebottle.activities.periodic_tasks import UnpublishedActivitiesReminderTask from bluebottle.fsm.effects import TransitionEffect from bluebottle.fsm.periodic_tasks import ModelPeriodicTask @@ -212,6 +213,7 @@ class TeamSlotFinishedTask(SlotFinishedTask): DateActivity.periodic_tasks = [ TimeBasedActivityRegistrationDeadlinePassedTask, DateActivityFinishedTask, + UnpublishedActivitiesReminderTask ] DateActivitySlot.periodic_tasks = [