WMDE
/
eva
forked from tohe/eva
7
1
Fork 0
eva/austritt/views.py

266 lines
10 KiB
Python

from smtplib import SMTPException
import collections
from xhtml2pdf import pisa
from django.views.generic.edit import CreateView
from django.views import View
from django.urls import reverse
from django.http import HttpResponse, HttpResponseRedirect
from django.core.mail import send_mail, BadHeaderError
from django.template.loader import get_template, render_to_string
from formtools.wizard.views import CookieWizardView
from django.shortcuts import render
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils.translation import gettext_lazy as _
from .models import Employee, DEPARTMENT_CHOICES, OS_CHOICES, \
LANG_CHOICES, HARDWARE_CHOICES, TRANSPONDER_CHOICES, KEYBOARD_CHOICES, JANEIN_CHOICES
from .forms import PersonalForm, HRForm, ITForm, RestForm, DummyForm, TYPE_CHOICES
from .settings import MAILS, EVA_MAIL, BASIC_DATA, ONLY_ONBOARDING
def success(request):
return HttpResponse(f"Vielen Dank! Du hast E.V.A. erfolgreich ausgefüllt. Die Mails an die Abteilungen wurden versendet. Kopien gehen an {request.user.email}.")
def long_process(wizard):
'''this method is called via urls.py to determine if a form is part of the IN-Process'''
if ONLY_ONBOARDING:
wizard.set_choice('IN')
return True
else:
data = wizard.get_cleaned_data_for_step('0') or {}
# print(data)
if data.get('choice') != 'CHANGE':
wizard.set_choice('IN')
# print('PROZESS IN')
return True
else:
wizard.set_choice('CHANGE')
# print('PROZESS NOT IN')
return False
def change_process(wizard):
''' this method is called via urls.py to determine if the form is part of the change process'''
# print('CHANGE PROZESS')
return not long_process(wizard)
def beautify_data_pdf(data):
# Function for displaying the form items in correct order for handover pdf
hardware = data.get('hardware', [])
choices_dict = dict(ITForm.base_fields['hardware'].choices)
selected_hardware = [choices_dict[val] for val in hardware]
return {
'firstname': data.get('firstname', ''),
'lastname': data.get('lastname', ''),
'laptop_id': data.get('laptop_id', ''),
'hardware': selected_hardware,
'mobile': data.get('mobile', ''),
'credit_card': data.get('credit_card', ''),
'sim': data.get('sim', ''),
'transponder_id': data.get('transponder_id', ''),
'pension': data.get('pension', ''),
'miscellaneous': data.get('miscellaneous', ''),
'bahncard': data.get('bahncard', ''),
}
class EvaFormView(LoginRequiredMixin, CookieWizardView):
template_name = 'austritt/employee_form.html'
form_list = [PersonalForm, HRForm, ITForm, RestForm, DummyForm, DummyForm, DummyForm]
instance = None
choice = 'IN'
# maybe we dont need this, if *_process() would be class methods,
# but unsure if this would work fine with the entries in urls.py
def set_choice(self, c):
self.choice = c
def generate_email(self, data):
(first, *_) = data['firstname'].split(maxsplit=1)
(last, *_) = data['lastname'].split(maxsplit=1)
name = first + '.' + last
#if not data['intern']:
# mail = name + '_ext@wikimedia.de'
#else:
mail = name + '@wikimedia.de'
data['email'] = mail
def get_all_cleaned_data(self):
'''this method deletes data which is only used temporary and is not in the modell,
it also changes the mail adress of the employee in some circumstances'''
data = super().get_all_cleaned_data()
self.generate_email(data)
# print("delete CHOICE FROM DATA")
if 'choice' in data:
del data['choice']
return data
def get_context_data(self, form, **kwargs):
'''this method is called to give context data to the template'''
#print('GETCONTEXT')
context = super().get_context_data(form=form, **kwargs)
testmode = settings.DEBUG or settings.MAILTEST
context.update({'choice': self.choice,
'choice_string': TYPE_CHOICES[self.choice],
'TESTMODE': testmode})
# six steps for testing purposes ONLY!!
# deliver context for forms if we are in the last step
if (self.steps.step1 == 6 or (self.choice != 'IN' and self.steps.step1 == 6)):
context.update({'data': self.beautify_data(self.get_all_cleaned_data()),
'datatable': 1,})
if (self.steps.step1 == 5):
pdf_data = beautify_data_pdf(self.get_all_cleaned_data())
# storing for PDF class
self.request.session['pdf_data'] = pdf_data
self.request.session.modified = True #forcing session saving
context.update({'pdf_data': pdf_data,})
return context
def get_form_instance(self,step):
''' this method assures, that we use the same model instance for all steps'''
if self.instance == None:
self.instance = Employee()
return self.instance
def done(self, form_list, **kwargs):
'''this method is called from CookieWizardView after all forms are filled'''
print ('INSTANCE_DICT')
print(self.instance_dict)
# save data to database
for form in form_list:
form.save()
# send data to departments
for dep in MAILS:
response = self.send_mail_to_department(dep)
if not settings.DEBUG:
self.instance.delete()
if response:
return response
else:
return HttpResponseRedirect('success')
def send_mail_to_department(self, department):
'send a mail to the given department with the nececcary notifications'
print(f'send mail to department {department}...')
contact = self.request.user.email
data = self.get_all_cleaned_data()
# some data should be in every mail
newdata = {k: v for k, v in data.items() if (k in BASIC_DATA)}
# only the relevant data should be in the context
newdata.update({k: v for k, v in data.items() if (k in MAILS[department]['DATA'])})
context = {'data': self.beautify_data(newdata), 'contact': contact}
firstname = data['firstname']
lastname = data['lastname']
lastday = data['lastdate_employment']
try:
mail_template = get_template(f'austritt/department_mail.txt')
if settings.MAILTEST:
send_mail(
f'EVA: Austritt {firstname} {lastname} {lastday} (MAILTEST)',
mail_template.render(context),
EVA_MAIL,
[EVA_MAIL],
fail_silently=False)
elif department != "SUBMITTER":
send_mail(
f'EVA: Austritt {firstname} {lastname} {lastday}',
mail_template.render(context),
EVA_MAIL,
[MAILS[department]['MAIL']],
fail_silently=False)
else:
send_mail(
f'EVA: Austritt {firstname} {lastname} {lastday}',
mail_template.render(context),
EVA_MAIL,
[contact],
fail_silently=False)
except BadHeaderError as error:
print(error)
self.instance.delete()
return HttpResponse(f'{error}<p>Invalid header found. Data not saved!')
except SMTPException as error:
print(error)
self.instance.delete()
return HttpResponse(f'{error}<p>Error in sending mails (probably wrong adress?). Data not saved!')
except Exception as error:
print(error)
# self.instance.delete()
return HttpResponse(f'{error}<p>Error in sending mails. Data not saved! Please contact ' + EVA_MAIL)
return False
def beautify_data(self, data):
''' # use long form for contextdata instead of short form if available
#
# ATTENTION!
# This implementation works only for unique keys over all of these dicts from model.py
#
'''
# update values in data dictionary with keys from *_CHOICES if present there
choices = {**DEPARTMENT_CHOICES, **TRANSPONDER_CHOICES,
**OS_CHOICES, **LANG_CHOICES, **KEYBOARD_CHOICES}
data.update({k:choices[v] for k,v in data.items() \
if isinstance(v,collections.abc.Hashable) \
and v in choices})
# replace values in accounts array from *_CHOICES
if 'accounts' in data:
data['accounts'] = [ACCOUNT_CHOICES[c] for c in data['accounts']]
# replace keys in data dictionary with verbose_name
# a bit ugly workaround here: we need to store 'email' away, because it es not in the modell
mail = ''
if 'email' in data:
mail = data.pop('email')
newdata = {self.instance._meta.get_field(k).verbose_name.title() : v for k,v in data.items()}
if mail:
newdata['Email'] = mail
# translate booleans
newdata.update({k:'Ja' for k,v in newdata.items() if isinstance(v,bool) and v == True})
newdata.update({k:'Nein' for k,v in newdata.items() if isinstance(v,bool) and v == False})
# handle some special data types
newdata.update({k:'' for k,v in newdata.items() if v == None})
newdata.update({k:'' for k,v in newdata.items() if v == []})
return newdata
# Class for rendering PDf
class PDFPreviewView(LoginRequiredMixin, View):
def get(self, request):
pdf_data=request.session.get('pdf_data')
#getting names for pdf file naming
firstname = pdf_data.get('firstname')
lastname = pdf_data.get('lastname')
context ={'pdf_data': pdf_data}
html_string =render_to_string('austritt/pdf_template.html', context)
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition']=f'inline; filename="Rueckgabe_Arbeitsmittel_{firstname}_{lastname}.pdf"'
pisa.CreatePDF(html_string, dest=response)
return response