Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added default email template with extended base #268

Open
wants to merge 25 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7c491ef
started adding feature in models.py
Vardane Oct 17, 2020
556d8b0
Started templates for particip. conf. emails
Vardane Oct 18, 2020
031d9dc
Started test for sending email confirmation
Vardane Oct 28, 2020
04defdc
added log functions to email.py functions
Vardane Nov 6, 2020
92ed309
edited logging in email.py
Vardane Nov 9, 2020
e50b010
edited tests for email sending in test_view_par...
Vardane Nov 9, 2020
75a5abe
updated volunteer/models.py
Vardane Nov 9, 2020
0ca81a1
edited tests for sending confirmation emails
Vardane Nov 15, 2020
c721605
added feature: sending cancellation emails
Vardane Nov 16, 2020
8ce6595
fix some tests
RignonNoel Nov 17, 2020
c276dd3
Merge pull request #1 from RignonNoel/Vardane-enhancement-default_ema…
Vardane Nov 17, 2020
4448c37
added test class to test sending emails
Vardane Nov 18, 2020
31abe56
added test_view_participation_emails.py
Vardane Nov 19, 2020
e05e6e8
4 tests email OK; with print statements commented
Vardane Nov 20, 2020
fc8de0e
4 tests email OK; no print comments
Vardane Nov 20, 2020
a1a7f2c
fixed test send custom emails
Vardane Nov 22, 2020
e026195
Edited participation confirm. template html file
Vardane Nov 23, 2020
37dd5ce
added css and ttf files for email templates
Vardane Dec 3, 2020
9e6ca18
-A
Vardane Dec 12, 2020
a706039
deleted base.html (non-testable with sendinblue)
Vardane Dec 12, 2020
17034e1
edited participation cancellation email template
Vardane Dec 12, 2020
17b0802
fine-tuned participation cancellation email template
Vardane Dec 13, 2020
463c09b
added developer_guide for email management
Vardane Dec 13, 2020
7e16c12
edited email_management.md documentation file
Vardane Dec 13, 2020
0109d8e
created base.html for emails
Vardane Dec 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ celerybeat-schedule
.venv
venv/
ENV/
env3

# Spyder project settings
.spyderproject
Expand All @@ -104,4 +105,4 @@ ENV/
*.sqlite3

# IDE
.idea
.idea
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"python.linting.pylintEnabled": true,
"python.linting.enabled": true
}
1 change: 1 addition & 0 deletions api_volontaria/apps/log_management/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class EmailLogAdmin(admin.ModelAdmin):
'id',
'user_email',
'type_email',
'template_id',
'nb_email_sent',
'created',
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.2.12 on 2020-11-16 23:54

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('log_management', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='emaillog',
name='template_id',
field=models.CharField(blank=True, max_length=1024, null=True, verbose_name='Template ID'),
),
]
23 changes: 21 additions & 2 deletions api_volontaria/apps/log_management/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ class EmailLog(models.Model):
max_length=1024,
verbose_name=_("Type email")
)
# either email "subject" when using django_send_email function via send_email
# or template key in ANYMAIL settings

template_id = models.CharField(
max_length=1024,
verbose_name=_("Template ID"),
null=True,
blank=True,
)

nb_email_sent = models.IntegerField(
verbose_name=_("Number email sent")
Expand All @@ -97,13 +106,23 @@ class Meta:
verbose_name = _("Email Log")
verbose_name_plural = _("Email Logs")

def __repr__(self):
return str({
'user_email': self.user_email,
'type_email': self.type_email,
'nb_email_sent': self.nb_email_sent,
'template_id': self.template_id,
'created': self.created,
})

@classmethod
def add(cls, user_email, type_email, nb_email_sent):
def add(cls, user_email, type_email, nb_email_sent, template_id=None):

new_email_log = cls.objects.create(
user_email=user_email,
type_email=type_email,
nb_email_sent=nb_email_sent
nb_email_sent=nb_email_sent,
template_id=template_id
)

return new_email_log
18 changes: 18 additions & 0 deletions api_volontaria/apps/position/migrations/0002_auto_20201116_1854.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.2.12 on 2020-11-16 23:54

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('position', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='application',
name='application_status',
field=models.CharField(choices=[('PENDING', 'Pending'), ('ACCEPTED', 'Accepted'), ('DECLINED', 'Declined')], default='PENDING', max_length=100, verbose_name='Application status'),
),
]
1 change: 1 addition & 0 deletions api_volontaria/apps/user/tests/tests_view_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from ..models import ActionToken
from ....testClasses import CustomAPITestCase

