Skip to content
Snippets Groups Projects
mail_template.py 10.6 KiB
Newer Older
Valentin Groues's avatar
Valentin Groues committed
# coding=utf-8
import datetime
import locale
from contextlib import contextmanager

from django.db import models

from .constants import MAIL_TEMPLATE_CONTEXT_CHOICES, MAIL_TEMPLATE_CONTEXT_APPOINTMENT, MAIL_TEMPLATE_CONTEXT_SUBJECT, \
    MAIL_TEMPLATE_CONTEXT_VISIT
from ..docx_helper import process_file
from ..models import Appointment, Visit, Subject, Worker

DATE_FORMAT_FULL = "%A %-d %B %Y"

DATETIME_FORMAT = "%A %-d %B %Y, %H:%m"

DATE_FORMAT_SHORT = "%d.%m.%Y"

DATE_FORMAT_TIME = "%H:%M"

now = datetime.datetime.now()


@contextmanager
def setlocale(name):
    saved = locale.setlocale(locale.LC_TIME)
    try:
        yield locale.setlocale(locale.LC_TIME, name)
    finally:
        locale.setlocale(locale.LC_TIME, saved)


class MailTemplate(models.Model):
    MAILS_TEMPLATE_GENERIC_TAGS = [
        ("##DATE_FULL##", "Current date when the mail will be generated (long format)", now.strftime(DATE_FORMAT_FULL)),
        ("##DATE_SHORT##", "Current date when the mail will be generated (short format)",
         now.strftime(DATE_FORMAT_SHORT)),
        ("##WORKER##", "The full name of the currently logged in user", "")
    ]

    MAILS_TEMPLATE_SUBJECT_TAGS = [
        ("##S_FULL_NAME##", "Subject's full name", "first_name last_name"),
        ("##S_FIRST_NAME##", "Subject's first name", ""),
        ("##S_LAST_NAME##", "Subject's last name", ""),
        ("##S_ADDRESS##", "Subject's address", "street name and number"),
        ("##S_CITY##", "Subject's city of residence", ""),
        ("##S_POST_CODE##", "Subject's post code of residence", ""),
        ("##S_COUNTRY##", "Subject's country of residence", ""),
        ("##S_SEX##", "Subject's gender", "Male/Female"),
        ("##S_TYPE##", "Subject's type", "CONTROL/PATIENT"),
        ("##S_DATE_BORN##", "Subject's date of birth", now.strftime(DATE_FORMAT_SHORT)),

        ("##S_EMAIL##", "Subject's email address", ""),
        ("##S_PHONE_NUMBER##", "Subject's phone number", ""),
        ("##S_PHONE_NUMBER_2##", "Subject's second phone number", ""),
        ("##S_PHONE_NUMBER_3##", "Subject's third phone number", ""),
        ("##S_MAIL_LANGUAGE##", "Subject's preferred language for written communication", ""),
        ("##S_KNOWN_LANGUAGES##", "List of languages known by the subject", "comma separated"),

        ("##S_SCREENING_NUMBER##", "Subject's screening number", ""),
        ("##S_DIAGNOSIS##", "Subject's diagnosis", ""),
        ("##S_DIAGNOSIS_YEAR##", "Subject's year of diagnosis", ""),
        ("##S_MPOWER_ID##", "Subject's mPower identifier", ""),
        ("##S_ND_NUMBER##", "Subject's ND number", ""),
        ("##S_DATE_ADDED##", "Subject's date of creation", now.strftime(DATE_FORMAT_SHORT)),
    ]

    MAILS_TEMPLATE_VISIT_TAGS = [
        ("##V_DATE_START_FULL##", "Visit's start date", now.strftime(DATETIME_FORMAT)),
        ("##V_DATE_START_SHORT##", "Visit's start date", now.strftime(DATE_FORMAT_SHORT)),
        ("##V_DATE_ENDS_FULL##", "Visit's end date", now.strftime(DATETIME_FORMAT)),
        ("##V_DATE_ENDS_SHORT##", "Visit's end date", now.strftime(DATE_FORMAT_SHORT)),
    ]

    MAILS_TEMPLATE_APPOINTMENT_TAGS = [
        ("##A_DATE_FULL##", "Appointment's date and time", now.strftime(DATETIME_FORMAT)),
        ("##A_DATE_SHORT##", "Appointment's date", now.strftime(DATE_FORMAT_SHORT)),
        ("##A_TIME##", "Appointment's time", now.strftime(DATE_FORMAT_TIME)),
        ("##A_FLYING_TEAM##", "Appointment's flying team location", ""),
        ("##A_LOCATION##", "Appointment's location", "value can be 'Flying Team'"),
        ("##A_LOCATION_OR_FLYINGTEAM##", "Appointment's real location",
         "if flying team then returns flying team exact location, otherwise returns location name"),
        ("##A_STATUS##", "Appointment's status", ""),
        ("##A_WORKER##", "Worker conducting the assessment", "first_name last_name"),
        ("##A_WORKER_PHONE##", "Phone number of the worker conducting the assessment", ""),
        ("##A_WORKER_EMAIL##", "Email address of the worker conducting the assessment", ""),
        ("##A_ROOM##", "Appointment's room", 'room_number address city'),
        ("##A_LENGTH##", "Appointment's duration", 'integer, value in minutes'),
        ("##A_TYPES##", "Appointment's types", "comma separated"),
    ]

    name = models.CharField(max_length=255)
    context = models.CharField(max_length=1, choices=MAIL_TEMPLATE_CONTEXT_CHOICES)
    language = models.ForeignKey("web.Language", on_delete=models.CASCADE)
    template_file = models.FileField(upload_to='templates/')

    @staticmethod
    def get_appointment_mail_templates(languages):
        return MailTemplate.get_mail_templates_for_context(languages, MAIL_TEMPLATE_CONTEXT_APPOINTMENT)

    @staticmethod
    def get_subject_mail_templates(languages):
        return MailTemplate.get_mail_templates_for_context(languages, MAIL_TEMPLATE_CONTEXT_SUBJECT)

    @staticmethod
    def get_visit_mail_templates(languages):
        return MailTemplate.get_mail_templates_for_context(languages, MAIL_TEMPLATE_CONTEXT_VISIT)

    @staticmethod
    def get_mail_templates_for_context(languages, context):
        languages_names = [language.name for language in languages]
        templates = list(MailTemplate.objects.filter(context=context).all())
        active_templates = []
        disabled_templates = []
        for template in templates:
            if template.language.name in languages_names:
                active_templates.append(template)
            else:
                disabled_templates.append(template)
        active_templates.sort(key=lambda x: languages_names.index(x.language.name))
        return active_templates, disabled_templates

    def apply(self, instance, user, stream):
        appointment = None
        visit = None
        subject = None
        if isinstance(instance, Appointment):
            appointment = instance
            visit = instance.visit
            subject = visit.subject
        elif isinstance(instance, Visit):
            visit = instance
            subject = visit.subject
        elif isinstance(instance, Subject):
            subject = instance
        # set locale to get correct date format
        with setlocale(self.language.locale.encode('utf8')):
            replacements = {}
            self._add_generic_replacements(replacements, Worker.get_by_user(user))
            self._add_appointment_replacements(replacements, appointment)
            self._add_visit_replacements(replacements, visit)
            self._add_subject_replacements(replacements, subject)
            process_file(self.template_file.path, stream, replacements)
        return stream

    def _add_generic_replacements(self, replacements, worker):
        current_datetime = datetime.datetime.now()
        replacements.update({
            "##DATE_FULL##": current_datetime.strftime(DATE_FORMAT_FULL),
            "##DATE_SHORT##": current_datetime.strftime(DATE_FORMAT_SHORT),
            "##WORKER##": str(worker)
        })

    def _add_appointment_replacements(self, replacements, appointment):
        if appointment is not None:
            if appointment.worker_assigned is not None:
                worker_phone_number = appointment.worker_assigned.phone_number
                worker_email_address = appointment.worker_assigned.email
            else:
                worker_phone_number = ""
                worker_email_address = ""
            if appointment.datetime_when is not None:
                appointment_date_full = appointment.datetime_when.strftime(DATETIME_FORMAT)
                appointment_date_short = appointment.datetime_when.strftime(DATE_FORMAT_SHORT)
                appointment_date_time = appointment.datetime_when.strftime(DATE_FORMAT_TIME)
            else:
                appointment_date_full = appointment_date_short = appointment_date_time = ""
            replacements.update({
                "##A_DATE_FULL##": appointment_date_full,
                "##A_DATE_SHORT##": appointment_date_short,
                "##A_TIME##": appointment_date_time,
                "##A_FLYING_TEAM##": appointment.flying_team,
                "##A_STATUS##": appointment.get_status_display(),
                "##A_LOCATION##": appointment.location.name,
                "##A_LOCATION_OR_FLYINGTEAM##": appointment.flying_team or appointment.location.name,
                "##A_WORKER##": str(appointment.worker_assigned),
                '##A_WORKER_PHONE##': worker_phone_number,
                '##A_WORKER_EMAIL##': worker_email_address,
                "##A_ROOM##": str(appointment.room),
                "##A_LENGTH##": appointment.length,
                "##A_TYPES##": ", ".join([a.description for a in appointment.appointment_types.all()])
            })

    def _add_visit_replacements(self, replacements, visit):
        if visit is not None:
            replacements.update({
                "##V_DATE_START_FULL##": visit.datetime_begin.strftime(DATETIME_FORMAT),
                "##V_DATE_START_SHORT##": visit.datetime_begin.strftime(DATE_FORMAT_SHORT),
                "##V_DATE_ENDS_FULL##": visit.datetime_end.strftime(DATETIME_FORMAT),
                "##V_DATE_ENDS_SHORT##": visit.datetime_end.strftime(DATE_FORMAT_SHORT),
            })

    def _add_subject_replacements(self, replacements, subject):
        if subject is not None:
            if subject.date_born is not None:
                date_born = subject.date_born.strftime(DATE_FORMAT_SHORT)
            else:
                date_born = None
            replacements.update({
                "##S_FULL_NAME##": str(subject),
                "##S_FIRST_NAME##": subject.first_name,
                "##S_LAST_NAME##": subject.last_name,
                "##S_ADDRESS##": subject.address,
                "##S_CITY##": subject.city,
                "##S_COUNTRY##": subject.country,
                "##S_DIAGNOSIS_YEAR##": subject.year_of_diagnosis,
                "##S_DATE_ADDED##": subject.date_added.strftime(DATE_FORMAT_SHORT),
                "##S_DATE_BORN##": date_born,
                "##S_DIAGNOSIS##": subject.diagnosis,
                "##S_EMAIL##": subject.email,
                "##S_SEX##": subject.get_sex_display(),
                "##S_MPOWER_ID##": subject.mpower_id,
                "##S_ND_NUMBER##": subject.nd_number,
                "##S_PHONE_NUMBER##": subject.phone_number,
                "##S_PHONE_NUMBER_2##": subject.phone_number_2,
                "##S_PHONE_NUMBER_3##": subject.phone_number_3,
                "##S_POST_CODE##": subject.postal_code,
                "##S_SCREENING_NUMBER##": subject.screening_number,
                "##S_TYPE##": subject.get_type_display(),
                '##S_MAIL_LANGUAGE##': subject.default_written_communication_language,
                '##S_KNOWN_LANGUAGES##': ", ".join([l.name for l in subject.languages.all()])
            })