diff --git a/.gitignore b/.gitignore index 27a2a022..b448d786 100644 --- a/.gitignore +++ b/.gitignore @@ -86,6 +86,7 @@ celerybeat-schedule .venv venv/ ENV/ +env3 # Spyder project settings .spyderproject @@ -104,4 +105,4 @@ ENV/ *.sqlite3 # IDE -.idea \ No newline at end of file +.idea diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..cc67606f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "python.linting.pylintEnabled": true, + "python.linting.enabled": true +} \ No newline at end of file diff --git a/api_volontaria/apps/log_management/admin.py b/api_volontaria/apps/log_management/admin.py index 87583416..0f2e75b5 100644 --- a/api_volontaria/apps/log_management/admin.py +++ b/api_volontaria/apps/log_management/admin.py @@ -35,6 +35,7 @@ class EmailLogAdmin(admin.ModelAdmin): 'id', 'user_email', 'type_email', + 'template_id', 'nb_email_sent', 'created', ) diff --git a/api_volontaria/apps/log_management/migrations/0002_emaillog_template_id.py b/api_volontaria/apps/log_management/migrations/0002_emaillog_template_id.py new file mode 100644 index 00000000..a2b37813 --- /dev/null +++ b/api_volontaria/apps/log_management/migrations/0002_emaillog_template_id.py @@ -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'), + ), + ] diff --git a/api_volontaria/apps/log_management/models.py b/api_volontaria/apps/log_management/models.py index 82d83ef3..73817a98 100644 --- a/api_volontaria/apps/log_management/models.py +++ b/api_volontaria/apps/log_management/models.py @@ -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") @@ -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 diff --git a/api_volontaria/apps/position/migrations/0002_auto_20201116_1854.py b/api_volontaria/apps/position/migrations/0002_auto_20201116_1854.py new file mode 100644 index 00000000..e5d755fd --- /dev/null +++ b/api_volontaria/apps/position/migrations/0002_auto_20201116_1854.py @@ -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'), + ), + ] diff --git a/api_volontaria/apps/user/tests/tests_view_users.py b/api_volontaria/apps/user/tests/tests_view_users.py index c208bbda..d0b468a8 100644 --- a/api_volontaria/apps/user/tests/tests_view_users.py +++ b/api_volontaria/apps/user/tests/tests_view_users.py @@ -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() diff --git a/api_volontaria/apps/volunteer/models.py b/api_volontaria/apps/volunteer/models.py index 21f83b1d..14f0cc31 100644 --- a/api_volontaria/apps/volunteer/models.py +++ b/api_volontaria/apps/volunteer/models.py @@ -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() @@ -323,19 +326,42 @@ 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_from@mondomain.ca", + [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')) @@ -343,6 +369,14 @@ def send_email_cancellation_emergency(self): 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, @@ -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, }, @@ -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_from@mondomain.ca", + [settings.LOCAL_SETTINGS['CONTACT_EMAIL']], + html_message=msg_html, + ) @staticmethod def has_destroy_permission(request): @@ -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')) @@ -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() diff --git a/api_volontaria/apps/volunteer/static/volunteer/img/logo_general.png b/api_volontaria/apps/volunteer/static/volunteer/img/logo_general.png new file mode 100644 index 00000000..38396f72 Binary files /dev/null and b/api_volontaria/apps/volunteer/static/volunteer/img/logo_general.png differ diff --git a/api_volontaria/apps/volunteer/static/volunteer/img/logo_volontaria.png b/api_volontaria/apps/volunteer/static/volunteer/img/logo_volontaria.png new file mode 100644 index 00000000..cb216d77 Binary files /dev/null and b/api_volontaria/apps/volunteer/static/volunteer/img/logo_volontaria.png differ diff --git a/api_volontaria/apps/volunteer/templates/base.html b/api_volontaria/apps/volunteer/templates/base.html new file mode 100644 index 00000000..8ae9a93c --- /dev/null +++ b/api_volontaria/apps/volunteer/templates/base.html @@ -0,0 +1,132 @@ +{% load static %} + + + + + + + +
+ + {% block content %} + + {% endblock content %} + +
+ + + \ No newline at end of file diff --git a/api_volontaria/apps/volunteer/templates/participation_cancellation_email.html b/api_volontaria/apps/volunteer/templates/participation_cancellation_email.html new file mode 100644 index 00000000..12d0e189 --- /dev/null +++ b/api_volontaria/apps/volunteer/templates/participation_cancellation_email.html @@ -0,0 +1,76 @@ +{% extends 'base.html' %} +{% load static %} + +{% block content %} + +
+

