From d2d470442e9efd9aac6b89d95516004d167c6bd3 Mon Sep 17 00:00:00 2001 From: ayachebaane Date: Mon, 14 Apr 2025 10:34:30 +0200 Subject: [PATCH] add new files --- eva/settings_development.py | 4 + eva/urls.py | 5 +- evapp/admin.py | 4 + evapp/apps.py | 4 +- evapp/forms.py | 6 +- .../0007_remove_employee_screen_and_more.py | 32 +++ evapp/static/evapp/offboarding.png | Bin 0 -> 100969 bytes evapp/static/evapp/onboarding1.png | Bin 0 -> 17344 bytes evapp/static/evapp/veränderung.png | Bin 0 -> 23430 bytes evapp/templates/account/login.html | 10 + evapp/templates/evapp/employee_form.html | 5 +- evapp/views.py | 2 +- home/__init__.py | 0 home/admin.py | 3 + home/apps.py | 9 + home/migrations/__init__.py | 0 home/models.py | 3 + home/templates/home/index.html | 97 ++++++++ home/tests.py | 3 + home/urls.py | 9 + home/views.py | 15 ++ offboarding/__init__.py | 0 offboarding/admin.py | 6 + offboarding/apps.py | 5 + offboarding/forms.py | 67 ++++++ offboarding/migrations/0001_initial.py | 46 ++++ .../migrations/0002_auto_20210914_1055.py | 18 ++ .../migrations/0003_auto_20220208_0955.py | 28 +++ ...oyee_accounts_alter_employee_department.py | 24 ++ .../0005_alter_employee_accounts.py | 19 ++ ...oyee_vendor_employee_framework_and_more.py | 32 +++ .../0007_remove_employee_screen_and_more.py | 32 +++ offboarding/migrations/__init__.py | 0 offboarding/models.py | 86 +++++++ offboarding/settings.py | 61 +++++ offboarding/static/evapp/logo.png | Bin 0 -> 5872 bytes offboarding/templates/account/login.html | 27 +++ .../templates/offboarding/dataloop.txt | 5 + .../templates/offboarding/department_mail.txt | 31 +++ .../templates/offboarding/employee_form.html | 110 +++++++++ offboarding/templates/registration/login.html | 35 +++ offboarding/tests.py | 127 ++++++++++ offboarding/urls.py | 13 ++ offboarding/views.py | 217 ++++++++++++++++++ settings.py | 1 + veränderung/__init__.py | 0 veränderung/admin.py | 6 + veränderung/apps.py | 5 + veränderung/forms.py | 67 ++++++ veränderung/migrations/0001_initial.py | 46 ++++ .../migrations/0002_auto_20210914_1055.py | 18 ++ .../migrations/0003_auto_20220208_0955.py | 28 +++ ...oyee_accounts_alter_employee_department.py | 24 ++ .../0005_alter_employee_accounts.py | 19 ++ ...oyee_vendor_employee_framework_and_more.py | 32 +++ .../0007_remove_employee_screen_and_more.py | 32 +++ veränderung/migrations/__init__.py | 0 veränderung/models.py | 86 +++++++ veränderung/settings.py | 61 +++++ veränderung/static/evapp/logo.png | Bin 0 -> 5872 bytes veränderung/templates/account/login.html | 27 +++ .../templates/registration/login.html | 35 +++ .../templates/veränderung/dataloop.txt | 5 + .../veränderung/department_mail.txt | 31 +++ .../templates/veränderung/employee_form.html | 110 +++++++++ veränderung/tests.py | 127 ++++++++++ veränderung/urls.py | 13 ++ veränderung/views.py | 217 ++++++++++++++++++ 68 files changed, 2182 insertions(+), 8 deletions(-) create mode 100644 evapp/migrations/0007_remove_employee_screen_and_more.py create mode 100644 evapp/static/evapp/offboarding.png create mode 100644 evapp/static/evapp/onboarding1.png create mode 100644 evapp/static/evapp/veränderung.png create mode 100644 home/__init__.py create mode 100644 home/admin.py create mode 100644 home/apps.py create mode 100644 home/migrations/__init__.py create mode 100644 home/models.py create mode 100644 home/templates/home/index.html create mode 100644 home/tests.py create mode 100644 home/urls.py create mode 100644 home/views.py create mode 100644 offboarding/__init__.py create mode 100644 offboarding/admin.py create mode 100644 offboarding/apps.py create mode 100644 offboarding/forms.py create mode 100644 offboarding/migrations/0001_initial.py create mode 100644 offboarding/migrations/0002_auto_20210914_1055.py create mode 100644 offboarding/migrations/0003_auto_20220208_0955.py create mode 100644 offboarding/migrations/0004_alter_employee_accounts_alter_employee_department.py create mode 100644 offboarding/migrations/0005_alter_employee_accounts.py create mode 100644 offboarding/migrations/0006_remove_employee_vendor_employee_framework_and_more.py create mode 100644 offboarding/migrations/0007_remove_employee_screen_and_more.py create mode 100644 offboarding/migrations/__init__.py create mode 100644 offboarding/models.py create mode 100644 offboarding/settings.py create mode 100644 offboarding/static/evapp/logo.png create mode 100644 offboarding/templates/account/login.html create mode 100644 offboarding/templates/offboarding/dataloop.txt create mode 100644 offboarding/templates/offboarding/department_mail.txt create mode 100644 offboarding/templates/offboarding/employee_form.html create mode 100644 offboarding/templates/registration/login.html create mode 100644 offboarding/tests.py create mode 100644 offboarding/urls.py create mode 100644 offboarding/views.py create mode 120000 settings.py create mode 100644 veränderung/__init__.py create mode 100644 veränderung/admin.py create mode 100644 veränderung/apps.py create mode 100644 veränderung/forms.py create mode 100644 veränderung/migrations/0001_initial.py create mode 100644 veränderung/migrations/0002_auto_20210914_1055.py create mode 100644 veränderung/migrations/0003_auto_20220208_0955.py create mode 100644 veränderung/migrations/0004_alter_employee_accounts_alter_employee_department.py create mode 100644 veränderung/migrations/0005_alter_employee_accounts.py create mode 100644 veränderung/migrations/0006_remove_employee_vendor_employee_framework_and_more.py create mode 100644 veränderung/migrations/0007_remove_employee_screen_and_more.py create mode 100644 veränderung/migrations/__init__.py create mode 100644 veränderung/models.py create mode 100644 veränderung/settings.py create mode 100644 veränderung/static/evapp/logo.png create mode 100644 veränderung/templates/account/login.html create mode 100644 veränderung/templates/registration/login.html create mode 100644 veränderung/templates/veränderung/dataloop.txt create mode 100644 veränderung/templates/veränderung/department_mail.txt create mode 100644 veränderung/templates/veränderung/employee_form.html create mode 100644 veränderung/tests.py create mode 100644 veränderung/urls.py create mode 100644 veränderung/views.py diff --git a/eva/settings_development.py b/eva/settings_development.py index fd37a2e..55986d6 100644 --- a/eva/settings_development.py +++ b/eva/settings_development.py @@ -39,6 +39,9 @@ ALLOWED_HOSTS = ['*'] # Application definition INSTALLED_APPS = [ + 'home', + 'offboarding', + 'veränderung', 'evapp.apps.EvappConfig', 'django.contrib.admin', 'django.contrib.auth', @@ -160,3 +163,4 @@ ACCOUNT_EMAIL_VERIFICATION = 'none' # ACCOUNT_EMAIL_REQUIRED = True LOGIN_REDIRECT_URL = 'home' ACCOUNT_LOGOUT_ON_GET = True +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/eva/urls.py b/eva/urls.py index 0cc51da..49ac613 100644 --- a/eva/urls.py +++ b/eva/urls.py @@ -17,7 +17,10 @@ from django.contrib import admin from django.urls import path, include urlpatterns = [ - path('', include("evapp.urls")), + path('onboarding/', include('evapp.urls')), + path('', include("home.urls")), + path('offboarding/', include("offboarding.urls")), + path('veränderung/', include("veränderung.urls")), path('admin/', admin.site.urls), path('accounts/', include('allauth.urls')), diff --git a/evapp/admin.py b/evapp/admin.py index 067bbae..c467c22 100644 --- a/evapp/admin.py +++ b/evapp/admin.py @@ -1,6 +1,10 @@ +# import Django´s admin interface module from django.contrib import admin +# import the Employee model from the current app from .models import Employee +# Register the Employee model with the Django admin site +# This makes the Employee model manageable through the admin interface admin.site.register([ Employee, ]) diff --git a/evapp/apps.py b/evapp/apps.py index b9f0e6d..d5ded80 100644 --- a/evapp/apps.py +++ b/evapp/apps.py @@ -1,5 +1,7 @@ +# import django´s base AppConfig class from django.apps import AppConfig - +# define the configuration class for the 'evapp' application class EvappConfig(AppConfig): + # give the app a name name = 'evapp' diff --git a/evapp/forms.py b/evapp/forms.py index 662df53..1239e19 100644 --- a/evapp/forms.py +++ b/evapp/forms.py @@ -22,15 +22,13 @@ class EvaForm(ModelForm): TYPE_CHOICES = {'IN': 'Eintritt', 'CHANGE': 'Veränderung', 'OUT': 'Austritt'} +# Form to capture basic personal and department-related information class PersonalForm(EvaForm): - # TODO: comment this back in to use implementation of change or exit process - # choice = ChoiceField(choices=TYPE_CHOICES.items(), widget=RadioSelect, - # label='Welcher Prozess soll angestoßen werden?') class Meta: model = Employee fields = ['firstname', 'lastname', 'department', 'team', 'add_to_wikimediade',] - +# Form to capture working conditions and job description class WorkingForm(EvaForm): def clean(self): diff --git a/evapp/migrations/0007_remove_employee_screen_and_more.py b/evapp/migrations/0007_remove_employee_screen_and_more.py new file mode 100644 index 0000000..87124e9 --- /dev/null +++ b/evapp/migrations/0007_remove_employee_screen_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 4.2.17 on 2024-12-17 14:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0006_remove_employee_vendor_employee_framework_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='employee', + name='screen', + ), + migrations.AlterField( + model_name='employee', + name='add_to_wikimediade', + field=models.CharField(choices=[('NEIN', 'Nein'), ('JA', 'Ja')], max_length=5, verbose_name='Soll die Person bei Ansprechpartner*innen auf der WMDE-Webseite mit aufgenommen werden?'), + ), + migrations.AlterField( + model_name='employee', + name='framework', + field=models.CharField(blank=True, max_length=300, null=True, verbose_name='Möchten Sie vom Standard des Frameworks (Laptop) abweichen, und wenn ja, warum?'), + ), + migrations.AlterField( + model_name='employee', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/evapp/static/evapp/offboarding.png b/evapp/static/evapp/offboarding.png new file mode 100644 index 0000000000000000000000000000000000000000..850a007279d7a7dd745ab21b51e341652df77467 GIT binary patch literal 100969 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
!A?m)qiP9Bs4T~wv_?PZ+ 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 HQ$iB}OumUp literal 0 HcmV?d00001 diff --git a/evapp/static/evapp/veränderung.png b/evapp/static/evapp/veränderung.png new file mode 100644 index 0000000000000000000000000000000000000000..1d7542ffff948941244494ac4c5149f82e67e814 GIT binary patch literal 23430 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 + + {{ form.media }} + @@ -14,12 +19,17 @@ {% block content %}
+ + +

