# coding=utf-8 import datetime import locale import platform 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 locale_name = self.language.locale if platform.system() == 'Windows': locale_name = self.language.windows_locale_name with setlocale(locale_name.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##": unicode(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##": str(appointment.flying_team), "##A_STATUS##": appointment.get_status_display(), "##A_LOCATION##": appointment.location.name, "##A_LOCATION_OR_FLYINGTEAM##": str(appointment.flying_team) or appointment.location.name, "##A_WORKER##": unicode(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##": unicode(subject), "##S_FIRST_NAME##": subject.first_name, "##S_LAST_NAME##": subject.last_name, "##S_ADDRESS##": subject.address, "##S_CITY##": subject.city, "##S_COUNTRY##": unicode(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##': str(subject.default_written_communication_language), '##S_KNOWN_LANGUAGES##': ", ".join([l.name for l in subject.languages.all()]) })