Zwischencommit Absence
This commit is contained in:
parent
db58c37c82
commit
37070e045d
|
|
@ -66,15 +66,18 @@ class UserTimeForm(forms.ModelForm):
|
||||||
labels = {
|
labels = {
|
||||||
"holiday" : "Urlaubstage",
|
"holiday" : "Urlaubstage",
|
||||||
"loose_holidedate" : "Urlaubstage aus Vorjahr verfallen am",
|
"loose_holidedate" : "Urlaubstage aus Vorjahr verfallen am",
|
||||||
|
"startdate" : "Einstellungsdatum",
|
||||||
|
"holiday_start" : "Urlaubstage bei Einstellung",
|
||||||
"wd_mo" : "Montag",
|
"wd_mo" : "Montag",
|
||||||
"wd_tu" : "Dienstag",
|
"wd_tu" : "Dienstag",
|
||||||
"wd_we" : "Mittwoch",
|
"wd_we" : "Mittwoch",
|
||||||
"wd_th" : "Donnerstag",
|
"wd_th" : "Donnerstag",
|
||||||
"wd_fr" : "Freitag",
|
"wd_fr" : "Freitag",
|
||||||
}
|
}
|
||||||
fields = ["holiday", "loose_holidedate", "wd_mo", "wd_tu", "wd_we", "wd_th", "wd_fr"]
|
fields = ["holiday", "loose_holidedate", "startdate", "holiday_start", "wd_mo", "wd_tu", "wd_we", "wd_th", "wd_fr"]
|
||||||
widgets = {
|
widgets = {
|
||||||
'loose_holidedate': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'})
|
'loose_holidedate': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'}),
|
||||||
|
"startdate" : DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -130,14 +133,14 @@ class UserProfileForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Profile
|
model = Profile
|
||||||
labels = {
|
labels = {
|
||||||
"persnumber" : "Personalnummer",
|
"persnumber" : "Personalnummer",
|
||||||
"visible" : "Im Organigramm sichtbar",
|
"visible" : "Im Organigramm sichtbar",
|
||||||
"phonemobile" : "Mobilnummer",
|
"phonemobile" : "Mobilnummer",
|
||||||
"phone_public" : "Nur Interne Verwendung der Mobilnummer",
|
"phone_public" : "Nur Interne Verwendung der Mobilnummer",
|
||||||
"phoneland" : "Festnetznummer",
|
"phoneland" : "Festnetznummer",
|
||||||
"image": "Profilbild",
|
"image": "Profilbild",
|
||||||
"func" : "Agenturfunktion",
|
"func" : "Agenturfunktion",
|
||||||
"compfunc" : "Tätigkeit"
|
"compfunc" : "Tätigkeit"
|
||||||
}
|
}
|
||||||
widgets = {"parent" : forms.HiddenInput()}
|
widgets = {"parent" : forms.HiddenInput()}
|
||||||
fields = ["parent", "func", "compfunc", "visible", "phoneland", "phonemobile", "phone_public", "persnumber", "image" ]
|
fields = ["parent", "func", "compfunc", "visible", "phoneland", "phonemobile", "phone_public", "persnumber", "image" ]
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@
|
||||||
<h5 class="mt-3">Agenturinformationen{% if request.user.profile.showtooltips %} <small><i data-toggle="tooltip" data-placement="top" title="Verwalten Sie hier die Informationen Ihrer Agentur, z.B. Adresse, E-Mailadresse und Telefon." class="far fa-question-circle"></i></small>{% endif %}
|
<h5 class="mt-3">Agenturinformationen{% if request.user.profile.showtooltips %} <small><i data-toggle="tooltip" data-placement="top" title="Verwalten Sie hier die Informationen Ihrer Agentur, z.B. Adresse, E-Mailadresse und Telefon." class="far fa-question-circle"></i></small>{% endif %}
|
||||||
</h5>
|
</h5>
|
||||||
<hr>
|
<hr>
|
||||||
{% block agency_content %}
|
{% block agency_content %}
|
||||||
{% include "dasettings/agency_content.html" %}
|
{% include "dasettings/agency_content.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,9 @@
|
||||||
<p>Urlaub <small><i data-toggle="tooltip" data-placement="top" title="Legen Sie fest, wie viel Urlaub dieser Mitarbeiter im Jahr hat." class="far fa-question-circle"></i></small></p>
|
<p>Urlaub <small><i data-toggle="tooltip" data-placement="top" title="Legen Sie fest, wie viel Urlaub dieser Mitarbeiter im Jahr hat." class="far fa-question-circle"></i></small></p>
|
||||||
{{usertime_form.media}}
|
{{usertime_form.media}}
|
||||||
{{usertime_form.holiday|as_crispy_field}}
|
{{usertime_form.holiday|as_crispy_field}}
|
||||||
|
{{usertime_form.holiday_start|as_crispy_field}}
|
||||||
{{usertime_form.loose_holidedate|as_crispy_field}}
|
{{usertime_form.loose_holidedate|as_crispy_field}}
|
||||||
|
{{usertime_form.startdate|as_crispy_field}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<hr>
|
<hr>
|
||||||
|
|
|
||||||
|
|
@ -544,7 +544,6 @@ def UserProfileUpdate(request, pk, newuser=0):
|
||||||
elif(request.POST["form_type"] == "contract"):
|
elif(request.POST["form_type"] == "contract"):
|
||||||
|
|
||||||
formtosave = UserTimeForm(request.POST, instance=UserTime.objects.get(user=usertochange))
|
formtosave = UserTimeForm(request.POST, instance=UserTime.objects.get(user=usertochange))
|
||||||
print(formtosave)
|
|
||||||
if(formtosave.is_valid()):
|
if(formtosave.is_valid()):
|
||||||
messages.success(request, f'Vertragsdaten gespeichert!')
|
messages.success(request, f'Vertragsdaten gespeichert!')
|
||||||
formtosave.save()
|
formtosave.save()
|
||||||
|
|
@ -792,7 +791,6 @@ def ManageAgInAgn(request, pk):
|
||||||
for a in network.adminagencys.all():
|
for a in network.adminagencys.all():
|
||||||
allagofagn.append(a)
|
allagofagn.append(a)
|
||||||
|
|
||||||
print(allagofagn)
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'active_link' : 'dasettings',
|
'active_link' : 'dasettings',
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
{% if perms.users.standardmanager %}
|
{% if perms.users.standardmanager %}
|
||||||
<li class="nav-item" style="float: right !important;">
|
<li class="nav-item" style="float: right !important;">
|
||||||
<a class="nav-link" id="agencys" data-toggle="tab" href="#t_agencys" role="tab" aria-controls="t_agencys" aria-selected="false">
|
<a class="nav-link" id="agencys" data-toggle="tab" href="#t_agencys" role="tab" aria-controls="t_agencys" aria-selected="false">
|
||||||
{% if unpubstandards_of_user|length > 0 %}
|
{% if unpubstandards_of_user|length > 0 %}
|
||||||
<span class="badge badge-primary badge-counter" style="float: right; margin-left: 5px; margin-top: 0px">{{unpubstandards_of_user|length}} </span>
|
<span class="badge badge-primary badge-counter" style="float: right; margin-left: 5px; margin-top: 0px">{{unpubstandards_of_user|length}} </span>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
Unveröffentlichte Standards
|
Unveröffentlichte Standards
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -2,7 +2,7 @@ from django import template
|
||||||
from django.contrib.auth.models import Group, User
|
from django.contrib.auth.models import Group, User
|
||||||
from users.models import AgencyGroup, Agency, AgencyNetwork, AgencyNetworkPreperation
|
from users.models import AgencyGroup, Agency, AgencyNetwork, AgencyNetworkPreperation
|
||||||
from standards.models import Standards, StandardCommentRate, StandardComments
|
from standards.models import Standards, StandardCommentRate, StandardComments
|
||||||
from timemanagement.models import Workday, FreeDays
|
from timemanagement.models import Workday, FreeDays, Absence
|
||||||
from message.models import Message
|
from message.models import Message
|
||||||
import os
|
import os
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
@ -415,3 +415,28 @@ def isfreedayname(user, daytocheck):
|
||||||
returnstat = True
|
returnstat = True
|
||||||
returnstat = fd[0].name
|
returnstat = fd[0].name
|
||||||
return returnstat
|
return returnstat
|
||||||
|
|
||||||
|
# RETURN ALL ABSENCE ELEMENTS FOR THAT DAY
|
||||||
|
@register.simple_tag
|
||||||
|
def getabscenceday(loggeduser, user, daytocheck):
|
||||||
|
|
||||||
|
returnstat = False
|
||||||
|
if(loggeduser.has_perm("users.absencemanager")):
|
||||||
|
absencedays = 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)
|
||||||
|
else:
|
||||||
|
absencedays = (Absence.objects.filter(agency=user.profile.agency, user=loggeduser, confirm_status=1) | 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 = list(absencedays)[0]
|
||||||
|
|
||||||
|
return returnstat
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def getsomeyears(start):
|
||||||
|
years = []
|
||||||
|
start_int = int(start)
|
||||||
|
years = [start_int-4, start_int-3,start_int-2,start_int-1,start_int, start_int+1, start_int+2, start_int+3, start_int+4]
|
||||||
|
return years
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def getsomemonths():
|
||||||
|
return ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]
|
||||||
|
|
@ -1,19 +1,65 @@
|
||||||
from bootstrap_datepicker_plus import DatePickerInput
|
from bootstrap_datepicker_plus import DatePickerInput
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from .models import Absence
|
from .models import Absence, AbsenceReason
|
||||||
|
from users.models import UserFullName
|
||||||
|
|
||||||
class AddAbsence(forms.ModelForm):
|
class AddAbsence(forms.ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Absence
|
model = Absence
|
||||||
labels = {
|
labels = {
|
||||||
"start" : "Beginn der Abwesenheit",
|
"start" : "Beginn der Abwesenheit",
|
||||||
"end" : "Ende der Abwesenheit",
|
"start_ishalf" : "Halber Tag?",
|
||||||
}
|
"end" : "Ende der Abwesenheit",
|
||||||
fields = ['start', 'end']
|
"end_ishalf" : "Halber Tag?",
|
||||||
|
"reason" : "Abwesenheitsgrund",
|
||||||
|
"representator" : "Vertreter",
|
||||||
|
"info" : "Begründung"
|
||||||
|
}
|
||||||
widgets = {
|
widgets = {
|
||||||
'start': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'}),
|
'start': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'}),
|
||||||
'end': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'}),
|
'end': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fields = ['start', 'start_ishalf', 'end','end_ishalf', 'reason', "representator", 'info']
|
||||||
|
|
||||||
|
def __init__(self, *arg, **kwargs):
|
||||||
|
super(AddAbsence, self).__init__(*arg, **kwargs)
|
||||||
|
self.fields['reason'].queryset = AbsenceReason.objects.filter(agency=kwargs['instance'].profile.agency).order_by('-name')
|
||||||
|
self.fields['representator'].queryset = UserFullName.objects.filter(profile__agency=kwargs['instance'].profile.agency)
|
||||||
|
self.fields['info'].widget.attrs['rows'] = 3
|
||||||
|
self.fields['start'].required = True
|
||||||
|
self.fields['end'].required = True
|
||||||
|
self.fields['reason'].required = True
|
||||||
|
|
||||||
|
self.fields['nextmonth'] = forms.CharField(initial="", required=False, widget=forms.HiddenInput())
|
||||||
|
self.fields['prevmonth'] = forms.CharField(initial="", required=False, widget=forms.HiddenInput())
|
||||||
|
self.fields['nextyear'] = forms.CharField(initial="", required=False, widget=forms.HiddenInput())
|
||||||
|
self.fields['prevyear'] = forms.CharField(initial="", required=False, widget=forms.HiddenInput())
|
||||||
|
self.fields['activemonth'] = forms.CharField(initial="", required=False, widget=forms.HiddenInput())
|
||||||
|
self.fields['activeyear'] = forms.CharField(initial="", required=False, widget=forms.HiddenInput())
|
||||||
|
self.fields['userid'] = forms.CharField(initial="", required=False, widget=forms.HiddenInput())
|
||||||
|
|
||||||
|
'''
|
||||||
|
def clean(self):
|
||||||
|
start_date = self.cleaned_data['start']
|
||||||
|
end_date = self.cleaned_data['end']
|
||||||
|
|
||||||
|
if end_date <= start_date:
|
||||||
|
raise forms.ValidationError("Das Ende der Abwesenheit muss am oder nach dem Start der Abwesenheit liegen.")
|
||||||
|
return super(AddAbsence, self).clean()
|
||||||
|
'''
|
||||||
|
|
||||||
|
class ConfirmAbsenceForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Absence
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"confirm_info" : "Begründung zur Annahme/zur Ablehnung"
|
||||||
|
}
|
||||||
|
fields = ['confirm_info']
|
||||||
|
|
||||||
|
def __init__(self, *arg, **kwargs):
|
||||||
|
super(ConfirmAbsenceForm, self).__init__(*arg, **kwargs)
|
||||||
|
self.fields['confirm_info'].widget.attrs['rows'] = 3
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from users.models import Agency
|
from users.models import Agency
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
class Workday(models.Model):
|
class Workday(models.Model):
|
||||||
|
|
@ -24,17 +25,31 @@ class AbsenceReason(models.Model):
|
||||||
need_rep = models.BooleanField(default=True)
|
need_rep = models.BooleanField(default=True)
|
||||||
is_holiday = models.BooleanField(default=True)
|
is_holiday = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.name}'
|
||||||
|
|
||||||
class Absence(models.Model):
|
class Absence(models.Model):
|
||||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
|
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
|
||||||
start = models.DateTimeField(default=None, null=True, blank=True)
|
start = models.DateTimeField(default=None, null=True, blank=True)
|
||||||
end = models.DateTimeField(default=None, null=True, blank=True)
|
end = models.DateTimeField(default=None, null=True, blank=True)
|
||||||
start_ishalf = models.BooleanField(default=False)
|
start_ishalf = models.BooleanField(default=False, blank=True)
|
||||||
end_ishalf = models.BooleanField(default=False)
|
end_ishalf = models.BooleanField(default=False, blank=True)
|
||||||
reason = models.ForeignKey("AbsenceReason", on_delete=models.SET_NULL, null=True, blank=True)
|
reason = models.ForeignKey("AbsenceReason", on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
info = models.TextField(blank=True, verbose_name='Abwesenheitsbegründung', default="")
|
info = models.TextField(blank=True, verbose_name='Abwesenheitsbegründung', default="")
|
||||||
|
'''
|
||||||
|
CONFIRM_STATUS INFOS
|
||||||
|
|
||||||
|
0 = NO NEED TO CONFIRM AND CONFORM OK
|
||||||
|
1 = IS CONFIRMED, AWAITING OK
|
||||||
|
2 = NOT CONFIRMED
|
||||||
|
|
||||||
|
'''
|
||||||
confirm_status = models.IntegerField(default=0)
|
confirm_status = models.IntegerField(default=0)
|
||||||
confirm_info = models.TextField(blank=True, verbose_name='Begründung', default="")
|
confirm_info = models.TextField(blank=True, verbose_name='Begründung', default="")
|
||||||
|
representator = models.ForeignKey(User, blank=True, default=None, null=True, on_delete=models.CASCADE, related_name="Vertreter")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FreeDays(models.Model):
|
class FreeDays(models.Model):
|
||||||
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
|
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
<h5>Abwesenheit für {{absence.user.first_name}} {{absence.user.last_name}} annehmen oder ablehnen</h5>
|
||||||
|
<hr>
|
||||||
|
<h6>Informationen der Abwesenheit</h6>
|
||||||
|
Von: {{absence.start|date:"d.m Y"}}<br />
|
||||||
|
Bis: {{absence.end|date:"d.m Y"}}<br />
|
||||||
|
Grund: {{absence.reason.name}}<br />
|
||||||
|
Informationen: {{absence.info}}<br />
|
||||||
|
<hr>
|
||||||
|
<form method="POST">
|
||||||
|
<input type="hidden" name="form_type" value="confirmform">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{confirmform|crispy}}
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-success" onclick="javascript:noconfirmAbsence({{absence.pk}})">Ablehnen</button>
|
||||||
|
<button type="button" class="btn btn-danger" onclick="javascript:confirmAbsence({{absence.pk}})">Annehmen</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<script type="text/javascript">
|
||||||
|
absencestring_confirm = 'Sicher, dass Sie die Abwesenheit für {{absence.user.first_name}} {{absence.user.last_name}} vom {{absence.start|date:"d.m Y"}} bis {{absence.end|date:"d.m Y"}} <b>annehmen</b> wollen?'
|
||||||
|
absencestring_noconfirm = 'Sicher, dass Sie die Abwesenheit für {{absence.user.first_name}} {{absence.user.last_name}} vom {{absence.start|date:"d.m Y"}} bis {{absence.end|date:"d.m Y"}} <b>ablehnen</b> wollen?'
|
||||||
|
</script>
|
||||||
|
|
@ -1,18 +1,17 @@
|
||||||
{% load counter_tag %}
|
{% load counter_tag %}
|
||||||
|
|
||||||
<div class="btn-group mr-2 mb-2" role="group" aria-label="calendarbuttons">
|
|
||||||
<button type="button" class="btn btn-primary mr-1" onclick="javascript:prevMonth()" ><i class="fas fa-arrow-circle-left"></i></button>
|
|
||||||
<button type="button" class="btn btn-primary mr-1" style="min-width: 150px !important;">{{days_this_month.0|date:"F Y"}}</button>
|
|
||||||
<button type="button" class="btn btn-primary mr-1" onclick="javascript:nextMonth()"><i class="fas fa-arrow-circle-right"></i></button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table class="table table-striped table-sm table-bordered" id="timetable_team">
|
<table class="table table-striped table-sm table-bordered" id="timetable_team">
|
||||||
<th>
|
<tr>
|
||||||
|
<td id="9999999999_tableheadid">
|
||||||
|
<div class="btn-group ml-3 mb-2 mt-2" role="group" aria-label="calendarbuttons">
|
||||||
|
<button type="button" class="btn btn-primary mr-1" onclick="javascript:prevMonth()" ><i class="fas fa-arrow-circle-left"></i></button>
|
||||||
|
<button type="button" class="btn btn-primary mr-1" style="min-width: 150px !important;" onclick="javascript:fastChangeModal()">{{days_this_month.0|date:"F Y"}}</button>
|
||||||
|
<button type="button" class="btn btn-primary mr-1" onclick="javascript:nextMonth()"><i class="fas fa-arrow-circle-right"></i></button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
{% for da in days_this_month %}
|
{% for da in days_this_month %}
|
||||||
<td id="{{forloop.counter0}}_tableheadid"><small>{{da|date:"d D"}}</small></td>
|
<td id="{{forloop.counter0}}_tableheadid"><small>{{da|date:"d D"}}</small></td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</th>
|
</tr>
|
||||||
|
|
||||||
{% for us in usersofagency %}
|
{% for us in usersofagency %}
|
||||||
{% setdateforloopcounter forloop.counter %}
|
{% setdateforloopcounter forloop.counter %}
|
||||||
|
|
@ -27,12 +26,72 @@
|
||||||
|
|
||||||
{% isfreeday user da as isfree %}
|
{% isfreeday user da as isfree %}
|
||||||
{% isfreedayname user da as isfreename %}
|
{% isfreedayname user da as isfreename %}
|
||||||
{% if isfree %}
|
{% getabscenceday user us da as abday %}
|
||||||
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_free" style="background-color: #e74a3b" data-toggle="tooltip" data-placement="top" title="{{isfreename}}">
|
|
||||||
|
|
||||||
|
{% if isfree %}
|
||||||
|
<!-- FREEDAYS -->
|
||||||
|
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_free" style="background-color: #e74a3b" data-toggle="tooltip" data-placement="top" title="{{isfreename}}">
|
||||||
{% elif da.weekday == 5 or da.weekday == 6 %}
|
{% elif da.weekday == 5 or da.weekday == 6 %}
|
||||||
|
<!-- WEEKEND -->
|
||||||
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_free" style="background-color: #d3d3d3">
|
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_free" style="background-color: #d3d3d3">
|
||||||
|
{% elif abday != False %}
|
||||||
|
<!-- USER IS NOT THERE -->
|
||||||
|
{% if abday.confirm_status == 0 %}
|
||||||
|
{% if user|usergperm:"absencemanager" %}
|
||||||
|
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_{{abday.pk}}_absence"
|
||||||
|
{% if abday.start_ishalf and abday.start.day == da.day %}
|
||||||
|
class="partialfilling negative"
|
||||||
|
style="background-size: 50% 100%"
|
||||||
|
{% elif abday.end_ishalf and abday.end.day == da.day %}
|
||||||
|
class="partialfilling"
|
||||||
|
style="background-size: 50% 100%"
|
||||||
|
{% else %}
|
||||||
|
style="background-color: #36b9cc"
|
||||||
|
{% endif %}
|
||||||
|
data-toggle="tooltip" data-placement="top" title="{{abday.reason.name}} {% if abday.representator != None %} | Vertreten durch {{abday.representator.first_name}} {{abday.representator.last_name}} {% endif %} ">
|
||||||
|
{% else %}
|
||||||
|
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_{{abday.pk}}_absence"
|
||||||
|
{% if abday.start_ishalf and abday.start.day == da.day %}
|
||||||
|
class="partialfilling negative"
|
||||||
|
style="background-size: 50% 100%"
|
||||||
|
{% elif abday.end_ishalf and abday.end.day == da.day %}
|
||||||
|
class="partialfilling"
|
||||||
|
style="background-size: 50% 100%"
|
||||||
|
{% else %}
|
||||||
|
style="background-color: #36b9cc"
|
||||||
|
{% endif %} data-toggle="tooltip" data-placement="top" title="Abwesend {% if abday.representator != None %} | Vertreten durch {{abday.representator.first_name}} {{abday.representator.last_name}} {% endif %} ">
|
||||||
|
{% endif %}
|
||||||
|
{% elif abday.confirm_status == 1 %}
|
||||||
|
{% if user|usergperm:"absencemanager" %}
|
||||||
|
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_{{abday.pk}}_absencetoc"
|
||||||
|
{% if abday.start_ishalf and abday.start.day == da.day %}
|
||||||
|
class="partialfilling_nf negative_nf"
|
||||||
|
style="background-size: 50% 100%"
|
||||||
|
{% elif abday.end_ishalf and abday.end.day == da.day %}
|
||||||
|
class="partialfilling_nf"
|
||||||
|
style="background-size: 50% 100%"
|
||||||
|
{% else %}
|
||||||
|
style="background-color: #858796"
|
||||||
|
{% endif %}
|
||||||
|
data-toggle="tooltip" data-placement="top" title="Nicht bestätigt | {{abday.reason.name}} {% if abday.representator != None %} | Vertreten durch {{abday.representator.first_name}} {{abday.representator.last_name}} {% endif %} ">
|
||||||
|
{% else %}
|
||||||
|
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_{{abday.pk}}_absencetoc"
|
||||||
|
{% if abday.start_ishalf and abday.start.day == da.day %}
|
||||||
|
class="partialfilling_nf negative_nf"
|
||||||
|
style="background-size: 50% 100%"
|
||||||
|
{% elif abday.end_ishalf and abday.end.day == da.day %}
|
||||||
|
class="partialfilling_nf"
|
||||||
|
style="background-size: 50% 100%"
|
||||||
|
{% else %}
|
||||||
|
style="background-color: #858796"
|
||||||
|
{% endif %} data-toggle="tooltip" data-placement="top" title="Nicht bestätigt | Abwesend {% if abday.representator != None %} | Vertreten durch {{abday.representator.first_name}} {{abday.representator.last_name}} {% endif %}">
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_{{da|date:'Y-m-d'}}" {% if us.pk == user.pk or user|usergperm:"absencemanager" %}class="tm-ab-tdhover"{% endif %}>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
<!-- NORMAL CHOICE -->
|
||||||
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_{{da|date:'Y-m-d'}}" {% if us.pk == user.pk or user|usergperm:"absencemanager" %}class="tm-ab-tdhover"{% endif %}>
|
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_{{da|date:'Y-m-d'}}" {% if us.pk == user.pk or user|usergperm:"absencemanager" %}class="tm-ab-tdhover"{% endif %}>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -43,23 +102,120 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
.partialfilling {
|
||||||
|
background-image: linear-gradient(to right, #36b9cc 0%, #36b9cc 17%, #36b9cc 33%, #36b9cc 67%, #36b9cc 83%, #36b9cc 100%); /* your gradient */
|
||||||
|
background-repeat: no-repeat; /* don't remove */
|
||||||
|
}
|
||||||
|
.partialfilling.negative {
|
||||||
|
background-image: linear-gradient(to left, #36b9cc 0%, #36b9cc 17%, #36b9cc 33%, #36b9cc 67%, #36b9cc 83%, #36b9cc 100%); /* your gradient */
|
||||||
|
background-position: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partialfilling_nf {
|
||||||
|
background-image: linear-gradient(to right, #858796 0%, #858796 17%, #858796 33%, #858796 67%, #858796 83%, #858796 100%); /* your gradient */
|
||||||
|
background-repeat: no-repeat; /* don't remove */
|
||||||
|
}
|
||||||
|
.partialfilling_nf.negative_nf {
|
||||||
|
background-image: linear-gradient(to left, #858796 0%, #858796 17%, #858796 33%, #858796 67%, #858796 83%, #858796 100%); /* your gradient */
|
||||||
|
background-position: 100% 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="modal fade" tabindex="-1" id="fastjumpmodal" data-backdrop="static">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Zeitraum auswählen</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="exampleFormControlSelect1">Jahr auswählen</label>
|
||||||
|
{% getsomeyears activeyear as years %}
|
||||||
|
<select class="form-control" id="choosenyear">
|
||||||
|
{% for y in years %}
|
||||||
|
<option val="{{y}}" {% if y == activeyear %} selected{% endif%}>{{y}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{% getsomemonths as months %}
|
||||||
|
{% for m in months %}
|
||||||
|
<button class="btn
|
||||||
|
{% if forloop.counter == activemonth %} btn-secondary {% else %} btn-primary {% endif %}
|
||||||
|
btn-sm mr-2 mb-2" onclick="javascript:goFastToMonth({{forloop.counter}})">{{m}}</button>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Schließen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
var choosenyear = "{{activeyear}}";
|
||||||
|
|
||||||
|
function goFastToMonth(month){
|
||||||
|
location.href = "/tm/abs/" + month +"/" + choosenyear
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("choosenyear").addEventListener("change", function(){
|
||||||
|
choosenyear = $('#choosenyear :selected').val();
|
||||||
|
})
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
$('[data-toggle="tooltip"]').tooltip()
|
$('[data-toggle="tooltip"]').tooltip()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function fastChangeModal(){
|
||||||
|
$("#fastjumpmodal").modal("toggle");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Set required repr or not
|
||||||
|
document.getElementById("id_reason").addEventListener("change", function(){
|
||||||
|
reasonid = $('#id_reason :selected').val();
|
||||||
|
//Get required-rep
|
||||||
|
$.ajax(
|
||||||
|
{
|
||||||
|
type: "GET",
|
||||||
|
url: "{% url 'tm-ajax' %}",
|
||||||
|
data:{
|
||||||
|
action : "checkrequired",
|
||||||
|
rid : reasonid
|
||||||
|
},
|
||||||
|
success : function(data){
|
||||||
|
if(data["isreq"]){
|
||||||
|
$("#id_representator").prop('required',true);
|
||||||
|
$("label[for*='id_representator']").html("Vertreter*");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$("#id_representator").prop('required',false);
|
||||||
|
$("label[for*='id_representator']").html("Vertreter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
$("#id_activemonth").val("{{activemonth}}")
|
||||||
|
$("#id_activeyear").val("{{activeyear}}")
|
||||||
|
$("#id_prevmonth").val("{{prevmonth}}")
|
||||||
|
$("#id_nextmonth").val("{{nextmonth}}")
|
||||||
|
$("#id_prevyear").val("{{prevyear}}")
|
||||||
|
$("#id_nextyear").val("{{nextyear}}")
|
||||||
|
|
||||||
function prevMonth(){
|
function prevMonth(){
|
||||||
$.ajax({
|
$.ajax(
|
||||||
|
{
|
||||||
type: "GET",
|
type: "GET",
|
||||||
url: "{% url 'tm-ajax' %}",
|
url: "{% url 'tm-ajax' %}",
|
||||||
data:{
|
data:{
|
||||||
action : "testdjango",
|
action : "getrenderedtable",
|
||||||
activeyear : {{prevyear}},
|
activeyear : {{prevyear}},
|
||||||
activemonth : {{prevmonth}}
|
activemonth : {{prevmonth}}
|
||||||
},
|
},
|
||||||
|
|
@ -69,9 +225,9 @@ function prevMonth(){
|
||||||
},
|
},
|
||||||
success : function(data){
|
success : function(data){
|
||||||
$("#overlay").fadeOut();
|
$("#overlay").fadeOut();
|
||||||
$("#rendered_table").html(data)
|
$("#rendered_table").html(data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextMonth(){
|
function nextMonth(){
|
||||||
|
|
@ -79,7 +235,7 @@ function nextMonth(){
|
||||||
type: "GET",
|
type: "GET",
|
||||||
url: "{% url 'tm-ajax' %}",
|
url: "{% url 'tm-ajax' %}",
|
||||||
data:{
|
data:{
|
||||||
action : "testdjango",
|
action : "getrenderedtable",
|
||||||
activeyear : {{nextyear}},
|
activeyear : {{nextyear}},
|
||||||
activemonth : {{nextmonth}}
|
activemonth : {{nextmonth}}
|
||||||
},
|
},
|
||||||
|
|
@ -106,7 +262,6 @@ else{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function recalculateChoosenDays(){
|
function recalculateChoosenDays(){
|
||||||
seldates = [];
|
seldates = [];
|
||||||
userid = "";
|
userid = "";
|
||||||
|
|
@ -119,6 +274,7 @@ function recalculateChoosenDays(){
|
||||||
date_end = new Date(seldates[seldates.length-1])
|
date_end = new Date(seldates[seldates.length-1])
|
||||||
|
|
||||||
$("#div_id_end").show();
|
$("#div_id_end").show();
|
||||||
|
$("#div_id_end_ishalf").show();
|
||||||
|
|
||||||
$("#startAbsenceProgress").modal("toggle");
|
$("#startAbsenceProgress").modal("toggle");
|
||||||
$("#id_start").data("DateTimePicker").date(date_start);
|
$("#id_start").data("DateTimePicker").date(date_start);
|
||||||
|
|
@ -126,10 +282,11 @@ function recalculateChoosenDays(){
|
||||||
|
|
||||||
if(seldates.length == 1){
|
if(seldates.length == 1){
|
||||||
$("#div_id_end").hide();
|
$("#div_id_end").hide();
|
||||||
|
$("#div_id_end_ishalf").hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$( function() {
|
$( function() {
|
||||||
$( "#timetable_team" ).selectable({
|
$( "#timetable_team" ).selectable({
|
||||||
filter: 'td',
|
filter: 'td',
|
||||||
|
|
@ -140,8 +297,58 @@ $( function() {
|
||||||
},
|
},
|
||||||
selecting: function(event, ui){
|
selecting: function(event, ui){
|
||||||
newid = ui["selecting"]["id"];
|
newid = ui["selecting"]["id"];
|
||||||
if(newid.split("_")[1] == "tableheadid" || newid.split("_")[3] == "firstcolum" || (newid.split("_")[2] != {{user.pk}} && user_has_right != true ) || newid.split("_")[3] == "free"){
|
if(newid.split("_")[1] == "tableheadid" || newid.split("_")[3] == "firstcolum" || (newid.split("_")[2] != {{user.pk}} && user_has_right != true ) || newid.split("_")[3] == "free" || newid.split("_")[4] == "absence"){
|
||||||
$("#" + newid).removeClass();
|
|
||||||
|
if($("#" + newid).hasClass("negative")){
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
$("#" + newid).addClass("partialfilling");
|
||||||
|
$("#" + newid).addClass("negative");
|
||||||
|
}
|
||||||
|
else if($("#" + newid).hasClass("partialfilling"))
|
||||||
|
{
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
$("#" + newid).addClass("partialfilling");
|
||||||
|
}
|
||||||
|
else if($("#" + newid).hasClass("negative_nf")){
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
$("#" + newid).addClass("partialfilling_nf");
|
||||||
|
$("#" + newid).addClass("negative_nf");
|
||||||
|
}
|
||||||
|
else if($("#" + newid).hasClass("partialfilling_nf"))
|
||||||
|
{
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
$("#" + newid).addClass("partialfilling_nf");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(newid.split("_")[4] == "absencetoc"){
|
||||||
|
if($("#" + newid).hasClass("negative")){
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
$("#" + newid).addClass("partialfilling");
|
||||||
|
$("#" + newid).addClass("negative");
|
||||||
|
}
|
||||||
|
else if($("#" + newid).hasClass("partialfilling"))
|
||||||
|
{
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
$("#" + newid).addClass("partialfilling");
|
||||||
|
}
|
||||||
|
else if($("#" + newid).hasClass("negative_nf")){
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
$("#" + newid).addClass("partialfilling_nf");
|
||||||
|
$("#" + newid).addClass("negative_nf");
|
||||||
|
}
|
||||||
|
else if($("#" + newid).hasClass("partialfilling_nf"))
|
||||||
|
{
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
$("#" + newid).addClass("partialfilling_nf");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
}
|
||||||
|
idtoopen = newid.split("_")[3];
|
||||||
|
openModalABChangeTable(idtoopen);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(selectedElements.length == 0){
|
if(selectedElements.length == 0){
|
||||||
|
|
@ -149,7 +356,20 @@ $( function() {
|
||||||
selectedElements.push(ui["selecting"]["id"]);
|
selectedElements.push(ui["selecting"]["id"]);
|
||||||
}
|
}
|
||||||
else if(newid.split("_")[0] != active_row){
|
else if(newid.split("_")[0] != active_row){
|
||||||
$("#" + newid).removeClass();
|
|
||||||
|
if($("#" + newid).hasClass("negative")){
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
$("#" + newid).addClass("partialfilling");
|
||||||
|
$("#" + newid).addClass("negative");
|
||||||
|
}
|
||||||
|
else if($("#" + newid).hasClass("partialfilling"))
|
||||||
|
{
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
$("#" + newid).addClass("partialfilling");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$("#" + newid).removeClass();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
selectedElements.push(ui["selecting"]["id"]);
|
selectedElements.push(ui["selecting"]["id"]);
|
||||||
|
|
@ -160,48 +380,21 @@ $( function() {
|
||||||
selectedElements.splice(selectedElements.indexOf(ui["unselecting"]["id"]),1);
|
selectedElements.splice(selectedElements.indexOf(ui["unselecting"]["id"]),1);
|
||||||
},
|
},
|
||||||
stop: function(){
|
stop: function(){
|
||||||
recalculateChoosenDays();
|
//Selection ends, check if elements set and open modal
|
||||||
|
if(selectedElements.length > 0){
|
||||||
|
$("#timetable_team tbody tr").each(function(i) {
|
||||||
|
// find the first td in the row
|
||||||
|
var value = $(this).find("td:first").text();
|
||||||
|
// display the value in console
|
||||||
|
checkrow = parseInt(active_row)
|
||||||
|
if(i == (checkrow)){
|
||||||
|
$("#username_abscence").html(value);
|
||||||
|
$("#id_userid").val(selectedElements[0].split("_")[2])
|
||||||
|
}
|
||||||
|
});
|
||||||
|
recalculateChoosenDays();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} );
|
} );
|
||||||
</script>
|
</script>
|
||||||
<style>
|
|
||||||
.loader {
|
|
||||||
position: relative;
|
|
||||||
border: 7px solid #d3d3d3;
|
|
||||||
border-radius: 50%;
|
|
||||||
border-top: 7px solid red;
|
|
||||||
width: 70px;
|
|
||||||
height: 70px;
|
|
||||||
left:50%;
|
|
||||||
top:50%;
|
|
||||||
-webkit-animation: spin 1s linear infinite; /* Safari */
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
#overlay{
|
|
||||||
position: absolute;
|
|
||||||
top:0px;
|
|
||||||
left:0px;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: black;
|
|
||||||
opacity: .4;
|
|
||||||
}
|
|
||||||
.container{
|
|
||||||
position:relative;
|
|
||||||
height: 300px;
|
|
||||||
width: 200px;
|
|
||||||
border:1px solid red;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Safari */
|
|
||||||
@-webkit-keyframes spin {
|
|
||||||
0% { -webkit-transform: rotate(0deg); }
|
|
||||||
100% { -webkit-transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spin {
|
|
||||||
0% { transform: rotate(0deg); }
|
|
||||||
100% { transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -68,7 +68,7 @@
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
Arbeitstag löschen
|
<h5 class="modal-title">Arbeitstag löschen</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
Möchten Sie wirklich den Arbeitstag am {{workday.start|date:"d.m"}} löschen?
|
Möchten Sie wirklich den Arbeitstag am {{workday.start|date:"d.m"}} löschen?
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
<div class="row col-12 mt-3" >
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover" id="table_allabsences">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Mitarbeiter</th>
|
||||||
|
<th scope="col">Start</th>
|
||||||
|
<th scope="col">Ende</th>
|
||||||
|
<th scope="col">Grund</th>
|
||||||
|
<th scope="col">Info</th>
|
||||||
|
<th scope="col">Status</th>
|
||||||
|
<th scope="col"> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="">
|
||||||
|
{% for abday in allabsences %}
|
||||||
|
<tr id="tableele_ab_{{abday.pk}}">
|
||||||
|
<td>{{abday.user.first_name}} {{abday.user.last_name}}</td>
|
||||||
|
<td>{{abday.start|date:"d.M Y"}}</td>
|
||||||
|
<td>{{abday.end|date:"d.M Y"}}</td>
|
||||||
|
<td>{{abday.reason.name}}</td>
|
||||||
|
<td>{{abday.info}}</td>
|
||||||
|
<td>{% if abday.confirm_status == 0 %} Genehmigt {% elif abday.confirm_status == 1 %} Beantragt {% else %} Abgelehnt {% endif %}</td>
|
||||||
|
<td>
|
||||||
|
<button type="button " class="btn btn-secondary btn-sm" onclick="javascript:$('#confirm-delete_{{abday.pk}}').modal('toggle')"><i class="fas fa-trash"></i></button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
$('#table_allabsences').DataTable({
|
||||||
|
"language": {
|
||||||
|
"search" : "Suche",
|
||||||
|
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
|
||||||
|
"lengthMenu": "Zeige _MENU_ Einträge",
|
||||||
|
"zeroRecords": "Nichts gefunden",
|
||||||
|
"infoEmpty": "Keine Einträge",
|
||||||
|
"paginate": {
|
||||||
|
"first": "Erste",
|
||||||
|
"last": "Letzte",
|
||||||
|
"next": "Nächste",
|
||||||
|
"previous": "Zurück"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"buttons" : {
|
||||||
|
"className" : "btn-danger"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% for ab in allabsences %}
|
||||||
|
<div class="modal fade" id="confirm-delete_{{ab.pk}}" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Abwesenheit löschen</h5>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
Möchten Sie wirklich die Abwesenheit von {{ab.user.first_name}} {{ab.user.last_name}} vom {{ab.start|date:"d.m.Y"}} bis {{ab.end|date:"d.m.Y"}} löschen?
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-danger" id="ab_{{ab.pk}}" >Löschen</button>
|
||||||
|
<button type="button" class="btn btn-success" data-dismiss="modal">Abbrechen</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$("#ab_{{ab.pk}}").click(function(){
|
||||||
|
$.ajax(
|
||||||
|
{
|
||||||
|
type: "GET",
|
||||||
|
url: "{% url 'tm-ajax' %}",
|
||||||
|
data:{
|
||||||
|
action : "remove_absence",
|
||||||
|
ab: {{ab.pk}},
|
||||||
|
},
|
||||||
|
success: function( data )
|
||||||
|
{
|
||||||
|
location.href = "{% url 'tma-management' activemonth activeyear %}"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endfor %}
|
||||||
|
|
@ -3,48 +3,143 @@
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
{% load counter_tag %}
|
{% load counter_tag %}
|
||||||
{% if request.user.profile.agency.module_timemanagement_ze %}
|
{% if request.user.profile.agency.module_timemanagement_ze %}
|
||||||
<!-- Moment.js -->
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.min.js" integrity="sha256-VBLiveTKyUZMEzJd6z2mhfxIqz3ZATCuVMawPZGzIfA=" crossorigin="anonymous"></script>
|
|
||||||
|
|
||||||
<!-- Tempus Dominus Bootstrap 4 -->
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.1.2/css/tempusdominus-bootstrap-4.min.css" integrity="sha256-XPTBwC3SBoWHSmKasAk01c08M6sIA5gF5+sRxqak2Qs=" crossorigin="anonymous" />
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.1.2/js/tempusdominus-bootstrap-4.min.js" integrity="sha256-z0oKYg6xiLq3yJGsp/LsY9XykbweQlHl42jHv2XTBz4=" crossorigin="anonymous"></script>
|
|
||||||
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
|
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
|
||||||
|
|
||||||
<div class="content-section col-12">
|
<div class="content-section col-12">
|
||||||
<h3>Abwesenheiten{% if request.user.profile.showtooltips %} <small><i data-toggle="tooltip" data-placement="top" title="Bearbeiten Sie hier Ihre Abwesenheiten." class="far fa-question-circle"></i></small>{% endif %}</h3>
|
<h3>Abwesenheiten{% if request.user.profile.showtooltips %} <small><i data-toggle="tooltip" data-placement="top" title="Bearbeiten Sie hier Ihre Abwesenheiten." class="far fa-question-circle"></i></small>{% endif %}</h3>
|
||||||
<hr>
|
<hr>
|
||||||
<div>
|
|
||||||
<div id="rendered_table">
|
<ul class="nav nav-tabs" id="absencetabs" role="tablist">
|
||||||
Lade Kalenderdaten...
|
<li class="nav-item">
|
||||||
</div>
|
<a class="nav-link active" id="team-tab" data-toggle="tab" href="#team" role="tab" aria-controls="team" aria-selected="false">Teamübersicht</a>
|
||||||
<div id="overlay" style="display: none;">
|
</li>
|
||||||
<div class="loader"></div>
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" id="userown-tab" data-toggle="tab" href="#userown" role="tab" aria-controls="userown" aria-selected="false">Meine Abwesenheiten</a>
|
||||||
|
</li>
|
||||||
|
{% if user|usergperm:"absencemanager" %}
|
||||||
|
<li class="nav-item ">
|
||||||
|
<a class="nav-link" id="absencemanagercontent-tab" data-toggle="tab" href="#absencemanagercontent" role="tab" aria-controls="absencemanagercontent" aria-selected="false">
|
||||||
|
{% if needtoconfirm|length > 0 %}
|
||||||
|
<span class="badge badge-primary badge-counter" style="float: right; margin-left: 5px; margin-top: 0px">{{needtoconfirm|length}} </span>
|
||||||
|
{%endif%}
|
||||||
|
Ausstehende Anträge
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item ">
|
||||||
|
<a class="nav-link" id="absencemanagercontent_all-tab" data-toggle="tab" href="#absencemanagercontent_all" role="tab" aria-controls="absencemanagercontent_all" aria-selected="false">
|
||||||
|
Alle Abwesenheiten
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="tab-content" id="absencetabsContent">
|
||||||
|
|
||||||
|
<div class="tab-pane fade" id="team" role="tabpanel" aria-labelledby="team-tab">
|
||||||
|
<div>
|
||||||
|
<div id="rendered_table">
|
||||||
|
Lade Kalenderdaten...
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-pane fade" id="userown" role="tabpanel" aria-labelledby="team-tab">
|
||||||
|
{% block ab_userown %}
|
||||||
|
{% include "timemanagement/tm_ab_userown.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if user|usergperm:"absencemanager" %}
|
||||||
|
<div class="tab-pane fade" id="absencemanagercontent" role="tabpanel" aria-labelledby="team-tab">
|
||||||
|
{% block ab_toconfirm %}
|
||||||
|
{% include "timemanagement/tm_ab_toconfirm.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-pane fade" id="absencemanagercontent_all" role="tabpanel" aria-labelledby="team-tab">
|
||||||
|
{% block ab_all %}
|
||||||
|
{% include "timemanagement/tm_ab_all.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- LOADER OVERLAY -->
|
||||||
|
<div id="overlay" style="display: none;">
|
||||||
|
<div class="loader"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- MODAL -->
|
||||||
<div class="modal fade" tabindex="-1" role="dialog" id="startAbsenceProgress" data-backdrop="static">
|
<div class="modal fade" tabindex="-1" role="dialog" id="startAbsenceProgress" data-backdrop="static">
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">Abwesenheit bentragen</h5>
|
<h5 class="modal-title">Abwesenheit beantragen</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
<h5>Abwesenheit für <b><span id="username_abscence"></span></b> beantragen</h5>
|
||||||
|
<hr>
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
|
<input type="hidden" name="form_type" value="absenceform">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{abscenceform.media}}
|
{{abscenceform.media}}
|
||||||
{{abscenceform|crispy}}
|
{{abscenceform|crispy}}
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-primary">Abwesenheit beantragen</button>
|
<button type="submit" class="btn btn-primary">Abwesenheit beantragen</button>
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Abbrechen</button>
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Abbrechen</button>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- MODAL -->
|
||||||
|
<div class="modal fade" tabindex="-1" id="updateAbsenceToConfirm" data-backdrop="static">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Abwesenheitsantrag</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="confirmcontent"></div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal" onclick="javascript:closeOnly()">Schließen</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" tabindex="-1" id="updateAbsenceToConfirmSecond" data-backdrop="static">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Abwesenheitsantrag</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="confirmcontentsecond"></div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-primary" onclick="javascript:confirmAbscenceFinal()">Bestätigung</button>
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Abbrechen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<style>
|
<style>
|
||||||
.tm-ab-tdhover:hover{
|
.tm-ab-tdhover:hover{
|
||||||
background-color: #858796 !important;
|
background-color: #858796 !important;
|
||||||
|
|
@ -78,20 +173,142 @@
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* DATATABLES */
|
/* DATATABLES */
|
||||||
.paginate_button {
|
.paginate_button {
|
||||||
padding: 0px !important;
|
padding: 0px !important;
|
||||||
border: 0px !important;
|
border: 0px !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.loader {
|
||||||
|
position: relative;
|
||||||
|
border: 7px solid #d3d3d3;
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top: 7px solid red;
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
left:50%;
|
||||||
|
top:35%;
|
||||||
|
-webkit-animation: spin 1s linear infinite; /* Safari */
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
#overlay{
|
||||||
|
position: absolute;
|
||||||
|
top:0px;
|
||||||
|
left:0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: black;
|
||||||
|
opacity: .4;
|
||||||
|
}
|
||||||
|
.container{
|
||||||
|
position:relative;
|
||||||
|
height: 300px;
|
||||||
|
width: 200px;
|
||||||
|
border:1px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Safari */
|
||||||
|
@-webkit-keyframes spin {
|
||||||
|
0% { -webkit-transform: rotate(0deg); }
|
||||||
|
100% { -webkit-transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<script>
|
<script>
|
||||||
//Initial Load
|
|
||||||
function loaddjango(){
|
var absencetowork = "";
|
||||||
|
var absencestring_confirm = "";
|
||||||
|
var absencestring_noconfirm = "";
|
||||||
|
var newconfstat = "";
|
||||||
|
var closeonly = false;
|
||||||
|
|
||||||
|
function closeOnly(){
|
||||||
|
closeonly = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmAbscenceFinal(){
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "GET",
|
type: "GET",
|
||||||
url: "{% url 'tm-ajax' %}",
|
url: "{% url 'tm-ajax' %}",
|
||||||
data:{
|
data:{
|
||||||
action : "testdjango",
|
action : "confirmornotabscence",
|
||||||
|
absencetowork : absencetowork,
|
||||||
|
newconfstat : newconfstat,
|
||||||
|
info : $("#id_confirm_info").val(),
|
||||||
|
activemonth : $("#id_activemonth").val(),
|
||||||
|
activeyear : $("#id_activeyear").val(),
|
||||||
|
},
|
||||||
|
success : function(data){
|
||||||
|
location.href = "/tm/abs/" + data["activemonth"] +"/" + data["activeyear"]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function openModalABChangeTable(idtopen){
|
||||||
|
closeonly = false;
|
||||||
|
absencetowork = idtopen;
|
||||||
|
$.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: "{% url 'tm-ajax' %}",
|
||||||
|
data:{
|
||||||
|
action : "getrenderedform",
|
||||||
|
abscenceid : idtopen
|
||||||
|
},
|
||||||
|
beforeSend: function(request) {
|
||||||
|
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||||
|
},
|
||||||
|
success : function(data){
|
||||||
|
$("#confirmcontent").html(data);
|
||||||
|
$("#updateAbsenceToConfirm").modal("show");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function noconfirmAbsence(id){
|
||||||
|
newconfstat = 2;
|
||||||
|
$("#updateAbsenceToConfirm").modal("toggle");
|
||||||
|
$('#updateAbsenceToConfirm').on('hidden.bs.modal', function () {
|
||||||
|
if(closeonly == false){
|
||||||
|
$("#updateAbsenceToConfirmSecond").modal("toggle");
|
||||||
|
$("#confirmcontentsecond").html(absencestring_noconfirm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmAbsence(id){
|
||||||
|
newconfstat = 0;
|
||||||
|
$("#updateAbsenceToConfirm").modal("toggle");
|
||||||
|
$('#updateAbsenceToConfirm').on('hidden.bs.modal', function () {
|
||||||
|
if(closeonly == false){
|
||||||
|
$("#updateAbsenceToConfirmSecond").modal("toggle");
|
||||||
|
$("#confirmcontentsecond").html(absencestring_confirm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Initial Load
|
||||||
|
function loaddjango(){
|
||||||
|
|
||||||
|
$("#id_activemonth").val("{{activemonth}}")
|
||||||
|
$("#id_activeyear").val("{{activeyear}}")
|
||||||
|
$("#id_prevmonth").val("{{prevmonth}}")
|
||||||
|
$("#id_nextmonth").val("{{nextmonth}}")
|
||||||
|
$("#id_prevyear").val("{{prevyear}}")
|
||||||
|
$("#id_nextyear").val("{{nextyear}}")
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: "{% url 'tm-ajax' %}",
|
||||||
|
data:{
|
||||||
|
action : "getrenderedtable",
|
||||||
activeyear : {{activeyear}},
|
activeyear : {{activeyear}},
|
||||||
activemonth : {{activemonth}}
|
activemonth : {{activemonth}}
|
||||||
},
|
},
|
||||||
|
|
@ -101,14 +318,46 @@ function loaddjango(){
|
||||||
success : function(data){
|
success : function(data){
|
||||||
$("#rendered_table").html(data)
|
$("#rendered_table").html(data)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
loaddjango();
|
loaddjango();
|
||||||
moment.locale('de');
|
|
||||||
|
var activeTab = localStorage.getItem('activeTabAbsence');
|
||||||
|
|
||||||
|
if(activeTab){
|
||||||
|
|
||||||
|
if($('#' + activeTab).find().prevObject.length != 0){
|
||||||
|
$('#' + activeTab).tab('show');
|
||||||
|
$(".nav-link").removeClass("active");
|
||||||
|
|
||||||
|
$("#" + activeTab + "-tab").addClass("active");
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
$("#team-tab").addClass("active");
|
||||||
|
$('#team').tab('show');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
$("#team-tab").addClass("active");
|
||||||
|
$('#team').tab('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#absencetabs a').on('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
lastview_name = $(this)[0]['hash'].substring(1);
|
||||||
|
localStorage.setItem('activeTabAbsence', lastview_name);
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h3>Das Modul Abwesenheits- und Zeiterfassung wurde in ihrer Agentur deaktiviert.</h3>
|
<h3>Das Modul Abwesenheits- und Zeiterfassung wurde in ihrer Agentur deaktiviert.</h3>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
{% load counter_tag %}
|
||||||
|
<div class="row col-12 mt-3" >
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover" id="table_toconfirmab">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Mitarbeiter</th>
|
||||||
|
<th scope="col">Start</th>
|
||||||
|
<th scope="col">Ende</th>
|
||||||
|
<th scope="col">Grund</th>
|
||||||
|
<th scope="col">Info</th>
|
||||||
|
<th scope="col">Status ändern</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="">
|
||||||
|
{% for abday in needtoconfirm %}
|
||||||
|
<tr>
|
||||||
|
<td>{{abday.user.first_name}} {{abday.user.last_name}}</td>
|
||||||
|
<td>{{abday.start|date:"d.M Y"}}</td>
|
||||||
|
<td>{{abday.end|date:"d.M Y"}}</td>
|
||||||
|
<td>{{abday.reason.name}}</td>
|
||||||
|
<td>{{abday.info}}</td>
|
||||||
|
<td>
|
||||||
|
<button type="button " class="btn btn-secondary btn-sm" onclick='javascript:openModalABChangeTable({{abday.pk}})'><i class="fas fa-eye"></i></button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
$('#table_toconfirmab').DataTable({
|
||||||
|
"language": {
|
||||||
|
"search" : "Suche",
|
||||||
|
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
|
||||||
|
"lengthMenu": "Zeige _MENU_ Einträge",
|
||||||
|
"zeroRecords": "Nichts gefunden",
|
||||||
|
"infoEmpty": "Keine Einträge",
|
||||||
|
"paginate": {
|
||||||
|
"first": "Erste",
|
||||||
|
"last": "Letzte",
|
||||||
|
"next": "Nächste",
|
||||||
|
"previous": "Zurück"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"buttons" : {
|
||||||
|
"className" : "btn-danger"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<div class="row col-12 mt-3" >
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover" id="table_userownab">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Start</th>
|
||||||
|
<th scope="col">Ende</th>
|
||||||
|
<th scope="col">Grund</th>
|
||||||
|
<th scope="col">Status</th>
|
||||||
|
<th scope="col">Begründung</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="">
|
||||||
|
{% for abday in userown %}
|
||||||
|
<tr>
|
||||||
|
<td>{{abday.start|date:"d.M Y"}}</td>
|
||||||
|
<td>{{abday.end|date:"d.M Y"}}</td>
|
||||||
|
<td>{{abday.reason.name}}</td>
|
||||||
|
<td>{% if abday.confirm_status == 0 %} Genehmigt {% elif abday.confirm_status == 1 %} Beantragt {% else %} Abgelehnt {% endif %}</td>
|
||||||
|
<td>{{abday.confirm_info}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
$('#table_userownab').DataTable({
|
||||||
|
"language": {
|
||||||
|
"search" : "Suche",
|
||||||
|
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
|
||||||
|
"lengthMenu": "Zeige _MENU_ Einträge",
|
||||||
|
"zeroRecords": "Nichts gefunden",
|
||||||
|
"infoEmpty": "Keine Einträge",
|
||||||
|
"paginate": {
|
||||||
|
"first": "Erste",
|
||||||
|
"last": "Letzte",
|
||||||
|
"next": "Nächste",
|
||||||
|
"previous": "Zurück"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"buttons" : {
|
||||||
|
"className" : "btn-danger"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render, redirect
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from .models import Workday, Breaks, FreeDays
|
from .models import Workday, Breaks, FreeDays, AbsenceReason, Absence
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
import requests, csv, os
|
import requests, csv, os
|
||||||
from django.templatetags.static import static
|
from django.templatetags.static import static
|
||||||
|
|
@ -11,7 +11,11 @@ from django.contrib.auth.models import User
|
||||||
from calendar import monthrange
|
from calendar import monthrange
|
||||||
import datetime
|
import datetime
|
||||||
import calendar
|
import calendar
|
||||||
from .forms import AddAbsence
|
from .forms import AddAbsence, ConfirmAbsenceForm
|
||||||
|
from django.contrib import messages
|
||||||
|
from users.models import UserFullName
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def loadingFreeDays(plz):
|
def loadingFreeDays(plz):
|
||||||
# Getting land
|
# Getting land
|
||||||
|
|
@ -46,66 +50,120 @@ def get_datetime_range(year, month):
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def AbsenceManagmenet(request, activemonth=False, activeyear=False):
|
def AbsenceManagmenet(request, activemonth=False, activeyear=False):
|
||||||
prevmonth = ""
|
|
||||||
nextmonth = ""
|
|
||||||
|
|
||||||
|
# NEW ABSENCE
|
||||||
|
if(request.method == "POST"):
|
||||||
|
'''
|
||||||
|
|
||||||
#MONTH
|
Nachdem eine neue Abwesenheit gespeichert wurde, geht es zur normalen Seite zurück, jedoch mit den Daten des
|
||||||
if(not activemonth or activemonth > 12 or activemonth < 1):
|
aktuell angezeigten Monate/Jahr
|
||||||
activemonth = int(activemonth)
|
|
||||||
#Active month
|
|
||||||
activemonth=date.today().month
|
|
||||||
|
|
||||||
if(activemonth == 1):
|
'''
|
||||||
prevmonth = 12
|
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
|
||||||
|
if(request.user.has_perm("absencemanager") == False):
|
||||||
|
confirmstat = 1
|
||||||
|
messages.success(request, f'Abwesenheit beantragt')
|
||||||
|
# SEND NOTIFICATION
|
||||||
|
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()
|
||||||
|
# USER NOT FOUND
|
||||||
|
except:
|
||||||
|
messages.success(request, f'Fehler bei Benutzerzuweisung!')
|
||||||
|
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:
|
else:
|
||||||
prevmonth = activemonth-1
|
return redirect('tma-management')
|
||||||
|
# NORMAL VIEW
|
||||||
if(activemonth == 12):
|
|
||||||
nextmonth = 1
|
|
||||||
else:
|
|
||||||
nextmonth = activemonth + 1
|
|
||||||
else:
|
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):
|
if(activemonth == 1):
|
||||||
prevmonth = 12
|
prevmonth = 12
|
||||||
|
else:
|
||||||
|
prevmonth = activemonth-1
|
||||||
|
|
||||||
|
if(activemonth == 12):
|
||||||
|
nextmonth = 1
|
||||||
|
else:
|
||||||
|
nextmonth = activemonth + 1
|
||||||
else:
|
else:
|
||||||
prevmonth = activemonth-1
|
|
||||||
|
|
||||||
if(activemonth == 12):
|
if(activemonth == 1):
|
||||||
nextmonth = 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:
|
else:
|
||||||
nextmonth = activemonth + 1
|
if(nextmonth == 1):
|
||||||
|
nextyear = activeyear + 1
|
||||||
|
else:
|
||||||
|
nextyear = activeyear
|
||||||
|
if(prevmonth == 12):
|
||||||
|
prevyear = activeyear - 1
|
||||||
|
else:
|
||||||
|
prevyear = activeyear
|
||||||
|
|
||||||
#YEAR
|
context = {
|
||||||
nextyear = date.today().year
|
"active_link" : "abscence",
|
||||||
prevyear = date.today().year
|
"usersofagency" : User.objects.filter(profile__agency=request.user.profile.agency).order_by("-last_name"),
|
||||||
|
"days_this_month" : get_datetime_range(activeyear,activemonth),
|
||||||
|
"nextmonth" : nextmonth,
|
||||||
|
"prevmonth" : prevmonth,
|
||||||
|
"nextyear" : nextyear,
|
||||||
|
"prevyear" : prevyear,
|
||||||
|
"activemonth" : activemonth,
|
||||||
|
"activeyear" : activeyear,
|
||||||
|
"abscenceform" : AddAbsence(instance=request.user),
|
||||||
|
"userown" : Absence.objects.filter(agency=request.user.profile.agency, user=request.user).order_by("start")
|
||||||
|
}
|
||||||
|
|
||||||
if(not activeyear):
|
if(request.user.has_perm("users.absencemanager")):
|
||||||
activeyear = date.today().year
|
context.update({
|
||||||
else:
|
"needtoconfirm" : Absence.objects.filter(agency=request.user.profile.agency, confirm_status=1).order_by("-start"),
|
||||||
if(nextmonth == 1):
|
"allabsences" : Absence.objects.filter(agency=request.user.profile.agency).order_by("-start")
|
||||||
nextyear = activeyear + 1
|
})
|
||||||
else:
|
|
||||||
nextyear = activeyear
|
|
||||||
if(prevmonth == 12):
|
|
||||||
prevyear = activeyear - 1
|
|
||||||
else:
|
|
||||||
prevyear = activeyear
|
|
||||||
|
|
||||||
context = {
|
return render(request, 'timemanagement/tm_ab_management.html', 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,
|
|
||||||
"prevmonth" : prevmonth,
|
|
||||||
"nextyear" : nextyear,
|
|
||||||
"prevyear" : prevyear,
|
|
||||||
"activemonth" : activemonth,
|
|
||||||
"activeyear" : activeyear,
|
|
||||||
"abscenceform" : AddAbsence()
|
|
||||||
}
|
|
||||||
return render(request, 'timemanagement/tm_ab_management.html', context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
|
@ -187,8 +245,8 @@ def TimeAjax(request):
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
data = { "success" : False}
|
data = { "success" : False}
|
||||||
# REMOVE WORKDAY
|
# Get Rendered Table
|
||||||
elif request.GET["action"] == "testdjango":
|
elif request.GET["action"] == "getrenderedtable":
|
||||||
prevmonth = ""
|
prevmonth = ""
|
||||||
nextmonth = ""
|
nextmonth = ""
|
||||||
activemonth = int(request.GET["activemonth"])
|
activemonth = int(request.GET["activemonth"])
|
||||||
|
|
@ -248,9 +306,57 @@ def TimeAjax(request):
|
||||||
"nextyear" : nextyear,
|
"nextyear" : nextyear,
|
||||||
"prevyear" : prevyear
|
"prevyear" : prevyear
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return render(request, "timemanagement/rendered_table.html", context)
|
return render(request, "timemanagement/rendered_table.html", context)
|
||||||
|
|
||||||
|
# Get Rendered Table
|
||||||
|
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
|
||||||
|
}
|
||||||
|
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":
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"confirmform" : ConfirmAbsenceForm(instance=request.user),
|
||||||
|
"absence" : Absence.objects.get(pk=request.GET["abscenceid"])
|
||||||
|
}
|
||||||
|
|
||||||
|
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"]
|
||||||
|
|
||||||
|
if(absence.user.profile.agency == request.user.profile.agency and request.user.has_perm("users.absencemanager")):
|
||||||
|
absence.confirm_status = new_stat
|
||||||
|
absence.confirm_info = info
|
||||||
|
absence.save()
|
||||||
|
messages.success(request, f'Abwesenheit gespeichert!')
|
||||||
|
else:
|
||||||
|
messages.success(request, f'Das dürfen Sie nicht!')
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"success" : True,
|
||||||
|
"activemonth" : request.GET["activemonth"],
|
||||||
|
"activeyear" : request.GET["activeyear"]
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
data = {
|
data = {
|
||||||
"success" : False
|
"success" : False
|
||||||
|
|
@ -258,3 +364,4 @@ def TimeAjax(request):
|
||||||
|
|
||||||
return JsonResponse(data)
|
return JsonResponse(data)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ from django.contrib.auth.models import Permission
|
||||||
from message.models import Message
|
from message.models import Message
|
||||||
from cloud.models import DataFile
|
from cloud.models import DataFile
|
||||||
from organizer.models import AGContacts
|
from organizer.models import AGContacts
|
||||||
from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays
|
from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays, Absence
|
||||||
|
|
||||||
admin.site.register(StandardComments)
|
admin.site.register(StandardComments)
|
||||||
admin.site.register(StandardCommentRate)
|
admin.site.register(StandardCommentRate)
|
||||||
|
|
@ -25,4 +25,5 @@ admin.site.register(UserTime)
|
||||||
admin.site.register(Workday)
|
admin.site.register(Workday)
|
||||||
admin.site.register(Breaks)
|
admin.site.register(Breaks)
|
||||||
admin.site.register(AbsenceReason)
|
admin.site.register(AbsenceReason)
|
||||||
|
admin.site.register(Absence)
|
||||||
admin.site.register(FreeDays)
|
admin.site.register(FreeDays)
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,9 @@ class UserTime(models.Model):
|
||||||
wd_th = models.FloatField(default=8.0)
|
wd_th = models.FloatField(default=8.0)
|
||||||
wd_fr = models.FloatField(default=8.0)
|
wd_fr = models.FloatField(default=8.0)
|
||||||
holiday = models.FloatField(default=24.0)
|
holiday = models.FloatField(default=24.0)
|
||||||
|
holiday_start = models.FloatField(default=0.0)
|
||||||
loose_holidedate = models.DateField(default=datetime.date(datetime.datetime.now().year + 1, 4,30))
|
loose_holidedate = models.DateField(default=datetime.date(datetime.datetime.now().year + 1, 4,30))
|
||||||
|
startdate = models.DateTimeField(default=None, blank=True, null=True)
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 456 KiB After Width: | Height: | Size: 149 KiB |
Loading…
Reference in New Issue