E (V A) - Eintritt, (Veränderung, Austritt)

+ Bitte via Wolke einloggen: + {% include "socialaccount/snippets/provider_list.html" with process="login" %}
diff --git a/evapp/templates/evapp/employee_form.html b/evapp/templates/evapp/employee_form.html index 9df6037..34944b2 100644 --- a/evapp/templates/evapp/employee_form.html +++ b/evapp/templates/evapp/employee_form.html @@ -38,6 +38,7 @@

E (V A) - Eintritt, (Veränderung, Austritt)

{% translate "Du bist eingeloggt als" %} {{ user.email }} +

{% translate "Schritt" %} {{ wizard.steps.step1 }} {% translate "von" %} {{ wizard.steps.count }}

{% if wizard.steps.step1 == 1 %} @@ -60,13 +61,15 @@ {% endif %}

+ {% if datatable == True %} - +
{% for key, value in data.items %} {% endfor %}
{{ key }}{{ value }}
{% endif %} +
{% csrf_token %} diff --git a/evapp/views.py b/evapp/views.py index 6da4f7a..67097f3 100644 --- a/evapp/views.py +++ b/evapp/views.py @@ -189,7 +189,7 @@ class EvaFormView(LoginRequiredMixin, CookieWizardView): # update values in data dictionary with keys from *_CHOICES if present there choices = {**DEPARTMENT_CHOICES, **TRANSPONDER_CHOICES, - **OS_CHOICES, **LANG_CHOICES, **VENDOR_CHOICES, **KEYBOARD_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}) diff --git a/home/__init__.py b/home/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/home/admin.py b/home/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/home/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/home/apps.py b/home/apps.py new file mode 100644 index 0000000..75167e0 --- /dev/null +++ b/home/apps.py @@ -0,0 +1,9 @@ +# import django´s base Appconfig class +from django.apps import AppConfig + +# configuration class for the 'home' application +class HomeConfig(AppConfig): + # set the default type of primary key field for models in this app + default_auto_field = 'django.db.models.BigAutoField' + # give the application a name + name = 'home' diff --git a/home/migrations/__init__.py b/home/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/home/models.py b/home/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/home/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/home/templates/home/index.html b/home/templates/home/index.html new file mode 100644 index 0000000..df32d03 --- /dev/null +++ b/home/templates/home/index.html @@ -0,0 +1,97 @@ + +{% load i18n %} +{% load static %} + + + + + Button Navigation + + + +

Choose Your Destination

