2025-04-14 08:34:30 +00:00
from smtplib import SMTPException
import collections
from django . views . generic . edit import CreateView
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
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 , ACCOUNT_CHOICES , TRANSPONDER_CHOICES , KEYBOARD_CHOICES , JANEIN_CHOICES
from . forms import PersonalForm , WorkingForm , ITForm , OfficeForm , DummyForm , \
ChangeForm , 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 )
class EvaFormView ( LoginRequiredMixin , CookieWizardView ) :
2025-04-29 06:33:15 +00:00
template_name = ' veraenderung/employee_form.html '
2025-04-14 08:34:30 +00:00
form_list = [ PersonalForm , WorkingForm , ITForm , OfficeForm , ChangeForm , 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 } )
# deliver context for forms if we are in the last step
if ( self . steps . step1 == 5 or ( self . choice != ' IN ' and self . steps . step1 == 3 ) ) :
context . update ( { ' data ' : self . beautify_data ( self . get_all_cleaned_data ( ) ) ,
' datatable ' : True , } )
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 ' ]
firstday = data [ ' firstdate_employment ' ]
try :
mail_template = get_template ( f ' evapp/department_mail.txt ' )
if settings . MAILTEST :
send_mail (
f ' EVA: Neuzugang { firstname } { lastname } { firstday } (MAILTEST) ' ,
mail_template . render ( context ) ,
EVA_MAIL ,
[ EVA_MAIL ] ,
fail_silently = False )
elif department != " SUBMITTER " :
send_mail (
f ' EVA: Neuzugang { firstname } { lastname } { firstday } ' ,
mail_template . render ( context ) ,
EVA_MAIL ,
[ MAILS [ department ] [ ' MAIL ' ] ] ,
fail_silently = False )
else :
send_mail (
f ' EVA: Neuzugang { firstname } { lastname } { firstday } ' ,
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 (propably 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