from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from .models import Workday, Breaks, FreeDays, AbsenceReason, Absence
from django.utils import timezone
import requests, csv, os
from django.templatetags.static import static
from django.conf import settings
from datetime import date
from django.contrib.auth.models import User
from calendar import monthrange
import datetime
import calendar
from .forms import AddAbsence, ConfirmAbsenceForm, UpdateAbsence, UpdateWorkdayForm, AddBreakForm, AddWorkdayForm
from django.contrib import messages
from users.models import UserFullName, UserYearAbsenceInfo
from users.models import UserTime
from datetime import timedelta
from django.db.models.signals import post_save
from users.signals import save_newabsence
import locale
from django.template.loader import render_to_string
from django.core.mail import send_mail
# Load freedays
def loadingFreeDays(plz):
# Getting land
file_path = os.path.join(settings.STATIC_ROOT, 'users/extra/plz_short.csv')
land = False
with open(file_path, 'rt') as csvfile:
filecsv = csv.reader(csvfile, delimiter=';')
for row in filecsv:
if row[1] == plz:
land = row[6]
break;
if(land != False):
# CALCULATE FREEDAYS AS JSON
year = today = date.today().year
URL = "https://feiertage-api.de/api/"
PARAMS = {'jahr':year,'nur_land':land}
r = requests.get(url = URL, params = PARAMS)
return r.json()
else:
return False
def get_datetime_range(year, month):
nb_days = monthrange(year, month)[1]
return [datetime.date(year, month, day) for day in range(1, nb_days+1)]
@login_required
def AbsenceUpdate(request, pk):
if request.method == "GET":
absence = Absence.objects.get(pk=pk)
timeinfo_thisyear = list(UserYearAbsenceInfo.objects.filter(year=absence.start.year, user=absence.user))[0]
try:
timeinfo_nextyear = list(UserYearAbsenceInfo.objects.filter(year=absence.start.year+1, user=absence.user))[0]
except:
timeinfo_nextyear = False
context = {
"active_link" : "abscence",
"form" : UpdateAbsence(instance=request.user),
"absence" : absence,
"timeinfo_thisyear" : timeinfo_thisyear,
"timeinfo_nextyear" : timeinfo_nextyear,
"start" : absence.start.strftime("%d.%m.%Y"),
"end" : absence.end.strftime("%d.%m.%Y"),
}
return render(request, 'timemanagement/tm_ab_update.html', context)
elif request.method == "POST":
absence = Absence.objects.get(pk=pk)
formtocheck = UpdateAbsence(request.POST, instance=request.user)
if(formtocheck.is_valid()):
abinfo = list(UserYearAbsenceInfo.objects.filter(user=absence.user, year=absence.start.year))[0]
abinfo_lastyear = ""
abinfo_nextyear = ""
is_lastyear = False
abinfo_lastyear = list(UserYearAbsenceInfo.objects.filter(user=absence.user, year=absence.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=absence.user, year=absence.start.year+1))
if(len(abinfo_nextyear) > 0):
is_nextyear = True
abinfo_nextyear = abinfo_nextyear[0]
abinfo.days_inuse -= formtocheck.cleaned_data["holidays_normal"]
abinfo.restdays -= formtocheck.cleaned_data["holidays_rest"]
abinfo.save()
abinfo_nextyear.days_inuse -= formtocheck.cleaned_data["holidays_normal_next"]
abinfo_nextyear.restdays -= formtocheck.cleaned_data["holidays_rest_next"]
abinfo_nextyear.save()
absence.start = formtocheck.cleaned_data["start"]
absence.end = formtocheck.cleaned_data["end"]
absence.startday_info = str(formtocheck.cleaned_data["startday_info"])
absence.endday_info = str(formtocheck.cleaned_data["endday_info"])
absence.reason = formtocheck.cleaned_data["reason"]
#absence.info = formtocheck.cleaned_data["info"]
#absence.confirm_info = formtocheck.cleaned_data["confirm_info"]
rep = None
if(formtocheck.cleaned_data["representator"] != None):
rep = User.objects.get(pk=formtocheck.cleaned_data["representator"].pk)
absence.representator = rep
absence.holidays_normal = 0.0
absence.holidays_rest = 0.0
absence.holidays_normal_next = 0.0
absence.holidays_rest_next = 0.0
absence.save()
messages.success(request, f'Abwesenheit aktualisiert!')
else:
messages.success(request, f'Fehler bei Abwesenheitsaktualisierung!')
context = {
"active_link" : "abscence",
}
return redirect("tma-management")
@login_required
def AbsenceManagmenet(request, activemonth=False, activeyear=False):
# NEW ABSENCE
if(request.method == "POST"):
'''
Nachdem eine neue Abwesenheit gespeichert wurde, geht es zur normalen Seite zurück, jedoch mit den Daten des aktuell angezeigten Monate/Jahr
'''
if(request.POST.get("form_type") == "absenceform"):
formtocheck = AddAbsence(request.POST, instance=request.user)
if(formtocheck.is_valid()):
#try:
workinguser = UserFullName.objects.get(pk=formtocheck.cleaned_data["userid"])
# DIFFERENT USER AGENCY
if(workinguser.profile.agency != request.user.profile.agency):
messages.success(request, f'Das dürfen Sie nicht!')
return redirect('tma-management', formtocheck.cleaned_data['activemonth'], formtocheck.cleaned_data['activeyear'])
# ALL OK - START SAVING ABSENCE
else:
confirmstat = 0
reason = AbsenceReason.objects.filter(name=formtocheck.cleaned_data["reason"], agency=request.user.profile.agency)[0]
if(request.user.has_perm("users.absencemanager") == False and reason.need_confirm == True):
confirmstat = 1
messages.success(request, f'Abwesenheit beantragt')
# SEND NOTIFICATION
elif(request.user.has_perm("users.absencemanager") == False and reason.need_confirm == False):
confirm_status = 0
messages.success(request, f'Abwesenheit eingetragen')
else:
messages.success(request, f'Abwesenheit eingetragen')
rep = None
if(formtocheck.cleaned_data["representator"] != None):
rep = User.objects.get(pk=formtocheck.cleaned_data["representator"].pk)
#newab = Absence(agency=request.user.profile.agency, user=workinguser, start=formtocheck.cleaned_data["start"],end=formtocheck.cleaned_data["end"], representator=rep, confirm_status=confirmstat, info=formtocheck.cleaned_data["info"], reason=formtocheck.cleaned_data["reason"], start_ishalf=formtocheck.cleaned_data["start_ishalf"], end_ishalf=formtocheck.cleaned_data["end_ishalf"]).save()
newab = Absence(agency=request.user.profile.agency, user=workinguser, start=formtocheck.cleaned_data["start"],end=formtocheck.cleaned_data["end"], representator=rep, confirm_status=confirmstat, info=formtocheck.cleaned_data["info"], reason=formtocheck.cleaned_data["reason"], startday_info=formtocheck.cleaned_data["startday_info"], endday_info=formtocheck.cleaned_data["endday_info"]).save()
# USER NOT FOUND
#except:
# messages.success(request, f'Fehler bei Abwesenheitsbearbeitung! Bitte wenden Sie sich an den Support.')
# return redirect('tma-management', formtocheck.cleaned_data['activemonth'], formtocheck.cleaned_data['activeyear'])
return redirect('tma-management', formtocheck.cleaned_data['activemonth'], formtocheck.cleaned_data['activeyear'])
else:
messages.success(request, f'Fehler beim eintragen der neuen Abwesenheit!')
return redirect('tma-management', formtocheck.cleaned_data['activemonth'], formtocheck.cleaned_data['activeyear'])
else:
return redirect('tma-management')
# NORMAL VIEW
else:
prevmonth = ""
nextmonth = ""
#MONTH
if(not activemonth or activemonth > 12 or activemonth < 1):
activemonth = int(activemonth)
#Active month
activemonth=date.today().month
if(activemonth == 1):
prevmonth = 12
else:
prevmonth = activemonth-1
if(activemonth == 12):
nextmonth = 1
else:
nextmonth = activemonth + 1
else:
if(activemonth == 1):
prevmonth = 12
else:
prevmonth = activemonth-1
if(activemonth == 12):
nextmonth = 1
else:
nextmonth = activemonth + 1
#YEAR
nextyear = date.today().year
prevyear = date.today().year
if(not activeyear):
activeyear = date.today().year
else:
if(nextmonth == 1):
nextyear = activeyear + 1
else:
nextyear = activeyear
if(prevmonth == 12):
prevyear = activeyear - 1
else:
prevyear = activeyear
missinguserdata = []
#CHECK, ob alle nötigen Infos zur Urlaubsberechnung vorliegen
for user in User.objects.filter(profile__agency=request.user.profile.agency):
tempTime = UserTime.objects.get(user=user)
if(tempTime.startdate == None):
missinguserdata.append(user)
kontingent = 0
inuse = 0
yearinfo = False
try:
yearinfo = list(UserYearAbsenceInfo.objects.filter(year=activeyear, user=request.user))[0]
inuse = yearinfo.days_inuse
kontingent = yearinfo.days - inuse
except:
pass
# ABSENCE AUFLISTUNG NACH GRUND
allreasons = AbsenceReason.objects.filter(agency=request.user.profile.agency).order_by("name")
final_reasons = []
for ar in allreasons:
tempabsece = Absence.objects.filter(reason=ar, user=request.user, start__year=activeyear, confirm_status=0)
temp_sum = 0.0
for t in tempabsece:
temp_sum += calculatingHolidaysByAbsence(request, t)
final_reasons.append([ar, temp_sum])
context = {
"active_link" : "abscence",
"usersofagency" : User.objects.filter(profile__agency=request.user.profile.agency).order_by("-last_name"),
"days_this_month" : get_datetime_range(activeyear,activemonth),
"nextmonth" : nextmonth,
"missinguserdata" : missinguserdata,
"prevmonth" : prevmonth,
"nextyear" : nextyear,
"prevyear" : prevyear,
"activemonth" : activemonth,
"activeyear" : activeyear,
"inuse" : inuse,
"final_reasons" : final_reasons,
"yearinfo" : yearinfo,
"kontingent" : kontingent,
"today" : date.today(),
"abscenceform" : AddAbsence(instance=request.user),
"userown" : Absence.objects.filter(agency=request.user.profile.agency, user=request.user).order_by("-start")
}
if(request.user.has_perm("users.absencemanager")):
context.update({
"needtoconfirm" : Absence.objects.filter(agency=request.user.profile.agency, confirm_status=1).order_by("-start"),
"allabsences" : Absence.objects.filter(agency=request.user.profile.agency).order_by("-start")
})
return render(request, 'timemanagement/tm_ab_management.html', context)
@login_required
def TimeManagementTeamSingle(request, pk, activemonth=False, activeyear=False):
if(request.user.has_perm("users.usermanager")):
# Setzt die Monatsausgabe auf Deutsch
locale.setlocale(locale.LC_TIME, 'de_DE.UTF-8')
user = User.objects.get(pk=pk)
# Hier wird der Monat und das Jahr für die Buttons gebaut
if(activemonth == False):
today = datetime.datetime.today()
active_month = str(today.strftime("%B"))
active_year = str(today.strftime("%Y"))
activemonth = today.month
else:
today = datetime.datetime(activeyear, activemonth, 1)
active_month = activemonth
active_month = str(today.strftime("%B"))
active_year = str(today.strftime("%Y"))
prev_year = active_year
next_year = active_year
next_month = today.month + 1
if(next_month == 13):
next_month = 1
next_year = int(next_year) + 1
prev_month = today.month - 1
if(prev_month == 0):
prev_month = 12
prev_year = int(prev_year) - 1
# Initialprüfung, ob Arbeitstage vorliegen
tempworkday = Workday.objects.filter(agency=request.user.profile.agency, user=user).order_by("start").exclude(end=None)[:1]
user_has_workdays = False
if len(tempworkday) == 1:
user_has_workdays = True
# Hier werden nur die Arbeitstage gefiltert, die auch aktuell zur Ansicht stehen sollen
context = {
"next_month" : next_month,
"breakmonthline" : date.today() - timedelta(days=30),
"prev_month" : prev_month,
"next_year" : next_year,
"prev_year" : prev_year,
"active_year" : int(active_year),
"active_month" : active_month,
"activemonth" : activemonth,
"active_link" : "timemanagement",
"days_this_month" : get_datetime_range(int(active_year), int(activemonth)),
"workdays" : Workday.objects.filter(agency=request.user.profile.agency, user=user, start__month=activemonth, start__year=active_year).order_by("start").exclude(end=None),
"userhasworkdays" : user_has_workdays,
"user" : user
}
return render(request, 'timemanagement/timemanagement_teamview_single.html', context)
# Requestet User has no rights...
else:
messages.success(request, f'Das dürfen Sie nicht!')
return redirect("tm-management")
@login_required
def TimeManagement(request, activemonth=False, activeyear=False):
# Setzt die Monatsausgabe auf Deutsch
locale.setlocale(locale.LC_TIME, 'de_DE.UTF-8')
# Hier wird der Monat und das Jahr für die Buttons gebaut
if(activemonth == False):
today = datetime.datetime.today()
active_month = str(today.strftime("%B"))
active_year = str(today.strftime("%Y"))
activemonth = today.month
else:
today = datetime.datetime(activeyear, activemonth, 1)
active_month = activemonth
active_month = str(today.strftime("%B"))
active_year = str(today.strftime("%Y"))
prev_year = active_year
next_year = active_year
next_month = today.month + 1
if(next_month == 13):
next_month = 1
next_year = int(next_year) + 1
prev_month = today.month - 1
if(prev_month == 0):
prev_month = 12
prev_year = int(prev_year) - 1
# Initialprüfung, ob Arbeitstage vorliegen
tempworkday = Workday.objects.filter(agency=request.user.profile.agency, user=request.user).order_by("start").exclude(end=None)[:1]
user_has_workdays = False
if len(tempworkday) == 1:
user_has_workdays = True
# Hier werden nur die Arbeitstage gefiltert, die auch aktuell zur Ansicht stehen sollen
context = {
"next_month" : next_month,
"breakmonthline" : date.today() - timedelta(days=30),
"prev_month" : prev_month,
"next_year" : next_year,
"prev_year" : prev_year,
"active_year" : int(active_year),
"active_month" : active_month,
"activemonth" : activemonth,
"active_link" : "timemanagement",
"days_this_month" : get_datetime_range(int(active_year), int(activemonth)),
"workdays" : Workday.objects.filter(agency=request.user.profile.agency, user=request.user, start__month=activemonth, start__year=active_year).order_by("start").exclude(end=None),
"userhasworkdays" : user_has_workdays
}
if(request.user.has_perm("users.usermanager")):
context.update({"usersofagencytm" : User.objects.filter(profile__agency=request.user.profile.agency).order_by('last_name')})
return render(request, 'timemanagement/timemanagement_management.html', context)
@login_required
def TimeUpdate(request, pk, team=0):
workday = Workday.objects.get(pk=pk)
user = workday.user
if(request.method == "POST"):
if(team == 0):
form = UpdateWorkdayForm(request.POST, instance=request.user)
else:
form = UpdateWorkdayForm(request.POST, instance=user)
start = datetime.datetime(int(workday.start.year), int(workday.start.month), int(workday.start.day), int(((str(form["start"].value()).split(":"))[0])), int(((str(form["start"].value()).split(":"))[1])))
end = datetime.datetime(int(workday.end.year), int(workday.end.month), int(workday.end.day), int(((str(form["end"].value()).split(":"))[0])), int(((str(form["end"].value()).split(":"))[1])))
workday.start = start
workday.end = end
workday.freefield = form["freefield"].value()
workday.target = form["target"].value()
workday.save()
messages.success(request, f'Arbeitstag aktualisiert')
if(team == 1):
return redirect('tm-team-single', user.pk, workday.start.month, workday.start.year)
else:
return redirect('tm-management')
else:
context = {
"active_link" : "timemanagement",
"workday" : Workday.objects.get(pk=pk),
"form" : UpdateWorkdayForm(instance= Workday.objects.get(pk=pk)),
"team" : team,
"user" : workday.user
}
return render(request, 'timemanagement/timemanagement_update.html', context)
@login_required
def TimeAdd(request, team=0, pk=0):
# Nutzer fügt selber einen neuen Arbeitstag hinzu
if(team == 0):
user = request.user
form = AddWorkdayForm(request.POST, instance=request.user)
#form.fields['target'] = 2.0
# Verwalter fügt einen Arbeitstag hinzu
else:
user = User.objects.get(pk=pk)
form = AddWorkdayForm(request.POST, instance=user)
if(request.method == "POST"):
if form.is_valid():
#start = datetime.datetime(int(workday.start.year), int(workday.start.month), int(workday.start.day), int(((str(form["start"].value()).split(":"))[0])), int(((str(form["start"].value()).split(":"))[1])))
#end = datetime.datetime(int(workday.end.year), int(workday.end.month), int(workday.end.day), int(((str(form["end"].value()).split(":"))[0])), int(((str(form["end"].value()).split(":"))[1])))
workday = Workday(start=form.cleaned_data["start"], end=form.cleaned_data["end"], target=form.cleaned_data["target"], user=user, freefield=form.cleaned_data["freefield"], agency=request.user.profile.agency)
if workday.start.day != workday.end.day or workday.start.month != workday.end.month or workday.start.year != workday.end.year or workday.start > workday.end:
messages.success(request, f'Der Arbeitstag darf nur an einem Tag stattfinden und das Ende muss nach dem Anfang liegen.')
context = {
"active_link" : "timemanagement",
"form" : AddWorkdayForm(),
"team" : team,
"user" : user
}
return render(request, 'timemanagement/timemanagement_add.html', context)
else:
workday.save()
messages.success(request, f'Arbeitstag hinzugefügt')
if (team == 1):
return redirect('tm-team-single', user.pk, workday.start.month, workday.start.year)
else:
return redirect('tm-management')
else:
messages.success(request, f'Bitte valide Daten eingeben!')
context = {
"active_link" : "timemanagement",
"form" : AddWorkdayForm(),
"team" : team,
"user" : user
}
return render(request, 'timemanagement/timemanagement_add.html', context)
else:
form = AddWorkdayForm()
# Setzt die Zielarbeitszeit auf die in den Vertragsdaten hinterlegten Wert
today = date.today()
if(today.isoweekday() == 1):
form.fields["target"].initial = user.usertime.wd_mo
elif(today.isoweekday() == 2):
form.fields["target"].initial = user.usertime.wd_tu
elif(today.isoweekday() == 3):
form.fields["target"].initial = user.usertime.wd_we
elif(today.isoweekday() == 4):
form.fields["target"].initial = user.usertime.wd_th
elif(today.isoweekday() == 5):
form.fields["target"].initial = user.usertime.wd_fr
elif(today.isoweekday() == 6):
form.fields["target"].initial = user.usertime.wd_sa
elif(today.isoweekday() == 7):
form.fields["target"].initial = user.usertime.wd_so
context = {
"active_link" : "timemanagement",
"form" : form,
"team" : team,
"user" : user
}
return render(request, 'timemanagement/timemanagement_add.html', context)
@login_required
def AddBreak(request, pk, team=0):
workday = Workday.objects.get(pk=pk)
user = workday.user
if(request.method == "POST"):
if(team == 0):
form = AddBreakForm(request.POST, instance=request.user)
else:
form = AddBreakForm(request.POST, instance=user)
start = datetime.datetime(int(workday.start.year), int(workday.start.month), int(workday.start.day), int(((str(form["start"].value()).split(":"))[0])), int(((str(form["start"].value()).split(":"))[1])))
end = datetime.datetime(int(workday.end.year), int(workday.end.month), int(workday.end.day), int(((str(form["end"].value()).split(":"))[0])), int(((str(form["end"].value()).split(":"))[1])))
if(team == 0):
newbreak = Breaks.objects.create(workday=workday, user=request.user, agency=request.user.profile.agency, start=start, end=end)
else:
newbreak = Breaks.objects.create(workday=workday, user=user, agency=user.profile.agency, start=start, end=end)
workday.breaks.add(newbreak)
workday.save()
messages.success(request, f'Pause hinzugefügt')
if(team == 0):
return redirect('tm-update', pk=pk)
else:
return redirect('tm-team-single', user.pk, workday.start.month, workday.start.year)
else:
if(team == 0):
context = {
"active_link" : "timemanagement",
"workday" : Workday.objects.get(pk=pk),
"form" : AddBreakForm(instance=request.user)
}
else:
context = {
"active_link" : "timemanagement",
"workday" : Workday.objects.get(pk=pk),
"form" : AddBreakForm(instance=user)
}
return render(request, 'timemanagement/timemanagement_break.html', context)
@login_required
def TimeAjax(request):
data = {}
if request.method == "GET":
# START WORKDAY
if request.GET["action"] == "start_day":
today = date.today()
targettime = 0.0
if(today.isoweekday() == 1):
targettime = request.user.usertime.wd_mo
elif(today.isoweekday() == 2):
targettime = request.user.usertime.wd_tu
elif(today.isoweekday() == 3):
targettime = request.user.usertime.wd_we
elif(today.isoweekday() == 4):
targettime = request.user.usertime.wd_th
elif(today.isoweekday() == 5):
targettime = request.user.usertime.wd_fr
elif(today.isoweekday() == 6):
targettime = request.user.usertime.wd_sa
elif(today.isoweekday() == 7):
targettime = request.user.usertime.wd_so
wd = Workday(user=request.user, agency=request.user.profile.agency, start=timezone.now(), target=targettime)
wd.save()
data = {
"success" : True,
"wd_starttime" : wd.start.strftime("%H:%M:%S"),
"wd_starttime_complete" : wd.start
}
# END DAY
elif request.GET["action"] == "end_day":
wd = list(Workday.objects.filter(user=request.user, agency=request.user.profile.agency, end=None))[0]
# END ALL BREAKS
for b in wd.breaks.all():
if b.end == None:
b.end = timezone.now()
b.save()
wd.end = timezone.now()
wd.save()
breaksum = 0
for b in wd.breaks.all():
if(b.end != None):
breaksum += (b.end - b.start).seconds
data = {
"success" : True,
"wd_endtime" : wd.end.strftime("%H:%M:%S"),
"actualbreaktime" : breaksum*1000
}
# START A BREAK
elif request.GET["action"] == "start_break":
wd = list(Workday.objects.filter(user=request.user, agency=request.user.profile.agency, end=None))[0]
newbreak = Breaks(workday=wd, user=request.user, agency=request.user.profile.agency, start=timezone.now())
newbreak.save()
wd.breaks.add(newbreak)
data = {
"success" : True,
"break_starttime" : newbreak.start,
}
# END BREAK
elif request.GET["action"] == "end_break":
wd = list(Workday.objects.filter(user=request.user, agency=request.user.profile.agency, end=None))[0]
toendbreak = list(wd.breaks.filter(end=None))[0]
toendbreak.end = timezone.now()
toendbreak.save()
wd = list(Workday.objects.filter(user=request.user, agency=request.user.profile.agency, end=None))[0]
breaksum = 0
for b in wd.breaks.all():
if(b.end != None):
breaksum += (b.end - b.start).seconds
data = {
"success" : True,
"actualbreaktime" : breaksum*1000
}
# REMOVE WORKDAY
elif request.GET["action"] == "remove_workday":
try:
wd = Workday.objects.get(pk=request.GET.get("workday"))
if(wd.agency == request.user.profile.agency):
wd.delete()
data = {
"success" : True
}
else:
data = { "success" : False}
except:
data = { "success" : False}
# REMOVE BREAK
elif request.GET["action"] == "remove_break":
breakwd = Breaks.objects.get(pk=request.GET.get("break"))
if(breakwd.agency == request.user.profile.agency):
breakwd.delete()
data = {
"success" : True
}
else:
data = { "success" : False}
# LOADING INTIAIL WORKDAYS
elif request.GET["action"] == "initial_load":
allfreedays = FreeDays.objects.filter(agency=request.user.profile.agency, day__gt=request.user.usertime.usetime_start, day__lt=date.today())
weekdays = [6,7]
for dt in daterange(request.user.usertime.usetime_start, date.today()):
if dt.isoweekday() not in weekdays:
in_freedays = False
for freeday in allfreedays.all():
if(dt == freeday.day):
in_freedays = True
break;
if(not in_freedays):
# MONDAY
if(dt.isoweekday() == 1):
start_time = datetime.timedelta(hours=8)
start_date = datetime.date(int(dt.year), int(dt.month), int(dt.day))
end_time = datetime.timedelta(hours=request.user.usertime.wd_mo) + start_time
time_start = datetime.datetime.strptime(str(start_time), "%H:%M:%S").time()
time_end = datetime.datetime.strptime(str(end_time), "%H:%M:%S").time()
start_datetime = datetime.datetime.combine(start_date, time_start)
end_datetime = datetime.datetime.combine(start_date, time_end)
Workday.objects.create(user=request.user, agency=request.user.profile.agency, start=start_datetime, end=end_datetime, target=request.user.usertime.wd_mo)
if(dt.isoweekday() == 2):
start_time = datetime.timedelta(hours=8)
start_date = datetime.date(int(dt.year), int(dt.month), int(dt.day))
end_time = datetime.timedelta(hours=request.user.usertime.wd_tu) + start_time
time_start = datetime.datetime.strptime(str(start_time), "%H:%M:%S").time()
time_end = datetime.datetime.strptime(str(end_time), "%H:%M:%S").time()
start_datetime = datetime.datetime.combine(start_date, time_start)
end_datetime = datetime.datetime.combine(start_date, time_end)
Workday.objects.create(user=request.user, agency=request.user.profile.agency, start=start_datetime, end=end_datetime, target=request.user.usertime.wd_tu)
if(dt.isoweekday() == 3):
start_time = datetime.timedelta(hours=8)
start_date = datetime.date(int(dt.year), int(dt.month), int(dt.day))
end_time = datetime.timedelta(hours=request.user.usertime.wd_we) + start_time
time_start = datetime.datetime.strptime(str(start_time), "%H:%M:%S").time()
time_end = datetime.datetime.strptime(str(end_time), "%H:%M:%S").time()
start_datetime = datetime.datetime.combine(start_date, time_start)
end_datetime = datetime.datetime.combine(start_date, time_end)
Workday.objects.create(user=request.user, agency=request.user.profile.agency, start=start_datetime, end=end_datetime, target=request.user.usertime.wd_we)
if(dt.isoweekday() == 4):
start_time = datetime.timedelta(hours=8)
start_date = datetime.date(int(dt.year), int(dt.month), int(dt.day))
end_time = datetime.timedelta(hours=request.user.usertime.wd_th) + start_time
time_start = datetime.datetime.strptime(str(start_time), "%H:%M:%S").time()
time_end = datetime.datetime.strptime(str(end_time), "%H:%M:%S").time()
start_datetime = datetime.datetime.combine(start_date, time_start)
end_datetime = datetime.datetime.combine(start_date, time_end)
Workday.objects.create(user=request.user, agency=request.user.profile.agency, start=start_datetime, end=end_datetime, target=request.user.usertime.wd_th)
if(dt.isoweekday() == 5):
start_time = datetime.timedelta(hours=8)
start_date = datetime.date(int(dt.year), int(dt.month), int(dt.day))
end_time = datetime.timedelta(hours=request.user.usertime.wd_fr) + start_time
time_start = datetime.datetime.strptime(str(start_time), "%H:%M:%S").time()
time_end = datetime.datetime.strptime(str(end_time), "%H:%M:%S").time()
start_datetime = datetime.datetime.combine(start_date, time_start)
end_datetime = datetime.datetime.combine(start_date, time_end)
Workday.objects.create(user=request.user, agency=request.user.profile.agency, start=start_datetime, end=end_datetime, target=request.user.usertime.wd_fr)
if(dt.isoweekday() == 6):
start_time = datetime.timedelta(hours=8)
start_date = datetime.date(int(dt.year), int(dt.month), int(dt.day))
end_time = datetime.timedelta(hours=request.user.usertime.wd_sa) + start_time
time_start = datetime.datetime.strptime(str(start_time), "%H:%M:%S").time()
time_end = datetime.datetime.strptime(str(end_time), "%H:%M:%S").time()
start_datetime = datetime.datetime.combine(start_date, time_start)
end_datetime = datetime.datetime.combine(start_date, time_end)
Workday.objects.create(user=request.user, agency=request.user.profile.agency, start=start_datetime, end=end_datetime, target=request.user.usertime.wd_sa)
if(dt.isoweekday() == 7):
start_time = datetime.timedelta(hours=8)
start_date = datetime.date(int(dt.year), int(dt.month), int(dt.day))
end_time = datetime.timedelta(hours=request.user.usertime.wd_so) + start_time
time_start = datetime.datetime.strptime(str(start_time), "%H:%M:%S").time()
time_end = datetime.datetime.strptime(str(end_time), "%H:%M:%S").time()
start_datetime = datetime.datetime.combine(start_date, time_start)
end_datetime = datetime.datetime.combine(start_date, time_end)
Workday.objects.create(user=request.user, agency=request.user.profile.agency, start=start_datetime, end=end_datetime, target=request.user.usertime.wd_so)
# Get Rendered Table
elif request.GET["action"] == "getrenderedtable":
prevmonth = ""
nextmonth = ""
activemonth = int(request.GET["activemonth"])
activeyear = int(request.GET["activeyear"])
#MONTH
if(not activemonth or activemonth > 12 or activemonth < 1):
activemonth = int(activemonth)
#Active month
activemonth=date.today().month
if(activemonth == 1):
prevmonth = 12
else:
prevmonth = activemonth-1
if(activemonth == 12):
nextmonth = 1
else:
nextmonth = activemonth + 1
else:
if(activemonth == 1):
prevmonth = 12
else:
prevmonth = activemonth-1
if(activemonth == 12):
nextmonth = 1
else:
nextmonth = activemonth + 1
#YEAR
nextyear = date.today().year
prevyear = date.today().year
if(not activeyear):
activeyear = date.today().year
else:
if(nextmonth == 1):
nextyear = activeyear + 1
else:
nextyear = activeyear
if(prevmonth == 12):
prevyear = activeyear - 1
else:
prevyear = activeyear
missinguserdata = []
#CHECK, ob alle nötigen Infos zur Urlaubsberechnung vorliegen
for user in User.objects.filter(profile__agency=request.user.profile.agency):
tempTime = UserTime.objects.get(user=user)
if(tempTime.startdate == None):
missinguserdata.append(user)
context = {
"active_link" : "abscence",
"usersofagency" : User.objects.filter(profile__agency=request.user.profile.agency).order_by("-last_name"),
"days_this_month" : get_datetime_range(activeyear,activemonth),
"activemonth" : activemonth,
"missinguserdata" : missinguserdata,
"activeyear" : activeyear,
"nextmonth" : nextmonth,
"prevmonth" : prevmonth,
"nextyear" : nextyear,
"prevyear" : prevyear,
"today" : date.today(),
}
return render(request, "timemanagement/rendered_table.html", context)
# Prüfung, ob eine Vertretung nötig ist oder nicht
elif request.GET["action"] == "checkrequired":
reason = AbsenceReason.objects.get(pk=request.GET["rid"])
if(reason.agency == request.user.profile.agency):
data = {
"success" : True,
"isreq" : reason.need_rep,
"isholiday" : reason.is_holiday
}
else:
data = {
"success" : False
}
# DELETE ABSENCE
elif request.GET["action"] == "remove_absence":
absence = Absence.objects.get(pk=request.GET["ab"])
if(request.user.has_perm("users.absencemanager") and absence.agency == request.user.profile.agency):
absence.delete()
data = {
"success" : True
}
# GET FORM FOR CONFIRM ABSENCE
elif request.GET["action"] == "getrenderedform":
absence = Absence.objects.get(pk=request.GET["abscenceid"])
timeinfo_thisyear = list(UserYearAbsenceInfo.objects.filter(year=absence.start.year, user=absence.user))[0]
try:
timeinfo_nextyear = list(UserYearAbsenceInfo.objects.filter(year=absence.start.year+1, user=absence.user))[0]
except:
timeinfo_nextyear = False
# POrüfen, ob es in diesem Zeitraum noch andere Abwesenheiten gibt
other_absences = Absence.objects.filter(start__lte=absence.start, end__gte=absence.end, agency=request.user.profile.agency, confirm_status=0).exclude(user=absence.user)
other_absences_string = False
if (len(other_absences) > 0):
other_absences_string = []
for a in other_absences:
other_absences_string.append(a.user.first_name + " " + a.user.last_name + " - Vom " + a.start.strftime("%d.%m.%Y") + " bis " + a.end.strftime("%d.%m.%Y"))
context = {
"confirmform" : ConfirmAbsenceForm(instance=request.user),
"absence" : absence,
"other_absences_string" : other_absences_string,
"timeinfo_thisyear" : timeinfo_thisyear,
"timeinfo_nextyear" : timeinfo_nextyear
}
return render(request, "timemanagement/rendered_confirmform.html", context)
elif request.GET["action"] == "confirmornotabscence":
absence = Absence.objects.get(pk=request.GET["absencetowork"])
new_stat = request.GET["newconfstat"]
info = request.GET["info"]
# Eingeloggter Nutzer hat Rechte, Urlaube einzutragen
if(absence.user.profile.agency == request.user.profile.agency and request.user.has_perm("users.absencemanager")):
absence.confirm_status = new_stat
# Wenn eine Abwesenheit abgelehnt wurde, werden hier die Tage wieder auf das Kontingent geschrieben. Die Abewesenheit selber wird aber nicht gelöscht, sondern ist dann einfach "leer"
if(new_stat == "2"):
year = absence.start.year
userabinfo_thisyear = list(UserYearAbsenceInfo.objects.filter(user=absence.user, year=year))[0]
userabinfo_nextyear = list(UserYearAbsenceInfo.objects.filter(user=absence.user, year=year+1))[0]
userabinfo_thisyear.days_inuse = userabinfo_thisyear.days_inuse - absence.holidays_normal - absence.holidays_rest
userabinfo_thisyear.restdays = userabinfo_thisyear.restdays + absence.holidays_rest
userabinfo_nextyear.days_inuse = userabinfo_nextyear.days_inuse - absence.holidays_normal_next - absence.holidays_rest_next
userabinfo_nextyear.restdays = userabinfo_nextyear.restdays + absence.holidays_rest_next
userabinfo_thisyear.save()
userabinfo_nextyear.save()
absence.holidays_normal = 0
absence.holidays_rest = 0
absence.holidays_normal_next = 0
absence.holidays_rest_next = 0
absence.confirm_info = info
post_save.disconnect(save_newabsence, sender=Absence)
absence.save()
post_save.connect(save_newabsence, sender=Absence)
messages.success(request, f'Abwesenheit gespeichert!')
if(absence.user.usernotifications.absence_created_mail):
notificationtext = " es wurde eine Abwesenheit bearbeitet!"
msg_html = render_to_string('notificsys/notification_mail.html', {'username': absence.user.first_name + " " + absence.user.last_name, 'notificationtext' : notificationtext, 'linktarget' : ""})
send_mail(
'Agentur-Benachrichtigung',
'Hallo ' + absence.user.first_name + " " + absence.user.last_name + '! ' + notificationtext,
'noreply@digitale-agentur.com',
[absence.user.email],
html_message=msg_html,
fail_silently=True
)
else:
messages.success(request, f'Das dürfen Sie nicht!')
data = {
"success" : True,
"activemonth" : request.GET["activemonth"],
"activeyear" : request.GET["activeyear"]
}
# Berechnung starten, da Urlaub vorhanden ist
elif request.GET["action"] == "getrestholidays":
user = User.objects.get(pk=request.GET["userid"])
usertimedata = UserTime.objects.get(user=user)
today = date.today()
if(user.profile.agency == request.user.profile.agency):
start_day = request.GET["startdate"].split("__")
# TASK: Diese Zeile wirft eine Fehler: invalid literal for int() with base 10: 'NaN'
start_day_obj = datetime.date(int(start_day[0]), int(start_day[1]), int(start_day[2]))
end_day = request.GET["enddate"].split("__")
end_day_obj = datetime.date(int(end_day[0]), int(end_day[1]), int(end_day[2]))
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]))
# GET INFO IF DAY IS HALF OR NOT, EQUAL PRE-POST-DAY
start_half = False
if request.GET["startday_info"] == "1" or request.GET["startday_info"] == "2":
start_half = True
end_half = False
if request.GET["endday_info"] == "1" or request.GET["endday_info"] == "2":
end_half = True
choosenyear = int(start_day[0])
yeardata = list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency, year=choosenyear))[0]
holiday_thisyear = 0
holiday_lastyear = yeardata.restdays
holiday_nextyear = 0
holiday_nextyear_rest = 0
two_years = False
need_days_next = 0
need_days_this = 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(request, start_day_obj, end_day_obj, start_half, end_half, user))*(-1)
holiday_thisyear = yeardata.days - yeardata.days_inuse - need_days
else:
need_days = (calculateHolidays(request, start_day_obj, end_day_obj, start_half, end_half, user))*(-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
else:
holiday_lastyear = yeardata.restdays - need_days
# 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(request, start_day_obj, date_splitter, start_half, False), user)*(-1)
need_days_next = (calculateHolidays(request, date_splitter, end_day_obj, False, end_half, user))*(-1)
need_days = (calculateHolidays(request, start_day_obj, date_splitter, start_half, False, user))*(-1) + (calculateHolidays(request, 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(request, date_splitter, end_day_obj, False, end_half, user))*(-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
# POrüfen, ob es in diesem Zeitraum noch andere Abwesenheiten gibt
other_absences = Absence.objects.filter(start__lte=start_day_obj, end__gte=end_day_obj, agency=request.user.profile.agency, confirm_status=0).exclude(user=user)
other_absences_string = False
if (len(other_absences) > 0):
other_absences_string = ""
for a in other_absences:
other_absences_string += a.user.first_name + " " + a.user.last_name + " - Vom " + a.start.strftime("%d.%m.%Y") + " bis " + a.end.strftime("%d.%m.%Y") + "
"
# Prüfen, ob der Nutzer selbst schon Abwesenheiten in diesem Zeitraum hat
userown_absences = Absence.objects.filter(start__lte=start_day_obj, end__gte=end_day_obj, agency=request.user.profile.agency, user=user, confirm_status=0)
userown_absences_string = False
if (len(userown_absences) > 0):
userown_absences_string = ""
for a in userown_absences:
userown_absences_string += a.reason.name + " - Vom " + a.start.strftime("%d.%m.%Y") + " bis " + a.end.strftime("%d.%m.%Y") + "
"
data = {
"restholiday_thisyear" : holiday_thisyear,
"restholiday_lastyear" : holiday_lastyear,
"restholiday_nextyear" : holiday_nextyear,
"restholiday_nextyear_rest" : holiday_nextyear_rest,
"two_years" : two_years,
"need_days" : need_days,
"need_days_next" : need_days_next,
"need_days_this" : need_days_this,
"other_absences" : other_absences_string,
"userown_absences" : userown_absences_string,
"choosenuser_name" : user.first_name + " " + user.last_name
}
print(data)
# REQUEST USER NO RIGHTS
else:
data = {
"success" : False
}
# GET REQUEST ACTION UNKNOWN
else:
data = {
"success" : False
}
return JsonResponse(data)
'''
Gibt einen Integer zurück, welcher die Urlaubstage von Start zu Enddatum auf der Grundlage von Freitagen berechnet.
Berücksichtigt sowohl Wochenende als auch in der Agentur hinterlegte Freitage/Schließtage
'''
@login_required
def calculateHolidays(request, start, end, start_half, end_half, user):
restdays = 0
#allfreedays = FreeDays.objects.filter(agency=request.user.profile.agency).distinct('start', 'year')
allfreedays = FreeDays.objects.filter(agency=request.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
# Prüfung, ob der Mitarbeiter an diesem Tag überhaupt arbeitet. Wenn nicht, wird der Freedaycounter einfach erhöht
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
@login_required
def calculatingHolidaysByAbsence(request, absence):
# Freitage laden, die innerhalb der gewünschten Abwesenheit liegen
allfreedays = FreeDays.objects.filter(agency=request.user.profile.agency, day__gt=absence.start, day__lt=absence.end)
finalholidayinabsence = 0
# Start und Ende gleich, nur ein Tag. Checken, ob Halber Tag
if(absence.start == absence.end):
if absence.startday_info == "1" or absence.startday_info == "2":
finalholidayinabsence = 0.5
else:
finalholidayinabsence = 1
return finalholidayinabsence
else:
if absence.startday_info == "1" or absence.startday_info == "2":
finalholidayinabsence -= 0.5
if absence.endday_info == "1" or absence.endday_info == "2":
finalholidayinabsence -= 0.5
weekdays = []
freedaycounter = 0
for dt in daterange(absence.start, absence.end):
day_found = False
if dt.isoweekday() not in weekdays:
finalholidayinabsence += 1
# Prüfung, ob freie Tage vorhanden sind
for freeday in allfreedays.all():
# FREEDAY FOUND
if(dt == freeday.day):
freedaycounter += 1
day_found = True
# Prüfung, ob der Mitarbeiter an diesem Tag überhaupt arbeitet. Wenn nicht, wird der Freedaycounter einfach erhöht
stat = False
if day_found == False:
if(dt.isoweekday() == 1):
if absence.user.usertime.wd_mo == 0.0:
freedaycounter += 1
elif(dt.isoweekday() == 2):
if absence.user.usertime.wd_tu == 0.0:#
freedaycounter += 1
elif(dt.isoweekday() == 3):
if absence.user.usertime.wd_we == 0.0:
freedaycounter += 1
elif(dt.isoweekday() == 4):
if absence.user.usertime.wd_th == 0.0:
freedaycounter += 1
elif(dt.isoweekday() == 5):
if absence.user.usertime.wd_fr == 0.0:
freedaycounter += 1
elif(dt.isoweekday() == 6):
if absence.user.usertime.wd_sa == 0.0:
freedaycounter += 1
elif(dt.isoweekday() == 7):
if absence.user.usertime.wd_so == 0.0:
freedaycounter += 1
return finalholidayinabsence - 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)