+
+ +
+ + + +
+ +
+ + +
+ +
+ + +
+ +
+ + + + + diff --git a/home/tests.py b/home/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/home/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/home/urls.py b/home/urls.py new file mode 100644 index 0000000..d4d8f55 --- /dev/null +++ b/home/urls.py @@ -0,0 +1,9 @@ +# home/urls.py + +from django.urls import path +from . import views # import views from the current app + +# Define the URL patterns for the 'home' app +urlpatterns = [ + path('', views.index, name='home-index'), # Map the URL '' to the index view with the name 'home-index' +] \ No newline at end of file diff --git a/home/views.py b/home/views.py new file mode 100644 index 0000000..7a10a70 --- /dev/null +++ b/home/views.py @@ -0,0 +1,15 @@ +from django.shortcuts import render + +# Create your views here. +# Import the render function from Django to render templates +from django.shortcuts import render + +def index(request): + # Context dictionary to pass dynamic data to the template + context = { + 'title': 'Welcome to Pycouse!', + 'author': 'Brian', + } + # Render the 'index.html' template located in the 'home' directory + # Pass the context dictionary to the template for dynamic content + return render(request, 'home/index.html', context) \ No newline at end of file diff --git a/offboarding/__init__.py b/offboarding/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/offboarding/admin.py b/offboarding/admin.py new file mode 100644 index 0000000..067bbae --- /dev/null +++ b/offboarding/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from .models import Employee + +admin.site.register([ + Employee, + ]) diff --git a/offboarding/apps.py b/offboarding/apps.py new file mode 100644 index 0000000..4f4a80f --- /dev/null +++ b/offboarding/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class EvappConfig(AppConfig): + name = 'offboarding' diff --git a/offboarding/forms.py b/offboarding/forms.py new file mode 100644 index 0000000..662df53 --- /dev/null +++ b/offboarding/forms.py @@ -0,0 +1,67 @@ +from django.db import models +from django.forms import ModelForm, DateInput, Form, ChoiceField, RadioSelect +from django.core.exceptions import ValidationError + +from .models import Employee + +# class EmployeeForm(ModelForm): +# class Meta: +# model = Employee +# fields = '__all__' +# widgets = {'firstdate_employment': DateInput(attrs={'type': 'date'}), +# 'firstdate_presence': DateInput(attrs={'type': 'date'}),} + +class DummyForm(ModelForm): + class Meta: + model = Employee + fields = [] + +class EvaForm(ModelForm): + '''this base class provides the required css class for all forms''' + required_css_class = 'required' + +TYPE_CHOICES = {'IN': 'Eintritt', 'CHANGE': 'Veränderung', 'OUT': 'Austritt'} + +class PersonalForm(EvaForm): + # TODO: comment this back in to use implementation of change or exit process + # choice = ChoiceField(choices=TYPE_CHOICES.items(), widget=RadioSelect, + # label='Welcher Prozess soll angestoßen werden?') + + class Meta: + model = Employee + fields = ['firstname', 'lastname', 'department', 'team', 'add_to_wikimediade',] + +class WorkingForm(EvaForm): + + def clean(self): + data = self.cleaned_data + if data['works_in_gs'] and data['desk'] is None: + raise ValidationError('Wer nicht remote arbeitet braucht einen Schreibtisch!') + return data + + class Meta: + model = Employee + fields = ['firstdate_employment', 'firstdate_presence', 'jobdescription_german', + 'jobdescription_english', 'works_in_gs', 'desk',] + widgets = {'firstdate_employment': DateInput(attrs={'type': 'date'}), + 'firstdate_presence': DateInput(attrs={'type': 'date'}),} + +class ITForm(EvaForm): + + class Meta: + model = Employee + fields = [ + 'framework', 'os', 'keyboard', 'mobile', 'landline', + 'comment', 'language', 'accounts', 'lists', 'rebu2go' ] + +class OfficeForm(EvaForm): + class Meta: + model = Employee + fields = ['transponder', 'special', 'post_office_box',] + +class ChangeForm(EvaForm): + class Meta: + model = Employee + fields = ['firstdate_employment', 'jobdescription_german', 'jobdescription_english', + 'desk', 'comment', 'accounts', 'lists', 'transponder'] + widgets = {'firstdate_employment': DateInput(attrs={'type': 'date'}),} diff --git a/offboarding/migrations/0001_initial.py b/offboarding/migrations/0001_initial.py new file mode 100644 index 0000000..8ec82ff --- /dev/null +++ b/offboarding/migrations/0001_initial.py @@ -0,0 +1,46 @@ +# Generated by Django 3.1.4 on 2021-09-13 12:41 + +from django.db import migrations, models +import multiselectfield.db.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Employee', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('firstname', models.CharField(max_length=50, verbose_name='Vorname')), + ('lastname', models.CharField(max_length=50, verbose_name='Nachname')), + ('department', models.CharField(choices=[('PROG', 'Programme'), ('SOFT', 'Softwareentwicklung'), ('CENT', 'Central'), ('VOR', 'Vorstand')], max_length=5, verbose_name='Bereich')), + ('team', models.CharField(blank=True, max_length=20, null=True)), + ('add_to_wikimediade', models.BooleanField(default=False, verbose_name='Soll auf wikimedia.de irgendwo stehen?')), + ('firstdate_employment', models.DateField(null=True, verbose_name='Erster Arbeitstag')), + ('firstdate_presence', models.DateField(null=True, verbose_name='Erster Tag der Anwesenheit in der Geschäftsstelle')), + ('jobdescription_german', models.CharField(max_length=100, null=True, verbose_name='Stellenbezeichnung(deutsch)')), + ('jobdescription_english', models.CharField(max_length=100, null=True, verbose_name='Job description(english)')), + ('remote', models.BooleanField(default=True, verbose_name='Braucht Arbeitsplatz in der Geschäftsstelle?')), + ('desk', models.CharField(blank=True, max_length=100, null=True, verbose_name='Wo soll der Arbeitsplatz sein?')), + ('vendor', models.CharField(choices=[('STANDARD', 'Dell Latitude'), ('LENOVO', 'Lenovo Thinkpad'), ('MAC', 'Mac (nur für Grafiker_innen)')], default='STANDARD', max_length=8, verbose_name='Hersteller')), + ('os', models.CharField(choices=[('UBU', 'Ubuntu (Standard)'), ('WIN', 'Windows (bitte Begründung angeben)'), ('MOS', 'Mac OS (nur wenn Mac gewählt)')], default='UBU', max_length=3, verbose_name='Betriebssystem')), + ('screen', models.BooleanField(default=False, verbose_name='Zusätzlicher Monitor? Einer ist standard.')), + ('mobile', models.BooleanField(default=False, max_length=6, verbose_name='Diensttelefon (Handy)')), + ('landline', models.BooleanField(default=False, verbose_name='Festnetznummer (Sipgate)')), + ('keyboard', models.CharField(choices=[('DE', 'Deutsch'), ('US', 'USA'), ('OT', 'Anderes (Bitte unten angeben)')], default='DE', max_length=2, verbose_name='Tastaturlayout')), + ('comment', models.TextField(blank=True, max_length=500, null=True, verbose_name='zusätzliche IT-Anforderungen')), + ('language', models.CharField(choices=[('GER', 'Deutsch'), ('ENG', 'English')], default='GER', max_length=3, verbose_name='Sprache für Onboarding')), + ('accounts', multiselectfield.db.fields.MultiSelectField(blank=True, choices=[('OTRSWMDE', 'OTRS Ticketsystem'), ('CIVIC1', 'Civic CRM (allgemein)'), ('CIVIC2', 'Civic CRM (Mailings, impliziert allgemein)'), ('WEB', 'www.wikimedia.de (edit)'), ('BLOG', 'blog.wikimedia.de (edit)'), ('FORUM', 'forum.wikimedia.de')], max_length=37, null=True, verbose_name='Zusätzliche Accounts')), + ('lists', models.CharField(blank=True, max_length=100, null=True, verbose_name='Zusätzliche Mailinglisten')), + ('rebu2go', models.BooleanField(default=False, verbose_name='Rebu2Go-Zugang benötigt?')), + ('transponder', models.CharField(choices=[('NORM', 'Allgemeiner Transponder'), ('SPECIAL', 'Besondere Schließungen (bitte angeben)'), ('NOTRANS', 'Kein Transponder')], default='NORM', max_length=7)), + ('special', models.TextField(blank=True, max_length=500, null=True, verbose_name='Besondere Schließungen hier eintragen')), + ('post_office_box', models.BooleanField(default=True, verbose_name='Postfach am Empfang benötigt?')), + ], + ), + ] diff --git a/offboarding/migrations/0002_auto_20210914_1055.py b/offboarding/migrations/0002_auto_20210914_1055.py new file mode 100644 index 0000000..0797935 --- /dev/null +++ b/offboarding/migrations/0002_auto_20210914_1055.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.4 on 2021-09-14 10:55 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='employee', + old_name='remote', + new_name='works_in_gs', + ), + ] diff --git a/offboarding/migrations/0003_auto_20220208_0955.py b/offboarding/migrations/0003_auto_20220208_0955.py new file mode 100644 index 0000000..e91daf4 --- /dev/null +++ b/offboarding/migrations/0003_auto_20220208_0955.py @@ -0,0 +1,28 @@ +# Generated by Django 3.1.4 on 2022-02-08 09:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0002_auto_20210914_1055'), + ] + + operations = [ + migrations.AlterField( + model_name='employee', + name='department', + field=models.CharField(choices=[('PROG', 'Programme'), ('SOFT', 'Softwareentwicklung'), ('CENT', 'Central'), ('KOMEV', 'Kommunikation und Events'), ('VOR', 'Vorstand')], max_length=5, verbose_name='Bereich'), + ), + migrations.AlterField( + model_name='employee', + name='team', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='employee', + name='works_in_gs', + field=models.BooleanField(default=True, verbose_name='Braucht Arbeitsplatz in der Geschäftsstelle?)'), + ), + ] diff --git a/offboarding/migrations/0004_alter_employee_accounts_alter_employee_department.py b/offboarding/migrations/0004_alter_employee_accounts_alter_employee_department.py new file mode 100644 index 0000000..3456ec8 --- /dev/null +++ b/offboarding/migrations/0004_alter_employee_accounts_alter_employee_department.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2.4 on 2023-08-11 10:28 + +from django.db import migrations, models +import multiselectfield.db.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0003_auto_20220208_0955'), + ] + + operations = [ + migrations.AlterField( + model_name='employee', + name='accounts', + field=multiselectfield.db.fields.MultiSelectField(blank=True, choices=[('OTRSWMDE', 'OTRS Ticketsystem'), ('CIVIC1', 'Civic CRM (allgemein)'), ('CIVIC2', 'Civic CRM (Mailings, impliziert allgemein)'), ('WEB', 'www.wikimedia.de (edit)'), ('BLOG', 'blog.wikimedia.de (edit)'), ('FORUM', 'forum.wikimedia.de')], max_length=10, null=True, verbose_name='Zusätzliche Accounts'), + ), + migrations.AlterField( + model_name='employee', + name='department', + field=models.CharField(choices=[('COENG', 'Communitys & Engagement'), ('SOFT', 'Softwareentwicklung'), ('CENT', 'Central'), ('KOMAD', 'Kommunikation & Advocacy'), ('VOR', 'Vorstand')], max_length=5, verbose_name='Bereich'), + ), + ] diff --git a/offboarding/migrations/0005_alter_employee_accounts.py b/offboarding/migrations/0005_alter_employee_accounts.py new file mode 100644 index 0000000..ca42bb6 --- /dev/null +++ b/offboarding/migrations/0005_alter_employee_accounts.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.4 on 2023-08-17 11:08 + +from django.db import migrations +import multiselectfield.db.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0004_alter_employee_accounts_alter_employee_department'), + ] + + operations = [ + migrations.AlterField( + model_name='employee', + name='accounts', + field=multiselectfield.db.fields.MultiSelectField(blank=True, choices=[('OTRSWMDE', 'OTRS Ticketsystem'), ('CIVIC1', 'Civic CRM (allgemein)'), ('CIVIC2', 'Civic CRM (Mailings, impliziert allgemein)'), ('WEB', 'www.wikimedia.de (edit)'), ('BLOG', 'blog.wikimedia.de (edit)'), ('FORUM', 'forum.wikimedia.de')], max_length=40, null=True, verbose_name='Zusätzliche Accounts'), + ), + ] diff --git a/offboarding/migrations/0006_remove_employee_vendor_employee_framework_and_more.py b/offboarding/migrations/0006_remove_employee_vendor_employee_framework_and_more.py new file mode 100644 index 0000000..b34e5fd --- /dev/null +++ b/offboarding/migrations/0006_remove_employee_vendor_employee_framework_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 4.2.16 on 2024-11-26 09:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0005_alter_employee_accounts'), + ] + + operations = [ + migrations.RemoveField( + model_name='employee', + name='vendor', + ), + migrations.AddField( + model_name='employee', + name='framework', + field=models.CharField(blank=True, max_length=300, null=True, verbose_name='Möchten Sie vom Standard des Frameworks abweichen, und wenn ja, warum?'), + ), + migrations.AlterField( + model_name='employee', + name='add_to_wikimediade', + field=models.CharField(choices=[('NEIN', 'Nein'), ('JA', 'Ja')], default=True, max_length=5, verbose_name='Soll die Person bei Ansprechpartner*innen auf der WMDE-Webseite mit aufgenommen werden?'), + ), + migrations.AlterField( + model_name='employee', + name='os', + field=models.CharField(choices=[('FED', 'Fedora (Standard)'), ('WIN', 'Windows (bitte Begründung angeben)'), ('MOS', 'Mac OS (nur wenn Mac gewählt)'), ('UBU', 'Ubuntu')], default='FED', max_length=3, verbose_name='Betriebssystem'), + ), + ] diff --git a/offboarding/migrations/0007_remove_employee_screen_and_more.py b/offboarding/migrations/0007_remove_employee_screen_and_more.py new file mode 100644 index 0000000..87124e9 --- /dev/null +++ b/offboarding/migrations/0007_remove_employee_screen_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 4.2.17 on 2024-12-17 14:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0006_remove_employee_vendor_employee_framework_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='employee', + name='screen', + ), + migrations.AlterField( + model_name='employee', + name='add_to_wikimediade', + field=models.CharField(choices=[('NEIN', 'Nein'), ('JA', 'Ja')], max_length=5, verbose_name='Soll die Person bei Ansprechpartner*innen auf der WMDE-Webseite mit aufgenommen werden?'), + ), + migrations.AlterField( + model_name='employee', + name='framework', + field=models.CharField(blank=True, max_length=300, null=True, verbose_name='Möchten Sie vom Standard des Frameworks (Laptop) abweichen, und wenn ja, warum?'), + ), + migrations.AlterField( + model_name='employee', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/offboarding/migrations/__init__.py b/offboarding/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/offboarding/models.py b/offboarding/models.py new file mode 100644 index 0000000..e07fcac --- /dev/null +++ b/offboarding/models.py @@ -0,0 +1,86 @@ +from django.db import models +from multiselectfield import MultiSelectField +from django.utils.translation import gettext_lazy as _ + +# ATTENTION!!! +# No key should be used twice in any of these dicts because of the +# suboptimal implementation in views.EvaFormView.beautify_data() +# + +DEPARTMENT_CHOICES = {'COENG': _('Communitys & Engagement'), + 'SOFT': _('Softwareentwicklung'), + 'CENT': 'Central', + 'KOMAD': _('Kommunikation & Advocacy'), + 'VOR': _('Vorstand'),} + +#VENDOR_CHOICES = {'STANDARD': 'Dell Latitude', +# 'LENOVO': 'Lenovo Thinkpad', +# 'MAC': _('Mac (nur für Grafiker_innen)')} + +OS_CHOICES = {'FED': 'Fedora (Standard)', + 'WIN': _('Windows (bitte Begründung angeben)'), + 'MOS': _('Mac OS (nur wenn Mac gewählt)'), + 'UBU': _('Ubuntu')} + +LANG_CHOICES = {'GER': 'Deutsch', + 'ENG': 'English',} + +KEYBOARD_CHOICES = {'DE': 'Deutsch', + 'US': 'USA', + 'OT': _('Anderes (Bitte unten angeben)')} + +ACCOUNT_CHOICES = {'OTRSWMDE': 'OTRS Ticketsystem', + 'CIVIC1': _('Civic CRM (allgemein)'), + 'CIVIC2': _("Civic CRM (Mailings, impliziert allgemein)"), + 'WEB': 'www.wikimedia.de (edit)', + 'BLOG': 'blog.wikimedia.de (edit)', + 'FORUM': 'forum.wikimedia.de', + } + +TRANSPONDER_CHOICES = {'NORM': _('Allgemeiner Transponder'), + 'SPECIAL': _('Besondere Schließungen (bitte angeben)'), + 'NOTRANS': _('Kein Transponder'),} + +JANEIN_CHOICES = {'NEIN': ('Nein'), + 'JA': _('Ja'),} + +class Employee(models.Model): + + # email adress of user. should not be necessary if we use openauth one day + # usermail = models.EmailField(max_length=50, verbose_name="Deine Mailadresse (Ansprechpartner_in)", default='bestechefin@wikimedia.de') + + # personal data + firstname = models.CharField(max_length=50, verbose_name=_("Vorname")) + lastname = models.CharField(max_length=50, verbose_name=_("Nachname")) + # intern = models.BooleanField(verbose_name='Interne_r Mitarbeiter_in?', default=True) + department = models.CharField(max_length=5, choices=DEPARTMENT_CHOICES.items(), verbose_name=_('Bereich')) + team = models.CharField(max_length=50, null=True, blank=True) # TODO? better with choices? + add_to_wikimediade = models.CharField(max_length=5, choices=JANEIN_CHOICES.items(), verbose_name=_("Soll die Person bei Ansprechpartner*innen auf der WMDE-Webseite mit aufgenommen werden?")) + + # general work related stuff + firstdate_employment = models.DateField(null=True, verbose_name=_("Erster Arbeitstag")) + firstdate_presence = models.DateField(null=True, verbose_name=_("Erster Tag der Anwesenheit in der Geschäftsstelle")) + jobdescription_german = models.CharField(null=True, max_length=100, verbose_name="Stellenbezeichnung(deutsch)") + jobdescription_english = models.CharField(null=True, max_length=100, verbose_name="Job description(english)") + works_in_gs = models.BooleanField(verbose_name=_('Braucht Arbeitsplatz in der Geschäftsstelle?)'), default=True) + desk = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Wo soll der Arbeitsplatz sein?")) + + # IT related stuff + #vendor = models.CharField(max_length=8, choices=VENDOR_CHOICES.items(), default='STANDARD', verbose_name=_('Hersteller')) + framework = models.CharField(max_length=300, null=True, blank=True, verbose_name=_("Möchten Sie vom Standard des Frameworks (Laptop) abweichen, und wenn ja, warum?")) + os = models.CharField(max_length=3, choices=OS_CHOICES.items(), default='FED', verbose_name=_('Betriebssystem')) + #screen = models.BooleanField(default=False, verbose_name=_('Zusätzlicher Monitor? Einer ist standard.')) + mobile = models.BooleanField(max_length=6, default=False, verbose_name=_('Diensttelefon (Handy)')) + landline = models.BooleanField(default = False, verbose_name=_('Festnetznummer (Sipgate)')) + # sim = models.BooleanField(default=False, verbose_name="Mobilfunkvertrag") + keyboard = models.CharField(max_length=2, choices=KEYBOARD_CHOICES.items(), default='DE', verbose_name=_("Tastaturlayout")) + comment = models.TextField(max_length=500, null=True, blank=True, verbose_name=_("zusätzliche IT-Anforderungen")) + language = models.CharField(max_length=3, choices=LANG_CHOICES.items(), default="GER", verbose_name=_("Sprache für Onboarding")) + accounts = MultiSelectField(choices=ACCOUNT_CHOICES.items(), max_length=40, null=True, blank=True, verbose_name=_("Zusätzliche Accounts")) + lists = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Zusätzliche Mailinglisten")) + rebu2go = models.BooleanField(verbose_name=_("Rebu2Go-Zugang benötigt?"), default=False) + + # office related stuff + transponder = models.CharField(max_length=7, choices=TRANSPONDER_CHOICES.items(), default='NORM') + special = models.TextField(max_length=500, null=True, blank=True, verbose_name=_("Besondere Schließungen hier eintragen")) + post_office_box = models.BooleanField(default=True, verbose_name=_('Postfach am Empfang benötigt?')) diff --git a/offboarding/settings.py b/offboarding/settings.py new file mode 100644 index 0000000..10e3d99 --- /dev/null +++ b/offboarding/settings.py @@ -0,0 +1,61 @@ +# temporary setting while change and exit is not yet fully implemented +ONLY_ONBOARDING = True + +# sender mail adress also used for MAILTEST mode +EVA_MAIL = 'it-support@wikimedia.de' + +# these Fields should be included in every mail +BASIC_DATA = ['firstname', 'lastname', 'firstdate_employment', 'firstdate_presence', + 'jobdescription_german', 'jobdescription_english',] + +# for every department: 'MAIL' => mail adress, 'DATA': additional fields to include +# also one copy with all fields to the person filling the form. +MAILS = { + 'IT': { + 'MAIL': 'wmde-it@wikimedia.de', + 'DATA': [ + 'laptop', 'os', 'comment', 'email', 'landline', 'lists', 'mobile', + 'department', 'accounts', 'language', 'screen', 'works_in_gs', 'desk', + 'keyboard', + ], + }, + 'OFFICE': { + 'MAIL': 'office@wikimedia.de', + 'DATA': [ + 'transponder', 'special', 'post_office_box', 'mobile', + 'works_in_gs', 'desk', + ], + }, + 'KOMM': { + 'MAIL': 'presse@wikimedia.de', + 'DATA': [ + 'department', 'team', 'add_to_wikimediade' + ], + }, + 'CENTRAL': { + 'MAIL': 'anna.noelte@wikimedia.de', + 'DATA': [ + 'department', 'team', 'language', 'mobile', 'rebu2go' + ], + }, + 'HR': { + 'MAIL': 'personal@wikimedia.de', + 'DATA': [ + 'department', 'team', 'language', + ] + }, + 'FINANCE': { + 'MAIL': 'claudia.langrock@wikimedia.de', + 'DATA': [ + 'rebu2go' + ] + }, + 'SUBMITTER': { + 'MAIL': 'submitter@wikimedia.de', + 'DATA': [ + 'department', 'team', 'add_to_wikimediade', 'remote', 'desk', 'vendor', + 'os', 'screen', 'mobile', 'landline', 'keyboard', 'comment', 'language', + 'accounts', 'lists', 'rebu2go', 'transponder', 'special', 'post_office_box' + ] + } + } diff --git a/offboarding/static/evapp/logo.png b/offboarding/static/evapp/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cec78db9baef07f068c60e1a8af631ed97e1f397 GIT binary patch literal 5872 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 a%=2DeuX>ls^Y06r!bsmtukoHk-2VW2I8j6Z literal 0 HcmV?d00001 diff --git a/offboarding/templates/account/login.html b/offboarding/templates/account/login.html new file mode 100644 index 0000000..7a0ea12 --- /dev/null +++ b/offboarding/templates/account/login.html @@ -0,0 +1,27 @@ +{% load i18n %} +{% load static %} + + + + + +{{ form.media }} + + + + +{% load account socialaccount %} + +{% block content %} +
+ +

