Skip to content

Commit

Permalink
Merge pull request #5219 from onepercentclub/ticket/user-reminder-mai…
Browse files Browse the repository at this point in the history
…l-setting

Ticket/user reminder mail setting
  • Loading branch information
gannetson committed Aug 30, 2022
2 parents 6baa2db + a0330eb commit 24ce94b
Show file tree
Hide file tree
Showing 18 changed files with 509 additions and 35 deletions.
60 changes: 55 additions & 5 deletions bluebottle/activities/messages.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from pytz import timezone
from datetime import timedelta

from django.urls import reverse
from django.db.models import Sum, Q
from django.template.defaultfilters import time, date
from django.urls import reverse
from django.utils.timezone import get_current_timezone, now
from django.utils.translation import pgettext_lazy as pgettext
from pytz import timezone

from bluebottle.initiatives.models import InitiativePlatformSettings
from django.utils.timezone import get_current_timezone

from bluebottle.notifications.messages import TransitionMessage
from django.utils.translation import pgettext_lazy as pgettext
from bluebottle.utils.utils import get_current_host, get_current_language


Expand Down Expand Up @@ -445,3 +446,52 @@ def get_recipients(self):
return [self.obj.team.owner]
else:
return []


class BaseDoGoodHoursReminderNotification(TransitionMessage):

@property
def action_link(self):
return self.obj.get_absolute_url()

action_title = pgettext('email', 'Find activities')

def get_recipients(self):
"""members with do good hours"""
from bluebottle.members.models import Member
from bluebottle.members.models import MemberPlatformSettings

year = now().year
do_good_hours = timedelta(hours=MemberPlatformSettings.load().do_good_hours)

members = Member.objects.annotate(
hours=Sum(
'contributor__contributions__timecontribution__value',
filter=Q(contributor__contributions__start__year=year)
),
).filter(
Q(hours__lt=do_good_hours) | Q(hours__isnull=True),
is_active=True,
receive_reminder_emails=True
).distinct()
return members


class DoGoodHoursReminderQ1Notification(BaseDoGoodHoursReminderNotification):
subject = pgettext('email', "Are you ready to do good? Q1")
template = 'messages/do-good-hours/reminder-q1'


class DoGoodHoursReminderQ2Notification(BaseDoGoodHoursReminderNotification):
subject = pgettext('email', "Are you ready to do good? Q2")
template = 'messages/do-good-hours/reminder-q2'


class DoGoodHoursReminderQ3Notification(BaseDoGoodHoursReminderNotification):
subject = pgettext('email', "Are you ready to do good? Q3")
template = 'messages/do-good-hours/reminder-q3'


class DoGoodHoursReminderQ4Notification(BaseDoGoodHoursReminderNotification):
subject = pgettext('email', "Are you ready to do good? Q4")
template = 'messages/do-good-hours/reminder-q4'
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% extends "base.mail.html" %}
{% load i18n %}

{% block content %}
<p>
{% blocktrans context 'email' %}Hi {{ recipient_name }},{% endblocktrans %}
</p>
{% block message %}{% endblock %}
{% endblock %}

