Zwischencommit Absence
This commit is contained in:
parent
db58c37c82
commit
37070e045d
|
|
@ -66,15 +66,18 @@ class UserTimeForm(forms.ModelForm):
|
|||
labels = {
|
||||
"holiday" : "Urlaubstage",
|
||||
"loose_holidedate" : "Urlaubstage aus Vorjahr verfallen am",
|
||||
"startdate" : "Einstellungsdatum",
|
||||
"holiday_start" : "Urlaubstage bei Einstellung",
|
||||
"wd_mo" : "Montag",
|
||||
"wd_tu" : "Dienstag",
|
||||
"wd_we" : "Mittwoch",
|
||||
"wd_th" : "Donnerstag",
|
||||
"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 = {
|
||||
'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:
|
||||
model = Profile
|
||||
labels = {
|
||||
"persnumber" : "Personalnummer",
|
||||
"visible" : "Im Organigramm sichtbar",
|
||||
"phonemobile" : "Mobilnummer",
|
||||
"phone_public" : "Nur Interne Verwendung der Mobilnummer",
|
||||
"phoneland" : "Festnetznummer",
|
||||
"image": "Profilbild",
|
||||
"func" : "Agenturfunktion",
|
||||
"compfunc" : "Tätigkeit"
|
||||
"persnumber" : "Personalnummer",
|
||||
"visible" : "Im Organigramm sichtbar",
|
||||
"phonemobile" : "Mobilnummer",
|
||||
"phone_public" : "Nur Interne Verwendung der Mobilnummer",
|
||||
"phoneland" : "Festnetznummer",
|
||||
"image": "Profilbild",
|
||||
"func" : "Agenturfunktion",
|
||||
"compfunc" : "Tätigkeit"
|
||||
}
|
||||
widgets = {"parent" : forms.HiddenInput()}
|
||||
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>
|
||||
<hr>
|
||||
{% block agency_content %}
|
||||
{% block agency_content %}
|
||||
{% include "dasettings/agency_content.html" %}
|
||||
{% endblock %}
|
||||
</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>
|
||||
{{usertime_form.media}}
|
||||
{{usertime_form.holiday|as_crispy_field}}
|
||||
{{usertime_form.loose_holidedate|as_crispy_field}}
|
||||
{{usertime_form.holiday_start|as_crispy_field}}
|
||||
{{usertime_form.loose_holidedate|as_crispy_field}}
|
||||
{{usertime_form.startdate|as_crispy_field}}
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<hr>
|
||||
|
|
|
|||
|
|
@ -544,7 +544,6 @@ def UserProfileUpdate(request, pk, newuser=0):
|
|||
elif(request.POST["form_type"] == "contract"):
|
||||
|
||||
formtosave = UserTimeForm(request.POST, instance=UserTime.objects.get(user=usertochange))
|
||||
print(formtosave)
|
||||
if(formtosave.is_valid()):
|
||||
messages.success(request, f'Vertragsdaten gespeichert!')
|
||||
formtosave.save()
|
||||
|
|
@ -792,8 +791,7 @@ def ManageAgInAgn(request, pk):
|
|||
for a in network.adminagencys.all():
|
||||
allagofagn.append(a)
|
||||
|
||||
print(allagofagn)
|
||||
|
||||
|
||||
context = {
|
||||
'active_link' : 'dasettings',
|
||||
'agn' : list(agn)[0],
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
{% if perms.users.standardmanager %}
|
||||
<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">
|
||||
{% 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>
|
||||
{%endif%}
|
||||
Unveröffentlichte Standards
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -2,7 +2,7 @@ from django import template
|
|||
from django.contrib.auth.models import Group, User
|
||||
from users.models import AgencyGroup, Agency, AgencyNetwork, AgencyNetworkPreperation
|
||||
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
|
||||
import os
|
||||
from django.conf import settings
|
||||
|
|
@ -414,4 +414,29 @@ def isfreedayname(user, daytocheck):
|
|||
if len(fd) > 0:
|
||||
returnstat = True
|
||||
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 django import forms
|
||||
from django.forms import ModelForm
|
||||
from .models import Absence
|
||||
|
||||
from .models import Absence, AbsenceReason
|
||||
from users.models import UserFullName
|
||||
|
||||
class AddAbsence(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Absence
|
||||
labels = {
|
||||
"start" : "Beginn der Abwesenheit",
|
||||
"end" : "Ende der Abwesenheit",
|
||||
}
|
||||
fields = ['start', 'end']
|
||||
"start" : "Beginn der Abwesenheit",
|
||||
"start_ishalf" : "Halber Tag?",
|
||||
"end" : "Ende der Abwesenheit",
|
||||
"end_ishalf" : "Halber Tag?",
|
||||
"reason" : "Abwesenheitsgrund",
|
||||
"representator" : "Vertreter",
|
||||
"info" : "Begründung"
|
||||
}
|
||||
widgets = {
|
||||
'start': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'}),
|
||||
'end': 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'}),
|
||||
}
|
||||
|
||||
|
||||
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.contrib.auth.models import User
|
||||
from users.models import Agency
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
# Create your models here.
|
||||
class Workday(models.Model):
|
||||
|
|
@ -24,17 +25,31 @@ class AbsenceReason(models.Model):
|
|||
need_rep = models.BooleanField(default=True)
|
||||
is_holiday = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.name}'
|
||||
|
||||
class Absence(models.Model):
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
|
||||
start = models.DateTimeField(default=None, null=True, blank=True)
|
||||
end = models.DateTimeField(default=None, null=True, blank=True)
|
||||
start_ishalf = models.BooleanField(default=False)
|
||||
end_ishalf = models.BooleanField(default=False)
|
||||
start_ishalf = models.BooleanField(default=False, blank=True)
|
||||
end_ishalf = models.BooleanField(default=False, 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="")
|
||||
'''
|
||||
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_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):
|
||||
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 %}
|
||||
|
||||
<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">
|
||||
<th>
|
||||
{% for da in days_this_month %}
|
||||
<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 %}
|
||||
<td id="{{forloop.counter0}}_tableheadid"><small>{{da|date:"d D"}}</small></td>
|
||||
{% endfor %}
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
{% for us in usersofagency %}
|
||||
{% setdateforloopcounter forloop.counter %}
|
||||
|
|
@ -27,12 +26,72 @@
|
|||
|
||||
{% isfreeday user da as isfree %}
|
||||
{% isfreedayname user da as isfreename %}
|
||||
{% if isfree %}
|
||||
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_free" style="background-color: #e74a3b" data-toggle="tooltip" data-placement="top" title="{{isfreename}}">
|
||||
{% getabscenceday user us da as abday %}
|
||||
|
||||
{% 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 %}
|
||||
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_free" style="background-color: #d3d3d3">
|
||||
{% else %}
|
||||
<!-- WEEKEND -->
|
||||
<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 %}
|
||||
<!-- 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 %}>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
|
@ -40,26 +99,123 @@
|
|||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
<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">
|
||||
var choosenyear = "{{activeyear}}";
|
||||
|
||||
function goFastToMonth(month){
|
||||
location.href = "/tm/abs/" + month +"/" + choosenyear
|
||||
}
|
||||
|
||||
document.getElementById("choosenyear").addEventListener("change", function(){
|
||||
choosenyear = $('#choosenyear :selected').val();
|
||||
})
|
||||
|
||||
$(function () {
|
||||
$('[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(){
|
||||
$.ajax({
|
||||
$.ajax(
|
||||
{
|
||||
type: "GET",
|
||||
url: "{% url 'tm-ajax' %}",
|
||||
data:{
|
||||
action : "testdjango",
|
||||
action : "getrenderedtable",
|
||||
activeyear : {{prevyear}},
|
||||
activemonth : {{prevmonth}}
|
||||
},
|
||||
|
|
@ -69,9 +225,9 @@ function prevMonth(){
|
|||
},
|
||||
success : function(data){
|
||||
$("#overlay").fadeOut();
|
||||
$("#rendered_table").html(data)
|
||||
$("#rendered_table").html(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function nextMonth(){
|
||||
|
|
@ -79,7 +235,7 @@ function nextMonth(){
|
|||
type: "GET",
|
||||
url: "{% url 'tm-ajax' %}",
|
||||
data:{
|
||||
action : "testdjango",
|
||||
action : "getrenderedtable",
|
||||
activeyear : {{nextyear}},
|
||||
activemonth : {{nextmonth}}
|
||||
},
|
||||
|
|
@ -106,7 +262,6 @@ else{
|
|||
}
|
||||
|
||||
|
||||
|
||||
function recalculateChoosenDays(){
|
||||
seldates = [];
|
||||
userid = "";
|
||||
|
|
@ -119,6 +274,7 @@ function recalculateChoosenDays(){
|
|||
date_end = new Date(seldates[seldates.length-1])
|
||||
|
||||
$("#div_id_end").show();
|
||||
$("#div_id_end_ishalf").show();
|
||||
|
||||
$("#startAbsenceProgress").modal("toggle");
|
||||
$("#id_start").data("DateTimePicker").date(date_start);
|
||||
|
|
@ -126,10 +282,11 @@ function recalculateChoosenDays(){
|
|||
|
||||
if(seldates.length == 1){
|
||||
$("#div_id_end").hide();
|
||||
$("#div_id_end_ishalf").hide();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
$( function() {
|
||||
$( "#timetable_team" ).selectable({
|
||||
filter: 'td',
|
||||
|
|
@ -140,16 +297,79 @@ $( function() {
|
|||
},
|
||||
selecting: function(event, ui){
|
||||
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"){
|
||||
$("#" + newid).removeClass();
|
||||
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"){
|
||||
|
||||
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{
|
||||
if(selectedElements.length == 0){
|
||||
active_row = newid.split("_")[0];
|
||||
selectedElements.push(ui["selecting"]["id"]);
|
||||
}
|
||||
else if(newid.split("_")[0] != active_row){
|
||||
$("#" + newid).removeClass();
|
||||
else if(newid.split("_")[0] != active_row){
|
||||
|
||||
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{
|
||||
selectedElements.push(ui["selecting"]["id"]);
|
||||
|
|
@ -160,48 +380,21 @@ $( function() {
|
|||
selectedElements.splice(selectedElements.indexOf(ui["unselecting"]["id"]),1);
|
||||
},
|
||||
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>
|
||||
<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-content">
|
||||
<div class="modal-header">
|
||||
Arbeitstag löschen
|
||||
<h5 class="modal-title">Arbeitstag löschen</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
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 counter_tag %}
|
||||
{% 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">
|
||||
|
||||
<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>
|
||||
<hr>
|
||||
<div>
|
||||
<div id="rendered_table">
|
||||
Lade Kalenderdaten...
|
||||
</div>
|
||||
<div id="overlay" style="display: none;">
|
||||
<div class="loader"></div>
|
||||
|
||||
<ul class="nav nav-tabs" id="absencetabs" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="team-tab" data-toggle="tab" href="#team" role="tab" aria-controls="team" aria-selected="false">Teamübersicht</a>
|
||||
</li>
|
||||
<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 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-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<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">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h5>Abwesenheit für <b><span id="username_abscence"></span></b> beantragen</h5>
|
||||
<hr>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="form_type" value="absenceform">
|
||||
{% csrf_token %}
|
||||
{{abscenceform.media}}
|
||||
{{abscenceform|crispy}}
|
||||
</form>
|
||||
{{abscenceform|crispy}}
|
||||
</div>
|
||||
<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>
|
||||
</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 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>
|
||||
.tm-ab-tdhover:hover{
|
||||
background-color: #858796 !important;
|
||||
|
|
@ -78,20 +173,142 @@
|
|||
<style>
|
||||
|
||||
|
||||
|
||||
/* DATATABLES */
|
||||
.paginate_button {
|
||||
padding: 0px !important;
|
||||
border: 0px !important;
|
||||
}
|
||||
</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>
|
||||
//Initial Load
|
||||
function loaddjango(){
|
||||
|
||||
var absencetowork = "";
|
||||
var absencestring_confirm = "";
|
||||
var absencestring_noconfirm = "";
|
||||
var newconfstat = "";
|
||||
var closeonly = false;
|
||||
|
||||
function closeOnly(){
|
||||
closeonly = true;
|
||||
}
|
||||
|
||||
function confirmAbscenceFinal(){
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "{% url 'tm-ajax' %}",
|
||||
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}},
|
||||
activemonth : {{activemonth}}
|
||||
},
|
||||
|
|
@ -101,14 +318,46 @@ function loaddjango(){
|
|||
success : function(data){
|
||||
$("#rendered_table").html(data)
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
$(document).ready(function(){
|
||||
loaddjango();
|
||||
moment.locale('de');
|
||||
loaddjango();
|
||||
|
||||
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>
|
||||
{% else %}
|
||||
<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.http import JsonResponse
|
||||
from .models import Workday, Breaks, FreeDays
|
||||
from .models import Workday, Breaks, FreeDays, AbsenceReason, Absence
|
||||
from django.utils import timezone
|
||||
import requests, csv, os
|
||||
from django.templatetags.static import static
|
||||
|
|
@ -11,7 +11,11 @@ from django.contrib.auth.models import User
|
|||
from calendar import monthrange
|
||||
import datetime
|
||||
import calendar
|
||||
from .forms import AddAbsence
|
||||
from .forms import AddAbsence, ConfirmAbsenceForm
|
||||
from django.contrib import messages
|
||||
from users.models import UserFullName
|
||||
|
||||
|
||||
|
||||
def loadingFreeDays(plz):
|
||||
# Getting land
|
||||
|
|
@ -46,70 +50,124 @@ def get_datetime_range(year, month):
|
|||
|
||||
@login_required
|
||||
def AbsenceManagmenet(request, activemonth=False, activeyear=False):
|
||||
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
|
||||
# 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
|
||||
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:
|
||||
nextmonth = activemonth + 1
|
||||
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
|
||||
|
||||
if(activemonth == 1):
|
||||
prevmonth = 12
|
||||
else:
|
||||
prevmonth = activemonth-1
|
||||
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(instance=request.user),
|
||||
"userown" : Absence.objects.filter(agency=request.user.profile.agency, user=request.user).order_by("start")
|
||||
}
|
||||
|
||||
if(activemonth == 12):
|
||||
nextmonth = 1
|
||||
else:
|
||||
nextmonth = activemonth + 1
|
||||
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")
|
||||
})
|
||||
|
||||
#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
|
||||
|
||||
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)
|
||||
return render(request, 'timemanagement/tm_ab_management.html', context)
|
||||
|
||||
|
||||
@login_required
|
||||
def TimeManagement(request):
|
||||
def TimeManagement(request):
|
||||
context = {
|
||||
"active_link" : "timemanagement",
|
||||
"workdays" : Workday.objects.filter(agency=request.user.profile.agency, user=request.user).order_by("-start")
|
||||
|
|
@ -187,8 +245,8 @@ def TimeAjax(request):
|
|||
}
|
||||
else:
|
||||
data = { "success" : False}
|
||||
# REMOVE WORKDAY
|
||||
elif request.GET["action"] == "testdjango":
|
||||
# Get Rendered Table
|
||||
elif request.GET["action"] == "getrenderedtable":
|
||||
prevmonth = ""
|
||||
nextmonth = ""
|
||||
activemonth = int(request.GET["activemonth"])
|
||||
|
|
@ -248,9 +306,57 @@ def TimeAjax(request):
|
|||
"nextyear" : nextyear,
|
||||
"prevyear" : prevyear
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
data = {
|
||||
"success" : False
|
||||
|
|
@ -258,3 +364,4 @@ def TimeAjax(request):
|
|||
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from django.contrib.auth.models import Permission
|
|||
from message.models import Message
|
||||
from cloud.models import DataFile
|
||||
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(StandardCommentRate)
|
||||
|
|
@ -25,4 +25,5 @@ admin.site.register(UserTime)
|
|||
admin.site.register(Workday)
|
||||
admin.site.register(Breaks)
|
||||
admin.site.register(AbsenceReason)
|
||||
admin.site.register(Absence)
|
||||
admin.site.register(FreeDays)
|
||||
|
|
|
|||
|
|
@ -252,7 +252,9 @@ class UserTime(models.Model):
|
|||
wd_th = models.FloatField(default=8.0)
|
||||
wd_fr = models.FloatField(default=8.0)
|
||||
holiday = models.FloatField(default=24.0)
|
||||
loose_holidedate = models.DateField(default=datetime.date(datetime.datetime.now().year + 1, 4,30))
|
||||
holiday_start = models.FloatField(default=0.0)
|
||||
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