+ E (V A) - Eintritt, (Veränderung, Austritt)

+

+ +Bitte via Wolke einloggen: +{% include "socialaccount/snippets/provider_list.html" with process="login" %} + +
+ +{% endblock %} diff --git a/offboarding/templates/offboarding/dataloop.txt b/offboarding/templates/offboarding/dataloop.txt new file mode 100644 index 0000000..6e484a9 --- /dev/null +++ b/offboarding/templates/offboarding/dataloop.txt @@ -0,0 +1,5 @@ +{% load i18n %} +{% autoescape off %} +{% for key, value in data.items %}{% if key == 'laptop' %} {{ key }}: {{ value | safe}}{% else %} +{% trans key %}: {{ value }}{% endif %}{% endfor %} +{% endautoescape %} diff --git a/offboarding/templates/offboarding/department_mail.txt b/offboarding/templates/offboarding/department_mail.txt new file mode 100644 index 0000000..8645617 --- /dev/null +++ b/offboarding/templates/offboarding/department_mail.txt @@ -0,0 +1,31 @@ +{% load i18n %} + +(english below) + +Hallo! + +Es gibt einen Neuzugang bei Wikimedia! Hier ( https://wiki.wikimedia.de/wiki/Onboarding ) kannst Du nachsehen, +welche Schritte jetzt für Deine Abteilung nötig werden. Im Folgenden alle Daten, +die Du dafür brauchst: + +{% include 'evapp/dataloop.txt' %} + +Wenn Du Fragen hast, melde Dich bei {{contact}}. + +Grüße, Deine E.V.A. + +------------------------- +{% language 'en' %} +Hi! + +There is a new employee at Wikimedia! Here ( https://wiki.wikimedia.de/wiki/Onboarding ) you can see, which +steps are now necessary for your department. + +All Data you need for this: + +{% include 'evapp/dataloop.txt' %} + +If you have any questions please write to {{contact}}. + +Regards, Your E.V.A. +{% endlanguage %} diff --git a/offboarding/templates/offboarding/employee_form.html b/offboarding/templates/offboarding/employee_form.html new file mode 100644 index 0000000..7f6a5e5 --- /dev/null +++ b/offboarding/templates/offboarding/employee_form.html @@ -0,0 +1,110 @@ + +{% load i18n %} +{% load static %} + + + + + +{{ form.media }} + + + + +{% load socialaccount %} +{% if user.is_authenticated %} +{% block content %} + +{% get_current_language as LANGUAGE_CODE %} + +
+ + + + {% if TESTMODE %} +

{% translate "WARNUNG! Test-MODUS aktiviert. Es werden keine Mails verschickt!" %}

+ {% endif %} +

+ E (V A) - Austritt, (Veränderung, Austritt)

+

{% translate "Du bist eingeloggt als" %} {{ user.email }} + +

+

{% translate "Schritt" %} {{ wizard.steps.step1 }} {% translate "von" %} {{ wizard.steps.count }}

+

{% if wizard.steps.step1 == 1 %} + {% translate "Angaben zur Person" %} {% endif %} +{% if choice == 'IN' %} + {% if wizard.steps.step1 == 2 %} + {% translate "Angaben zum neuen Arbeitsverhältnis" %} + {% elif wizard.steps.step1 == 3 %} + {% translate "IT-relevante Angaben" %} + {% elif wizard.steps.step1 == 4 %} + {% translate "Office-relevante Angaben" %} + {% endif %} +{% else %} + {% if wizard.steps.step1 == 2 %} + Veränderungsrelevante Angaben + {% endif %} +{% endif %} +{% if datatable == True %} + {% translate "Bestätigungsschritt" %} +{% endif %} +

+

+ + {% if datatable == True %} +
+ {% for key, value in data.items %} + + {% endfor %} +
{{ key }}{{ value }}
+ {% endif %} + + + {% csrf_token %} + + {% comment %} + comment this back in if you want to use CHANGE and EXIT process + {% if wizard.steps.step1 > 1 %} + Du hast den Prozess "{{choice_string}}" ausgewählt. + {% endif %} + {% endcomment %} + {{ wizard.management_form }} + {% if wizard.form.forms %} + {{ wizard.form.management_form }} + {% for form in wizard.form.forms %} + {{ form }} + {% endfor %} + {% else %} + {{ wizard.form }} + {% endif %} +
+

+ * {% translate "Pflichtfeld" %} +

+ {% if wizard.steps.prev %} + + {% endif %} + {% if datatable == True %} + + {% else %} + + {% endif %} +

+

+ {% translate "logout" %} + +{% endblock %} +{% else %} +{% translate "Bitte einloggen!" %} +{% endif %} diff --git a/offboarding/templates/registration/login.html b/offboarding/templates/registration/login.html new file mode 100644 index 0000000..cbceed1 --- /dev/null +++ b/offboarding/templates/registration/login.html @@ -0,0 +1,35 @@ +{% block content %} + + {% if form.errors %} +

Your username and password didn't match. Please try again.

+ {% endif %} + + {% if next %} + {% if user.is_authenticated %} +

Your account doesn't have access to this page. To proceed, + please login with an account that has access.

+ {% else %} +

Please login to see this page.

+ {% endif %} + {% endif %} + +
+ {% csrf_token %} + + + + + + + + + +
{{ form.username.label_tag }}{{ form.username }}
{{ form.password.label_tag }}{{ form.password }}
+ + +
+ + {# Assumes you setup the password_reset view in your URLconf #} +

Lost password?

+ +{% endblock %} diff --git a/offboarding/tests.py b/offboarding/tests.py new file mode 100644 index 0000000..909b612 --- /dev/null +++ b/offboarding/tests.py @@ -0,0 +1,127 @@ +from django.test import TestCase +from django.test import Client +from django.contrib.auth.models import User +from django.conf import settings +from django.http import HttpResponse +from django.core import mail +from django.utils import translation + +from .forms import ITForm, WorkingForm, OfficeForm, DummyForm + +class LoginTestCase(TestCase): + def setUp(self): + self.client = Client() + self.user = User.objects.create_user('vladimir', 'vladimir@reiherzehe.com', 'reiherzehe') + self.client.login(username='vladimir', password='reiherzehe') + self.response = self.client.get('/') + + def testLogin(self): + self.assertContains(self.response, 'Du bist eingeloggt als vladimir@reiherzehe.com', status_code=200) + response_en = self.client.get('/', HTTP_ACCEPT_LANGUAGE='en-us') + self.assertContains(response_en, 'You are logged in as vladimir@reiherzehe.com', status_code=200) + self.assertContains(response_en, 'Firstname', status_code=200) + response_en = self.client.get('/', HTTP_ACCEPT_LANGUAGE='en') + self.assertContains(response_en, 'You are logged in as vladimir@reiherzehe.com', status_code=200) + self.assertContains(response_en, 'Firstname', status_code=200) + + def testDebugWarning(self): + with self.settings(DEBUG=True): + self.response = self.client.get('/') # we need to do it again with DEBUG = True + self.assertContains(self.response, "WARNUNG! Test-MODUS aktiviert. Es werden keine Mails verschickt!", status_code=200) + with self.settings(DEBUG=False) and self.settings(MAILTEST=False): + self.response = self.client.get('/') # we need to do it again with DEBUG = False + self.assertNotContains(self.response, "WARNUNG! Test-MODUS aktiviert. Es werden keine Mails verschickt!", status_code=200) + + def _postform(self, data, expected_form): + '''helper function to manage the Wizzard''' + response = self.client.post('/', data, follow=True) + # print(type(response)) + self.assertEqual(200, self.response.status_code) + if not type(response) == HttpResponse: + if 'form' in response.context: + self.assertFalse(response.context['form'].errors) + else: + raise "NO FORM FOUND" + self.assertEqual( + type(response.context['wizard']['form']), + expected_form + ) + return response + + def test_department(self): + self.assertContains(self.response, 'Programme', status_code=200) + self.assertContains(self.response, 'Kommunikation und Events', status_code=200) + + def test_wizzard_in(self): + ''' this test goes through the whole onboarding process of the EvaFormView from start to end ''' + + self.assertEqual(200, self.response.status_code) + + response = self._postform({ + 'eva_form_view-current_step': '0', + '0-firstname': 'Ara', + '0-lastname': 'Seva', + '0-department': 'CENT', + '0-team': 'Community Communications', + '0-choice': 'IN', + }, WorkingForm) + + response = self._postform({ + 'eva_form_view-current_step': '1', + '1-firstdate_employment': '2021-01-01', + '1-firstdate_presence': '2021-01-01', + '1-jobdescription_german': 'hau drauf', + '1-jobdescription_english': 'und schluss', + '1-works_in_gs': False + }, ITForm) + + response = self._postform({ + 'eva_form_view-current_step': '2', + '2-vendor': 'STANDARD', + '2-os': 'UBU', + '2-keyboard': 'DE', + '2-language': 'GER' + }, OfficeForm) + + response = self._postform({ + 'eva_form_view-current_step': '3', + '3-transponder': 'NORM' + }, DummyForm) + + response = self._postform({ + 'eva_form_view-current_step': '5', + }, DummyForm) + + + + + def test_mail(self): + self.test_wizzard_in() + # print(mail.outbox[0].body) + self.assertGreater(len(mail.outbox), 2) + self.assertIn("Vorname", mail.outbox[0].body) + self.assertIn("Firstname", mail.outbox[0].body) + for i in (0,1,3): + self.assertIn("Handy", mail.outbox[i].body) + self.assertIn("Ara Seva", mail.outbox[0].subject) + +class NoLoginTestCase(TestCase): + def setUp(self): + self.client = Client() + + def test_details(self): + response = self.client.get('/') + self.assertEqual(response.status_code, 302) + response2 = self.client.get(response.url) + self.assertContains( response2, 'Bitte via Wolke einloggen:', status_code=200) + +class ITFORMTestCase(TestCase): + def test_mac(self): + form = ITForm(data={"vendor": 'MAC', 'os': 'UBU'}) + #print (form.errors) + self.assertEqual(form.non_field_errors(), ['Ein MAC sollte Mac OS installiert haben']) + + def test_ubu(self): + form = ITForm(data={"vendor": 'STANDARD', 'os': 'UBU'}) + #print (form.errors) + self.assertNotEqual(form.non_field_errors(), ['Ein MAC sollte Mac OS installiert haben']) diff --git a/offboarding/urls.py b/offboarding/urls.py new file mode 100644 index 0000000..7d0a9d1 --- /dev/null +++ b/offboarding/urls.py @@ -0,0 +1,13 @@ +from django.urls import path + +from .views import EvaFormView, success, long_process, change_process + +urlpatterns = [ + path('', EvaFormView.as_view(condition_dict = {'1': long_process, + '2': long_process, + '3': long_process, + + '4': change_process,}), + name='evaform'), + path('success', success, name='success') + ] diff --git a/offboarding/views.py b/offboarding/views.py new file mode 100644 index 0000000..74fefc7 --- /dev/null +++ b/offboarding/views.py @@ -0,0 +1,217 @@ +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): + template_name = 'offboarding/employee_form.html' + 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}

Invalid header found. Data not saved!') + except SMTPException as error: + print(error) + self.instance.delete() + return HttpResponse(f'{error}

Error in sending mails (propably wrong adress?). Data not saved!') + except Exception as error: + print(error) + # self.instance.delete() + return HttpResponse(f'{error}

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 diff --git a/settings.py b/settings.py new file mode 120000 index 0000000..3dd5fee --- /dev/null +++ b/settings.py @@ -0,0 +1 @@ +settings_development.py \ No newline at end of file diff --git a/veränderung/__init__.py b/veränderung/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/veränderung/admin.py b/veränderung/admin.py new file mode 100644 index 0000000..067bbae --- /dev/null +++ b/veränderung/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from .models import Employee + +admin.site.register([ + Employee, + ]) diff --git a/veränderung/apps.py b/veränderung/apps.py new file mode 100644 index 0000000..f8024ad --- /dev/null +++ b/veränderung/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class EvappConfig(AppConfig): + name = 'veränderung' diff --git a/veränderung/forms.py b/veränderung/forms.py new file mode 100644 index 0000000..662df53 --- /dev/null +++ b/veränderung/forms.py @@ -0,0 +1,67 @@ +from django.db import models +from django.forms import ModelForm, DateInput, Form, ChoiceField, RadioSelect +from django.core.exceptions import ValidationError + +from .models import Employee + +# class EmployeeForm(ModelForm): +# class Meta: +# model = Employee +# fields = '__all__' +# widgets = {'firstdate_employment': DateInput(attrs={'type': 'date'}), +# 'firstdate_presence': DateInput(attrs={'type': 'date'}),} + +class DummyForm(ModelForm): + class Meta: + model = Employee + fields = [] + +class EvaForm(ModelForm): + '''this base class provides the required css class for all forms''' + required_css_class = 'required' + +TYPE_CHOICES = {'IN': 'Eintritt', 'CHANGE': 'Veränderung', 'OUT': 'Austritt'} + +class PersonalForm(EvaForm): + # TODO: comment this back in to use implementation of change or exit process + # choice = ChoiceField(choices=TYPE_CHOICES.items(), widget=RadioSelect, + # label='Welcher Prozess soll angestoßen werden?') + + class Meta: + model = Employee + fields = ['firstname', 'lastname', 'department', 'team', 'add_to_wikimediade',] + +class WorkingForm(EvaForm): + + def clean(self): + data = self.cleaned_data + if data['works_in_gs'] and data['desk'] is None: + raise ValidationError('Wer nicht remote arbeitet braucht einen Schreibtisch!') + return data + + class Meta: + model = Employee + fields = ['firstdate_employment', 'firstdate_presence', 'jobdescription_german', + 'jobdescription_english', 'works_in_gs', 'desk',] + widgets = {'firstdate_employment': DateInput(attrs={'type': 'date'}), + 'firstdate_presence': DateInput(attrs={'type': 'date'}),} + +class ITForm(EvaForm): + + class Meta: + model = Employee + fields = [ + 'framework', 'os', 'keyboard', 'mobile', 'landline', + 'comment', 'language', 'accounts', 'lists', 'rebu2go' ] + +class OfficeForm(EvaForm): + class Meta: + model = Employee + fields = ['transponder', 'special', 'post_office_box',] + +class ChangeForm(EvaForm): + class Meta: + model = Employee + fields = ['firstdate_employment', 'jobdescription_german', 'jobdescription_english', + 'desk', 'comment', 'accounts', 'lists', 'transponder'] + widgets = {'firstdate_employment': DateInput(attrs={'type': 'date'}),} diff --git a/veränderung/migrations/0001_initial.py b/veränderung/migrations/0001_initial.py new file mode 100644 index 0000000..8ec82ff --- /dev/null +++ b/veränderung/migrations/0001_initial.py @@ -0,0 +1,46 @@ +# Generated by Django 3.1.4 on 2021-09-13 12:41 + +from django.db import migrations, models +import multiselectfield.db.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Employee', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('firstname', models.CharField(max_length=50, verbose_name='Vorname')), + ('lastname', models.CharField(max_length=50, verbose_name='Nachname')), + ('department', models.CharField(choices=[('PROG', 'Programme'), ('SOFT', 'Softwareentwicklung'), ('CENT', 'Central'), ('VOR', 'Vorstand')], max_length=5, verbose_name='Bereich')), + ('team', models.CharField(blank=True, max_length=20, null=True)), + ('add_to_wikimediade', models.BooleanField(default=False, verbose_name='Soll auf wikimedia.de irgendwo stehen?')), + ('firstdate_employment', models.DateField(null=True, verbose_name='Erster Arbeitstag')), + ('firstdate_presence', models.DateField(null=True, verbose_name='Erster Tag der Anwesenheit in der Geschäftsstelle')), + ('jobdescription_german', models.CharField(max_length=100, null=True, verbose_name='Stellenbezeichnung(deutsch)')), + ('jobdescription_english', models.CharField(max_length=100, null=True, verbose_name='Job description(english)')), + ('remote', models.BooleanField(default=True, verbose_name='Braucht Arbeitsplatz in der Geschäftsstelle?')), + ('desk', models.CharField(blank=True, max_length=100, null=True, verbose_name='Wo soll der Arbeitsplatz sein?')), + ('vendor', models.CharField(choices=[('STANDARD', 'Dell Latitude'), ('LENOVO', 'Lenovo Thinkpad'), ('MAC', 'Mac (nur für Grafiker_innen)')], default='STANDARD', max_length=8, verbose_name='Hersteller')), + ('os', models.CharField(choices=[('UBU', 'Ubuntu (Standard)'), ('WIN', 'Windows (bitte Begründung angeben)'), ('MOS', 'Mac OS (nur wenn Mac gewählt)')], default='UBU', max_length=3, verbose_name='Betriebssystem')), + ('screen', models.BooleanField(default=False, verbose_name='Zusätzlicher Monitor? Einer ist standard.')), + ('mobile', models.BooleanField(default=False, max_length=6, verbose_name='Diensttelefon (Handy)')), + ('landline', models.BooleanField(default=False, verbose_name='Festnetznummer (Sipgate)')), + ('keyboard', models.CharField(choices=[('DE', 'Deutsch'), ('US', 'USA'), ('OT', 'Anderes (Bitte unten angeben)')], default='DE', max_length=2, verbose_name='Tastaturlayout')), + ('comment', models.TextField(blank=True, max_length=500, null=True, verbose_name='zusätzliche IT-Anforderungen')), + ('language', models.CharField(choices=[('GER', 'Deutsch'), ('ENG', 'English')], default='GER', max_length=3, verbose_name='Sprache für Onboarding')), + ('accounts', multiselectfield.db.fields.MultiSelectField(blank=True, choices=[('OTRSWMDE', 'OTRS Ticketsystem'), ('CIVIC1', 'Civic CRM (allgemein)'), ('CIVIC2', 'Civic CRM (Mailings, impliziert allgemein)'), ('WEB', 'www.wikimedia.de (edit)'), ('BLOG', 'blog.wikimedia.de (edit)'), ('FORUM', 'forum.wikimedia.de')], max_length=37, null=True, verbose_name='Zusätzliche Accounts')), + ('lists', models.CharField(blank=True, max_length=100, null=True, verbose_name='Zusätzliche Mailinglisten')), + ('rebu2go', models.BooleanField(default=False, verbose_name='Rebu2Go-Zugang benötigt?')), + ('transponder', models.CharField(choices=[('NORM', 'Allgemeiner Transponder'), ('SPECIAL', 'Besondere Schließungen (bitte angeben)'), ('NOTRANS', 'Kein Transponder')], default='NORM', max_length=7)), + ('special', models.TextField(blank=True, max_length=500, null=True, verbose_name='Besondere Schließungen hier eintragen')), + ('post_office_box', models.BooleanField(default=True, verbose_name='Postfach am Empfang benötigt?')), + ], + ), + ] diff --git a/veränderung/migrations/0002_auto_20210914_1055.py b/veränderung/migrations/0002_auto_20210914_1055.py new file mode 100644 index 0000000..0797935 --- /dev/null +++ b/veränderung/migrations/0002_auto_20210914_1055.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.4 on 2021-09-14 10:55 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='employee', + old_name='remote', + new_name='works_in_gs', + ), + ] diff --git a/veränderung/migrations/0003_auto_20220208_0955.py b/veränderung/migrations/0003_auto_20220208_0955.py new file mode 100644 index 0000000..e91daf4 --- /dev/null +++ b/veränderung/migrations/0003_auto_20220208_0955.py @@ -0,0 +1,28 @@ +# Generated by Django 3.1.4 on 2022-02-08 09:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0002_auto_20210914_1055'), + ] + + operations = [ + migrations.AlterField( + model_name='employee', + name='department', + field=models.CharField(choices=[('PROG', 'Programme'), ('SOFT', 'Softwareentwicklung'), ('CENT', 'Central'), ('KOMEV', 'Kommunikation und Events'), ('VOR', 'Vorstand')], max_length=5, verbose_name='Bereich'), + ), + migrations.AlterField( + model_name='employee', + name='team', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='employee', + name='works_in_gs', + field=models.BooleanField(default=True, verbose_name='Braucht Arbeitsplatz in der Geschäftsstelle?)'), + ), + ] diff --git a/veränderung/migrations/0004_alter_employee_accounts_alter_employee_department.py b/veränderung/migrations/0004_alter_employee_accounts_alter_employee_department.py new file mode 100644 index 0000000..3456ec8 --- /dev/null +++ b/veränderung/migrations/0004_alter_employee_accounts_alter_employee_department.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2.4 on 2023-08-11 10:28 + +from django.db import migrations, models +import multiselectfield.db.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0003_auto_20220208_0955'), + ] + + operations = [ + migrations.AlterField( + model_name='employee', + name='accounts', + field=multiselectfield.db.fields.MultiSelectField(blank=True, choices=[('OTRSWMDE', 'OTRS Ticketsystem'), ('CIVIC1', 'Civic CRM (allgemein)'), ('CIVIC2', 'Civic CRM (Mailings, impliziert allgemein)'), ('WEB', 'www.wikimedia.de (edit)'), ('BLOG', 'blog.wikimedia.de (edit)'), ('FORUM', 'forum.wikimedia.de')], max_length=10, null=True, verbose_name='Zusätzliche Accounts'), + ), + migrations.AlterField( + model_name='employee', + name='department', + field=models.CharField(choices=[('COENG', 'Communitys & Engagement'), ('SOFT', 'Softwareentwicklung'), ('CENT', 'Central'), ('KOMAD', 'Kommunikation & Advocacy'), ('VOR', 'Vorstand')], max_length=5, verbose_name='Bereich'), + ), + ] diff --git a/veränderung/migrations/0005_alter_employee_accounts.py b/veränderung/migrations/0005_alter_employee_accounts.py new file mode 100644 index 0000000..ca42bb6 --- /dev/null +++ b/veränderung/migrations/0005_alter_employee_accounts.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.4 on 2023-08-17 11:08 + +from django.db import migrations +import multiselectfield.db.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0004_alter_employee_accounts_alter_employee_department'), + ] + + operations = [ + migrations.AlterField( + model_name='employee', + name='accounts', + field=multiselectfield.db.fields.MultiSelectField(blank=True, choices=[('OTRSWMDE', 'OTRS Ticketsystem'), ('CIVIC1', 'Civic CRM (allgemein)'), ('CIVIC2', 'Civic CRM (Mailings, impliziert allgemein)'), ('WEB', 'www.wikimedia.de (edit)'), ('BLOG', 'blog.wikimedia.de (edit)'), ('FORUM', 'forum.wikimedia.de')], max_length=40, null=True, verbose_name='Zusätzliche Accounts'), + ), + ] diff --git a/veränderung/migrations/0006_remove_employee_vendor_employee_framework_and_more.py b/veränderung/migrations/0006_remove_employee_vendor_employee_framework_and_more.py new file mode 100644 index 0000000..b34e5fd --- /dev/null +++ b/veränderung/migrations/0006_remove_employee_vendor_employee_framework_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 4.2.16 on 2024-11-26 09:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0005_alter_employee_accounts'), + ] + + operations = [ + migrations.RemoveField( + model_name='employee', + name='vendor', + ), + migrations.AddField( + model_name='employee', + name='framework', + field=models.CharField(blank=True, max_length=300, null=True, verbose_name='Möchten Sie vom Standard des Frameworks abweichen, und wenn ja, warum?'), + ), + migrations.AlterField( + model_name='employee', + name='add_to_wikimediade', + field=models.CharField(choices=[('NEIN', 'Nein'), ('JA', 'Ja')], default=True, max_length=5, verbose_name='Soll die Person bei Ansprechpartner*innen auf der WMDE-Webseite mit aufgenommen werden?'), + ), + migrations.AlterField( + model_name='employee', + name='os', + field=models.CharField(choices=[('FED', 'Fedora (Standard)'), ('WIN', 'Windows (bitte Begründung angeben)'), ('MOS', 'Mac OS (nur wenn Mac gewählt)'), ('UBU', 'Ubuntu')], default='FED', max_length=3, verbose_name='Betriebssystem'), + ), + ] diff --git a/veränderung/migrations/0007_remove_employee_screen_and_more.py b/veränderung/migrations/0007_remove_employee_screen_and_more.py new file mode 100644 index 0000000..87124e9 --- /dev/null +++ b/veränderung/migrations/0007_remove_employee_screen_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 4.2.17 on 2024-12-17 14:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('evapp', '0006_remove_employee_vendor_employee_framework_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='employee', + name='screen', + ), + migrations.AlterField( + model_name='employee', + name='add_to_wikimediade', + field=models.CharField(choices=[('NEIN', 'Nein'), ('JA', 'Ja')], max_length=5, verbose_name='Soll die Person bei Ansprechpartner*innen auf der WMDE-Webseite mit aufgenommen werden?'), + ), + migrations.AlterField( + model_name='employee', + name='framework', + field=models.CharField(blank=True, max_length=300, null=True, verbose_name='Möchten Sie vom Standard des Frameworks (Laptop) abweichen, und wenn ja, warum?'), + ), + migrations.AlterField( + model_name='employee', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/veränderung/migrations/__init__.py b/veränderung/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/veränderung/models.py b/veränderung/models.py new file mode 100644 index 0000000..e07fcac --- /dev/null +++ b/veränderung/models.py @@ -0,0 +1,86 @@ +from django.db import models +from multiselectfield import MultiSelectField +from django.utils.translation import gettext_lazy as _ + +# ATTENTION!!! +# No key should be used twice in any of these dicts because of the +# suboptimal implementation in views.EvaFormView.beautify_data() +# + +DEPARTMENT_CHOICES = {'COENG': _('Communitys & Engagement'), + 'SOFT': _('Softwareentwicklung'), + 'CENT': 'Central', + 'KOMAD': _('Kommunikation & Advocacy'), + 'VOR': _('Vorstand'),} + +#VENDOR_CHOICES = {'STANDARD': 'Dell Latitude', +# 'LENOVO': 'Lenovo Thinkpad', +# 'MAC': _('Mac (nur für Grafiker_innen)')} + +OS_CHOICES = {'FED': 'Fedora (Standard)', + 'WIN': _('Windows (bitte Begründung angeben)'), + 'MOS': _('Mac OS (nur wenn Mac gewählt)'), + 'UBU': _('Ubuntu')} + +LANG_CHOICES = {'GER': 'Deutsch', + 'ENG': 'English',} + +KEYBOARD_CHOICES = {'DE': 'Deutsch', + 'US': 'USA', + 'OT': _('Anderes (Bitte unten angeben)')} + +ACCOUNT_CHOICES = {'OTRSWMDE': 'OTRS Ticketsystem', + 'CIVIC1': _('Civic CRM (allgemein)'), + 'CIVIC2': _("Civic CRM (Mailings, impliziert allgemein)"), + 'WEB': 'www.wikimedia.de (edit)', + 'BLOG': 'blog.wikimedia.de (edit)', + 'FORUM': 'forum.wikimedia.de', + } + +TRANSPONDER_CHOICES = {'NORM': _('Allgemeiner Transponder'), + 'SPECIAL': _('Besondere Schließungen (bitte angeben)'), + 'NOTRANS': _('Kein Transponder'),} + +JANEIN_CHOICES = {'NEIN': ('Nein'), + 'JA': _('Ja'),} + +class Employee(models.Model): + + # email adress of user. should not be necessary if we use openauth one day + # usermail = models.EmailField(max_length=50, verbose_name="Deine Mailadresse (Ansprechpartner_in)", default='bestechefin@wikimedia.de') + + # personal data + firstname = models.CharField(max_length=50, verbose_name=_("Vorname")) + lastname = models.CharField(max_length=50, verbose_name=_("Nachname")) + # intern = models.BooleanField(verbose_name='Interne_r Mitarbeiter_in?', default=True) + department = models.CharField(max_length=5, choices=DEPARTMENT_CHOICES.items(), verbose_name=_('Bereich')) + team = models.CharField(max_length=50, null=True, blank=True) # TODO? better with choices? + add_to_wikimediade = models.CharField(max_length=5, choices=JANEIN_CHOICES.items(), verbose_name=_("Soll die Person bei Ansprechpartner*innen auf der WMDE-Webseite mit aufgenommen werden?")) + + # general work related stuff + firstdate_employment = models.DateField(null=True, verbose_name=_("Erster Arbeitstag")) + firstdate_presence = models.DateField(null=True, verbose_name=_("Erster Tag der Anwesenheit in der Geschäftsstelle")) + jobdescription_german = models.CharField(null=True, max_length=100, verbose_name="Stellenbezeichnung(deutsch)") + jobdescription_english = models.CharField(null=True, max_length=100, verbose_name="Job description(english)") + works_in_gs = models.BooleanField(verbose_name=_('Braucht Arbeitsplatz in der Geschäftsstelle?)'), default=True) + desk = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Wo soll der Arbeitsplatz sein?")) + + # IT related stuff + #vendor = models.CharField(max_length=8, choices=VENDOR_CHOICES.items(), default='STANDARD', verbose_name=_('Hersteller')) + framework = models.CharField(max_length=300, null=True, blank=True, verbose_name=_("Möchten Sie vom Standard des Frameworks (Laptop) abweichen, und wenn ja, warum?")) + os = models.CharField(max_length=3, choices=OS_CHOICES.items(), default='FED', verbose_name=_('Betriebssystem')) + #screen = models.BooleanField(default=False, verbose_name=_('Zusätzlicher Monitor? Einer ist standard.')) + mobile = models.BooleanField(max_length=6, default=False, verbose_name=_('Diensttelefon (Handy)')) + landline = models.BooleanField(default = False, verbose_name=_('Festnetznummer (Sipgate)')) + # sim = models.BooleanField(default=False, verbose_name="Mobilfunkvertrag") + keyboard = models.CharField(max_length=2, choices=KEYBOARD_CHOICES.items(), default='DE', verbose_name=_("Tastaturlayout")) + comment = models.TextField(max_length=500, null=True, blank=True, verbose_name=_("zusätzliche IT-Anforderungen")) + language = models.CharField(max_length=3, choices=LANG_CHOICES.items(), default="GER", verbose_name=_("Sprache für Onboarding")) + accounts = MultiSelectField(choices=ACCOUNT_CHOICES.items(), max_length=40, null=True, blank=True, verbose_name=_("Zusätzliche Accounts")) + lists = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Zusätzliche Mailinglisten")) + rebu2go = models.BooleanField(verbose_name=_("Rebu2Go-Zugang benötigt?"), default=False) + + # office related stuff + transponder = models.CharField(max_length=7, choices=TRANSPONDER_CHOICES.items(), default='NORM') + special = models.TextField(max_length=500, null=True, blank=True, verbose_name=_("Besondere Schließungen hier eintragen")) + post_office_box = models.BooleanField(default=True, verbose_name=_('Postfach am Empfang benötigt?')) diff --git a/veränderung/settings.py b/veränderung/settings.py new file mode 100644 index 0000000..10e3d99 --- /dev/null +++ b/veränderung/settings.py @@ -0,0 +1,61 @@ +# temporary setting while change and exit is not yet fully implemented +ONLY_ONBOARDING = True + +# sender mail adress also used for MAILTEST mode +EVA_MAIL = 'it-support@wikimedia.de' + +# these Fields should be included in every mail +BASIC_DATA = ['firstname', 'lastname', 'firstdate_employment', 'firstdate_presence', + 'jobdescription_german', 'jobdescription_english',] + +# for every department: 'MAIL' => mail adress, 'DATA': additional fields to include +# also one copy with all fields to the person filling the form. +MAILS = { + 'IT': { + 'MAIL': 'wmde-it@wikimedia.de', + 'DATA': [ + 'laptop', 'os', 'comment', 'email', 'landline', 'lists', 'mobile', + 'department', 'accounts', 'language', 'screen', 'works_in_gs', 'desk', + 'keyboard', + ], + }, + 'OFFICE': { + 'MAIL': 'office@wikimedia.de', + 'DATA': [ + 'transponder', 'special', 'post_office_box', 'mobile', + 'works_in_gs', 'desk', + ], + }, + 'KOMM': { + 'MAIL': 'presse@wikimedia.de', + 'DATA': [ + 'department', 'team', 'add_to_wikimediade' + ], + }, + 'CENTRAL': { + 'MAIL': 'anna.noelte@wikimedia.de', + 'DATA': [ + 'department', 'team', 'language', 'mobile', 'rebu2go' + ], + }, + 'HR': { + 'MAIL': 'personal@wikimedia.de', + 'DATA': [ + 'department', 'team', 'language', + ] + }, + 'FINANCE': { + 'MAIL': 'claudia.langrock@wikimedia.de', + 'DATA': [ + 'rebu2go' + ] + }, + 'SUBMITTER': { + 'MAIL': 'submitter@wikimedia.de', + 'DATA': [ + 'department', 'team', 'add_to_wikimediade', 'remote', 'desk', 'vendor', + 'os', 'screen', 'mobile', 'landline', 'keyboard', 'comment', 'language', + 'accounts', 'lists', 'rebu2go', 'transponder', 'special', 'post_office_box' + ] + } + } diff --git a/veränderung/static/evapp/logo.png b/veränderung/static/evapp/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cec78db9baef07f068c60e1a8af631ed97e1f397 GIT binary patch literal 5872 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 a%=2DeuX>ls^Y06r!bsmtukoHk-2VW2I8j6Z literal 0 HcmV?d00001 diff --git a/veränderung/templates/account/login.html b/veränderung/templates/account/login.html new file mode 100644 index 0000000..7a0ea12 --- /dev/null +++ b/veränderung/templates/account/login.html @@ -0,0 +1,27 @@ +{% load i18n %} +{% load static %} + + + + + +{{ form.media }} + + + + +{% load account socialaccount %} + +{% block content %} +

+ +

+ E (V A) - Eintritt, (Veränderung, Austritt)

+

+ +Bitte via Wolke einloggen: +{% include "socialaccount/snippets/provider_list.html" with process="login" %} + +
+ +{% endblock %} diff --git a/veränderung/templates/registration/login.html b/veränderung/templates/registration/login.html new file mode 100644 index 0000000..cbceed1 --- /dev/null +++ b/veränderung/templates/registration/login.html @@ -0,0 +1,35 @@ +{% block content %} + + {% if form.errors %} +

Your username and password didn't match. Please try again.

+ {% endif %} + + {% if next %} + {% if user.is_authenticated %} +

Your account doesn't have access to this page. To proceed, + please login with an account that has access.

+ {% else %} +

Please login to see this page.

+ {% endif %} + {% endif %} + +
+ {% csrf_token %} + + + + + + + + + +
{{ form.username.label_tag }}{{ form.username }}
{{ form.password.label_tag }}{{ form.password }}
+ + +
+ + {# Assumes you setup the password_reset view in your URLconf #} +

Lost password?

+ +{% endblock %} diff --git a/veränderung/templates/veränderung/dataloop.txt b/veränderung/templates/veränderung/dataloop.txt new file mode 100644 index 0000000..6e484a9 --- /dev/null +++ b/veränderung/templates/veränderung/dataloop.txt @@ -0,0 +1,5 @@ +{% load i18n %} +{% autoescape off %} +{% for key, value in data.items %}{% if key == 'laptop' %} {{ key }}: {{ value | safe}}{% else %} +{% trans key %}: {{ value }}{% endif %}{% endfor %} +{% endautoescape %} diff --git a/veränderung/templates/veränderung/department_mail.txt b/veränderung/templates/veränderung/department_mail.txt new file mode 100644 index 0000000..8645617 --- /dev/null +++ b/veränderung/templates/veränderung/department_mail.txt @@ -0,0 +1,31 @@ +{% load i18n %} + +(english below) + +Hallo! + +Es gibt einen Neuzugang bei Wikimedia! Hier ( https://wiki.wikimedia.de/wiki/Onboarding ) kannst Du nachsehen, +welche Schritte jetzt für Deine Abteilung nötig werden. Im Folgenden alle Daten, +die Du dafür brauchst: + +{% include 'evapp/dataloop.txt' %} + +Wenn Du Fragen hast, melde Dich bei {{contact}}. + +Grüße, Deine E.V.A. + +------------------------- +{% language 'en' %} +Hi! + +There is a new employee at Wikimedia! Here ( https://wiki.wikimedia.de/wiki/Onboarding ) you can see, which +steps are now necessary for your department. + +All Data you need for this: + +{% include 'evapp/dataloop.txt' %} + +If you have any questions please write to {{contact}}. + +Regards, Your E.V.A. +{% endlanguage %} diff --git a/veränderung/templates/veränderung/employee_form.html b/veränderung/templates/veränderung/employee_form.html new file mode 100644 index 0000000..26ba681 --- /dev/null +++ b/veränderung/templates/veränderung/employee_form.html @@ -0,0 +1,110 @@ + +{% load i18n %} +{% load static %} + + + + + +{{ form.media }} + + + + +{% load socialaccount %} +{% if user.is_authenticated %} +{% block content %} + +{% get_current_language as LANGUAGE_CODE %} + +
+ + + + {% if TESTMODE %} +

{% translate "WARNUNG! Test-MODUS aktiviert. Es werden keine Mails verschickt!" %}

+ {% endif %} +

+ E (V A) - Veränderung, (Veränderung, Austritt)

+

{% translate "Du bist eingeloggt als" %} {{ user.email }} + +

+

{% translate "Schritt" %} {{ wizard.steps.step1 }} {% translate "von" %} {{ wizard.steps.count }}

+

{% if wizard.steps.step1 == 1 %} + {% translate "Angaben zur Person" %} {% endif %} +{% if choice == 'IN' %} + {% if wizard.steps.step1 == 2 %} + {% translate "Angaben zum neuen Arbeitsverhältnis" %} + {% elif wizard.steps.step1 == 3 %} + {% translate "IT-relevante Angaben" %} + {% elif wizard.steps.step1 == 4 %} + {% translate "Office-relevante Angaben" %} + {% endif %} +{% else %} + {% if wizard.steps.step1 == 2 %} + Veränderungsrelevante Angaben + {% endif %} +{% endif %} +{% if datatable == True %} + {% translate "Bestätigungsschritt" %} +{% endif %} +

+

+ + {% if datatable == True %} + + {% for key, value in data.items %} + + {% endfor %} +
{{ key }}{{ value }}
+ {% endif %} + +
+ {% csrf_token %} + + {% comment %} + comment this back in if you want to use CHANGE and EXIT process + {% if wizard.steps.step1 > 1 %} + Du hast den Prozess "{{choice_string}}" ausgewählt. + {% endif %} + {% endcomment %} + {{ wizard.management_form }} + {% if wizard.form.forms %} + {{ wizard.form.management_form }} + {% for form in wizard.form.forms %} + {{ form }} + {% endfor %} + {% else %} + {{ wizard.form }} + {% endif %} +
+

+ * {% translate "Pflichtfeld" %} +

+ {% if wizard.steps.prev %} + + {% endif %} + {% if datatable == True %} + + {% else %} + + {% endif %} +

+

+ {% translate "logout" %} +

+{% endblock %} +{% else %} +{% translate "Bitte einloggen!" %} +{% endif %} diff --git a/veränderung/tests.py b/veränderung/tests.py new file mode 100644 index 0000000..909b612 --- /dev/null +++ b/veränderung/tests.py @@ -0,0 +1,127 @@ +from django.test import TestCase +from django.test import Client +from django.contrib.auth.models import User +from django.conf import settings +from django.http import HttpResponse +from django.core import mail +from django.utils import translation + +from .forms import ITForm, WorkingForm, OfficeForm, DummyForm + +class LoginTestCase(TestCase): + def setUp(self): + self.client = Client() + self.user = User.objects.create_user('vladimir', 'vladimir@reiherzehe.com', 'reiherzehe') + self.client.login(username='vladimir', password='reiherzehe') + self.response = self.client.get('/') + + def testLogin(self): + self.assertContains(self.response, 'Du bist eingeloggt als vladimir@reiherzehe.com', status_code=200) + response_en = self.client.get('/', HTTP_ACCEPT_LANGUAGE='en-us') + self.assertContains(response_en, 'You are logged in as vladimir@reiherzehe.com', status_code=200) + self.assertContains(response_en, 'Firstname', status_code=200) + response_en = self.client.get('/', HTTP_ACCEPT_LANGUAGE='en') + self.assertContains(response_en, 'You are logged in as vladimir@reiherzehe.com', status_code=200) + self.assertContains(response_en, 'Firstname', status_code=200) + + def testDebugWarning(self): + with self.settings(DEBUG=True): + self.response = self.client.get('/') # we need to do it again with DEBUG = True + self.assertContains(self.response, "WARNUNG! Test-MODUS aktiviert. Es werden keine Mails verschickt!", status_code=200) + with self.settings(DEBUG=False) and self.settings(MAILTEST=False): + self.response = self.client.get('/') # we need to do it again with DEBUG = False + self.assertNotContains(self.response, "WARNUNG! Test-MODUS aktiviert. Es werden keine Mails verschickt!", status_code=200) + + def _postform(self, data, expected_form): + '''helper function to manage the Wizzard''' + response = self.client.post('/', data, follow=True) + # print(type(response)) + self.assertEqual(200, self.response.status_code) + if not type(response) == HttpResponse: + if 'form' in response.context: + self.assertFalse(response.context['form'].errors) + else: + raise "NO FORM FOUND" + self.assertEqual( + type(response.context['wizard']['form']), + expected_form + ) + return response + + def test_department(self): + self.assertContains(self.response, 'Programme', status_code=200) + self.assertContains(self.response, 'Kommunikation und Events', status_code=200) + + def test_wizzard_in(self): + ''' this test goes through the whole onboarding process of the EvaFormView from start to end ''' + + self.assertEqual(200, self.response.status_code) + + response = self._postform({ + 'eva_form_view-current_step': '0', + '0-firstname': 'Ara', + '0-lastname': 'Seva', + '0-department': 'CENT', + '0-team': 'Community Communications', + '0-choice': 'IN', + }, WorkingForm) + + response = self._postform({ + 'eva_form_view-current_step': '1', + '1-firstdate_employment': '2021-01-01', + '1-firstdate_presence': '2021-01-01', + '1-jobdescription_german': 'hau drauf', + '1-jobdescription_english': 'und schluss', + '1-works_in_gs': False + }, ITForm) + + response = self._postform({ + 'eva_form_view-current_step': '2', + '2-vendor': 'STANDARD', + '2-os': 'UBU', + '2-keyboard': 'DE', + '2-language': 'GER' + }, OfficeForm) + + response = self._postform({ + 'eva_form_view-current_step': '3', + '3-transponder': 'NORM' + }, DummyForm) + + response = self._postform({ + 'eva_form_view-current_step': '5', + }, DummyForm) + + + + + def test_mail(self): + self.test_wizzard_in() + # print(mail.outbox[0].body) + self.assertGreater(len(mail.outbox), 2) + self.assertIn("Vorname", mail.outbox[0].body) + self.assertIn("Firstname", mail.outbox[0].body) + for i in (0,1,3): + self.assertIn("Handy", mail.outbox[i].body) + self.assertIn("Ara Seva", mail.outbox[0].subject) + +class NoLoginTestCase(TestCase): + def setUp(self): + self.client = Client() + + def test_details(self): + response = self.client.get('/') + self.assertEqual(response.status_code, 302) + response2 = self.client.get(response.url) + self.assertContains( response2, 'Bitte via Wolke einloggen:', status_code=200) + +class ITFORMTestCase(TestCase): + def test_mac(self): + form = ITForm(data={"vendor": 'MAC', 'os': 'UBU'}) + #print (form.errors) + self.assertEqual(form.non_field_errors(), ['Ein MAC sollte Mac OS installiert haben']) + + def test_ubu(self): + form = ITForm(data={"vendor": 'STANDARD', 'os': 'UBU'}) + #print (form.errors) + self.assertNotEqual(form.non_field_errors(), ['Ein MAC sollte Mac OS installiert haben']) diff --git a/veränderung/urls.py b/veränderung/urls.py new file mode 100644 index 0000000..7d0a9d1 --- /dev/null +++ b/veränderung/urls.py @@ -0,0 +1,13 @@ +from django.urls import path + +from .views import EvaFormView, success, long_process, change_process + +urlpatterns = [ + path('', EvaFormView.as_view(condition_dict = {'1': long_process, + '2': long_process, + '3': long_process, + + '4': change_process,}), + name='evaform'), + path('success', success, name='success') + ] diff --git a/veränderung/views.py b/veränderung/views.py new file mode 100644 index 0000000..1d33197 --- /dev/null +++ b/veränderung/views.py @@ -0,0 +1,217 @@ +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): + template_name = 'veränderung/employee_form.html' + 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}

Invalid header found. Data not saved!') + except SMTPException as error: + print(error) + self.instance.delete() + return HttpResponse(f'{error}

Error in sending mails (propably wrong adress?). Data not saved!') + except Exception as error: + print(error) + # self.instance.delete() + return HttpResponse(f'{error}

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