{% block action %}
<a href="{{ action_link }}" class="action-email">{{ action_title }}</a>
{% endblock %}`
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% extends "mails/messages/do-good-hours/reminder-base.html" %}
{% load i18n %}

{% block message %}
{% blocktrans context 'email' %}
First reminder
{% endblocktrans %}
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% extends "mails/messages/do-good-hours/reminder-base.html" %}
{% load i18n %}

{% block message %}
{% blocktrans context 'email' %}
Second reminder
{% endblocktrans %}
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% extends "mails/messages/do-good-hours/reminder-base.html" %}
{% load i18n %}

{% block message %}
{% blocktrans context 'email' %}
Third reminder
{% endblocktrans %}
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% extends "mails/messages/do-good-hours/reminder-base.html" %}
{% load i18n %}

{% block message %}
{% blocktrans context 'email' %}
Fourth reminder
{% endblocktrans %}
{% endblock %}
116 changes: 114 additions & 2 deletions bluebottle/activities/tests/test_notifications.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
from datetime import timedelta

from django.utils.timezone import now

from bluebottle.activities.messages import (
ActivityRejectedNotification, ActivityCancelledNotification,
ActivitySucceededNotification, ActivityRestoredNotification,
ActivityExpiredNotification, TeamAddedMessage,
TeamAppliedMessage, TeamCancelledMessage,
TeamCancelledTeamCaptainMessage, TeamWithdrawnActivityOwnerMessage,
TeamWithdrawnMessage, TeamMemberAddedMessage, TeamMemberWithdrewMessage,
TeamMemberRemovedMessage, TeamReappliedMessage, TeamCaptainAcceptedMessage
TeamMemberRemovedMessage, TeamReappliedMessage, TeamCaptainAcceptedMessage, DoGoodHoursReminderQ1Notification,
DoGoodHoursReminderQ3Notification, DoGoodHoursReminderQ2Notification, DoGoodHoursReminderQ4Notification
)
from bluebottle.activities.tests.factories import TeamFactory
from bluebottle.members.models import MemberPlatformSettings, Member
from bluebottle.notifications.models import NotificationPlatformSettings
from bluebottle.test.factory_models.accounts import BlueBottleUserFactory
from bluebottle.test.utils import NotificationTestCase
from bluebottle.time_based.tests.factories import (
DateActivityFactory, PeriodActivityFactory, PeriodParticipantFactory
DateActivityFactory, PeriodActivityFactory, PeriodParticipantFactory, DateActivitySlotFactory,
DateParticipantFactory, SlotParticipantFactory
)


Expand Down Expand Up @@ -260,3 +268,107 @@ def test_team_member_removed_notification(self):

self.assertActionLink(self.obj.activity.get_absolute_url())
self.assertActionTitle('View activity')


class DoGoodHoursReminderNotificationTestCase(NotificationTestCase):

def setUp(self):
self.obj = NotificationPlatformSettings.load()
self.obj = MemberPlatformSettings.load()
self.obj.do_good_hours = 8
self.obj.save()
activity = DateActivityFactory.create(
slots=[],
slot_selection='free',
)

slot1 = DateActivitySlotFactory.create(
start=now() - timedelta(days=2),
duration=timedelta(hours=4),
activity=activity
)
slot2 = DateActivitySlotFactory.create(
start=now() - timedelta(days=1),
duration=timedelta(hours=4),
activity=activity
)
old_slot = DateActivitySlotFactory.create(
start=now().replace(year=2011),
duration=timedelta(hours=8),
activity=activity
)

self.active_user = BlueBottleUserFactory.create(first_name='Active')
part1 = DateParticipantFactory.create(
user=self.active_user,
activity=activity
)
SlotParticipantFactory.create(
participant=part1,
slot=slot1
)
SlotParticipantFactory.create(
participant=part1,
slot=slot2
)
self.moderate_user = BlueBottleUserFactory.create(first_name='Moderate')
part2 = DateParticipantFactory.create(
user=self.moderate_user,
activity=activity
)
SlotParticipantFactory.create(
participant=part2,
slot=slot1
)
SlotParticipantFactory.create(
participant=part2,
slot=old_slot
)
self.passive_user = BlueBottleUserFactory.create(first_name='Passive')
part3 = DateParticipantFactory.create(
user=self.passive_user,
activity=activity
)

SlotParticipantFactory.create(
participant=part3,
slot=old_slot
)

Member.objects.exclude(id__in=[
self.active_user.id,
self.passive_user.id,
self.moderate_user.id,
]).update(receive_reminder_emails=False)

def test_reminder_q1(self):
self.message_class = DoGoodHoursReminderQ1Notification
self.create()
self.assertRecipients([self.moderate_user, self.passive_user])
self.assertSubject("Are you ready to do good? Q1")
self.assertBodyContains('First reminder')
self.assertActionTitle('Find activities')

def test_reminder_q2(self):
self.message_class = DoGoodHoursReminderQ2Notification
self.create()
self.assertRecipients([self.moderate_user, self.passive_user])
self.assertSubject("Are you ready to do good? Q2")
self.assertBodyContains('Second reminder')
self.assertActionTitle('Find activities')

def test_reminder_q3(self):
self.message_class = DoGoodHoursReminderQ3Notification
self.create()
self.assertRecipients([self.moderate_user, self.passive_user])
self.assertSubject("Are you ready to do good? Q3")
self.assertBodyContains('Third reminder')
self.assertActionTitle('Find activities')

def test_reminder_q4(self):
self.message_class = DoGoodHoursReminderQ4Notification
self.create()
self.assertRecipients([self.moderate_user, self.passive_user])
self.assertSubject("Are you ready to do good? Q4")
self.assertBodyContains('Fourth reminder')
self.assertActionTitle('Find activities')
14 changes: 11 additions & 3 deletions bluebottle/members/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,16 @@ class MemberPlatformSettingsAdmin(BasePlatformSettingsAdmin, NonSortableParentAd
}
),
(
_('Initiatives'),
_('Engagement'),
{
'fields': (
'create_initiatives',
)
'do_good_hours',
'reminder_q1',
'reminder_q2',
'reminder_q3',
'reminder_q4'
),
}
),
)
Expand Down Expand Up @@ -385,6 +390,8 @@ def get_fieldsets(self, request, obj=None):
{
'fields':
[
'hours_spent',
'hours_planned',
'initiatives',
'date_activities',
'period_activities',
Expand Down Expand Up @@ -439,7 +446,8 @@ def get_readonly_fields(self, request, obj=None):
'updated', 'deleted', 'login_as_link',
'reset_password', 'resend_welcome_link',
'initiatives', 'period_activities', 'date_activities',
'funding', 'deeds', 'collect', 'kyc'
'funding', 'deeds', 'collect', 'kyc',
'hours_spent', 'hours_planned'
]

user_groups = request.user.groups.all()
Expand Down
25 changes: 25 additions & 0 deletions bluebottle/members/migrations/0063_auto_20220818_0637.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 2.2.24 on 2022-08-18 04:37

import bluebottle.bb_accounts.models
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('members', '0062_auto_20220815_1751'),
]

operations = [
migrations.AddField(
model_name='memberplatformsettings',
name='do_good_hours',
field=models.IntegerField(
blank=True,
help_text='The amount of hours users can spend each year. '
'Leave empty if no restrictions apply.',
null=True
),
),
]
35 changes: 35 additions & 0 deletions bluebottle/members/migrations/0064_auto_20220825_0840.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Generated by Django 2.2.24 on 2022-08-25 06:40

import bluebottle.bb_accounts.models
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('members', '0063_auto_20220818_0637'),
]

operations = [
migrations.AddField(
model_name='memberplatformsettings',
name='reminder_q1',
field=models.BooleanField(default=False, help_text='This activation mail is send on January 15th.'),
),
migrations.AddField(
model_name='memberplatformsettings',
name='reminder_q2',
field=models.BooleanField(default=False, help_text='This activation mail is send on April 15th.'),
),
migrations.AddField(
model_name='memberplatformsettings',
name='reminder_q3',
field=models.BooleanField(default=False, help_text='This activation mail is send on September 1st.'),
),
migrations.AddField(
model_name='memberplatformsettings',
name='reminder_q4',
field=models.BooleanField(default=False, help_text='This activation mail is send on October 15th.'),
),
]
18 changes: 18 additions & 0 deletions bluebottle/members/migrations/0065_auto_20220825_1055.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.2.24 on 2022-08-25 08:55

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('members', '0064_auto_20220825_0840'),
]

operations = [
migrations.AddField(
model_name='member',
name='receive_reminder_emails',
field=models.BooleanField(default=True, help_text='User receives emails reminding them about their do good hours', verbose_name='Receive reminder emails'),
),
]
Loading

0 comments on commit 24ce94b

Please sign in to comment.