digitaleagenturnc/users/views.py

2074 lines
72 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, AgencyNetwork
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
from organizer.models import QuickLinks
from areas.models import Areas
from tasks.models import Tasks
''' ICS '''
from ics import Calendar, Event
import base64
from django.contrib.auth import authenticate
def getICSFile(request, ag):
if 'HTTP_AUTHORIZATION' in request.META:
auth = request.META['HTTP_AUTHORIZATION'].split()
if len(auth) == 2:
if auth[0].lower() == "basic":
temp = base64.b64decode(auth[1] + "==")
username = temp.decode("utf-8").split(":")[0]
passwd = temp.decode("utf-8").split(":")[1]
user = authenticate(username=username, password=passwd)
if user is not None:
if user.is_active:
if user.profile.agency.pk == ag:
request.user = user
c = Calendar()
absencedays = Absence.objects.filter(agency=ag)
for ab in absencedays:
e = Event()
e.name = ab.user.first_name + " " + ab.user.last_name + " abwesend"
e.uid = "da-ab-" + str(ab.pk)
e.begin = ab.start
e.end = ab.end
e.allday = True
c.events.add(e)
return HttpResponse(c, content_type='text/calendar')
realm = ""
response = HttpResponse()
response.status_code = 401
response['WWW-Authenticate'] = 'Basic realm="%s"' % realm
return response
def getICSFileAll(request, ag):
if 'HTTP_AUTHORIZATION' in request.META:
auth = request.META['HTTP_AUTHORIZATION'].split()
if len(auth) == 2:
if auth[0].lower() == "basic":
temp = base64.b64decode(auth[1] + "==")
username = temp.decode("utf-8").split(":")[0]
passwd = temp.decode("utf-8").split(":")[1]
user = authenticate(username=username, password=passwd)
if user is not None:
if user.is_active:
if user.profile.agency.pk == ag and user.has_perm('users.absencemanager'):
request.user = user
c = Calendar()
absencedays = Absence.objects.filter(agency=ag)
for ab in absencedays:
e = Event()
e.name = ab.user.first_name + " " + ab.user.last_name + " | " + ab.reason.name
e.uid = "da-ab-" + str(ab.pk)
e.begin = ab.start
e.end = ab.end
e.allday = True
c.events.add(e)
return HttpResponse(c, content_type='text/calendar')
realm = ""
response = HttpResponse()
response.status_code = 401
response['WWW-Authenticate'] = 'Basic realm="%s"' % realm
return response
def getICSFileEx(request, code, ag):
try:
agency = Agency.objects.get(pk=ag)
if agency != None and agency.agencycal_publicstatus == 1 and code == agency.agencycalurl:
c = Calendar()
absencedays = Absence.objects.filter(agency=ag)
for ab in absencedays:
e = Event()
e.name = ab.user.first_name + " " + ab.user.last_name + " abwesend "
e.uid = "da-ab-" + str(ab.pk)
e.begin = ab.start
e.end = ab.end
e.allday = True
c.events.add(e)
return HttpResponse(c, content_type='text/calendar')
else:
realm = ""
response = HttpResponse()
response.status_code = 401
return response
except:
realm = ""
response = HttpResponse()
response.status_code = 401
return response
def getICSFileExAll(request, code, ag):
try:
agency = Agency.objects.get(pk=ag)
if agency != None and agency.agencycal_publicstatus == 1 and code == agency.agencycalurl_all:
c = Calendar()
absencedays = Absence.objects.filter(agency=ag)
for ab in absencedays:
e = Event()
e.name = ab.user.first_name + " " + ab.user.last_name + " | " + ab.reason.name
e.uid = "da-ab-" + str(ab.pk)
e.begin = ab.start
e.end = ab.end
e.allday = True
c.events.add(e)
return HttpResponse(c, content_type='text/calendar')
else:
realm = ""
response = HttpResponse()
response.status_code = 401
return response
except:
realm = ""
response = HttpResponse()
response.status_code = 401
return response
'''
Standardstruktur laden
4x Verbünde automatisch übernehmen --> Die 4 Verbünde aus der VVE Geschäftsstelle
'''
def loadPreStructure(agency):
########## VERMARKTEN
a_vermarkten = Areas(agency=agency, name="Vermarkten", color="#27ae60", desc="", created_area_by=None)
a_vermarkten.save()
a_vermarkten_tasks = ["Bewertungen", "Empfehlungsmanagement", "ERGO Mein Lokales Marketing", "Kampagnenmanagement", "Google My Business", "Hybride Agentur", "Social Media", "Zielgruppen"]
for l in a_vermarkten_tasks:
temp = Tasks(agency=agency, area=a_vermarkten, name=l)
temp.save()
# VERKAUFEN
a_verkaufen = Areas(agency=agency, name="Verkaufen", color="#8e44ad", desc="", created_area_by=None)
a_verkaufen.save()
a_verkaufen_tasks = ["Aktionen", "Antragsprozesse", "Cross-Selling", "Kooperationen", "Leads", "Skype-Beratung", "Telefon-Beratung", "Terminvorbereitung", "Verkaufsgespräch", "Terminnachbereitung", "Terminierung/KKM"]
for l in a_verkaufen_tasks:
temp = Tasks(agency=agency, area=a_verkaufen, name=l)
temp.save()
# VERWALTEN
a_verwalten = Areas(agency=agency, name="Verwalten", color="#f39c12", desc="", created_area_by=None)
a_verwalten.save()
a_verwalten_tasks = ["Agenturverwaltung", "Vertragsverwaltung", "EASY Anwendungen", "Host-Anwendungen", "Fremdverträge", "Kundenanschreiben", "Schaden und Leistung", "Textbaustein"]
for l in a_verwalten_tasks:
temp = Tasks(agency=agency, area=a_verwalten, name=l)
temp.save()
# BÜRPO INTERN
a_buerointern = Areas(agency=agency, name="Büroabläufe intern", color="#c0392b", desc="", created_area_by=None)
a_buerointern.save()
a_buero_tasks = ["Bestellungen", "Büroordnung", "Post", "Technik"]
for l in a_buero_tasks:
temp = Tasks(agency=agency, area=a_buerointern, name=l)
temp.save()
# AG-Netzwork Joins
# Join ID 8, 7, 6, 5
try:
agn_8 = AgencyNetwork.objects.get(pk=8)
agn_8.members.add(agency)
agn_7 = AgencyNetwork.objects.get(pk=7)
agn_7.members.add(agency)
agn_6 = AgencyNetwork.objects.get(pk=6)
agn_6.members.add(agency)
agn_5 = AgencyNetwork.objects.get(pk=5)
agn_5.members.add(agency)
except:
pass
# CREATE WELCOME NEWS
welcome_news = News(agency=agency, name="Herzlich Willkommen in der Digitalen Agentur", content='<p>Hallo lieber DA-Nutzer,</p><p>nicht erschrecken, wir haben für Sie schon einmal eine erste News mit allen wichtigen Informationen rund um diese Anwendung angelegt.&nbsp;</p><h4>Was bietet mir die Digitale Agentur für den Alltag?</h4><p>Bilder sagen mehr als tausend Worte - Videos sagen mehr als tausend Bilder. Hier haben wir für Sie unser Produktvideo verlinkt, um Ihnen die wesentlichen Funktionen noch einmal vorzustellen:</p><p><iframe frameborder="0" src="//www.youtube.com/embed/rGRZTZlHdEQ" width="640" height="360" class="note-video-clip"></iframe><br></p><h4>Womit fangen Sie nun am besten an?</h4><p>Damit Ihnen die ersten Schritte ein bisschen leichter fallen, haben wir für Sie eine Checkliste angelegt, die Ihnen die wichtigsten Einstellungen einmal zeigt. Die Checkliste erreichen Sie über den folgenden Link:&nbsp;<a href="https://digitale-agentur.com/article/erste-schritte/" target="_blank">digitale-agentur.com/article/erste-schritte/</a></p><h4>Wo kann ich mir Hilfe bei Fragen holen?</h4><p>Auf unserer Website finden Sie viele interessante und hilfreiche Kategorien und Artikel zur Arbeit mit der Anwendung. Wenn Sie also mal eine Frage haben oder sich inspirieren lassen wollen. Schauen Sie hier gerne vorbei:&nbsp;<a href="https://digitale-agentur.com/" target="_blank">digitale-agentur.com</a></p><p><span style="font-size: 1rem;">Bei inhaltlichen und technischen Fragen rund um die Anwendung klicken Sie einfach Links in der Navigation auf die Schaltfläche "Support", um Ihre Frage an unser Support-Team zu stellen.</span></p><p>Nun fürs erste aber genug - wir wünschen Ihnen viel Spaß und Erfolg mit der Digitalen Agentur!</p><p>Viele Grüße aus Hamburg ;)<br>Ihr DA-Team</p>')
welcome_news.save()
# ORGANIZER
hw = QuickLinks(agency=agency, name="Hilfe und Wiki", link="https://digitale-agentur.com")
hw.save()
vve = QuickLinks(agency=agency, name="myvve", link="https://myvve.de")
vve.save()
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))
def randomStringNum(stringLength=20):
"""Generate a random string of fixed length """
lettersAndNumbers = string.ascii_lowercase + string.digits + string.ascii_uppercase
return ''.join(random.choice(lettersAndNumbers) for i in range(stringLength))
@login_required
def toUpdate(request):
# NO AGENVYJOBS
# CREATE DEFAULT
'''
Agenturleiter
Außendienst
Innendienst
Auszubildender
'''
if len(request.user.profile.agency.agencycalurl) == 0:
request.user.profile.agency.agencycalurl = randomStringNum(30)
request.user.profile.agency.agencycalurl_all = randomStringNum(30)
request.user.profile.agency.save()
print("CAL-URLS updated for " + str(request.user.profile.agency.pk))
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")
pass
# 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:
pass
#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")
pass
# 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
'''
from django.views.decorators.csrf import csrf_protect
@csrf_protect
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()
loadPreStructure(agency)
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()
loadPreStructure(agency)
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()
loadPreStructure(agency)
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)
#from django.core.mail import EmailMessage
#from django.core.mail import EmailMultiAlternatives
from auditlog.models import LogEntry
@login_required
def showUserLog(request, pk):
if (request.user.pk == pk):
logdata = LogEntry.objects.filter(object_pk=request.user.pk)[:50]
logdata_logins = []
for ele in reversed(logdata):
try:
datestring = json.loads(ele.changes)["last_login"][1]
datestring = datestring.split(".")[0]
logdata_logins.append(datetime.strptime(datestring, '%Y-%m-%d %H:%M:%S'))
except:
pass
context = {
'logdata' : logdata_logins
}
return render(request, 'users/userlog.html', context)
else:
context = {}
return render(request, 'users/userlog_forbidden.html', context)
@login_required
def dashboard(request):
# UPDATE FUNCTIONS BY NEW MODEL-CHANGES FOR COPIEN SOME DATA
toUpdate(request)
'''
# BCC Mail with Object - NICHT DEN IMPORT VERGESSEN!!!
email = EmailMultiAlternatives(
'Subject',
'Bitte aktivieren Sie HTML in Ihrem Mailprogramm.',
'noreply@digitale-agentur.com',
['mail@holgertrampe.de'],
['htrampe@gmail.com'],
#reply_to=['noreply@digitale-agentur.com'],
headers={},
)
email.attach_alternative("<html><body><h1>Lobbt der Shit!</h1><hr></body></html>", "text/html")
email.send()
'''
#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_all = News.objects.filter(agency__pk=request.user.profile.agency.pk).filter(go_online_on__lt=filterdate).filter(go_offline_on__gt=filterdate).order_by('-go_online_on') | News.objects.filter(agency__pk=request.user.profile.agency.pk).filter(go_online_on__lt=filterdate).filter(go_offline_on__isnull=True).order_by('-go_online_on')
# Maximal fünf News final zur Seite schicken!
news = []
for n in news_all:
if len(news) < 5:
news.append(n)
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) +")\nBrowser: " + request.META['HTTP_USER_AGENT'] + "\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()) +'!')
# TASK: Hier Browserversion usw. mit einfügen beim TICKET!
send_mail(
"Digitale Agentur: " + str(problemconc),
"Hallo " + name, ", wir haben Ihre Anfrage unter der Ticketnummer " + str(r.json()) + " aufgenommen. Vielen Dank. Ihr Team der Digitalen Agentur",
'noreply@digitale-agentur.com',
[mail],
fail_silently=True
)
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)
'''
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 = {}
today = date.today()
mailstatus = "BEGIN CRONJOB DAILY" + str(today)
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!
'''
for user in allusers:
mailstatus += "\n USER: " + user.first_name + " " + user.last_name + " ID: (" + str(user.pk) + ")"
# 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
''' DAS IST UNNÖTIG '''
'''
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()
'''
# Arbeitstage beenden
try:
if(user.usertime.usetime):
try:
workdays = Workday.objects.filter(user=user, end=None)
for wd in workdays:
mailstatus += "\n WORKDAY AUTEND ID " + wd.pk
wd.end = datetime(wd.start.year, wd.start.month, wd.start.day, 23, 59)
wd.save()
except:
mailstatus += "ERROR WORKDAYS AUTO END"
# AUTO ARBEITSTAGE HINZUFÜGEN
try:
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()
except:
mailstatus += "ERROR AUTO ADDING WORKDAYS"
try:
# 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 + "!"})
except:
mailstatus += "ERROR REMINDER ABSENCEMAIL"
data.update({"status " + str(user.pk) : "ok"})
except ObjectDoesNotExist:
data.update({"status" + str(user.pk) : "no usertime found for " + user.get_full_name()})
mailstatus += "USER HAS NO USERTIMEOBJECT USER-ID: " + str(user.pk)
else:
data.update({"status" : "failed"})
send_mail(
'DAILYCRONJOB FEEDBACK',
mailstatus,
'noreply@digitale-agentur.com',
["htrampe@gmail.com", "info@digitale-agentur.com"],
fail_silently=True
)
return JsonResponse(data)
#import datetime
from django.db.models.signals import post_save
from users.signals import save_newabsence
from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays, Absence
def recalculateAbsence(request, code):
data = {}
calcstat = "BEGIN RECALCULATE ABSENCE"
today = date.today()
year = today.year
post_save.disconnect(save_newabsence, sender=Absence)
if(code == settings.CRONAPIKEY):
for user in User.objects.all():
calcstat += "\n USER " + str(user.pk)
try:
abinfo_lastyear = UserYearAbsenceInfo.objects.get(user=user, year=str(int(year)-1))
abinfo_thisyear = UserYearAbsenceInfo.objects.get(user=user, year=year)
abinfo_thisyear.restdays = abinfo_lastyear.days - abinfo_lastyear.days_inuse
abinfo_thisyear.save()
calcstat += " DAYS UPDATED - NEW RESTDAYS: " + str(abinfo_thisyear.restdays)
for ab in Absence.objects.filter(user=user, start__year=year):
if(ab.reason.is_holiday):
calculateNewAbsenceDate(ab)
daysinuse_thisyear = 0.0
for ab in Absence.objects.filter(user=user, start__year=year):
daysinuse_thisyear += ab.holidays_normal
calcstat += " NEW DAYSINUSE THIS YEAR " + str(daysinuse_thisyear)
abinfo_thisyear.days_inuse = daysinuse_thisyear
abinfo_thisyear.save()
except:
calcstat += "ERROR LASTYEAR/THISYEAR USER " + str(user.pk)
post_save.connect(save_newabsence, sender=Absence)
send_mail(
'RECALCULATING ABSENCE YEAR INFO PROTOCOLL',
calcstat,
'noreply@digitale-agentur.com',
["info@digitale-agentur.com"],
#["htrampe@gmail.com"],
fail_silently=True
)
return JsonResponse(data)
def calculateNewAbsenceDate(instance):
newdata = getFinalHolidayData(instance)
abinfo = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year))[0]
abinfo_lastyear = ""
abinfo_nextyear = ""
is_lastyear = False
abinfo_lastyear = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year-1))
if(len(abinfo_lastyear) > 0):
is_lastyear = True
abinfo_lastyear = abinfo_lastyear[0]
is_nextyear = False
abinfo_nextyear = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year+1))
if(len(abinfo_nextyear) > 0):
is_nextyear = True
abinfo_nextyear = abinfo_nextyear[0]
multiple_info_needays = False
if(hasattr(newdata[3], "__len__")):
multiple_info_needays = True
# Gleiches Jahr MIT Rest
if(multiple_info_needays and newdata[3][2] == False):
# Rest ist positiv, daher bleibt rest übrig, rest wird in absence gespeichert und vom rest des Jahres-Restes abgezogen
# Rest ist positiv, damit bleibt Rest übrig
if(newdata[3][0] > 0):
instance.holidays_rest = abinfo.restdays - newdata[3][0]
instance.save()
abinfo.restdays = newdata[3][0]
abinfo.save()
# Rest ist negativ
elif(newdata[3][0] < 0):
instance.holidays_rest = (abinfo.restdays - newdata[3][0]) - newdata[3][0]*(-1)
instance.holidays_normal = newdata[3][0]*(-1)
instance.save()
abinfo.restdays = 0
abinfo.days_inuse = abinfo.days_inuse + newdata[3][0]*(-1)
abinfo.save()
# Rest ist Urlaubsdauer
else:
instance.holidays_rest = abinfo.restdays
instance.save()
#abinfo.days_inuse = abinfo.days_inuse + abinfo.restdays
abinfo.restdays = 0
abinfo.save()
# Gleiches Jahr ohne Rest
elif(not multiple_info_needays):
abinfo.days_inuse = abinfo.days_inuse + newdata[3]
abinfo.save()
instance.holidays_normal = newdata[3]
instance.save()
# Mehrere Jahre
elif(multiple_info_needays and newdata[3][2] == True):
abinfo.days_inuse = abinfo.days_inuse + newdata[3][0]
abinfo.save()
abinfo_nextyear.days_inuse = abinfo_nextyear.days_inuse + newdata[3][1]
abinfo_nextyear.restdays = abinfo_nextyear.restdays - newdata[3][3]
abinfo_nextyear.save()
# Hier werden alle benötigten Tage von Vor- und Nächstem Jahr gespeichert
instance.holidays_normal = newdata[3][0]
instance.holidays_rest = 0
instance.holidays_normal_next = newdata[3][1]
instance.holidays_rest_next = newdata[3][3]
instance.save()
'''
ABRECHNUNG CRON JOB
'''
from dateutil.relativedelta import *
def cronactionsbill(request, code):
data = {}
today = date.today()
mailstatus = "BEGIN CRONJOB BILL" + str(today)
if(code == settings.CRONAPIKEY):
# 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.paymentstatus == 0 and bill.agency.paymentplan == 1:
agency = bill.agency
month = today
# 30 Tage weiter, nicht einen Monat!
next_month = today + relativedelta(days=30)
# 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(days=30)
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" : 19
},
},
{
"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" : 19
},
}
],
"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)
# WIEDER RAUSNEHMEN
# NEUE RECHNUNG ALs ENTWURF
#r = requests.post("https://api.lexoffice.io/v1/invoices/", data=json_data, headers=headers)
# RICHTIGE RECHNUNG
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})
mailstatus += "NEW BILL FOR AGENCY " + str(agency.pk)
else:
data.update({"status" : "failed"})
send_mail(
'DAILYCRONJOB BILLS FEEDBACK',
mailstatus,
'noreply@digitale-agentur.com',
["htrampe@gmail.com", "info@digitale-agentur.com"],
fail_silently=True
)
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})
''' AB HIER WIEDER RAUSNEHMEN '''
def getFinalHolidayData(abscence):
user = abscence.user
usertimedata = UserTime.objects.get(user=user)
today = date.today()
start_day_obj = abscence.start
end_day_obj = abscence.end
try:
holidayloose_date = datetime.date(start_day_obj.year, int(usertimedata.loose_holidedate.split(".")[1]), int(usertimedata.loose_holidedate.split(".")[0]))
except:
holidayloose_date = datetime.date(2020, int(usertimedata.loose_holidedate.split(".")[1]), int(usertimedata.loose_holidedate.split(".")[0]))
#start_half = abscence.start_ishalf
#end_half = abscence.end_ishalf
start_half = False
if abscence.startday_info == "1" or abscence.startday_info == "2":
start_half = True
end_half = False
if abscence.endday_info == "1" or abscence.endday_info == "2":
end_half = True
choosenyear = abscence.start.year
yeardata = list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency, year=choosenyear))[0]
holiday_thisyear = 0
holiday_lastyear = yeardata.restdays
holiday_nextyear = 0
try:
holiday_nextyear = list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency,
year=choosenyear+1))[0].days - list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency,
year=choosenyear+1))[0].days_inuse
holiday_nextyear_rest = list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency,
year=choosenyear+1))[0].restdays
except:
holiday_nextyear = yeardata.days
# Urlaub innerhalb eines Jahres inkl. Prüfung auf Resturlaubsanspruch
if(end_day_obj.year == start_day_obj.year):
# Startt des Urlaubs NACH Verfallsdatum - nur aktuelles JAhr und die Zahl interessiert
if(start_day_obj > holidayloose_date):
need_days = (calculateHolidays(user, start_day_obj, end_day_obj, start_half, end_half))*(-1)
holiday_thisyear = yeardata.days - yeardata.days_inuse - need_days
else:
need_days = (calculateHolidays(user, start_day_obj, end_day_obj, start_half, end_half))*(-1)
# Kein Resturlaub
if(yeardata.restdays == 0.0):
holiday_thisyear = yeardata.days - yeardata.days_inuse - need_days
# Resturlaub vorhanden, berechne mit Resturlaub
else:
holiday_lastyear = yeardata.restdays
holiday_thisyear = yeardata.days - yeardata.days_inuse
temp_holiday = holiday_lastyear - need_days
if(temp_holiday < 0):
holiday_lastyear = 0
holiday_thisyear = yeardata.days - yeardata.days_inuse + temp_holiday
need_days = [temp_holiday, holiday_thisyear, False]
else:
holiday_lastyear = yeardata.restdays - need_days
need_days = [temp_holiday, holiday_lastyear, False]
# Urlaub geht über das nächstes Jahr hinweg
else:
two_years = True
holiday_lastyear = yeardata.restdays
date_splitter = datetime.date(end_day_obj.year, 1, 1)
need_days_this = (calculateHolidays(user, start_day_obj, date_splitter, start_half, False))*(-1)
need_days_next = (calculateHolidays(user, date_splitter, end_day_obj, False, end_half))*(-1)
need_days = (calculateHolidays(user, start_day_obj, date_splitter, start_half, False))*(-1) + (calculateHolidays(user, date_splitter, end_day_obj, False, end_half))*(-1)
holiday_thisyear = yeardata.days - yeardata.days_inuse - need_days_this
days_nextyear_normal = 0
days_nextyear_rest = 0
# Urlaub nächstes Jahr MIT und OHNE Rest
if(holiday_nextyear_rest == 0.0):
holiday_nextyear = holiday_nextyear - (calculateHolidays(user, date_splitter, end_day_obj, False, end_half))*(-1)
else:
temprest = holiday_nextyear_rest - need_days_next
# Rest reicht!
if(temprest >= 0):
holiday_nextyear_rest = temprest
days_nextyear_normal = 0
days_nextyear_rest = need_days_next
# Rest reicht nicht
else:
holiday_nextyear_rest = 0
holiday_nextyear += temprest
days_nextyear_rest = need_days_next + temprest
days_nextyear_normal = temprest * -1
# TAGE NORMAL, TAGE NEXT NORMAL, TRUE für 2jahre, TAGE NEXT REST
need_days = [need_days_this, days_nextyear_normal, True, days_nextyear_rest]
data = [ holiday_thisyear, holiday_lastyear, holiday_nextyear, need_days ]
return data
def calculateHolidays(user, start, end, start_half, end_half):
restdays = 0
allfreedays = FreeDays.objects.filter(agency=user.profile.agency)
if(end == start):
if(start_half):
return restdays - 0.5
else:
return restdays - 1
else:
if(end < start):
return False
else:
counter = 0
if(start_half):
counter -= 0.5
if(end_half):
counter -= 0.5
weekdays = []
freedaycounter = 0
for dt in daterange(start, end):
day_found = False
if dt.isoweekday() not in weekdays:
counter += 1
for freeday in allfreedays.all():
if(dt == freeday.day):
freedaycounter += 1
day_found = True
if day_found == False:
if(dt.isoweekday() == 1):
if user.usertime.wd_mo == 0.0:
freedaycounter += 1
elif(dt.isoweekday() == 2):
if user.usertime.wd_tu == 0.0:
freedaycounter += 1
elif(dt.isoweekday() == 3):
if user.usertime.wd_we == 0.0:
freedaycounter += 1
elif(dt.isoweekday() == 4):
if user.usertime.wd_th == 0.0:
freedaycounter += 1
elif(dt.isoweekday() == 5):
if user.usertime.wd_fr == 0.0:
freedaycounter += 1
elif(dt.isoweekday() == 6):
if user.usertime.wd_sa == 0.0:
freedaycounter += 1
elif(dt.isoweekday() == 7):
if user.usertime.wd_so == 0.0:
freedaycounter += 1
return restdays - counter + freedaycounter
# Gibt die Woche als Wochentage zurück
def daterange(date1, date2):
for n in range(int ((date2 - date1).days)+1):
yield date1 + timedelta(n)