1451 lines
51 KiB
Python
1451 lines
51 KiB
Python
from django.shortcuts import render, redirect, reverse
|
|
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.conf import settings
|
|
from .usersforms import UsersAddNewUser, UsersAddProfileForm, UsersChangeProfil, AgencyUpdateForm, UsersPermForm, UserAreaTaskForm, SupportForm, NewAgencyForm, NewAgencyFormRD, FormRD
|
|
from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView, View, TemplateView
|
|
from django.contrib import messages
|
|
from django.contrib.auth.models import User, Permission
|
|
from django.db import models
|
|
from .models import Profile, Agency, UserTime, UserYearAbsenceInfo, AgencyBills, RegNotfallhilfe
|
|
from django.core.mail import send_mail
|
|
from django.http import HttpResponseRedirect,HttpResponse, JsonResponse
|
|
from areas.models import Areas
|
|
from tasks.models import Tasks
|
|
from organizer.models import QuickLinks
|
|
from .priomodel import Prio
|
|
from standards.models import Standards
|
|
from datetime import datetime
|
|
from django.utils import timezone
|
|
from django.utils import formats
|
|
from news.models import News
|
|
from cloud.models import DataFile
|
|
import requests
|
|
import json
|
|
import random
|
|
import string
|
|
from PIL import Image
|
|
from django.template.loader import render_to_string
|
|
from django.contrib.auth.forms import PasswordResetForm
|
|
from django.template.loader import render_to_string
|
|
from io import StringIO
|
|
from users.models import AgencyJob, AgencyGroup
|
|
from django.contrib.auth.models import Group
|
|
from cloud.models import DataDir
|
|
from message.models import Message
|
|
from notificsys.models import UserNotification
|
|
from organizer.models import AGContacts, AGPassword
|
|
import sys, os
|
|
from asgiref.sync import async_to_sync
|
|
from channels_presence.models import Room
|
|
from channels_presence.models import Presence
|
|
import channels.layers
|
|
from datetime import date, timedelta
|
|
from timemanagement.models import Workday, Absence, Breaks
|
|
import base64
|
|
import filetype
|
|
from django.db.models.signals import m2m_changed
|
|
from django.contrib.auth.models import User, Group
|
|
from users.signals import adjust_group_notifications_permission
|
|
from django.core.exceptions import ObjectDoesNotExist
|
|
|
|
def randomString(stringLength=10):
|
|
"""Generate a random string of fixed length """
|
|
letters = string.ascii_lowercase
|
|
return ''.join(random.choice(letters) for i in range(stringLength))
|
|
|
|
@login_required
|
|
def toUpdate(request):
|
|
# NO AGENVYJOBS
|
|
# CREATE DEFAULT
|
|
'''
|
|
|
|
Agenturleiter
|
|
Außendienst
|
|
Innendienst
|
|
Auszubildender
|
|
|
|
'''
|
|
agencyjobsobject = AgencyJob.objects.filter(agency__pk=request.user.profile.agency.pk)
|
|
if(len(agencyjobsobject) == 0):
|
|
defaultAgencyJobs = ['Agenturleiter', 'Außendienst', 'Innendienst', 'Auszubildender']
|
|
for ele in defaultAgencyJobs:
|
|
tempAgencyJob = AgencyJob(name=ele, agency=request.user.profile.agency)
|
|
tempAgencyJob.save()
|
|
|
|
agencygroups = AgencyGroup.objects.filter(agency__pk=request.user.profile.agency.pk)
|
|
if(len(agencygroups) == 0):
|
|
print("default groups not existing - creating")
|
|
# MITARBEITER
|
|
letters = string.ascii_lowercase
|
|
temgroup_mitarbeiter = Group(name=str(request.user.profile.agency.pk) + "_" + randomString(8))
|
|
temgroup_mitarbeiter.save()
|
|
temgroup_mitarbeiter_ag = AgencyGroup(savefordel=True, group=temgroup_mitarbeiter, agency=request.user.profile.agency, agencygroupname="Mitarbeiter")
|
|
temgroup_mitarbeiter_ag.save()
|
|
|
|
# VERWALTUNG
|
|
temgroup_verwaltung = Group(name=str(request.user.profile.agency.pk) + "_" + randomString(8))
|
|
temgroup_verwaltung.save()
|
|
temgroup_verwaltung_ag = AgencyGroup(savefordel=True, is_admin=True, group=temgroup_verwaltung, agency=request.user.profile.agency, agencygroupname="Administratoren")
|
|
temgroup_verwaltung_ag.save()
|
|
|
|
print("default groups created...adding users...")
|
|
users_of_agency = User.objects.filter(profile__agency__pk=request.user.profile.agency.pk)
|
|
for user in users_of_agency:
|
|
#print(temgroup_verwaltung_ag)
|
|
#print(temgroup_verwaltung_ag.group)
|
|
temgroup_verwaltung_ag.group.user_set.add(user)
|
|
temgroup_mitarbeiter_ag.group.user_set.add(user)
|
|
|
|
# ADDING ALL RIGHTS TO GROUP "VERWALTUNG"
|
|
perms = AgencyGroup._meta.permissions
|
|
for p in perms:
|
|
tempperm = Permission.objects.get(codename=p[0])
|
|
temgroup_verwaltung_ag.group.permissions.add(tempperm)
|
|
print("default groups created and users added")
|
|
else:
|
|
print("default groups existing")
|
|
|
|
# UPDATE - Notfallhilfe
|
|
# Gruppe Notfallhilfe wird hinzugefügt, wenn die Anzahl der Gruppen savefordel=True zwei ist
|
|
if (len(AgencyGroup.objects.filter(agency=request.user.profile.agency, savefordel=True)) == 2):
|
|
print("missing recoverdir-group...adding")
|
|
# Notfallhilfe
|
|
letters = string.ascii_lowercase
|
|
temgroup_Notfallhilfe = Group(name=str(request.user.profile.agency.pk) + "_" + randomString(8))
|
|
temgroup_Notfallhilfe.save()
|
|
temgroup_Notfallhilfe_ag = AgencyGroup(savefordel=True, group=temgroup_Notfallhilfe, agency=request.user.profile.agency, agencygroupname="Notfallhilfe")
|
|
temgroup_Notfallhilfe_ag.save()
|
|
|
|
recoverdirmanagingperm = Permission.objects.get(codename='recoverdirmanager')
|
|
temgroup_Notfallhilfe_ag.group.permissions.add(recoverdirmanagingperm)
|
|
print("recoverdirgroup added and perms set")
|
|
|
|
# CHECK FOR ALL POSSIBLE RIGHTS ON ADMINGROUP
|
|
m2m_changed.disconnect(adjust_group_notifications_permission, sender=Group.permissions.through)
|
|
|
|
ag_admingroup = list(AgencyGroup.objects.filter(agency=request.user.profile.agency, is_admin=True))[0]
|
|
perms = AgencyGroup._meta.permissions
|
|
for p in perms:
|
|
tempperm = Permission.objects.get(codename=p[0])
|
|
ag_admingroup.group.permissions.add(tempperm)
|
|
|
|
|
|
|
|
# INITIAL ROOT DIR
|
|
rootdir = DataDir.objects.filter(is_root=True, agency__pk=request.user.profile.agency.pk)
|
|
|
|
if(len(rootdir) == 0):
|
|
print("NO MAIN DIR FOUND - CREATE")
|
|
rootdir = DataDir(is_root=True, agency=request.user.profile.agency)
|
|
rootdir.save()
|
|
print("AGENCY ROOT DIR CREATED")
|
|
else:
|
|
print("MAIN ROOT DIR FOUND - FILESMODULE READY")
|
|
|
|
# CHECK IF AGENCY DIRS EXIST
|
|
path = settings.MEDIA_ROOT + "/agencydata/agency_" + str(request.user.profile.agency.pk)
|
|
if(os.path.isdir(path) == False):
|
|
# CREATE AGENCY DEFAULT DIRS
|
|
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk)))
|
|
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/files"))
|
|
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/agencystats"))
|
|
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/agencystats/profilepics"))
|
|
|
|
# DEF STANDARD DIR
|
|
defstandard = DataDir.objects.filter(is_defaultstandard=True, agency__pk=request.user.profile.agency.pk)
|
|
|
|
if(len(defstandard) == 0):
|
|
print("NO DEF STANDARD FOUND - CREATE")
|
|
rootdir = list(DataDir.objects.filter(is_root=True, agency__pk=request.user.profile.agency.pk))[0]
|
|
defstandard = DataDir(is_defaultstandard=True, agency=request.user.profile.agency, name="Standards Uploadbereich", parent_id=rootdir.pk)
|
|
defstandard.save()
|
|
print("AGENCY DEF STANDARD DIR CREATED")
|
|
else:
|
|
print("AGENCY DEF STANDARD DIR - FILESMODULE READY")
|
|
|
|
|
|
# CHANGE RIGHTS ORGNAIZER
|
|
admingroups = AgencyGroup.objects.filter(is_admin=True)
|
|
for a in admingroups:
|
|
a.group.permissions.add(Permission.objects.get(codename="moduleorganizer"))
|
|
a.group.permissions.add(Permission.objects.get(codename="agencynetwork"))
|
|
|
|
|
|
m2m_changed.connect(adjust_group_notifications_permission, sender=Group.permissions.through)
|
|
|
|
# USER TIME MODEL
|
|
usersofagency = User.objects.filter(profile__agency=request.user.profile.agency)
|
|
|
|
for u in usersofagency:
|
|
# CREATE USERTIME-OBJECT
|
|
if(len(UserTime.objects.filter(user=u)) == 0):
|
|
usertime_new = UserTime(user=u)
|
|
usertime_new.save()
|
|
else:
|
|
ut = UserTime.objects.get(user=u)
|
|
if(ut.loose_holidedate == "2020-" or ut.loose_holidedate == "2021-"):
|
|
ut.loose_holidedate = "30.04"
|
|
ut.save()
|
|
|
|
def onlyRD(request):
|
|
if request.method == "POST":
|
|
rdform = FormRD(request.POST)
|
|
|
|
if rdform.is_valid():
|
|
rd = RegNotfallhilfe()
|
|
rd.mail = rdform.cleaned_data.get('mail')
|
|
rd.name = rdform.cleaned_data.get('name')
|
|
rd.persnumber = rdform.cleaned_data.get("persnumber")
|
|
rd.mitgliedsnummer = rdform.cleaned_data.get("mitgliedsnummer")
|
|
rd.plz = rdform.cleaned_data.get("plz")
|
|
rd.stadt = rdform.cleaned_data.get("stadt")
|
|
rd.street = rdform.cleaned_data.get("street")
|
|
rd.data_to_vh = True
|
|
rd.rabatt = False
|
|
rd.save()
|
|
return render (request, 'users/rdorder_complete.html')
|
|
else:
|
|
messages.success(request, f'Bitte geben Sie korrekte Daten ein!')
|
|
context = {
|
|
"form" : FormRD(request.POST)
|
|
}
|
|
return render (request, 'users/register_rd.html',context)
|
|
else:
|
|
context = {
|
|
"form" : FormRD()
|
|
}
|
|
return render (request, 'users/register_rd.html',context)
|
|
|
|
|
|
|
|
'''
|
|
|
|
Neue Agentur UND Notfallhilfe bestellen
|
|
|
|
'''
|
|
def registerNewAgencyRD(request):
|
|
if request.method == "POST":
|
|
newagencyform = NewAgencyFormRD(request.POST)
|
|
|
|
|
|
if newagencyform.is_valid():
|
|
# Check Mail
|
|
email = newagencyform.cleaned_data.get('mail')
|
|
|
|
mailset = User.objects.filter(email=email)
|
|
if(len(mailset) == 0):
|
|
# AGENTURREGISTRIERUNG
|
|
newuser_name = newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name')
|
|
|
|
agency = Agency()
|
|
agency.name = newagencyform.cleaned_data.get("agencyname")
|
|
agency.vve = newagencyform.cleaned_data.get("vve")
|
|
agency.street = newagencyform.cleaned_data.get("street")
|
|
agency.city = newagencyform.cleaned_data.get("stadt")
|
|
agency.plz = newagencyform.cleaned_data.get("plz")
|
|
agency.save()
|
|
pr=Profile()
|
|
pr.agency=agency
|
|
user = ""
|
|
try:
|
|
user=User.objects.create_user(email, email, randomString(30))
|
|
except:
|
|
user = User.objects.get(username=email)
|
|
user.first_name = newagencyform.cleaned_data.get('first_name')
|
|
user.last_name = newagencyform.cleaned_data.get('last_name')
|
|
pr.user=user
|
|
pr.save()
|
|
user.profile = pr
|
|
user.save()
|
|
|
|
msg_html = render_to_string('users/register_mail.html', {'username': newuser_name})
|
|
|
|
|
|
# NOTFALLHILFE-DATEN SPEICHERN
|
|
rd = RegNotfallhilfe()
|
|
rd.mail = email
|
|
rd.name = newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name')
|
|
rd.persnumber = newagencyform.cleaned_data.get("persnumber")
|
|
rd.mitgliedsnummer = newagencyform.cleaned_data.get("vve")
|
|
rd.plz = newagencyform.cleaned_data.get("plz")
|
|
rd.stadt = newagencyform.cleaned_data.get("stadt")
|
|
rd.street = newagencyform.cleaned_data.get("street")
|
|
rd.data_to_vh = True
|
|
rd.rabatt = True
|
|
rd.save()
|
|
|
|
# E-Mail für Passwort-Setzung!
|
|
form = PasswordResetForm({'email': email})
|
|
if form.is_valid():
|
|
form.save(request=request,html_email_template_name='users/password_reset_mail.html')
|
|
return render (request, 'users/registercomplete.html')
|
|
|
|
else:
|
|
messages.success(request, f'Diese E-Mailadresse ist bereits vergeben!')
|
|
context = {
|
|
"form" : NewAgencyFormRD(request.POST)
|
|
}
|
|
return render (request, 'users/register_da_rd.html',context)
|
|
else:
|
|
messages.success(request, f'Bitte die korrekten Symbole aus dem Bild eingeben!')
|
|
|
|
context = {
|
|
"form" : NewAgencyForm(request.POST)
|
|
}
|
|
return render (request, 'users/register_da_rd.html',context)
|
|
|
|
else:
|
|
context = {
|
|
"form" : NewAgencyFormRD()
|
|
}
|
|
return render (request, 'users/register_da_rd.html',context)
|
|
|
|
|
|
|
|
'''
|
|
Neue Agentur registrieren
|
|
|
|
'''
|
|
def registerNewAgency(request):
|
|
if request.method == "POST":
|
|
|
|
newagencyform = NewAgencyForm(request.POST)
|
|
|
|
if newagencyform.is_valid():
|
|
|
|
# Check Mail
|
|
email = newagencyform.cleaned_data.get('mail')
|
|
|
|
mailset = User.objects.filter(email=email)
|
|
if(len(mailset) == 0):
|
|
newuser_name = newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name')
|
|
|
|
agency = Agency()
|
|
agency.name = newagencyform.cleaned_data.get("agencyname")
|
|
agency.vve = newagencyform.cleaned_data.get("vve")
|
|
agency.save()
|
|
pr=Profile()
|
|
pr.agency=agency
|
|
user = ""
|
|
try:
|
|
user=User.objects.create_user(email, email, randomString(30))
|
|
except:
|
|
user = User.objects.get(username=email)
|
|
user.first_name = newagencyform.cleaned_data.get('first_name')
|
|
user.last_name = newagencyform.cleaned_data.get('last_name')
|
|
pr.user=user
|
|
pr.save()
|
|
user.profile = pr
|
|
user.save()
|
|
|
|
msg_html = render_to_string('users/register_mail.html', {'username': newuser_name})
|
|
|
|
# E-Mail für Passwort-Setzung!
|
|
form = PasswordResetForm({'email': email})
|
|
if form.is_valid():
|
|
form.save(request=request,html_email_template_name='users/password_reset_mail.html')
|
|
return render (request, 'users/registercomplete.html')
|
|
|
|
'''
|
|
send_mail(
|
|
'Agenturanmeldung',
|
|
'Hallo ' + newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name') + '! Bitte setzen sie sich auf https://app.digitale-agentur.com/password-reset/ ein Passwort. Anschließend können Sie weitere Details Ihrer Agentur eingeben.',
|
|
'noreply@digitale-agentur.com',
|
|
[email],
|
|
html_message=msg_html,
|
|
fail_silently=True
|
|
)
|
|
'''
|
|
return render (request, 'users/registercomplete.html')
|
|
|
|
else:
|
|
messages.success(request, f'Diese E-Mailadresse ist bereits vergeben!')
|
|
context = {
|
|
"form" : NewAgencyForm(request.POST)
|
|
}
|
|
return render (request, 'users/register.html',context)
|
|
|
|
else:
|
|
messages.success(request, f'Bitte die korrekten Symbole aus dem Bild eingeben!')
|
|
|
|
context = {
|
|
"form" : NewAgencyForm(request.POST)
|
|
}
|
|
return render (request, 'users/register.html',context)
|
|
else:
|
|
context = {
|
|
"form" : NewAgencyForm()
|
|
}
|
|
return render (request, 'users/register.html',context)
|
|
|
|
class AgencyCreateView(CreateView):
|
|
model = User
|
|
fields = ['first_name', 'last_name','username', 'email']
|
|
success_url = '/register/done'
|
|
|
|
def form_valid(self, form):
|
|
# Send message to the site
|
|
messages.success(self.request, f'Agentur erstellt! Es wurde eine E-Mail verschickt mit weitere Infos zur Passworterstellung.')
|
|
# SAVE OBJECTS TO SIGNALE!
|
|
agency = Agency()
|
|
agency.name = self.request.POST.get("agency_name")
|
|
agency.save()
|
|
newuser_name = form.cleaned_data.get('first_name') + ' ' + form.cleaned_data.get('last_name')
|
|
form.instance.agency = agency
|
|
form.instance.parent = None
|
|
msg_html = render_to_string('users/register_mail.html', {'username': newuser_name})
|
|
# E-Mail für Passwort-Setzung!
|
|
send_mail(
|
|
'Agenturanmeldung',
|
|
'Hallo ' + form.cleaned_data.get('first_name') + ' ' + form.cleaned_data.get('last_name') + '! Bitte setzen sie sich auf https://app.digitale-agentur.com/password-reset/ ein Passwort. Anschließend können Sie weitere Details Ihrer Agentur eingeben.',
|
|
'noreply@digitale-agentur.com',
|
|
[form.cleaned_data.get('email')],
|
|
html_message=msg_html,
|
|
fail_silently=True
|
|
)
|
|
return super().form_valid(form)
|
|
|
|
|
|
@login_required
|
|
def dashboard(request):
|
|
|
|
# UPDATE FUNCTIONS BY NEW MODEL-CHANGES FOR COPIEN SOME DATA
|
|
toUpdate(request)
|
|
|
|
|
|
#storageinfo = sys.getfilesystemencoding()
|
|
|
|
context = {
|
|
'active_link' : 'dashboard',
|
|
#"systemencode" : storageinfo
|
|
}
|
|
# Adding active_link
|
|
# Loading only user same agency
|
|
# Change context and return for template-data
|
|
# # Get all Users of the Same Agency as logged user
|
|
standards_of_agency = Standards.objects.filter(agency__pk=request.user.profile.agency.pk).filter(public=True).exclude(area=None).exclude(task=None).order_by('-last_modified_on')[:5]
|
|
|
|
filterdate = datetime.now()
|
|
#news = News.objects.filter(agency__pk=request.user.profile.agency.pk).filter(go_online_on__let=filterdate).filter(go_offline_on__get=filterdate).order_by('-go_online_on')[:4]
|
|
news = news = News.objects.filter(agency__pk=request.user.profile.agency.pk).filter(go_online_on__lt=filterdate).filter(go_offline_on__gt=filterdate).order_by('-created_date') | News.objects.filter(agency__pk=request.user.profile.agency.pk).filter(go_online_on__lt=filterdate).filter(go_offline_on__isnull=True).order_by('-created_date')
|
|
context.update({'active_link' : 'dashboard', 'standards_of_agency' : standards_of_agency, 'news' : news})
|
|
|
|
# GET ACUTAL ABSENCES
|
|
today = date.today()
|
|
acutal_absences = Absence.objects.filter(agency=request.user.profile.agency, end__gte=today, start__lte=today, confirm_status=0).order_by('user')
|
|
context.update({'acutal_absences' : acutal_absences})
|
|
return render (request, 'users/dashboard.html', context)
|
|
|
|
class UsersManagement(LoginRequiredMixin, ListView):
|
|
model = User
|
|
|
|
# Adding active_link
|
|
# Loading only user same agency
|
|
# Change context and return for template-data
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
# Get all Users of the Same Agency as logged user
|
|
users_of_agency = User.objects.filter(profile__agency__pk=self.request.user.profile.agency.pk).order_by('last_name')
|
|
context.update({'active_link' : 'usersmanagement', 'users_of_agency':users_of_agency})
|
|
return context
|
|
|
|
'''
|
|
Class AddNewUser()
|
|
|
|
Erstellt einen neuen Nutzer mit SIGNALS, Profile und Agency (des aktuellen Users mit Rechten)
|
|
|
|
'''
|
|
class UsersCreateUser(LoginRequiredMixin, CreateView):
|
|
model = User
|
|
fields = ['first_name', 'last_name', 'email']
|
|
success_url = '/settings/newuser/s2/'
|
|
|
|
# Adding active_link
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context.update({'active_link' : 'settings'})
|
|
return context
|
|
|
|
def form_valid(self, form):
|
|
# Send message to the site
|
|
messages.success(self.request, f'Neuer Mitarbeiter angelegt!')
|
|
# SAVE OBJECTS TO SIGNALE!
|
|
form.instance.agency = self.request.user.profile.agency
|
|
form.instance.parent = None
|
|
newuser_name = form.cleaned_data.get('first_name') + " " + form.cleaned_data.get('last_name')
|
|
msg_html = render_to_string('users/newusers_email.html', {'username': newuser_name})
|
|
'''
|
|
if(self.request.POST.get("sendmailnewuser")):
|
|
send_mail(
|
|
self.request.user.profile.agency.name + ' Account',
|
|
'Hallo ' + form.cleaned_data.get('first_name') + ' ' + form.cleaned_data.get('last_name') + '! Bitte setzen sie sich auf https://app.digitale-agentur.com/password-reset/ ein Passwort.',
|
|
'noreply@digitale-agentur.com',
|
|
[form.cleaned_data.get('email')],
|
|
html_message=msg_html,
|
|
fail_silently=True,
|
|
)
|
|
'''
|
|
return super().form_valid(form)
|
|
|
|
# USER muss eingeloggt sein, um diese Seite zu sehen
|
|
@login_required
|
|
def profile(request):
|
|
if request.method == 'POST':
|
|
u_form = UsersChangeProfil(request.POST, instance=request.user)
|
|
|
|
if u_form.is_valid():
|
|
u_form.save()
|
|
prename = request.user.first_name
|
|
name = request.user.last_name
|
|
messages.success(request, f'Daten für {prename} {name} aktualisiert!')
|
|
# Daten neu laden und nicht die "Mächten sie die Daten speichern...?"
|
|
return redirect('users-dashboard')
|
|
|
|
else:
|
|
# Form in Klammern sind die aktuellen Daten :)
|
|
u_form = UsersChangeProfil(instance=request.user)
|
|
#p_form = UsersAddProfileForm(instance=request.user.profile)
|
|
|
|
context = {
|
|
'u_form' : u_form,
|
|
#'p_form' : p_form,
|
|
'active_link' : 'dashboard'
|
|
}
|
|
return render(request, 'users/profile.html', context)
|
|
|
|
# Hier andere Nutzer ändern, wenn man Usersmanagement darf!
|
|
class UserManagementUpdateForm(LoginRequiredMixin, UpdateView):
|
|
model = Profile
|
|
labels = {
|
|
"phoneland" : "Telefon",
|
|
"phonemobile" : "Mobil",
|
|
"compfunc" : "Agenturfunktion",
|
|
}
|
|
fields = ['phoneland','phonemobile','compfunc']
|
|
|
|
# Update der Zugrifssrechte eines Users
|
|
class UsersPermUpdateView(LoginRequiredMixin, View):
|
|
template_name = 'users/users_perm.html'
|
|
form_class = UsersPermForm
|
|
success_url = '/dashboard/usersman/'
|
|
|
|
|
|
# Form wird geladen; Checkboxen werden vorbereitet und hier rausgerendert.
|
|
def get(self,request,*args, **kwargs):
|
|
# User ist der hier Aufgerufene, bzw. das Profil!
|
|
user_tochange = Profile.objects.get(pk=kwargs['pk']).user
|
|
return render (request, self.template_name, {'form':self.form_class(user_tochange), 'active_link': 'usersmanagement', 'user_tochange': user_tochange})
|
|
|
|
# Handle POST GTTP requests
|
|
def post(self, request, *args, **kwargs):
|
|
permissions_loaded = dict(request.POST.lists())
|
|
user_tochange = Profile.objects.get(pk=kwargs['pk']).user
|
|
# ITERATION Über alle Elemente gehen und Rechte entziehen (nicht vorhanden) oder adden (wenn vorhanden)
|
|
# Hat ein user ein Recht NICHT, ist es NICHT in permissions
|
|
# LOAD PERMISSIONS
|
|
temprof = Profile
|
|
for ele in temprof._meta.permissions:
|
|
tempperm = Permission.objects.get(codename=ele[0])
|
|
if ele[0] in permissions_loaded:
|
|
user_tochange.user_permissions.add(tempperm)
|
|
else:
|
|
# Eingeloggter User darf sich nicht selbst die Userverwaltungsrechte entziehen
|
|
if user_tochange == request.user and ele[0]=='usermanager':
|
|
messages.warning(request, f'Benutzerverwaltungsrechte für {user_tochange.first_name} {user_tochange.last_name} kann nicht entfernt werden.')
|
|
else:
|
|
user_tochange.user_permissions.remove(tempperm)
|
|
user_tochange.save()
|
|
messages.success(request, f'Berechtigungen für {user_tochange.first_name} {user_tochange.last_name} aktualisiert!')
|
|
return HttpResponseRedirect('/dashboard/usersman/')
|
|
|
|
# Benutzerprofil wird aktualisiert
|
|
@login_required
|
|
def ProfileUpdateView(request, pk):
|
|
prof_user = User.objects.get(profile__pk=pk)
|
|
|
|
if request.method == 'POST':
|
|
profileform_form = UsersAddProfileForm(request.POST, request.FILES, instance=prof_user.profile)
|
|
#profileform_parents = UsersAddProfileFormParents(request.POST, instance=request.user)
|
|
prename = prof_user.first_name
|
|
name = prof_user.last_name
|
|
|
|
if profileform_form.is_valid():
|
|
profileform_form.save()
|
|
messages.success(request, f'Daten für {prename} {name} aktualisiert!')
|
|
return redirect('users-management')
|
|
|
|
else:
|
|
# Form in Klammern sind die aktuellen Daten :)
|
|
profileform_form = UsersAddProfileForm(instance=prof_user.profile)
|
|
|
|
# Nur User, die im Organigramm auch sichtbar sein, können ausgewählt werden
|
|
possible_users = User.objects.filter(profile__agency__pk=prof_user.profile.agency.pk).filter(profile__visible=True)
|
|
|
|
context = {
|
|
'prof_user' : prof_user,
|
|
'profileform_form' : profileform_form,
|
|
'active_link' : 'usersmanagement',
|
|
'possible_users' : possible_users
|
|
}
|
|
|
|
|
|
return render(request, 'users/profile_update.html', context)
|
|
|
|
'''
|
|
|
|
Set users Parent by AJAX
|
|
|
|
'''
|
|
@login_required
|
|
def setuserparent(request):
|
|
if request.method == 'GET':
|
|
if request.GET['action'] == 'adduserp':
|
|
userid = request.GET['objectid']
|
|
toadd = request.GET['userid']
|
|
toadd_user = User.objects.get(pk=toadd)
|
|
workinguser = User.objects.get(pk=userid)
|
|
username_clean = toadd_user.first_name + " " + toadd_user.last_name
|
|
workinguser.profile.parent = toadd_user
|
|
workinguser.save()
|
|
# Getting Remaining-Users
|
|
possible_users = User.objects.filter(profile__agency__pk=request.user.profile.agency.pk)
|
|
possible_users_js = list(possible_users.values())
|
|
# Cleaned out, that only data is neede will send to the side (first/last-name and id)
|
|
final_possible_users = {}
|
|
for ele in possible_users_js:
|
|
final_possible_users.update({'first_name':ele['first_name'],'last_name':ele['last_name'],'id':ele['id']})
|
|
# Counter for remaining users to show/hide "Keine Mitarbeiter"-Div
|
|
return JsonResponse({'userid' : userid, 'username_clean' : username_clean, 'remaining_users':possible_users_js})
|
|
else:
|
|
return HttpResponse("Request method is not a GET")
|
|
|
|
@login_required
|
|
def changeonlinestat(request):
|
|
if request.method == 'GET':
|
|
request.user.profile.onlinestatus = request.GET["newstat"]
|
|
request.user.save()
|
|
return JsonResponse({"newstat" : request.GET["newstat"]})
|
|
|
|
'''
|
|
|
|
# DELETE A USER
|
|
|
|
Hier wird das Profil gelöscht, aber damit auch der User. Zusätzlich werden
|
|
alle Standards, Bereiche und Tasks des zu löschenden Nutzers dem User
|
|
zugeschrieben, welcher eingeloggt ist. Das passiert VOR dem löschen!
|
|
|
|
'''
|
|
|
|
|
|
import csv
|
|
|
|
@login_required
|
|
def getDataFromToDelUser(request, pk):
|
|
if(request.method == "GET"):
|
|
user = User.objects.get(pk=pk)
|
|
|
|
response = HttpResponse(content_type='text/csv')
|
|
response['Content-Disposition'] = 'attachment; filename="DA-Export_'+ user.first_name + "_" + user.last_name + '.csv"'
|
|
|
|
writer = csv.writer(response)
|
|
|
|
# TASK: Hier besprechen, ob das Recht als Benutzermanager ausreicht!
|
|
if(request.user.has_perm("users.usermanager") and user.profile.agency == request.user.profile.agency):
|
|
|
|
user_absences = Absence.objects.filter(agency=request.user.profile.agency, user=user).order_by("-start")
|
|
|
|
for ab in user_absences:
|
|
status = "OK"
|
|
if(ab.confirm_status == 1 or ab.confirm_status == 2):
|
|
status = "Abgelehnt"
|
|
writer.writerow(['Abwesenheit', str(ab.start), str(ab.end), 'Grund: '+ab.reason.name, 'Status: '+status])
|
|
|
|
user_workdays = Workday.objects.filter(agency=request.user.profile.agency, user=user).order_by("-start")
|
|
for wd in user_workdays:
|
|
breaks = Breaks.objects.filter(agency=request.user.profile.agency, user=user, workday=wd)
|
|
breaks_string = ""
|
|
for b in breaks:
|
|
breaks_string += str(b.start) + " bis " + str(b.end) + ", "
|
|
|
|
writer.writerow(['Arbeitstag', str(wd.start), str(wd.end), 'Pausen: ' + breaks_string])
|
|
return response
|
|
else:
|
|
pass
|
|
|
|
|
|
class ProfileDeleteView(LoginRequiredMixin, DeleteView):
|
|
model = User
|
|
success_url = '/dasettings/main'
|
|
template_name = 'users/user_confirm_delete.html'
|
|
|
|
# Adding active_link
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
# Hier Daten zusammenstellen, damit alle Daten bzgl Vertrag nicht verloren gehen (Zeiterfassung, Urlaub und Abwesenheiten)
|
|
|
|
response = HttpResponse(content_type='text/csv')
|
|
response['Content-Disposition'] = 'attachment; filename="file.csv"'
|
|
writer = csv.writer(response)
|
|
writer.writerow(['1001', 'John', 'Domil', 'CA'])
|
|
writer.writerow(['1002', 'Amit', 'Mukharji', 'LA', '"Testing"'])
|
|
context.update({"response" : response})
|
|
print(response)
|
|
return context
|
|
|
|
|
|
def delete(self, request, *args, **kwargs):
|
|
user = User.objects.get(pk=kwargs['pk'])
|
|
logged_user = request.user
|
|
|
|
''' ALTER LÖSCHBEREICH - User wird einfach entfernt '''
|
|
|
|
'''
|
|
|
|
areas_fs = Areas.objects.filter(created_area_by=user)
|
|
for a in areas_fs:
|
|
a.created_area_by = logged_user
|
|
a.save()
|
|
|
|
# ACHTUNG! Bei Tasks heißt es leider auch created_area...
|
|
task_fs = Tasks.objects.filter(created_area_by=user)
|
|
for t in task_fs:
|
|
t.created_area_by = logged_user
|
|
t.save()
|
|
|
|
standards_fs = Standards.objects.filter(created_standard_by=user)
|
|
#print(standards_fs)
|
|
for a in standards_fs:
|
|
a.created_standard_by = logged_user
|
|
a.save()
|
|
|
|
standards_fs = Standards.objects.filter(last_modified_by=user)
|
|
for a in standards_fs:
|
|
a.last_modified_by = logged_user
|
|
a.save()
|
|
|
|
standards_fs = Standards.objects.filter(published_by=user)
|
|
for a in standards_fs:
|
|
a.published_by = logged_user
|
|
a.save()
|
|
'''
|
|
|
|
response = super(ProfileDeleteView, self).delete(request, *args, **kwargs)
|
|
name = user.first_name + " " + user.last_name
|
|
messages.success(request, f'Benutzer ' +name+ ' wurde gelöscht!')
|
|
return response
|
|
|
|
@login_required
|
|
def agency(request):
|
|
context = {
|
|
'active_link' : 'agencyinfo'
|
|
}
|
|
return render(request, 'users/agency.html', context)
|
|
|
|
|
|
class AgencyUpdateView(LoginRequiredMixin, UpdateView):
|
|
model = Agency
|
|
form_class = AgencyUpdateForm
|
|
template_name = 'users/agency_update.html'
|
|
success_url = '/dashboard/agencyinfo'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(AgencyUpdateView, self).get_context_data(**kwargs)
|
|
context['active_link'] = 'agencyinfo'
|
|
return context
|
|
|
|
|
|
# PRIORISIERUNG
|
|
'''
|
|
|
|
Es werden alle Aufgabenbereiche den Bereichen der Agentur zugeordnet und ausgegeben.
|
|
|
|
'''
|
|
@login_required
|
|
def UsersPrio(request, pk):
|
|
|
|
user = User.objects.get(pk=pk)
|
|
|
|
if(user.profile.agency.pk != request.user.profile.agency.pk):
|
|
return HttpResponseRedirect('users-dashboard')
|
|
else:
|
|
prios = Prio.objects.filter(user__pk=pk)
|
|
areas = Areas.objects.filter(agency__pk=request.user.profile.agency.pk)
|
|
user_first_name = user.first_name
|
|
user_last_name = user.last_name
|
|
user_id = user.pk
|
|
context = {
|
|
'active_link' : '',
|
|
'areas' : areas,
|
|
'user_first_name' : user_first_name,
|
|
'user_last_name' : user_last_name,
|
|
'user_id' : user_id,
|
|
'prios' : prios
|
|
}
|
|
|
|
return render(request, 'users/users_prio.html', context)
|
|
'''
|
|
|
|
Ajax-Call für Prio.Updates seitens des Users
|
|
im Profil
|
|
|
|
'''
|
|
@login_required
|
|
def UsersPrioUpdate(request):
|
|
tempuser = User.objects.get(pk=request.GET['userid'])
|
|
if request.method == 'GET' and tempuser.profile.agency.pk == request.user.profile.agency.pk:
|
|
prio = Prio.objects.filter(user__pk=request.GET['userid']).filter(task__pk=request.GET['taskid'])
|
|
prio = list(prio)[0]
|
|
prio.prio = request.GET['value']
|
|
prio.save()
|
|
return HttpResponse("udated...")
|
|
else:
|
|
return HttpResponse("Request method is not a GET")
|
|
|
|
import re
|
|
|
|
|
|
def cleanhtml(raw_html):
|
|
cleanr = re.compile('<.*?>')
|
|
cleantext = re.sub(cleanr, '', raw_html)
|
|
return cleantext
|
|
|
|
# Searxh for Standards by name, content, creator - standards needs to be public!
|
|
@login_required
|
|
def GlobalSearch(request):
|
|
if request.method == 'GET':
|
|
searchfor = request.GET['searchstring']
|
|
ag = request.user.profile.agency.pk
|
|
res_standard = Standards.objects.filter(agency__pk=ag, public=True).filter(name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(content__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(area__name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(task__name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(created_standard_by__last_name__icontains=searchfor)|Standards.objects.filter(agency__pk=ag, public=True).filter(created_standard_by__first_name__icontains=searchfor)
|
|
|
|
res_news = News.objects.filter(agency__pk=ag).filter(name__icontains=searchfor) | News.objects.filter(agency__pk=ag).filter(content__icontains=searchfor) | News.objects.filter(agency__pk=ag).filter(created_by__last_name__icontains=searchfor)|News.objects.filter(agency__pk=ag).filter(created_by__first_name__icontains=searchfor)
|
|
|
|
res_pass = AGPassword.objects.filter(agency__pk=ag).filter(name__icontains=searchfor)
|
|
res_contacts = AGContacts.objects.filter(agency__pk=ag).filter(personname__icontains=searchfor) | AGContacts.objects.filter(agency__pk=ag).filter(name__icontains=searchfor)
|
|
|
|
|
|
res_areas = Areas.objects.filter(agency__pk=ag).filter(name__icontains=searchfor)
|
|
res_tasks = Tasks.objects.filter(agency__pk=ag).filter(name__icontains=searchfor) |Tasks.objects.filter(agency__pk=ag).filter(area__name__icontains=searchfor)
|
|
res_pers = User.objects.filter(profile__agency__pk=ag).filter(first_name__icontains=searchfor) | User.objects.filter(profile__agency__pk=ag).filter(last_name__icontains=searchfor)
|
|
links = QuickLinks.objects.filter(agency__pk=ag).filter(name__icontains=searchfor) | QuickLinks.objects.filter(agency__pk=ag).filter(link__icontains=searchfor)
|
|
|
|
res_files = DataFile.objects.filter(agency__pk=ag).filter(name__icontains=searchfor)
|
|
|
|
|
|
|
|
html = render_to_string('users/searchres.html', {'links': links, 'res_standard': res_standard, 'res_areas': res_areas, 'res_tasks': res_tasks, 'res_pers': res_pers, 'res_news' : res_news, 'res_pass' : res_pass, 'res_contacts' : res_contacts, 'res_files' : res_files, 'user' : request.user})
|
|
return HttpResponse(html)
|
|
else:
|
|
return HttpResponse("Request method is not a GET")
|
|
|
|
@login_required
|
|
def searchStandardRouter(request):
|
|
if request.method == 'GET':
|
|
return redirect('/standards/standard/'+request.GET['s_id']+'/single')
|
|
else:
|
|
return redirect('dashboard')
|
|
'''
|
|
|
|
Hier werden die Zuständigkeiten eines Benutzers über alle Bereiche/Aufgaben hinweg gesetzt.
|
|
Das Update erfolgt per Booleanfields.
|
|
|
|
'''
|
|
@login_required
|
|
def UsersAreaTaskUpdate(request, pk):
|
|
|
|
user = User.objects.get(pk=pk)
|
|
if request.user.profile.agency.pk != user.profile.agency.pk:
|
|
return redirect('dashboard')
|
|
else:
|
|
finaldata = {}
|
|
context = {
|
|
'active_link' : 'usersmanagement',
|
|
'user_id' : user.pk,
|
|
}
|
|
|
|
if request.method == 'POST':
|
|
form = request.POST
|
|
areatask_formdata = list(form)
|
|
# CRSF-Token löschen
|
|
del areatask_formdata[0]
|
|
# Formular übertragen
|
|
area_ids = []
|
|
task_ids = []
|
|
|
|
# Areas in Formular laden
|
|
for ar in areatask_formdata:
|
|
tempdata = ar.split("_")
|
|
if(tempdata[0] == 'area'):
|
|
area_ids.append(int(tempdata[1]))
|
|
elif(tempdata[0] == 'task'):
|
|
task_ids.append(int(tempdata[1]))
|
|
|
|
# Alle Areas und Tasks laden
|
|
areas = Areas.objects.filter(agency__pk=user.profile.agency.pk)
|
|
tasks = Tasks.objects.filter(agency__pk=user.profile.agency.pk)
|
|
|
|
# Prüfen, ob der User in Area ist oder nicht und ihn ggf. hinzufügen/entfernen
|
|
for area in areas:
|
|
if area.pk in area_ids:
|
|
area.usersfield.add(user)
|
|
else:
|
|
area.usersfield.remove(user)
|
|
area.save()
|
|
|
|
'''
|
|
|
|
Prüfen, ob ein User einem Aufgabenbereich hinzugeprdnet ist.
|
|
Ist er im Bereich, passiert nichts. Ist er nicht in diesem
|
|
Bereich, wird er dem usersfield der Aufgabe und der Tabelle
|
|
Prio hinzugeüfügt. Damit kann der User seine individuellen
|
|
Prios im Profil anpassen.
|
|
|
|
'''
|
|
for task in tasks:
|
|
if task.pk in task_ids:
|
|
prio_check = Prio.objects.filter(user__pk=pk, task=task)
|
|
if(len(prio_check) == 0):
|
|
prio = Prio(user=User.objects.get(pk=pk), task=task)
|
|
prio.save()
|
|
task.usersfield.add(user)
|
|
else:
|
|
task.usersfield.remove(user)
|
|
Prio.objects.filter(user__pk=pk).filter(task__pk=task.pk).delete()
|
|
task.save()
|
|
username_message = user.first_name + " " + user.last_name
|
|
messages.success(request, f'Zuständigkeiten für {username_message} aktualisiert!')
|
|
return redirect('users-management')
|
|
else:
|
|
form = UserAreaTaskForm(user)
|
|
user_first_name = user.first_name
|
|
user_last_name = user.last_name
|
|
user_id = user.pk
|
|
context = {
|
|
'active_link' : '',
|
|
'user_first_name' : user_first_name,
|
|
'user_last_name' : user_last_name,
|
|
'user_id' : user_id,
|
|
'form' : form
|
|
}
|
|
|
|
return render(request, 'users/users_areatasks.html', context)
|
|
|
|
@login_required
|
|
def support(request):
|
|
context = {
|
|
'active_link' : 'support',
|
|
'form' : SupportForm(request.user)
|
|
}
|
|
|
|
if request.method == 'POST':
|
|
form = request.POST
|
|
'''
|
|
fileblob = ""
|
|
attachments=[] #myfile is the key of a multi value dictionary, values are the uploaded files
|
|
for f in request.FILES.getlist('attachment_1'): #myfile is the name of your html file button
|
|
filename = f.name
|
|
attachment_type = filetype.guess(f)
|
|
fileblob = str(base64.b64encode(f.read()))
|
|
fileblob = fileblob[1 : : ]
|
|
fileblob = fileblob[1 : : ]
|
|
fileblob = fileblob[:-1:]
|
|
attachments.append({str(filename) : "data:" + attachment_type.mime + ";base64," + fileblob})
|
|
fileblob = "data:" + attachment_type.mime + ";base64," + fileblob
|
|
|
|
for f in request.FILES.getlist('attachment_2'): #myfile is the name of your html file button
|
|
filename = f.name
|
|
attachment_type = filetype.guess(f)
|
|
fileblob = str(base64.b64encode(f.read()))
|
|
fileblob = fileblob[1 : : ]
|
|
fileblob = fileblob[1 : : ]
|
|
fileblob = fileblob[:-1:]
|
|
attachments.append({str(filename) : "data:" + attachment_type.mime + ";base64," + fileblob})
|
|
for f in request.FILES.getlist('attachment_2'): #myfile is the name of your html file button
|
|
filename = f.name
|
|
attachment_type = filetype.guess(f)
|
|
fileblob = str(base64.b64encode(f.read()))
|
|
fileblob = fileblob[1 : : ]
|
|
fileblob = fileblob[1 : : ]
|
|
fileblob = fileblob[:-1:]
|
|
attachments.append({str(filename) : "data:" + attachment_type.mime + ";base64," + fileblob})
|
|
'''
|
|
#image = request.FILES
|
|
supportdata = dict(form)
|
|
# Data from Form to JSON-Format
|
|
name = str(supportdata['name'][0])
|
|
mail = str(supportdata['mail'][0])
|
|
problemconc = str(supportdata['problemconc'][0])
|
|
problem = str(supportdata['problem'][0])
|
|
|
|
# HEADERS CURL
|
|
headers = {'X-API-Key': 'F025A238EB74914E3653BA2989BFF7C4'}
|
|
subject = "Digitale Agentur: " + str(problemconc)
|
|
|
|
|
|
# TASK: Hier die Auswahl des DropDown in die API mit einbauen, damit das Ticket in das entsprechende Department läuft
|
|
|
|
# DataJSON
|
|
ostdata = {
|
|
"topicId" : str(supportdata['department'][0]),
|
|
"name": name,
|
|
"email": mail,
|
|
"subject": 'Digitale Agentur: '+problemconc,
|
|
"ip": "1.1.1.1",
|
|
"message": "*****************************\nAgentur: "+ request.user.profile.agency.name +" (ID: "+ str(request.user.profile.agency.pk) +")\nBenutzer: "+request.user.first_name+" "+request.user.last_name+" (ID: "+ str(request.user.pk) +")\n*******************************\n\n" + problem
|
|
#"attachments" : attachments
|
|
|
|
}
|
|
json_data = json.dumps(ostdata)
|
|
|
|
r = requests.post("https://support.vh-solutions.de/api/http.php/tickets.json", data=json_data, headers=headers)
|
|
|
|
# IF request FAILED error-Message
|
|
if(r.status_code != 201):
|
|
messages.warning(request, f'Supportanfrage fehlgeschlagen!' + str(r))
|
|
else:
|
|
messages.success(request, f'Supportanfrage erfolgreich! Ihre Ticketnummer ist '+ str(r.json()) +'!')
|
|
|
|
return render(request, 'users/support_done.html', context)
|
|
else:
|
|
|
|
return render(request, 'users/support.html', context)
|
|
|
|
'''
|
|
|
|
Schickt eine E-Mail an den User inkl. Passwortlink zum zurücksetzen.
|
|
|
|
'''
|
|
def sendpassmail(request):
|
|
if(request.method == 'GET'):
|
|
userid = request.GET['userid']
|
|
tempuser = User.objects.get(pk=userid)
|
|
# E-Mail für Passwort-Setzung!
|
|
form = PasswordResetForm({'email': tempuser.email})
|
|
if form.is_valid():
|
|
form.save(request=request,html_email_template_name='users/password_reset_mail.html')
|
|
return render (request, 'users/registercomplete.html')
|
|
return JsonResponse({'message' : 0})
|
|
|
|
def datenschutz(request):
|
|
if request.user.is_authenticated:
|
|
return render(request, 'users/datenschutz.html')
|
|
else:
|
|
return render(request, 'users/datenschutz_p.html')
|
|
|
|
def impressum(request):
|
|
if request.user.is_authenticated:
|
|
return render(request, 'users/impressum.html')
|
|
else:
|
|
return render(request, 'users/impressum_p.html')
|
|
|
|
'''
|
|
|
|
ERROR HANDLER VIEWS
|
|
|
|
'''
|
|
def handler404(request, exception):
|
|
context = {}
|
|
response = render(request, "users/errors/404.html", context=context)
|
|
response.status_code = 404
|
|
return response
|
|
|
|
|
|
def handler500(request):
|
|
context = {}
|
|
response = render(request, "users/errors/500.html", context=context)
|
|
response.status_code = 500
|
|
return response
|
|
|
|
|
|
'''
|
|
|
|
CRONJOB FUNCTION
|
|
|
|
'''
|
|
# CRONJOBS ALLE 5 MINUTEN
|
|
def cronactions(request, code):
|
|
data = {}
|
|
if(code == settings.CRONAPIKEY):
|
|
# NEWS CHECKING
|
|
all_unnotifc_news = News.objects.filter(agnotify=False, go_online_on__lt=timezone.now())
|
|
allusers = User.objects.all()
|
|
for news in all_unnotifc_news:
|
|
targeturl = settings.BASE_URL + "news/news/" + str(news.pk) + "/single"
|
|
# NEW NEWS FOUND WHICH HAVE TO GO ONLINE NOW!
|
|
news.agnotify = True
|
|
news.save()
|
|
for user in allusers:
|
|
# SEMI-SIGNAL FOR NEWS GOING ONLINE
|
|
if(user.usernotifications.news_created_mail and news.agency == user.profile.agency):
|
|
notificationtext = "Neue Agenturnews: " + news.name
|
|
username = user.first_name + " " + user.last_name
|
|
msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext, 'linktarget' : targeturl})
|
|
send_mail(
|
|
'Agentur-Benachrichtigung',
|
|
'Hallo ' + user.first_name + ' ' + user.last_name + '! ' + notificationtext,
|
|
'noreply@digitale-agentur.com',
|
|
[user.email],
|
|
html_message=msg_html,
|
|
fail_silently=True
|
|
)
|
|
|
|
if(user.usernotifications.news_created_push and news.agency == user.profile.agency):
|
|
newnotification = UserNotification(touser=user, notificationtext="Neue Agenturnews: " + news.name, notificationtype="agencynews", elementid=news.pk)
|
|
newnotification.save()
|
|
|
|
channel_layer = channels.layers.get_channel_layer()
|
|
async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__News | Neue Agenturnews: " + news.name})
|
|
|
|
# LEXOFFICE TEST
|
|
# HEADERS CURL
|
|
'''
|
|
headers = {
|
|
'Authorization': 'Bearer 33bfb1b9-2994-4fd4-b447-1f4754a5c7cb',
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
}
|
|
|
|
# DataJSON
|
|
lexdata = {
|
|
"voucherDate": "2020-07-09T00:00:00.000+01:00",
|
|
"address" : {
|
|
"name" : "Agenturname XXX",
|
|
"countryCode" : "DE"
|
|
},
|
|
"totalPrice" : {
|
|
"currency" : "EUR",
|
|
},
|
|
"lineItems" : [
|
|
{
|
|
"type" : "custom",
|
|
"name" : "Monatsbeitrag",
|
|
"quantity" : 1,
|
|
"unitName" : "Stück",
|
|
"unitPrice" :
|
|
{
|
|
"currency" : "EUR",
|
|
"netAmount" : 10,
|
|
"taxRatePercentage" : 16
|
|
},
|
|
},
|
|
{
|
|
"type" : "custom",
|
|
"name" : "Abwesenheitsmodul",
|
|
"quantity" : 1,
|
|
"unitName" : "Stück",
|
|
"unitPrice" :
|
|
{
|
|
"currency" : "EUR",
|
|
"netAmount" : 10,
|
|
"taxRatePercentage" : 16
|
|
},
|
|
}
|
|
],
|
|
"taxConditions": {
|
|
"taxType": "net"
|
|
},
|
|
"shippingConditions": {
|
|
"shippingDate": "2020-07-09T00:00:00.000+01:00",
|
|
"shippingType": "service"
|
|
},
|
|
}
|
|
json_data = json.dumps(lexdata)
|
|
r = requests.get("https://api.lexoffice.io/v1/invoices/0f9b6a1d-1912-4a10-9926-7909e5580202", data=json_data, headers=headers)
|
|
print(r)
|
|
|
|
print(r.text)
|
|
'''
|
|
|
|
|
|
else:
|
|
print("API CODE FAILED")
|
|
data.update({"status" : "failed"})
|
|
return JsonResponse(data)
|
|
|
|
|
|
'''
|
|
|
|
LANDING PAGE
|
|
|
|
'''
|
|
class landingPage(TemplateView):
|
|
template_name = "users/landingpage.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
self.request.session.flush()
|
|
|
|
'''
|
|
Gibt False zurück, wenn der User an diesem Tag KEINE Abwesenheiten hat, ansonsten True!
|
|
|
|
'''
|
|
def absencecheck(user, daytocheck):
|
|
returnstat = False
|
|
absencedays = Absence.objects.filter(agency=user.profile.agency, user=user, confirm_status=0) & (Absence.objects.filter(agency=user.profile.agency, user=user, start=daytocheck) | (Absence.objects.filter(agency=user.profile.agency, user=user, start__lt=daytocheck) & Absence.objects.filter(agency=user.profile.agency, user=user, end__gt=daytocheck)) | Absence.objects.filter(agency=user.profile.agency, user=user, end=daytocheck))
|
|
if(len(absencedays) > 0):
|
|
returnstat = True
|
|
|
|
return returnstat
|
|
|
|
# CRONJOBS UM 00:05!
|
|
def cronactionsdaily(request, code):
|
|
data = {}
|
|
if(code == settings.CRONAPIKEY):
|
|
allusers = User.objects.all()
|
|
'''
|
|
Pro User gibt es das Feld loose_holiday in der UserTime-Info. Ist dieser Tag vorbei, muss die Differenz der days_inuse des VORJHARES in den Rest das AKTUELLEN JAHRES gespeichert werden!
|
|
'''
|
|
today = date.today()
|
|
for user in allusers:
|
|
# REST URLAUB BERECHNUNG
|
|
try:
|
|
usertimedata = UserTime.objects.get(user=user)
|
|
day_tocheck = usertimedata.loose_holidedate.split(".")[0]
|
|
month_tocheck = usertimedata.loose_holidedate.split(".")[1]
|
|
month = today.month
|
|
day = today.day
|
|
if month < 10:
|
|
month = "0" + str(month)
|
|
day = today.day
|
|
else:
|
|
month = month
|
|
|
|
if day < 10:
|
|
day = "0" + str(day)
|
|
else:
|
|
day = day
|
|
# Restetag erreicht, Reste ins nächste Jahr übertragen
|
|
if(str(day_tocheck) == str(day) and str(month_tocheck) == str(month)):
|
|
sourceyear = today.year
|
|
this_year = list(UserYearAbsenceInfo.objects.filter(year=sourceyear, user=user))[0]
|
|
next_year = list(UserYearAbsenceInfo.objects.filter(year=sourceyear+1, user=user))[0]
|
|
next_year.restdays = this_year.days - this_year.days_inuse
|
|
next_year.save()
|
|
|
|
if(user.usertime.usetime):
|
|
workdays = Workday.objects.filter(user=user, end=None)
|
|
for wd in workdays:
|
|
wd.end = datetime(wd.start.year, wd.start.month, wd.start.day, 23, 59)
|
|
wd.save()
|
|
|
|
yesterday = date.today() - timedelta(days=1)
|
|
weekday = yesterday.weekday()
|
|
workdays_yesterday = len(Workday.objects.filter(user=user, start__day=yesterday.day, start__month=yesterday.month, start__year=yesterday.year))
|
|
|
|
targettworktime = 0.0
|
|
# Mitarbeiter hat für den gestrigen Tag keine Zeiten erfasst, daher automatisch auf null wenn KEINE Abwesenheit eingetragen wurde
|
|
if(weekday == 0):
|
|
targettworktime = user.usertime.wd_mo
|
|
if(weekday == 1):
|
|
targettworktime = user.usertime.wd_tu
|
|
if(weekday == 2):
|
|
targettworktime = user.usertime.wd_we
|
|
if(weekday == 3):
|
|
targettworktime = user.usertime.wd_th
|
|
if(weekday == 4):
|
|
targettworktime = user.usertime.wd_fr
|
|
if(weekday == 5):
|
|
targettworktime = user.usertime.wd_sa
|
|
if(weekday == 6):
|
|
targettworktime = user.usertime.wd_so
|
|
|
|
# Es wird nur ein Arbeitstag erstellt, wenn KEINE Abwesenheiten vorliegen und der Nutzer an diesem Tag arbeiten muss
|
|
if(workdays_yesterday == 0 and absencecheck(user, yesterday) == False and targettworktime > 0.0 and user.usertime.usetime_start <= today):
|
|
workdaytemp = Workday(user=user, agency=user.profile.agency, start=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), end=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), target=targettworktime)
|
|
workdaytemp.save()
|
|
|
|
|
|
# Erinnerungsmails/Push bei Vertretung verschicken
|
|
one_week_later = date.today() + timedelta(days=7)
|
|
repre_absence = Absence.objects.filter(representator=user, start=one_week_later, confirm_status=0)
|
|
|
|
for r in repre_absence:
|
|
if(r.representator.usernotifications.absence_user_is_rep_reminder_mail):
|
|
sendMailNoti(" in einer Woche startet Ihre Vertretung für " + r.user.first_name + " " + r.user.last_name + "!", user)
|
|
|
|
if(r.representator.usernotifications.absence_user_is_rep_reminder_push):
|
|
newnotification = UserNotification(touser=user, notificationtext="Erinnerung für Abwesenheitsvertretung!", notificationtype="", elementid=r.pk)
|
|
newnotification.save()
|
|
|
|
channel_layer = channels.layers.get_channel_layer()
|
|
async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Abwesenheit | In einer Woche startet Ihre Vertretung für " + r.user.first_name + " " + r.user.last_name + "!"})
|
|
|
|
data.update({"status " + str(user.pk) : "ok"})
|
|
except ObjectDoesNotExist:
|
|
data.update({"status" + str(user.pk) : "no usertime found for " + user.get_full_name()})
|
|
else:
|
|
print("API CODE FAILED")
|
|
data.update({"status" : "failed"})
|
|
|
|
return JsonResponse(data)
|
|
|
|
|
|
'''
|
|
ABRECHNUNG CRON JOB
|
|
|
|
'''
|
|
from dateutil.relativedelta import *
|
|
def cronactionsbill(request, code):
|
|
data = {}
|
|
if(code == settings.CRONAPIKEY):
|
|
today = date.today()
|
|
# Check, ob Rechnungen bezahlt wurden
|
|
unpaid_bills = AgencyBills.objects.all()
|
|
|
|
for bill in unpaid_bills:
|
|
# Für jede Rechnung eine Anfrage an die LexOffice API und voucherStatus auslesen
|
|
headers = {
|
|
'Authorization': 'Bearer ' + settings.LEX_API,
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
}
|
|
|
|
json_data = {}
|
|
|
|
r = requests.get("https://api.lexoffice.io/v1/invoices/"+AgencyBills.objects.get(pk=bill.pk).lexid, data=json_data, headers=headers)
|
|
if(json.loads(r.text)["voucherStatus"] == "paid"):
|
|
bill.billstatus="paid"
|
|
bill.save()
|
|
else:
|
|
bill.billstatus="open"
|
|
bill.save()
|
|
|
|
|
|
# Monatliche Berechnung
|
|
# Alle Rechnungen laden, deren Letzter Tag HEUTE ist und bei ausgewähltem Paymentplan 1 eine neue Rechnung erstellen, Mailverschicke, Nutzeraccouns zählen und neue Rechnung in der Agentur hinterlegen
|
|
new_bills = AgencyBills.objects.filter(end=today)
|
|
for bill in new_bills:
|
|
if bill.agency.paymentplan == 1:
|
|
|
|
agency = bill.agency
|
|
|
|
month = today
|
|
|
|
next_month = today + relativedelta(months=1)
|
|
# USERCOUNT BERECHNEN
|
|
usercount = len(User.objects.filter(profile__agency=agency))
|
|
|
|
if(usercount < 4):
|
|
usercount = 0
|
|
else:
|
|
usercount = usercount - 3
|
|
|
|
# HEADERS CURL
|
|
headers = {
|
|
'Authorization': 'Bearer ' + settings.LEX_API,
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
}
|
|
|
|
plan = 1
|
|
|
|
start_date = month
|
|
start_date_string = month.strftime("%d.%m.%Y")
|
|
end_date = month + relativedelta(months=plan)
|
|
end_date_string= end_date.strftime("%d.%m.%Y")
|
|
|
|
voucher_date_today = date.today().strftime("%Y-%m-%d")
|
|
|
|
monthword = "Monat"
|
|
|
|
lexdata = {
|
|
"voucherDate": voucher_date_today + "T00:00:00.000+00:00",
|
|
"address" : {
|
|
"name" : agency.name,
|
|
"street": agency.street,
|
|
"zip": agency.plz,
|
|
"city": agency.city,
|
|
"countryCode" : "DE"
|
|
},
|
|
"totalPrice" : {
|
|
"currency" : "EUR",
|
|
},
|
|
"lineItems" : [
|
|
{
|
|
"type" : "custom",
|
|
"name" : "Digitale Agentur: Grundbetrag für " + str(plan) + " " + monthword,
|
|
"quantity" : 1,
|
|
"unitName" : "Stück",
|
|
"description" : "Zeitraum " + start_date_string + " - " + end_date_string,
|
|
"unitPrice" :
|
|
{
|
|
"currency" : "EUR",
|
|
"netAmount" : 21.00,
|
|
"taxRatePercentage" : 16
|
|
},
|
|
},
|
|
{
|
|
"type" : "custom",
|
|
"name" : "Digitale Agentur: Zusätzliche Nutzer",
|
|
"description" : "Zeitraum " + start_date_string + " - " + end_date_string,
|
|
"quantity" : usercount,
|
|
"unitName" : "Stück",
|
|
"unitPrice" :
|
|
{
|
|
"currency" : "EUR",
|
|
"netAmount" : 3,
|
|
"taxRatePercentage" : 16
|
|
},
|
|
}
|
|
],
|
|
"taxConditions": {
|
|
"taxType": "net"
|
|
},
|
|
"paymentConditions": {
|
|
"paymentTermLabel": "Bitte zahlen Sie innerhalb von 14 Tagen.",
|
|
"paymentTermDuration": 14,
|
|
},
|
|
"shippingConditions": {
|
|
#"shippingDate": voucher_date_today + "T00:00:00.000+00:00",
|
|
"shippingType": "none"
|
|
}
|
|
}
|
|
json_data = json.dumps(lexdata)
|
|
|
|
r = requests.post("https://api.lexoffice.io/v1/invoices/?finalize=true", data=json_data, headers=headers)
|
|
|
|
if(r.status_code == 201):
|
|
messages.success(request, f"Rechnung erstellt!")
|
|
# Response in JSON umwandeln
|
|
|
|
response_text = json.loads(r.text)
|
|
newbill_id = response_text["id"]
|
|
|
|
# OrganizationId berechnen, wenn noch nicht gesetzt
|
|
r = requests.get("https://api.lexoffice.io/v1/invoices/" + response_text["id"], data=json_data, headers=headers)
|
|
response_text = json.loads(r.text)
|
|
|
|
newbill = AgencyBills(agency=agency, lexid=newbill_id, billtype="invoice", billnumber=response_text["voucherNumber"], billstatus=response_text["voucherStatus"], start=start_date, end=end_date, plan=plan, usercount=usercount)
|
|
newbill.save()
|
|
|
|
mail_to_send = ""
|
|
if(agency.payment_address == ""):
|
|
mail_to_send = agency.agency_email
|
|
else:
|
|
mail_to_send = agency.payment_address
|
|
msg_html = render_to_string('users/newbill_mail.html', {})
|
|
send_mail('Digitale Agentur | Rechnung', 'Sehr geehrte Nutzer, es wurde eine Rechnung für Ihre digitale Agentur erstellt. Diese können Sie unter Einstellungen, Abrechnung einsehen.','noreply@digitale-agentur.com',[mail_to_send],html_message=msg_html,fail_silently=True)
|
|
data.update({"newBill_" + str(agency.pk) : newbill.lexid})
|
|
else:
|
|
data.update({"status" : "failed"})
|
|
return JsonResponse(data)
|
|
|
|
|
|
|
|
def sendMailNoti(notificationtext, user_touched, linktarget=""):
|
|
|
|
username = user_touched.first_name + " " + user_touched.last_name
|
|
msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext, 'linktarget' : linktarget})
|
|
send_mail(
|
|
'Agentur-Benachrichtigung',
|
|
'Hallo ' + user_touched.first_name + ' ' + user_touched.last_name + '! ' + notificationtext,
|
|
'noreply@digitale-agentur.com',
|
|
[user_touched.email],
|
|
html_message=msg_html,
|
|
fail_silently=True
|
|
)
|
|
|
|
def isAlive(request):
|
|
return JsonResponse({"status" : True})
|