from api_volontaria.apps.log_management.models import EmailLog

User = get_user_model()

Expand Down
86 changes: 70 additions & 16 deletions api_volontaria/apps/volunteer/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
from django.db import models
from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
from django.template.loader import render_to_string
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import get_user_model
from dry_rest_permissions.generics import authenticated_users
from api_volontaria.email import EmailAPI

# from config import settings

User = get_user_model()


Expand Down Expand Up @@ -323,26 +326,57 @@ def send_email_confirmation(self):
'CITY': self.event.cell.city,
'STATE_PROVINCE': self.event.cell.state_province,
},
'ORGANIZATION_NAME': settings.LOCAL_SETTINGS['ORGANIZATION'],
}

EmailAPI().send_template_email(
self.user.email,
'CONFIRMATION_PARTICIPATION',
context,
)
TEMPLATES = settings.ANYMAIL.get('TEMPLATES')
id = TEMPLATES.get('CONFIRMATION_PARTICIPATION')
if id:
EmailAPI().send_template_email(
self.user.email,
'CONFIRMATION_PARTICIPATION',
context,
)
else:
msg_file_name = 'participation_confirmation_email'
plain_msg = render_to_string(
'.'.join([msg_file_name, 'txt']),
context
)
msg_html = render_to_string(
'.'.join([msg_file_name, 'html']),
context
)

EmailAPI().send_email(
"Objet: Confirmation de participation",
plain_msg,
"[email protected]",
[self.user.email],
html_message=msg_html,
)

def send_email_cancellation_emergency(self):
"""
An email to inform the administrator that a user just cancel his
reservation despite the fact that the event is really soon
:return: Nothing
:return: message file name (helps determine which type of email
template has been used, for example when testing application)
"""
start_time = self.event.start_time
start_time = start_time.astimezone(pytz.timezone('US/Eastern'))

end_time = self.event.end_time
end_time = end_time.astimezone(pytz.timezone('US/Eastern'))

# Headcount is "pre-delete";
# but email needs to show headcount after deletion.
# (and this only applies to actual participations (i.e. non-standby) since,
# when standby participation gets cancelled,
# no email gets sent)
if not self.is_standby:
updated_volunteer_count = self.event.nb_volunteers - 1

context = {
'PARTICIPANT': {
'FIRST_NAME': self.user.first_name,
Expand All @@ -359,10 +393,10 @@ def send_email_cancellation_emergency(self):
'END_TIME': end_time.strftime('%-Hh%M'),
'HOURS_BEFORE_EMERGENCY':
settings.NUMBER_OF_DAYS_BEFORE_EMERGENCY_CANCELLATION * 24,
'NUMBER_OF_VOLUNTEERS': self.event.nb_volunteers,

'NUMBER_OF_VOLUNTEERS': updated_volunteer_count,
'NUMBER_OF_VOLUNTEERS_NEEDED': self.event.nb_volunteers_needed,
'NUMBER_OF_VOLUNTEERS_STANDBY':
self.event.nb_volunteers_standby,
'NUMBER_OF_VOLUNTEERS_STANDBY': self.event.nb_volunteers_standby,
'NUMBER_OF_VOLUNTEERS_STANDBY_NEEDED':
self.event.nb_volunteers_standby_needed,
},
Expand All @@ -376,11 +410,31 @@ def send_email_cancellation_emergency(self):
},
}