+ Un bénévole vient de se désinscrire. +

+
+ {{PARTICIPANT.FIRST_NAME}} {{PARTICIPANT.LAST_NAME}} vient d'annuler sa participation à l'activité suivante qui se déroule dans moins de 48h: +
+ +
+ {{ACTIVITY.NAME}} +
+
+

+ {{ACTIVITY.START_DATE}} +

+ +

+ De {{ACTIVITY.START_TIME}} à {{ACTIVITY.END_TIME}} +

+ + + +

+ {{CELL.ADDRESS_LINE_1}} +

+ + {% if CELL.ADDRESS_LINE_2 %} +

+ {{CELL.ADDRESS_LINE_2}} +

+ {% endif %} + +

+ {{CELL.CITY}}, {{CELL.POSTAL_CODE}}, {{CELL.STATE_PROVINCE}} +

+
+ +
+ Statut des inscriptions après cette annulation: +
+ + +
+ {% if ACTIVITY.NUMBER_OF_VOLUNTEERS_STANDBY > 1 %} + N'hésitez pas à contacter des remplaçants + le plus rapidement possible + si vous avez besoin de combler cette annulation. + {% elif ACTIVITY.NUMBER_OF_VOLUNTEERS_STANDBY == 1 %} + N'hésitez pas à contacter un remplaçant + le plus rapidement possible + si vous avez besoin de combler cette annulation. + {% endif %} +
+
+

+ Bonne journée +

+
+
+

+ L'équipe de Volontaria +

+{% endblock content %} \ No newline at end of file diff --git a/api_volontaria/apps/volunteer/templates/participation_cancellation_email.txt b/api_volontaria/apps/volunteer/templates/participation_cancellation_email.txt new file mode 100644 index 00000000..56e8dd20 --- /dev/null +++ b/api_volontaria/apps/volunteer/templates/participation_cancellation_email.txt @@ -0,0 +1,52 @@ +{% load static %} +logo organisation +logo Volontaria + +Un bénévole vient de se désinscrire. + +Un participant vient d'annuler sa participation à une activité qui débute dans {{ACTIVITY.HOURS_BEFORE_EMERGENCY}} heures. + +{{PARTICIPANT.FIRST_NAME}} {{PARTICIPANT.LAST_NAME}} vient d'annuler sa participation à l'activité suivante qui se déroule dans moins de 48h: + + +{{ACTIVITY.NAME}} + +{{ACTIVITY.START_DATE}} + +De {{ACTIVITY.START_TIME}} à {{ACTIVITY.END_TIME}} + +{{CELL.NAME}} + +{{CELL.ADDRESS_LINE_1}} + +{% if CELL.ADDRESS_LINE_2 %} + +{{CELL.ADDRESS_LINE_2}} + +{% endif %} + +{{CELL.CITY}}, {{CELL.POSTAL_CODE}}, {{CELL.STATE_PROVINCE}} + +Statut des inscriptions après cette annulation: + +Nombre de bénévoles: {{ACTIVITY.NUMBER_OF_VOLUNTEERS}} / {{ACTIVITY.NUMBER_OF_VOLUNTEERS_NEEDED}} +Nombre de remplaçants: {{ACTIVITY.NUMBER_OF_VOLUNTEERS_STANDBY}} / {{ACTIVITY.NUMBER_OF_VOLUNTEERS_STANDBY_NEEDED}} + +{% if ACTIVITY.NUMBER_OF_VOLUNTEERS_STANDBY > 1 %} + N'hésitez pas à contacter des remplaçants + le plus rapidement possible + si vous avez besoin de combler cette annulation. +{% elif ACTIVITY.NUMBER_OF_VOLUNTEERS_STANDBY == 1 %} + N'hésitez pas à contacter un remplaçant + le plus rapidement possible + si vous avez besoin de combler cette annulation. +{% endif %} + +Bonne journée + +L'équipe de Volontaria + + +©2020 {{ORGANIZATION_NAME}} +Propulsé par Volontaria. + diff --git a/api_volontaria/apps/volunteer/templates/participation_confirmation_email.html b/api_volontaria/apps/volunteer/templates/participation_confirmation_email.html new file mode 100644 index 00000000..637c192c --- /dev/null +++ b/api_volontaria/apps/volunteer/templates/participation_confirmation_email.html @@ -0,0 +1,76 @@ +{% extends 'base.html' %} +{% load static %} + +{% block content %} + +