Compare commits
71 Commits
simpleauth
...
master
Author | SHA1 | Date |
---|---|---|
Masin Al-Dujaili | 1cc2a50df8 | |
Masin Al-Dujaili | a7774f6a41 | |
Masin Al-Dujaili | b776c4811b | |
Masin Al-Dujaili | ebe3cbedc6 | |
Masin Al-Dujaili | 371cb55544 | |
Tobias Herre | 87e1d6b8f0 | |
Benni Bärmann | 1496e3d4b6 | |
Benni Bärmann | c6dabb2213 | |
Benni Bärmann | ff1aef386f | |
Benni Bärmann | ad93ab5df1 | |
Benni Bärmann | 361b6b497c | |
Benni Bärmann | f992d4cc00 | |
Benni Bärmann | c72b6bd025 | |
Benni Bärmann | 19559553b4 | |
Benni Bärmann | 254ddd2496 | |
Benni Bärmann | 9802446e05 | |
Benni Bärmann | 40bcae239a | |
Benni Bärmann | 22e33327fc | |
Benni Bärmann | 1cb419f73f | |
Benni Bärmann | 82dd63a1b5 | |
Benni Bärmann | b94e471ae4 | |
Benni Bärmann | aec2fdac16 | |
Benni Bärmann | b1b68ae68d | |
Benni Bärmann | 76abe007ec | |
Benni Bärmann | db581e3208 | |
Benni Bärmann | f423f3c6b6 | |
Benni Bärmann | 594389be0c | |
Benni Bärmann | 1979dd819b | |
Benni Bärmann | 8d997e88f1 | |
Benni Bärmann | 9434752ebe | |
Benni Bärmann | b41f624a57 | |
Benni Bärmann | 4833038eff | |
Benni Bärmann | 476def4826 | |
Benni Bärmann | ed4d47dd40 | |
Benni Bärmann | 8cd195a336 | |
Benni Bärmann | 61523c32b2 | |
Benni Bärmann | 5cda8400cc | |
Benni Bärmann | 032245ae3b | |
Benni Bärmann | b0bdf31a2c | |
Benni Bärmann | db74d3db5e | |
Benni Bärmann | 5e8c99354e | |
Benni Bärmann | 20a38b5a82 | |
Benni Bärmann | bbd1e7ff6d | |
Benni Bärmann | 4229928aae | |
Benni Bärmann | 39cee37be8 | |
Benni Bärmann | 6becd8278b | |
Benni Bärmann | b1ba9e2cd0 | |
Benni Bärmann | b7456ca77b | |
Benni Bärmann | 4d11ce293f | |
Benni Bärmann | 0955751be3 | |
Benni Bärmann | 6bcb758952 | |
Benni Bärmann | 473f10cf43 | |
Benni Bärmann | 0d56626cb9 | |
Benni Bärmann | 24df9e4a93 | |
Benni Bärmann | 2b25c6d09d | |
Benni Bärmann | 0f55c8f82d | |
Benni Bärmann | 6352064931 | |
Benni Bärmann | 1b122d8f0d | |
Benni Bärmann | 60d870ca8d | |
Benni Bärmann | aaba27551c | |
Benni Bärmann | f56c61fee9 | |
Benni Bärmann | 3c6815fa6e | |
Benni Bärmann | 780a5a0464 | |
Benni Bärmann | 9854e42e9a | |
Benni Bärmann | e4207af2ef | |
Benni Bärmann | 54881f9b8b | |
Benni Bärmann | afcd73b287 | |
Benni Bärmann | dccc85a5d1 | |
Benni Bärmann | cec488054e | |
Benni Bärmann | 132bb76ab5 | |
Benni Bärmann | d97d3f6ae0 |
69
README.md
69
README.md
|
@ -7,46 +7,73 @@ meaning "Onboarding, Change, Offboarding"
|
||||||
|
|
||||||
# development
|
# development
|
||||||
|
|
||||||
- set up a virtual environment with virtualenvwrapper or some other
|
- install gettext for instance via `apt install gettext` for translations
|
||||||
environment managing tool
|
- set up a virtual environment with virtualenvwrapper or some other environment managing tool
|
||||||
|
|
||||||
- use this environment and do
|
- use this environment and do
|
||||||
|
```
|
||||||
pip install django django-multiselectfield django-formtools
|
pip install django django-multiselectfield django-formtools django-allauth
|
||||||
|
```
|
||||||
- clone this repository
|
- clone this repository
|
||||||
|
- `ln -sr eva/settings_development.py eva/settings.py`
|
||||||
|
- initialise your database with `python manage.py migrate`
|
||||||
|
- start your development server with `python manage.py runserver`
|
||||||
|
|
||||||
- initialise your database with
|
# oauth
|
||||||
|
|
||||||
python manage.py migrate
|
- You need to add oauth information in the django backend via .../admin in "Social Accounts"
|
||||||
|
|
||||||
- start your development server with
|
|
||||||
|
|
||||||
python manage.py runserver
|
|
||||||
|
|
||||||
# production
|
# production
|
||||||
|
|
||||||
- you can use gunicorn as server for example instead of the django development server.
|
- you can use gunicorn as server for example instead of the django development server.
|
||||||
|
|
||||||
- we use whitenoise for serving static files
|
- we use whitenoise for serving static files
|
||||||
|
|
||||||
- we still use the development SQLITE database from django
|
- we still use the development SQLITE database from django
|
||||||
|
|
||||||
do the following in the project main directory:
|
do the following in the project main directory:
|
||||||
|
```
|
||||||
ln -sr eva/settings_production.py eva/settings.py
|
ln -sr eva/settings_production.py eva/settings.py
|
||||||
|
```
|
||||||
edit /secrets.json to contain something similar to
|
edit /secrets.json to contain something similar to
|
||||||
|
```
|
||||||
{
|
{
|
||||||
"SECRET_KEY": "THIS IS ANOTHER SECRET!"
|
"SECRET_KEY": "THIS IS ANOTHER SECRET!"
|
||||||
}
|
}
|
||||||
|
```
|
||||||
run the following commands:
|
run the following commands:
|
||||||
|
```
|
||||||
python3 manage.py migrate
|
python3 manage.py migrate
|
||||||
python3 manage.py collectstatic
|
python3 manage.py collectstatic
|
||||||
|
django-admin compilemessages
|
||||||
|
```
|
||||||
|
|
||||||
server starts with
|
As root create a file `/etc/systemd/system` (it's already deployed by puppet when the corresponding manifest is applied):
|
||||||
|
|
||||||
nohup gunicorn --forwarded-allow-ips="*" -b '0:8000' eva.wsgi 2&> logfile &
|
```
|
||||||
|
# /etc/systemd/system/eva.service
|
||||||
|
#
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=gunicorn EVA daemon
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=eva
|
||||||
|
Group=eva
|
||||||
|
RuntimeDirectory=eva
|
||||||
|
WorkingDirectory=/home/eva/eva
|
||||||
|
Environment=PYTHONUNBUFFERED=TRUE
|
||||||
|
ExecStart=/usr/bin/gunicorn --forwarded-allow-ips='*' -b '0:8000' eva.wsgi
|
||||||
|
ExecReload=/bin/kill -s HUP $MAINPID
|
||||||
|
KillMode=mixed
|
||||||
|
TimeoutStopSec=5
|
||||||
|
PrivateTmp=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
Adapt the paths in the file accordingly. Then, still as root, run:
|
||||||
|
```
|
||||||
|
systemctl enable --now eva.service
|
||||||
|
```
|
||||||
|
This enables the service to start at boot time and starts it immediately now. The daemon logs to the journal. You can see the last 10 lines by running `systemctl status eva.service` or the whole log by running `journalctl -u eva.service`. The usual switches to manipulate that output are available.
|
8
TODO
8
TODO
|
@ -0,0 +1,8 @@
|
||||||
|
* switch to django 4
|
||||||
|
|
||||||
|
|
||||||
|
minor stuff:
|
||||||
|
|
||||||
|
* remove dot before "Nextcloud" at login page.
|
||||||
|
|
||||||
|
* add Testmode warning at login screen
|
|
@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/3.1/ref/settings/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import os
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
@ -45,6 +46,11 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'django.contrib.sites',
|
||||||
|
'allauth',
|
||||||
|
'allauth.account',
|
||||||
|
'allauth.socialaccount',
|
||||||
|
'allauth.socialaccount.providers.nextcloud',
|
||||||
'multiselectfield',
|
'multiselectfield',
|
||||||
'formtools',
|
'formtools',
|
||||||
]
|
]
|
||||||
|
@ -53,6 +59,7 @@ MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'whitenoise.middleware.WhiteNoiseMiddleware',
|
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
@ -114,7 +121,7 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/3.1/topics/i18n/
|
# https://docs.djangoproject.com/en/3.1/topics/i18n/
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
LANGUAGE_CODE = 'de'
|
||||||
|
|
||||||
TIME_ZONE = 'UTC'
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
@ -124,8 +131,31 @@ USE_L10N = True
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
LOCALE_PATHS = ( os.path.join(BASE_DIR, 'locale'), )
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
|
|
||||||
|
# settings needed for allauth
|
||||||
|
SOCIALACCOUNT_PROVIDERS = {
|
||||||
|
'nextcloud': {
|
||||||
|
'SERVER': 'https://develwolke.wikimedia.de/',
|
||||||
|
#'SERVER': 'https://wolke.wikimedia.de',
|
||||||
|
#'SERVER': 'https://cloud.bucky.uber.space/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AUTHENTICATION_BACKENDS = (
|
||||||
|
"django.contrib.auth.backends.ModelBackend",
|
||||||
|
"allauth.account.auth_backends.AuthenticationBackend",
|
||||||
|
)
|
||||||
|
|
||||||
|
SITE_ID = 1
|
||||||
|
|
||||||
|
ACCOUNT_EMAIL_VERIFICATION = 'none'
|
||||||
|
# ACCOUNT_EMAIL_REQUIRED = True
|
||||||
|
LOGIN_REDIRECT_URL = 'home'
|
||||||
|
ACCOUNT_LOGOUT_ON_GET = True
|
||||||
|
|
|
@ -25,9 +25,6 @@ EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||||
EMAIL_HOST = '10.0.6.25'
|
EMAIL_HOST = '10.0.6.25'
|
||||||
EMAIL_PORT = '25'
|
EMAIL_PORT = '25'
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
||||||
|
|
||||||
# get secrets
|
# get secrets
|
||||||
with open(os.path.join(BASE_DIR, 'secrets.json')) as secrets_file:
|
with open(os.path.join(BASE_DIR, 'secrets.json')) as secrets_file:
|
||||||
secrets = json.load(secrets_file)
|
secrets = json.load(secrets_file)
|
||||||
|
@ -50,14 +47,11 @@ SECRET_KEY = get_secret('SECRET_KEY')
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
|
|
||||||
# send mails only to debug mode adress even if in production
|
# send mails only to debug mode adress even if in production
|
||||||
MAILTEST = True
|
MAILTEST = False
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
|
||||||
# SECRET_KEY = 'g%+i6+gkwt3zz@+k-5x1dtstuw4)&qd$lxd^bt2oswy5e1#dul'
|
|
||||||
|
|
||||||
STATIC_ROOT = BASE_DIR / 'staticfiles'
|
STATIC_ROOT = BASE_DIR / 'staticfiles'
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['*']
|
ALLOWED_HOSTS = ['*']
|
||||||
|
@ -73,6 +67,11 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'django.contrib.sites',
|
||||||
|
'allauth',
|
||||||
|
'allauth.account',
|
||||||
|
'allauth.socialaccount',
|
||||||
|
'allauth.socialaccount.providers.nextcloud',
|
||||||
'multiselectfield',
|
'multiselectfield',
|
||||||
'formtools',
|
'formtools',
|
||||||
]
|
]
|
||||||
|
@ -82,6 +81,7 @@ MIDDLEWARE = [
|
||||||
'whitenoise.middleware.WhiteNoiseMiddleware',
|
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
@ -142,7 +142,7 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/3.1/topics/i18n/
|
# https://docs.djangoproject.com/en/3.1/topics/i18n/
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
LANGUAGE_CODE = 'de'
|
||||||
|
|
||||||
TIME_ZONE = 'UTC'
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
@ -152,8 +152,29 @@ USE_L10N = True
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
LOCALE_PATHS = ( os.path.join(BASE_DIR, 'locale'), )
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
|
# settings needed for allauth
|
||||||
|
SOCIALACCOUNT_PROVIDERS = {
|
||||||
|
'nextcloud': {
|
||||||
|
'SERVER': 'https://wolke.wikimedia.de/',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AUTHENTICATION_BACKENDS = (
|
||||||
|
"django.contrib.auth.backends.ModelBackend",
|
||||||
|
"allauth.account.auth_backends.AuthenticationBackend",
|
||||||
|
)
|
||||||
|
|
||||||
|
SITE_ID = 1
|
||||||
|
|
||||||
|
ACCOUNT_EMAIL_VERIFICATION = 'none'
|
||||||
|
# ACCOUNT_EMAIL_REQUIRED = True
|
||||||
|
ACCOUNT_LOGOUT_ON_GET = True
|
||||||
|
|
||||||
|
LOGIN_REDIRECT_URL = 'home'
|
||||||
|
|
|
@ -19,5 +19,6 @@ from django.urls import path, include
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', include("evapp.urls")),
|
path('', include("evapp.urls")),
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
path('accounts/', include('django.contrib.auth.urls')),
|
path('accounts/', include('allauth.urls')),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -29,28 +29,35 @@ class PersonalForm(EvaForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Employee
|
model = Employee
|
||||||
fields = ['usermail', 'firstname', 'lastname', 'intern', 'department', 'team', ]
|
fields = ['firstname', 'lastname', 'department', 'team', ]
|
||||||
|
|
||||||
class WorkingForm(EvaForm):
|
class WorkingForm(EvaForm):
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
data = self.cleaned_data
|
data = self.cleaned_data
|
||||||
if not data['remote'] and data['desk'] is None:
|
if data['works_in_gs'] and data['desk'] is None:
|
||||||
raise ValidationError('Wer nicht remote arbeitet braucht einen Schreibtisch!')
|
raise ValidationError('Wer nicht remote arbeitet braucht einen Schreibtisch!')
|
||||||
return data
|
return data
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Employee
|
model = Employee
|
||||||
fields = ['firstdate_employment', 'firstdate_presence', 'jobdescription_german',
|
fields = ['firstdate_employment', 'firstdate_presence', 'jobdescription_german',
|
||||||
'jobdescription_english', 'remote', 'desk',]
|
'jobdescription_english', 'works_in_gs', 'desk',]
|
||||||
widgets = {'firstdate_employment': DateInput(attrs={'type': 'date'}),
|
widgets = {'firstdate_employment': DateInput(attrs={'type': 'date'}),
|
||||||
'firstdate_presence': DateInput(attrs={'type': 'date'}),}
|
'firstdate_presence': DateInput(attrs={'type': 'date'}),}
|
||||||
|
|
||||||
class ITForm(EvaForm):
|
class ITForm(EvaForm):
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
data = self.cleaned_data
|
||||||
|
if data['vendor'] == 'MAC' and data['os'] != 'MOS':
|
||||||
|
raise ValidationError('Ein MAC sollte Mac OS installiert haben')
|
||||||
|
return data
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Employee
|
model = Employee
|
||||||
fields = [
|
fields = [
|
||||||
'vendor', 'os', 'keyboard', 'screen', 'mobile', 'sim', 'comment',
|
'vendor', 'os', 'keyboard', 'screen', 'mobile', 'comment',
|
||||||
'language', 'accounts', 'lists', 'rebu2go' ]
|
'language', 'accounts', 'lists', 'rebu2go' ]
|
||||||
|
|
||||||
class OfficeForm(EvaForm):
|
class OfficeForm(EvaForm):
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 3.1.4 on 2020-12-23 12:14
|
# Generated by Django 3.1.4 on 2021-09-13 12:41
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import multiselectfield.db.fields
|
import multiselectfield.db.fields
|
||||||
|
@ -18,23 +18,27 @@ class Migration(migrations.Migration):
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('firstname', models.CharField(max_length=50, verbose_name='Vorname')),
|
('firstname', models.CharField(max_length=50, verbose_name='Vorname')),
|
||||||
('lastname', models.CharField(max_length=50, verbose_name='Nachname')),
|
('lastname', models.CharField(max_length=50, verbose_name='Nachname')),
|
||||||
('email', models.CharField(max_length=50, verbose_name='E-Mail-Adresse')),
|
('department', models.CharField(choices=[('PROG', 'Programme'), ('SOFT', 'Softwareentwicklung'), ('CENT', 'Central'), ('VOR', 'Vorstand')], max_length=5, verbose_name='Bereich')),
|
||||||
('department', models.CharField(choices=[('PROG', 'Programme'), ('SOFT', 'Softwareentwicklung'), ('CENT', 'Central'), ('VOR', 'Vorstand')], max_length=5)),
|
|
||||||
('team', models.CharField(blank=True, max_length=20, null=True)),
|
('team', models.CharField(blank=True, max_length=20, null=True)),
|
||||||
('firstdate_employment', models.DateField(null=True, verbose_name='erster Arbeitstag')),
|
('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')),
|
('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='Stellenbeschreibung(deutsch)')),
|
('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)')),
|
('jobdescription_english', models.CharField(max_length=100, null=True, verbose_name='Job description(english)')),
|
||||||
('desk', models.CharField(max_length=100, null=True, verbose_name='Wo soll der Arbeitsplatz sein?')),
|
('remote', models.BooleanField(default=True, verbose_name='Braucht Arbeitsplatz in der Geschäftsstelle?')),
|
||||||
('laptop', models.CharField(choices=[('14', '14", unser Standardgerät'), ('12', '12,5", geeignet für Vielreisende')], default='14', max_length=2)),
|
('desk', models.CharField(blank=True, max_length=100, null=True, verbose_name='Wo soll der Arbeitsplatz sein?')),
|
||||||
('os', models.CharField(choices=[('UBU', 'Ubuntu (Standard)'), ('WIN', 'Windows (bitte Begründung angeben)')], default='UBU', max_length=3)),
|
('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')),
|
||||||
('screen', models.BooleanField(default=False, verbose_name='zusätzlicher Monitor? Einer ist standard.')),
|
('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')),
|
||||||
('mobile', models.CharField(default='NO', max_length=6)),
|
('screen', models.BooleanField(default=False, verbose_name='Zusätzlicher Monitor? Einer ist standard.')),
|
||||||
('landline', models.BooleanField(default=True, verbose_name='Festnetztelefon')),
|
('mobile', models.BooleanField(default=False, max_length=6, verbose_name='Diensttelefon (Handy)')),
|
||||||
|
('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')),
|
('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)),
|
('language', models.CharField(choices=[('GER', 'Deutsch'), ('ENG', 'English')], default='GER', max_length=3, verbose_name='Sprache')),
|
||||||
('accounts', multiselectfield.db.fields.MultiSelectField(choices=[('OTRSWMDE', 'OTRS (WMDE)'), ('OTRSFUND', 'OTRS (Fundraising)'), ('CIVIC1', 'Civic CRM (allgemein)'), ('CIVIC2', 'Civic CRM (Mailings, impliziert allgemein)'), ('FUND', 'Fundraising Netzlaufwerk'), ('WEB', 'www.wikimedia.de (edit)'), ('BLOG', 'blog.wikimedia.de (edit)'), ('FORUM', 'forum.wikimedia.de')], max_length=51, null=True)),
|
('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(max_length=100, null=True)),
|
('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?')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2020-12-23 12:23
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='post_office_box',
|
|
||||||
field=models.BooleanField(default=True, verbose_name='Postfach am Empfang benötigt?'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='transponder',
|
|
||||||
field=models.CharField(choices=[('NORM', 'allgemeiner Transponder'), ('SPECIAL', 'besondere Schließungen (bitte angeben)'), ('NO', 'Kein Transponder')], default='NORM', max_length=7),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -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',
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-01-14 13:57
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0002_auto_20201223_1223'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='transponder',
|
|
||||||
field=models.CharField(choices=[('NORM', 'allgemeiner Transponder'), ('SPECIAL', 'besondere Schließungen (bitte angeben)'), ('NOTRANS', 'Kein Transponder')], default='NORM', max_length=7),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -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?)'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-02-08 11:19
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0003_auto_20210114_1357'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='intern',
|
|
||||||
field=models.BooleanField(default=True, verbose_name='Interne_r Mitarbeiter_in?'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-02-08 13:45
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0004_employee_intern'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='vendor',
|
|
||||||
field=models.CharField(choices=[('STANDARD', 'Dell Latitude'), ('LENOVO', 'Lenovo Thinkpad'), ('MAC', 'Mac (nur in Ausnahmefällen)')], default='STANDARD', max_length=8),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,24 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-02-09 09:39
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import multiselectfield.db.fields
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0005_employee_vendor'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='rebu2go',
|
|
||||||
field=models.BooleanField(default=False, verbose_name='Rebu2Go-Zugang benötigt?'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='accounts',
|
|
||||||
field=multiselectfield.db.fields.MultiSelectField(choices=[('OTRSWMDE', 'OTRS Ticketsystem'), ('CIVIC1', 'Civic CRM (allgemein)'), ('CIVIC2', 'Civic CRM (Mailings, impliziert allgemein)'), ('ZEDA', 'Zeda Nextcloud'), ('WEB', 'www.wikimedia.de (edit)'), ('BLOG', 'blog.wikimedia.de (edit)'), ('FORUM', 'forum.wikimedia.de')], max_length=42, null=True),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,23 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-02-09 11:46
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0006_auto_20210209_0939'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='remote',
|
|
||||||
field=models.BooleanField(default=False, verbose_name='Braucht keinen Arbeitsplatz weil Home-Office'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='desk',
|
|
||||||
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Wo soll der Arbeitsplatz sein?'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,53 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-03-01 10:53
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0007_auto_20210209_1146'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='special',
|
|
||||||
field=models.TextField(blank=True, max_length=500, null=True, verbose_name='Besondere Schließungen hier eintragen'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='firstdate_employment',
|
|
||||||
field=models.DateField(null=True, verbose_name='Erster Arbeitstag'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='firstdate_presence',
|
|
||||||
field=models.DateField(null=True, verbose_name='Erster Tag der Anwesenheit in der Geschäftsstelle'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='jobdescription_english',
|
|
||||||
field=models.CharField(max_length=100, null=True, verbose_name='Job description(english)'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='language',
|
|
||||||
field=models.CharField(choices=[('GER', 'Deutsch'), ('ENG', 'English')], default='GER', max_length=3),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='laptop',
|
|
||||||
field=models.CharField(choices=[('14', '14", uUser Standardgerät'), ('12', '12,5", Geeignet für Vielreisende')], default='14', max_length=2),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='screen',
|
|
||||||
field=models.BooleanField(default=False, verbose_name='Zusätzlicher Monitor? Einer ist standard.'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='transponder',
|
|
||||||
field=models.CharField(choices=[('NORM', 'Allgemeiner Transponder'), ('SPECIAL', 'Besondere Schließungen (bitte angeben)'), ('NOTRANS', 'Kein Transponder')], default='NORM', max_length=7),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,28 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-03-15 14:08
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0008_auto_20210301_1053'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='usermail',
|
|
||||||
field=models.EmailField(default='bestechefin@wikimedia.de', max_length=50, verbose_name='Deine Mailadresse'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='email',
|
|
||||||
field=models.EmailField(max_length=50, verbose_name='E-Mail-Adresse ders Mitarbeitenden'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='laptop',
|
|
||||||
field=models.CharField(choices=[('14', '14", Unser Standardgerät'), ('12', '12,5", Geeignet für Vielreisende')], default='14', max_length=2),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-03-25 08:13
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0009_auto_20210315_1408'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='jobdescription_german',
|
|
||||||
field=models.CharField(max_length=100, null=True, verbose_name='Stellenbezeichnung(deutsch)'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,23 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-03-29 12:54
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0010_auto_20210325_0813'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='sim',
|
|
||||||
field=models.BooleanField(default=False, verbose_name='Mobilfunkvertrag'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='sim2',
|
|
||||||
field=models.BooleanField(default=False, verbose_name='Zweite Sim (für Laptop zB)'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-03-30 08:25
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0011_auto_20210329_1254'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='bvg',
|
|
||||||
field=models.BooleanField(default=True, verbose_name='Bekommt eine BVG-Karte, weil in Berlin tätig'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,17 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-04-01 08:30
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0012_employee_bvg'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='employee',
|
|
||||||
name='bvg',
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,38 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-05-04 08:42
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import multiselectfield.db.fields
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0013_remove_employee_bvg'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='employee',
|
|
||||||
name='sim2',
|
|
||||||
),
|
|
||||||
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=37, null=True, verbose_name='Zusätzliche Accounts'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='lists',
|
|
||||||
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Zusätzliche Mailinglisten'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='mobile',
|
|
||||||
field=models.BooleanField(default=False, max_length=6, verbose_name='Handy benötigt?'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='vendor',
|
|
||||||
field=models.CharField(choices=[('STANDARD', 'Dell Latitude'), ('LENOVO', 'Lenovo Thinkpad'), ('MAC', 'Mac (nur in Ausnahmefällen)')], default='STANDARD', max_length=8, verbose_name='Hersteller'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,17 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-05-04 09:43
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0014_auto_20210504_0842'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='employee',
|
|
||||||
name='email',
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,27 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-05-04 10:40
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0015_remove_employee_email'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='employee',
|
|
||||||
name='landline',
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='employee',
|
|
||||||
name='keyboard',
|
|
||||||
field=models.CharField(choices=[('DE', 'Deutsch'), ('US', 'USA'), ('OT', 'Anderes (Bitte unten angeben)')], default='DE', max_length=2, verbose_name='Tastaturlayout'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='department',
|
|
||||||
field=models.CharField(choices=[('PROG', 'Programme'), ('SOFT', 'Softwareentwicklung'), ('CENT', 'Central'), ('VOR', 'Vorstand')], max_length=5, verbose_name='Bereich'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-05-04 12:24
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0016_auto_20210504_1040'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='os',
|
|
||||||
field=models.CharField(choices=[('UBU', 'Ubuntu (Standard)'), ('WIN', 'Windows (bitte Begründung angeben)')], default='UBU', max_length=3, verbose_name='Betriebssystem'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-05-04 12:51
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0017_auto_20210504_1224'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='usermail',
|
|
||||||
field=models.EmailField(default='bestechefin@wikimedia.de', max_length=50, verbose_name='Deine Mailadresse (Ansprechpartner_in)'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,22 +0,0 @@
|
||||||
# Generated by Django 3.1.4 on 2021-05-04 13:33
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evapp', '0018_auto_20210504_1251'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='employee',
|
|
||||||
name='laptop',
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='employee',
|
|
||||||
name='vendor',
|
|
||||||
field=models.CharField(choices=[('STANDARD', 'Dell Latitude'), ('LENOVO', 'Lenovo Thinkpad'), ('MAC', 'Mac (nur für Grafiker_innen)')], default='STANDARD', max_length=8, verbose_name='Hersteller'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,22 +1,25 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from multiselectfield import MultiSelectField
|
from multiselectfield import MultiSelectField
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
# ATTENTION!!!
|
# ATTENTION!!!
|
||||||
# No key should be used twice in any of these dicts because of the
|
# No key should be used twice in any of these dicts because of the
|
||||||
# suboptimal implementation in views.EvaFormView.beautify_data()
|
# suboptimal implementation in views.EvaFormView.beautify_data()
|
||||||
#
|
#
|
||||||
|
|
||||||
DEPARTMENT_CHOICES = {'PROG': 'Programme',
|
DEPARTMENT_CHOICES = {'COENG': _('Communitys & Engagement'),
|
||||||
'SOFT': 'Softwareentwicklung',
|
'SOFT': _('Softwareentwicklung'),
|
||||||
'CENT': 'Central',
|
'CENT': 'Central',
|
||||||
'VOR': 'Vorstand',}
|
'KOMAD': _('Kommunikation & Advocacy'),
|
||||||
|
'VOR': _('Vorstand'),}
|
||||||
|
|
||||||
VENDOR_CHOICES = {'STANDARD': 'Dell Latitude',
|
VENDOR_CHOICES = {'STANDARD': 'Dell Latitude',
|
||||||
'LENOVO': 'Lenovo Thinkpad',
|
'LENOVO': 'Lenovo Thinkpad',
|
||||||
'MAC': 'Mac (nur für Grafiker_innen)'}
|
'MAC': _('Mac (nur für Grafiker_innen)')}
|
||||||
|
|
||||||
OS_CHOICES = {'UBU': 'Ubuntu (Standard)',
|
OS_CHOICES = {'UBU': 'Ubuntu (Standard)',
|
||||||
'WIN': 'Windows (bitte Begründung angeben)',}
|
'WIN': _('Windows (bitte Begründung angeben)'),
|
||||||
|
'MOS': _('Mac OS (nur wenn Mac gewählt)')}
|
||||||
|
|
||||||
|
|
||||||
LANG_CHOICES = {'GER': 'Deutsch',
|
LANG_CHOICES = {'GER': 'Deutsch',
|
||||||
|
@ -24,54 +27,54 @@ LANG_CHOICES = {'GER': 'Deutsch',
|
||||||
|
|
||||||
KEYBOARD_CHOICES = {'DE': 'Deutsch',
|
KEYBOARD_CHOICES = {'DE': 'Deutsch',
|
||||||
'US': 'USA',
|
'US': 'USA',
|
||||||
'OT': 'Anderes (Bitte unten angeben)'}
|
'OT': _('Anderes (Bitte unten angeben)')}
|
||||||
|
|
||||||
ACCOUNT_CHOICES = {'OTRSWMDE': 'OTRS Ticketsystem',
|
ACCOUNT_CHOICES = {'OTRSWMDE': 'OTRS Ticketsystem',
|
||||||
'CIVIC1': 'Civic CRM (allgemein)',
|
'CIVIC1': _('Civic CRM (allgemein)'),
|
||||||
'CIVIC2': "Civic CRM (Mailings, impliziert allgemein)",
|
'CIVIC2': _("Civic CRM (Mailings, impliziert allgemein)"),
|
||||||
'WEB': 'www.wikimedia.de (edit)',
|
'WEB': 'www.wikimedia.de (edit)',
|
||||||
'BLOG': 'blog.wikimedia.de (edit)',
|
'BLOG': 'blog.wikimedia.de (edit)',
|
||||||
'FORUM': 'forum.wikimedia.de',
|
'FORUM': 'forum.wikimedia.de',
|
||||||
}
|
}
|
||||||
|
|
||||||
TRANSPONDER_CHOICES = {'NORM': 'Allgemeiner Transponder',
|
TRANSPONDER_CHOICES = {'NORM': _('Allgemeiner Transponder'),
|
||||||
'SPECIAL': 'Besondere Schließungen (bitte angeben)',
|
'SPECIAL': _('Besondere Schließungen (bitte angeben)'),
|
||||||
'NOTRANS': 'Kein Transponder',}
|
'NOTRANS': _('Kein Transponder'),}
|
||||||
|
|
||||||
class Employee(models.Model):
|
class Employee(models.Model):
|
||||||
|
|
||||||
# email adress of user. should not be necessary if we use openauth one day
|
# 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')
|
# usermail = models.EmailField(max_length=50, verbose_name="Deine Mailadresse (Ansprechpartner_in)", default='bestechefin@wikimedia.de')
|
||||||
|
|
||||||
# personal data
|
# personal data
|
||||||
firstname = models.CharField(max_length=50, verbose_name="Vorname")
|
firstname = models.CharField(max_length=50, verbose_name=_("Vorname"))
|
||||||
lastname = models.CharField(max_length=50, verbose_name="Nachname")
|
lastname = models.CharField(max_length=50, verbose_name=_("Nachname"))
|
||||||
intern = models.BooleanField(verbose_name='Interne_r Mitarbeiter_in?', default=True)
|
# intern = models.BooleanField(verbose_name='Interne_r Mitarbeiter_in?', default=True)
|
||||||
department = models.CharField(max_length=5, choices=DEPARTMENT_CHOICES.items(), verbose_name='Bereich')
|
department = models.CharField(max_length=5, choices=DEPARTMENT_CHOICES.items(), verbose_name=_('Bereich'))
|
||||||
team = models.CharField(max_length=20, null=True, blank=True) # TODO? better with choices?
|
team = models.CharField(max_length=50, null=True, blank=True) # TODO? better with choices?
|
||||||
|
|
||||||
# general work related stuff
|
# general work related stuff
|
||||||
firstdate_employment = models.DateField(null=True, verbose_name="Erster Arbeitstag")
|
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")
|
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_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)")
|
jobdescription_english = models.CharField(null=True, max_length=100, verbose_name="Job description(english)")
|
||||||
remote = models.BooleanField(verbose_name='Braucht keinen Arbeitsplatz weil Home-Office', default=False)
|
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?")
|
desk = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Wo soll der Arbeitsplatz sein?"))
|
||||||
|
|
||||||
# IT related stuff
|
# IT related stuff
|
||||||
vendor = models.CharField(max_length=8, choices=VENDOR_CHOICES.items(), default='STANDARD', verbose_name='Hersteller')
|
vendor = models.CharField(max_length=8, choices=VENDOR_CHOICES.items(), default='STANDARD', verbose_name=_('Hersteller'))
|
||||||
os = models.CharField(max_length=3, choices=OS_CHOICES.items(), default='UBU', verbose_name='Betriebssystem')
|
os = models.CharField(max_length=3, choices=OS_CHOICES.items(), default='UBU', verbose_name=_('Betriebssystem'))
|
||||||
screen = models.BooleanField(default=False, verbose_name='Zusätzlicher Monitor? Einer ist standard.')
|
screen = models.BooleanField(default=False, verbose_name=_('Zusätzlicher Monitor? Einer ist standard.'))
|
||||||
mobile = models.BooleanField(max_length=6, default=False, verbose_name='Handy benötigt?')
|
mobile = models.BooleanField(max_length=6, default=False, verbose_name=_('Diensttelefon (Handy)'))
|
||||||
sim = models.BooleanField(default=False, verbose_name="Mobilfunkvertrag")
|
# sim = models.BooleanField(default=False, verbose_name="Mobilfunkvertrag")
|
||||||
keyboard = models.CharField(max_length=2, choices=KEYBOARD_CHOICES.items(), default='DE', verbose_name="Tastaturlayout")
|
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")
|
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")
|
language = models.CharField(max_length=3, choices=LANG_CHOICES.items(), default="GER", verbose_name=_("Sprache"))
|
||||||
accounts = MultiSelectField(choices=ACCOUNT_CHOICES.items(), null=True, blank=True, verbose_name="Zusätzliche Accounts")
|
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")
|
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)
|
rebu2go = models.BooleanField(verbose_name=_("Rebu2Go-Zugang benötigt?"), default=False)
|
||||||
|
|
||||||
# office related stuff
|
# office related stuff
|
||||||
transponder = models.CharField(max_length=7, choices=TRANSPONDER_CHOICES.items(), default='NORM')
|
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")
|
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?')
|
post_office_box = models.BooleanField(default=True, verbose_name=_('Postfach am Empfang benötigt?'))
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
ONLY_ONBOARDING = True
|
ONLY_ONBOARDING = True
|
||||||
|
|
||||||
# sender mail adress also used for MAILTEST mode
|
# sender mail adress also used for MAILTEST mode
|
||||||
EVA_MAIL = 'benni.baermann@wikimedia.de'
|
EVA_MAIL = 'it-support@wikimedia.de'
|
||||||
|
|
||||||
# these Fields should be included in every mail
|
# these Fields should be included in every mail
|
||||||
BASIC_DATA = ['usermail', 'firstname', 'lastname', 'firstdate_employment', 'firstdate_presence',]
|
BASIC_DATA = ['firstname', 'lastname', 'firstdate_employment', 'firstdate_presence',
|
||||||
|
'jobdescription_german', 'jobdescription_english',]
|
||||||
|
|
||||||
# for every department: 'MAIL' => mail adress, 'DATA': additional fields to include
|
# for every department: 'MAIL' => mail adress, 'DATA': additional fields to include
|
||||||
MAILS = {
|
MAILS = {
|
||||||
|
@ -13,31 +14,31 @@ MAILS = {
|
||||||
'MAIL': 'wmde-it@wikimedia.de',
|
'MAIL': 'wmde-it@wikimedia.de',
|
||||||
'DATA': [
|
'DATA': [
|
||||||
'laptop', 'os', 'comment', 'email', 'landline', 'lists', 'mobile',
|
'laptop', 'os', 'comment', 'email', 'landline', 'lists', 'mobile',
|
||||||
'department', 'accounts', 'language', 'screen', 'remote', 'desk',
|
'department', 'accounts', 'language', 'screen', 'works_in_gs', 'desk',
|
||||||
|
'keyboard',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'OFFICE': {
|
'OFFICE': {
|
||||||
'MAIL': 'office@wikimedia.de',
|
'MAIL': 'office@wikimedia.de',
|
||||||
'DATA': [
|
'DATA': [
|
||||||
'transponder', 'special', 'post_office_box', 'sim', 'sim2',
|
'transponder', 'special', 'post_office_box', 'mobile',
|
||||||
'remote', 'desk',
|
'works_in_gs', 'desk',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'KOMM': {
|
'KOMM': {
|
||||||
'MAIL': 'presse@wikimedia.de',
|
'MAIL': 'presse@wikimedia.de',
|
||||||
'DATA': [
|
'DATA': [
|
||||||
'department', 'team',
|
'department', 'team',
|
||||||
'jobdescription_german', 'jobdescription_english',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'CENTRAL': {
|
'CENTRAL': {
|
||||||
'MAIL': 'eileen.miedtank@wikimedia.de',
|
'MAIL': 'anna.noelte@wikimedia.de',
|
||||||
'DATA': [
|
'DATA': [
|
||||||
'department', 'team', 'language', 'sim', 'sim2', 'rebu2go'
|
'department', 'team', 'language', 'mobile', 'rebu2go'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'HR': {
|
'HR': {
|
||||||
'MAIL': 'personal@wikimedia.de, eileen.miedtank@wikimedia.de',
|
'MAIL': 'personal@wikimedia.de',
|
||||||
'DATA': [
|
'DATA': [
|
||||||
'department', 'team', 'language',
|
'department', 'team', 'language',
|
||||||
]
|
]
|
||||||
|
@ -47,6 +48,11 @@ MAILS = {
|
||||||
'DATA': [
|
'DATA': [
|
||||||
'team', 'department', 'language',
|
'team', 'department', 'language',
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
'FINANCE': {
|
||||||
|
'MAIL': 'claudia.langrock@wikimedia.de',
|
||||||
|
'DATA': [
|
||||||
|
'rebu2go'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
{% load i18n %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
<script type="text/javascript" src="{% static 'admin/js/core.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'admin/js/jquery.init.js' %}"></script>
|
||||||
|
|
||||||
|
{{ form.media }}
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/base.css' %}" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/widgets.css' %}" />
|
||||||
|
|
||||||
|
{% load account socialaccount %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<center>
|
||||||
|
<img src="{% static 'evapp/logo.png' %}" />
|
||||||
|
<h1>
|
||||||
|
E (V A) - Eintritt, (Veränderung, Austritt)<p>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
Bitte via Wolke einloggen:
|
||||||
|
{% include "socialaccount/snippets/provider_list.html" with process="login" %}
|
||||||
|
|
||||||
|
</center>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -1,4 +1,5 @@
|
||||||
|
{% load i18n %}
|
||||||
{% autoescape off %}
|
{% autoescape off %}
|
||||||
{% for key, value in data.items %}{% if key == 'laptop' %} {{ key }}: {{ value | safe}}{% else %}
|
{% for key, value in data.items %}{% if key == 'laptop' %} {{ key }}: {{ value | safe}}{% else %}
|
||||||
{{ key }}: {{ value }}{% endif %}{% endfor %}
|
{% trans key %}: {{ value }}{% endif %}{% endfor %}
|
||||||
{% endautoescape %}
|
{% endautoescape %}
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
(english below)
|
||||||
|
|
||||||
Hallo!
|
Hallo!
|
||||||
|
|
||||||
Es gibt einen Neuzugang bei Wikimedia! Hier ( https://wiki.wikimedia.de/wiki/Onboarding ) kannst Du nachsehen,
|
Es gibt einen Neuzugang bei Wikimedia! Hier ( https://wiki.wikimedia.de/wiki/Onboarding ) kannst Du nachsehen,
|
||||||
|
@ -6,4 +10,22 @@ die Du dafür brauchst:
|
||||||
|
|
||||||
{% include 'evapp/dataloop.txt' %}
|
{% include 'evapp/dataloop.txt' %}
|
||||||
|
|
||||||
|
Wenn Du Fragen hast, melde Dich bei {{contact}}.
|
||||||
|
|
||||||
Grüße, Deine E.V.A.
|
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 %}
|
||||||
|
|
|
@ -11,7 +11,12 @@
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/base.css' %}" />
|
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/base.css' %}" />
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/widgets.css' %}" />
|
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/widgets.css' %}" />
|
||||||
|
|
||||||
|
{% load socialaccount %}
|
||||||
|
{% if user.is_authenticated %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
{% get_current_language as LANGUAGE_CODE %}
|
||||||
|
<!-- Current language: {{ LANGUAGE_CODE }} -->
|
||||||
<center>
|
<center>
|
||||||
<style>
|
<style>
|
||||||
ul > li {
|
ul > li {
|
||||||
|
@ -27,20 +32,23 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<img src="{% static 'evapp/logo.png' %}" />
|
<img src="{% static 'evapp/logo.png' %}" />
|
||||||
|
{% if TESTMODE %}
|
||||||
|
<h1 style="background-color:red;color:white">{% translate "WARNUNG! Test-MODUS aktiviert. Es werden keine Mails verschickt!" %}</h1>
|
||||||
|
{% endif %}
|
||||||
<h1>
|
<h1>
|
||||||
E (V A) - Eintritt, (Veränderung, Austritt)<p>
|
E (V A) - Eintritt, (Veränderung, Austritt)<p>
|
||||||
</h1>
|
</h1>{% translate "Du bist eingeloggt als" %} {{ user.email }}
|
||||||
<h2>
|
<h2>
|
||||||
<p>Schritt {{ wizard.steps.step1 }} von {{ wizard.steps.count }}</p>
|
<p> {% translate "Schritt" %} {{ wizard.steps.step1 }} {% translate "von" %} {{ wizard.steps.count }}</p>
|
||||||
<p>{% if wizard.steps.step1 == 1 %}
|
<p>{% if wizard.steps.step1 == 1 %}
|
||||||
Angaben zur Person {% endif %}
|
{% translate "Angaben zur Person" %} {% endif %}
|
||||||
{% if choice == 'IN' %}
|
{% if choice == 'IN' %}
|
||||||
{% if wizard.steps.step1 == 2 %}
|
{% if wizard.steps.step1 == 2 %}
|
||||||
Angaben zum neuen Arbeitsverhältnis
|
{% translate "Angaben zum neuen Arbeitsverhältnis" %}
|
||||||
{% elif wizard.steps.step1 == 3 %}
|
{% elif wizard.steps.step1 == 3 %}
|
||||||
IT-relevante Angaben
|
{% translate "IT-relevante Angaben" %}
|
||||||
{% elif wizard.steps.step1 == 4 %}
|
{% elif wizard.steps.step1 == 4 %}
|
||||||
Office-relevante Angaben
|
{% translate "Office-relevante Angaben" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if wizard.steps.step1 == 2 %}
|
{% if wizard.steps.step1 == 2 %}
|
||||||
|
@ -48,7 +56,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if datatable == True %}
|
{% if datatable == True %}
|
||||||
Bestätigungsschritt
|
{% translate "Bestätigungsschritt" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -79,17 +87,21 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</table>
|
</table>
|
||||||
<p>
|
<p>
|
||||||
<span style="color: red">*</span> Pflichtfeld
|
<span style="color: red">*</span> {% translate "Pflichtfeld" %}
|
||||||
<p>
|
<p>
|
||||||
{% if wizard.steps.prev %}
|
{% if wizard.steps.prev %}
|
||||||
<button formnovalidate="formnovalidate" name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">Zurück</button>
|
<button formnovalidate="formnovalidate" name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">{% translate "Zurück" %}</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if datatable == True %}
|
{% if datatable == True %}
|
||||||
<button type="submit" value="{% trans "Weiter" %}">Abschicken</button>
|
<button type="submit" value="{% trans "Weiter" %}">{% translate "Abschicken" %}</button>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button type="submit" value="{% trans "Weiter" %}">Weiter</button>
|
<button type="submit" value="{% trans "Weiter" %}">{% translate "Weiter" %}</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
<p>
|
<p>
|
||||||
|
<a href="{% url 'account_logout' %}">{% translate "logout" %}</a>
|
||||||
</center>
|
</center>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% else %}
|
||||||
|
<a href="{% provider_login_url 'nextcloud' %}">{% translate "Bitte einloggen!" %}</a>
|
||||||
|
{% endif %}
|
||||||
|
|
126
evapp/tests.py
126
evapp/tests.py
|
@ -1,3 +1,127 @@
|
||||||
from django.test import TestCase
|
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
|
||||||
|
|
||||||
# Create your tests here.
|
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'])
|
||||||
|
|
|
@ -10,6 +10,7 @@ from formtools.wizard.views import CookieWizardView
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from .models import Employee, DEPARTMENT_CHOICES, OS_CHOICES, VENDOR_CHOICES, \
|
from .models import Employee, DEPARTMENT_CHOICES, OS_CHOICES, VENDOR_CHOICES, \
|
||||||
LANG_CHOICES, ACCOUNT_CHOICES, TRANSPONDER_CHOICES, KEYBOARD_CHOICES
|
LANG_CHOICES, ACCOUNT_CHOICES, TRANSPONDER_CHOICES, KEYBOARD_CHOICES
|
||||||
|
@ -18,7 +19,7 @@ from .forms import PersonalForm, WorkingForm, ITForm, OfficeForm, DummyForm,\
|
||||||
from .settings import MAILS, EVA_MAIL, BASIC_DATA, ONLY_ONBOARDING
|
from .settings import MAILS, EVA_MAIL, BASIC_DATA, ONLY_ONBOARDING
|
||||||
|
|
||||||
def success(request):
|
def success(request):
|
||||||
return HttpResponse("Vielen Dank! Du hast E.V.A. erfolgreich ausgefüllt. Die Mails an die Abteilungen wurden versendet.")
|
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):
|
def long_process(wizard):
|
||||||
'''this method is called via urls.py to determine if a form is part of the IN-Process'''
|
'''this method is called via urls.py to determine if a form is part of the IN-Process'''
|
||||||
|
@ -28,19 +29,19 @@ def long_process(wizard):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
data = wizard.get_cleaned_data_for_step('0') or {}
|
data = wizard.get_cleaned_data_for_step('0') or {}
|
||||||
print(data)
|
# print(data)
|
||||||
if data.get('choice') != 'CHANGE':
|
if data.get('choice') != 'CHANGE':
|
||||||
wizard.set_choice('IN')
|
wizard.set_choice('IN')
|
||||||
print('PROZESS IN')
|
# print('PROZESS IN')
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
wizard.set_choice('CHANGE')
|
wizard.set_choice('CHANGE')
|
||||||
print('PROZESS NOT IN')
|
# print('PROZESS NOT IN')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def change_process(wizard):
|
def change_process(wizard):
|
||||||
''' this method is called via urls.py to determine if the form is part of the change process'''
|
''' this method is called via urls.py to determine if the form is part of the change process'''
|
||||||
print('CHANGE PROZESS')
|
# print('CHANGE PROZESS')
|
||||||
return not long_process(wizard)
|
return not long_process(wizard)
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,10 +60,10 @@ class EvaFormView(LoginRequiredMixin, CookieWizardView):
|
||||||
(first, *_) = data['firstname'].split(maxsplit=1)
|
(first, *_) = data['firstname'].split(maxsplit=1)
|
||||||
(last, *_) = data['lastname'].split(maxsplit=1)
|
(last, *_) = data['lastname'].split(maxsplit=1)
|
||||||
name = first + '.' + last
|
name = first + '.' + last
|
||||||
if not data['intern']:
|
#if not data['intern']:
|
||||||
mail = name + '_ext@wikimedia.de'
|
# mail = name + '_ext@wikimedia.de'
|
||||||
else:
|
#else:
|
||||||
mail = name + '@wikimedia.de'
|
mail = name + '@wikimedia.de'
|
||||||
data['email'] = mail
|
data['email'] = mail
|
||||||
|
|
||||||
def get_all_cleaned_data(self):
|
def get_all_cleaned_data(self):
|
||||||
|
@ -72,7 +73,7 @@ class EvaFormView(LoginRequiredMixin, CookieWizardView):
|
||||||
data = super().get_all_cleaned_data()
|
data = super().get_all_cleaned_data()
|
||||||
self.generate_email(data)
|
self.generate_email(data)
|
||||||
|
|
||||||
print("delete CHOICE FROM DATA")
|
# print("delete CHOICE FROM DATA")
|
||||||
if 'choice' in data:
|
if 'choice' in data:
|
||||||
del data['choice']
|
del data['choice']
|
||||||
return data
|
return data
|
||||||
|
@ -83,8 +84,10 @@ class EvaFormView(LoginRequiredMixin, CookieWizardView):
|
||||||
|
|
||||||
#print('GETCONTEXT')
|
#print('GETCONTEXT')
|
||||||
context = super().get_context_data(form=form, **kwargs)
|
context = super().get_context_data(form=form, **kwargs)
|
||||||
|
testmode = settings.DEBUG or settings.MAILTEST
|
||||||
context.update({'choice': self.choice,
|
context.update({'choice': self.choice,
|
||||||
'choice_string': TYPE_CHOICES[self.choice]})
|
'choice_string': TYPE_CHOICES[self.choice],
|
||||||
|
'TESTMODE': testmode})
|
||||||
|
|
||||||
# deliver context for forms if we are in the last step
|
# 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)):
|
if (self.steps.step1 == 5 or (self.choice != 'IN' and self.steps.step1 == 3)):
|
||||||
|
@ -93,7 +96,7 @@ class EvaFormView(LoginRequiredMixin, CookieWizardView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_form_instance(self,step):
|
def get_form_instance(self,step):
|
||||||
''' this method makes shure, that we use the same model instance for all steps'''
|
''' this method assures, that we use the same model instance for all steps'''
|
||||||
|
|
||||||
if self.instance == None:
|
if self.instance == None:
|
||||||
self.instance = Employee()
|
self.instance = Employee()
|
||||||
|
@ -112,12 +115,15 @@ class EvaFormView(LoginRequiredMixin, CookieWizardView):
|
||||||
|
|
||||||
# send data to departments
|
# send data to departments
|
||||||
for dep in MAILS:
|
for dep in MAILS:
|
||||||
self.send_mail_to_department(dep)
|
response = self.send_mail_to_department(dep)
|
||||||
|
|
||||||
if not settings.DEBUG:
|
if not settings.DEBUG:
|
||||||
self.instance.delete()
|
self.instance.delete()
|
||||||
|
|
||||||
return HttpResponseRedirect('success')
|
if response:
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
return HttpResponseRedirect('success')
|
||||||
|
|
||||||
|
|
||||||
def send_mail_to_department(self, department):
|
def send_mail_to_department(self, department):
|
||||||
|
@ -125,36 +131,45 @@ class EvaFormView(LoginRequiredMixin, CookieWizardView):
|
||||||
|
|
||||||
print(f'send mail to department {department}...')
|
print(f'send mail to department {department}...')
|
||||||
|
|
||||||
|
contact = self.request.user.email
|
||||||
data = self.get_all_cleaned_data()
|
data = self.get_all_cleaned_data()
|
||||||
# some data should be in every mail
|
# some data should be in every mail
|
||||||
newdata = {k: v for k, v in data.items() if (k in BASIC_DATA)}
|
newdata = {k: v for k, v in data.items() if (k in BASIC_DATA)}
|
||||||
# only the relevant data should be in the context
|
# 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'])})
|
newdata.update({k: v for k, v in data.items() if (k in MAILS[department]['DATA'])})
|
||||||
|
|
||||||
context = {'data': self.beautify_data(newdata)}
|
context = {'data': self.beautify_data(newdata), 'contact': contact}
|
||||||
|
firstname = data['firstname']
|
||||||
|
lastname = data['lastname']
|
||||||
try:
|
try:
|
||||||
mail_template = get_template(f'evapp/department_mail.txt')
|
mail_template = get_template(f'evapp/department_mail.txt')
|
||||||
if settings.MAILTEST:
|
if settings.MAILTEST:
|
||||||
send_mail(
|
send_mail(
|
||||||
'EVA: Neuzugang',
|
f'EVA: Neuzugang {firstname} {lastname} (MAILTEST)',
|
||||||
mail_template.render(context),
|
mail_template.render(context),
|
||||||
EVA_MAIL,
|
EVA_MAIL,
|
||||||
[EVA_MAIL, self.instance.usermail],
|
[EVA_MAIL, contact],
|
||||||
fail_silently=False)
|
fail_silently=False)
|
||||||
else:
|
else:
|
||||||
send_mail(
|
send_mail(
|
||||||
'EVA: Neuzugang',
|
f'EVA: Neuzugang {firstname} {lastname}',
|
||||||
mail_template.render(context),
|
mail_template.render(context),
|
||||||
EVA_MAIL,
|
EVA_MAIL,
|
||||||
[MAILS[department]['MAIL'], self.instance.usermail],
|
[MAILS[department]['MAIL'], contact],
|
||||||
fail_silently=False)
|
fail_silently=False)
|
||||||
except BadHeaderError:
|
except BadHeaderError as error:
|
||||||
|
print(error)
|
||||||
self.instance.delete()
|
self.instance.delete()
|
||||||
return HttpResponse('Invalid header found. Data not saved!')
|
return HttpResponse(f'{error}<p>Invalid header found. Data not saved!')
|
||||||
except SMTPException:
|
except SMTPException as error:
|
||||||
|
print(error)
|
||||||
self.instance.delete()
|
self.instance.delete()
|
||||||
return HttpResponse('Error in sending mails (propably wrong adress?). Data not saved!')
|
return HttpResponse(f'{error}<p>Error in sending mails (propably wrong adress?). Data not saved!')
|
||||||
|
except Exception as error:
|
||||||
|
print(error)
|
||||||
|
# self.instance.delete()
|
||||||
|
return HttpResponse(f'{error}<p>Error in sending mails. Data not saved! Please contact ' + EVA_MAIL)
|
||||||
|
return False
|
||||||
|
|
||||||
def beautify_data(self, data):
|
def beautify_data(self, data):
|
||||||
''' # use long form for contextdata instead of short form if available
|
''' # use long form for contextdata instead of short form if available
|
||||||
|
|
|
@ -0,0 +1,208 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2022-02-07 14:44+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#: evapp/models.py:10
|
||||||
|
msgid "Programme"
|
||||||
|
msgstr "Programs"
|
||||||
|
|
||||||
|
#: evapp/models.py:11
|
||||||
|
msgid "Softwareentwicklung"
|
||||||
|
msgstr "Software development"
|
||||||
|
|
||||||
|
#: evapp/models.py:13
|
||||||
|
msgid "Kommunikation und Events"
|
||||||
|
msgstr "Communication and events"
|
||||||
|
|
||||||
|
#: evapp/models.py:14
|
||||||
|
msgid "Vorstand"
|
||||||
|
msgstr "Board"
|
||||||
|
|
||||||
|
#: evapp/models.py:18
|
||||||
|
msgid "Mac (nur für Grafiker_innen)"
|
||||||
|
msgstr "Mac (for graphic designer only)"
|
||||||
|
|
||||||
|
#: evapp/models.py:21
|
||||||
|
msgid "Windows (bitte Begründung angeben)"
|
||||||
|
msgstr "Windows (please give justification)"
|
||||||
|
|
||||||
|
#: evapp/models.py:22
|
||||||
|
msgid "Mac OS (nur wenn Mac gewählt)"
|
||||||
|
msgstr "Mac OS (only if you choose Mac)"
|
||||||
|
|
||||||
|
#: evapp/models.py:30
|
||||||
|
msgid "Anderes (Bitte unten angeben)"
|
||||||
|
msgstr "Others (please note below)"
|
||||||
|
|
||||||
|
#: evapp/models.py:33
|
||||||
|
msgid "Civic CRM (allgemein)"
|
||||||
|
msgstr "Civic CRM (regular)"
|
||||||
|
|
||||||
|
#: evapp/models.py:34
|
||||||
|
msgid "Civic CRM (Mailings, impliziert allgemein)"
|
||||||
|
msgstr "Civic CRM (mailings, regular implied)"
|
||||||
|
|
||||||
|
#: evapp/models.py:40
|
||||||
|
msgid "Allgemeiner Transponder"
|
||||||
|
msgstr "Regular Transponder"
|
||||||
|
|
||||||
|
#: evapp/models.py:41
|
||||||
|
msgid "Besondere Schließungen (bitte angeben)"
|
||||||
|
msgstr "Special Doors (please note below)"
|
||||||
|
|
||||||
|
#: evapp/models.py:42
|
||||||
|
msgid "Kein Transponder"
|
||||||
|
msgstr "No transponder"
|
||||||
|
|
||||||
|
#: evapp/models.py:50 evapp/templates/evapp/department_mail.txt:26
|
||||||
|
msgid "Vorname"
|
||||||
|
msgstr "Firstname"
|
||||||
|
|
||||||
|
#: evapp/models.py:51
|
||||||
|
msgid "Nachname"
|
||||||
|
msgstr "Lastname"
|
||||||
|
|
||||||
|
#: evapp/models.py:53
|
||||||
|
msgid "Bereich"
|
||||||
|
msgstr "Department"
|
||||||
|
|
||||||
|
#: evapp/models.py:57
|
||||||
|
msgid "Erster Arbeitstag"
|
||||||
|
msgstr "First workday"
|
||||||
|
|
||||||
|
#: evapp/models.py:58
|
||||||
|
msgid "Erster Tag der Anwesenheit in der Geschäftsstelle"
|
||||||
|
msgstr "First day in the office"
|
||||||
|
|
||||||
|
#: evapp/models.py:61
|
||||||
|
msgid "Braucht Arbeitsplatz in der Geschäftsstelle?)"
|
||||||
|
msgstr "Needs a working place in the office"
|
||||||
|
|
||||||
|
#: evapp/models.py:62
|
||||||
|
msgid "Wo soll der Arbeitsplatz sein?"
|
||||||
|
msgstr "Where should the desk be?"
|
||||||
|
|
||||||
|
#: evapp/models.py:65
|
||||||
|
msgid "Hersteller"
|
||||||
|
msgstr "Manufacterer"
|
||||||
|
|
||||||
|
#: evapp/models.py:66
|
||||||
|
msgid "Betriebssystem"
|
||||||
|
msgstr "Operating system"
|
||||||
|
|
||||||
|
#: evapp/models.py:67
|
||||||
|
msgid "Zusätzlicher Monitor? Einer ist standard."
|
||||||
|
msgstr "Additional monitor. One is standard."
|
||||||
|
|
||||||
|
#: evapp/models.py:68
|
||||||
|
msgid "Diensttelefon (Handy)"
|
||||||
|
msgstr "work phone (mobile)"
|
||||||
|
|
||||||
|
#: evapp/models.py:70
|
||||||
|
msgid "Tastaturlayout"
|
||||||
|
msgstr "Keyboard layout"
|
||||||
|
|
||||||
|
#: evapp/models.py:71
|
||||||
|
msgid "zusätzliche IT-Anforderungen"
|
||||||
|
msgstr "Additional IT requirements"
|
||||||
|
|
||||||
|
#: evapp/models.py:72
|
||||||
|
msgid "Sprache"
|
||||||
|
msgstr "Language"
|
||||||
|
|
||||||
|
#: evapp/models.py:73
|
||||||
|
msgid "Zusätzliche Accounts"
|
||||||
|
msgstr "Additional accounts"
|
||||||
|
|
||||||
|
#: evapp/models.py:74
|
||||||
|
msgid "Zusätzliche Mailinglisten"
|
||||||
|
msgstr "additional mailing lists"
|
||||||
|
|
||||||
|
#: evapp/models.py:75
|
||||||
|
msgid "Rebu2Go-Zugang benötigt?"
|
||||||
|
msgstr "Needs Rebu2Go account"
|
||||||
|
|
||||||
|
#: evapp/models.py:79
|
||||||
|
msgid "Besondere Schließungen hier eintragen"
|
||||||
|
msgstr "Special access for doors"
|
||||||
|
|
||||||
|
#: evapp/models.py:80
|
||||||
|
msgid "Postfach am Empfang benötigt?"
|
||||||
|
msgstr "Needs mailbox at reception"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:36
|
||||||
|
msgid "WARNUNG! Test-MODUS aktiviert. Es werden keine Mails verschickt!"
|
||||||
|
msgstr "ATTENTION! Test mode activated. No mails will be send."
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:40
|
||||||
|
msgid "Du bist eingeloggt als"
|
||||||
|
msgstr "You are logged in as"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:42
|
||||||
|
msgid "Schritt"
|
||||||
|
msgstr "Step"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:42
|
||||||
|
msgid "von"
|
||||||
|
msgstr "from"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:44
|
||||||
|
msgid "Angaben zur Person"
|
||||||
|
msgstr "Personal Data"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:47
|
||||||
|
msgid "Angaben zum neuen Arbeitsverhältnis"
|
||||||
|
msgstr "Details of the employment"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:49
|
||||||
|
msgid "IT-relevante Angaben"
|
||||||
|
msgstr "IT-relevant details"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:51
|
||||||
|
msgid "Office-relevante Angaben"
|
||||||
|
msgstr "Office relevant details"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:59
|
||||||
|
msgid "Bestätigungsschritt"
|
||||||
|
msgstr "Confirmation step"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:91
|
||||||
|
msgid "Pflichtfeld"
|
||||||
|
msgstr "Required field"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:94
|
||||||
|
msgid "Zurück"
|
||||||
|
msgstr "Back"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:97
|
||||||
|
#: evapp/templates/evapp/employee_form.html:99
|
||||||
|
msgid "Weiter"
|
||||||
|
msgstr "Next"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:97
|
||||||
|
msgid "Abschicken"
|
||||||
|
msgstr "Send"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:103
|
||||||
|
msgid "logout"
|
||||||
|
msgstr "logout"
|
||||||
|
|
||||||
|
#: evapp/templates/evapp/employee_form.html:107
|
||||||
|
msgid "Bitte einloggen!"
|
||||||
|
msgstr "Please log in!"
|
Loading…
Reference in New Issue