EmailAPI().send_template_email(
settings.LOCAL_SETTINGS['CONTACT_EMAIL'],
'CANCELLATION_PARTICIPATION_EMERGENCY',
context,
)
TEMPLATES = settings.ANYMAIL.get('TEMPLATES')
id = TEMPLATES.get('CANCELLATION_PARTICIPATION_EMERGENCY')
if id:
EmailAPI().send_template_email(
settings.LOCAL_SETTINGS['CONTACT_EMAIL'],
'CANCELLATION_PARTICIPATION_EMERGENCY',
context,
)
else:
msg_file_name = 'participation_cancellation_email'
plain_msg = render_to_string(
'.'.join([msg_file_name, 'txt']),
context
)
msg_html = render_to_string(
'.'.join([msg_file_name, 'html']),
context
)
EmailAPI().send_email(
"Objet: Annulation de participation",
plain_msg,
"[email protected]",
[settings.LOCAL_SETTINGS['CONTACT_EMAIL']],
html_message=msg_html,
)

@staticmethod
def has_destroy_permission(request):
Expand Down Expand Up @@ -430,7 +484,7 @@ def send_participation_confirmation(sender, instance, created, **kwargs):


@receiver(pre_delete, sender=Participation)
def send_cancellattion_email_emergency(sender, instance, using, **kwargs):
def send_cancellation_email_emergency(sender, instance, using, **kwargs):
if not instance.is_standby:
start_time = instance.event.start_time
start_time = start_time.astimezone(pytz.timezone('US/Eastern'))
Expand All @@ -439,5 +493,5 @@ def send_cancellattion_email_emergency(sender, instance, using, **kwargs):
)

now = datetime.now(pytz.timezone('US/Eastern'))
if now > limit_date:
if now >= limit_date:
instance.send_email_cancellation_emergency()
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
132 changes: 132 additions & 0 deletions api_volontaria/apps/volunteer/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
{% load static %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style>
@import url('https://fonts.googleapis.com/css?family=Nunito+Sans');
@import url('https://fonts.googleapis.com/css?family=Pacifico+Sans');

body {
margin: 0;
font-family: 'Nunito Sans', sans-serif;
color: #142823;
}

ul {
margin: 20px 0 0 0;
padding: 0;
list-style-type: none;
}

.email {
background-color: #ffffff;
height:auto;
padding: 20px;
}

.email__single__logo {
margin: 20px;
text-align: center;
}

.email__single__logo img {
height: 60px;
margin: auto;
}

.email__double__logo {
margin: 20px;
text-align: center;
}

.email__double__logo img {
height: 60px;
margin: auto;
margin-inline: 100px;
}

.email__content {
background-color: #ffffff;
max-width: 600px;
padding: 20px;
margin: auto;
text-align: center;
}

.email__content__title {
font-size: 24px;
font-weight: 900;
text-align: center;
}

.email__introduction {
font-size: 18px;
margin-top: 50px;
margin-bottom: 50px;
}

.email__content__participation__type {
margin-top: 20px;
font-style: italic;
}

.email__content__activity__name {
margin-top: 10px;
font-size: 20px;
font-weight: 900;
}

.email__content__cell__name {
font-style: italic;
font-weight: 900;
}

.email__content__time__and__location__details {
margin-top: 10px;
font-size: 20px;
}

.email__conclusion {
font-size: 18px;
margin-top: 20px;
}

.email__sign__off {
text-align: right;
}

.email__organization__signature {
text-align: right;
font-style: italic;
}

.email__footer {
padding: 20px;
text-align: center;
color: rgba(54, 54, 54, 0.644);
background-color: rgb(251, 250, 250);
}

.volontaria__font{
font-family: 'Pacifico', sans-serif;
font-style: normal;
color: #142823;
}

</style>
</head>
<body>
<div class='email'>

{% block content %}

{% endblock content %}

</div>
<div class="email__footer">
<div>©2020 {{ORGANIZATION_NAME}}</div>
<div>Propulsé par <span class=volontaria__font>Volontaria</span>.</div>
</div>
</body>
</html>
Loading