Abwesenheit usw.
This commit is contained in:
parent
7c49e9cdb5
commit
2059671f3c
44
adm/forms.py
44
adm/forms.py
|
|
@ -1,6 +1,8 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from users.models import AgencyBills
|
from users.models import AgencyBills
|
||||||
|
from timemanagement.models import Absence, AbsenceReason, FreeDays, Workday, Breaks
|
||||||
|
from bootstrap_datepicker_plus import DatePickerInput
|
||||||
|
|
||||||
class AgencyBillForm(forms.ModelForm):
|
class AgencyBillForm(forms.ModelForm):
|
||||||
|
|
||||||
|
|
@ -11,3 +13,45 @@ class AgencyBillForm(forms.ModelForm):
|
||||||
'agency' : "Agentur",
|
'agency' : "Agentur",
|
||||||
'start' : "Leistungszeitraum Start",
|
'start' : "Leistungszeitraum Start",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AdmWorkdayForm(forms.ModelForm):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Workday
|
||||||
|
labels = {
|
||||||
|
"start" : "Start",
|
||||||
|
"end" : "Ende",
|
||||||
|
"target" : "Zielarbeitszeit",
|
||||||
|
"freefield" : "Notiz"
|
||||||
|
}
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
"start", "end", "target", "freefield"
|
||||||
|
]
|
||||||
|
widgets = {
|
||||||
|
'start': DatePickerInput(options={"format":'DD.MM.YYYY HH:mm', "locale":'de'}),
|
||||||
|
'end': DatePickerInput(options={"format":'DD.MM.YYYY HH:mm', "locale":'de'}),
|
||||||
|
}
|
||||||
|
|
||||||
|
# ADD BREAK FORM
|
||||||
|
class AdmBreakAddForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Breaks
|
||||||
|
labels = {
|
||||||
|
"start" : "Start",
|
||||||
|
"end" : "Ende"
|
||||||
|
}
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
"start", "end"
|
||||||
|
]
|
||||||
|
widgets = {
|
||||||
|
'start': DatePickerInput(options={"format":'DD.MM.YYYY HH:mm', "locale":'de'}),
|
||||||
|
'end': DatePickerInput(options={"format":'DD.MM.YYYY HH:mm', "locale":'de'}),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *arg, **kwargs):
|
||||||
|
super(AdmBreakAddForm, self).__init__(*arg, **kwargs)
|
||||||
|
self.fields['start'].required = True
|
||||||
|
self.fields['end'].required = True
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
{% extends "adm/adm_base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
{% if request.user.profile.agency.module_timemanagement %}
|
||||||
|
<div class="content-section col-7">
|
||||||
|
|
||||||
|
<h3>Zum Arbeitstag am {{workday.start|date:"d.m.Y"}} Pause hinzufügen</h3>
|
||||||
|
<hr>
|
||||||
|
<div class="col-6" style="margin-left: -10px;">
|
||||||
|
<form method="POST" class="">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{form.media}}
|
||||||
|
{{form}}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<a class="btn" href="{% url 'adm-workday-update' workday.pk %}">Abbrechen</a>
|
||||||
|
<button type="submit" class="btn btn-primary">Pause hinzufügen</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
{% extends "adm/adm_base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
<div class="content-section col-12">
|
||||||
|
<h4>Pause des Arbeitstags von {{object.user.get_full_name}} am {{object.workday.start|date:"d.m.Y"}} löschen?</h4>
|
||||||
|
<hr>
|
||||||
|
<form method="POST" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
<p>Achtung! Das Löschen kann nicht rückgängig gemacht werden. Die Pause von {{object.start|date:"H:i"}} bis {{object.end|date:"H:i"}} wird entfernt!</p>
|
||||||
|
<a class="btn btn-secondary" href="{% url 'adm-workday-update' object.workday.pk %}" name="action">Abbrechen</a>
|
||||||
|
<button style="float: right" class="btn btn-primary" type="submit" name="action">Pause löschen</button>
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -144,22 +144,26 @@
|
||||||
<div class="tab-pane fade" id="nav-contract" role="tabpanel" aria-labelledby="nav-contract-tab">
|
<div class="tab-pane fade" id="nav-contract" role="tabpanel" aria-labelledby="nav-contract-tab">
|
||||||
<br />
|
<br />
|
||||||
<h5>Arbeitstage</h5>
|
<h5>Arbeitstage</h5>
|
||||||
|
<a class="btn btn-sm btn-primary" href="{% url 'adm-workday-add' userdata.pk %}">+ Arbeitstag</a><br />
|
||||||
|
<br />
|
||||||
<table class="table table-hover" id="user_workdays" >
|
<table class="table table-hover" id="user_workdays" >
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col"></th>
|
<th scope="col">ID</th>
|
||||||
<th scope="col">Start</th>
|
<th scope="col">Start</th>
|
||||||
<th scope="col">Ende</th>
|
<th scope="col">Ende</th>
|
||||||
<th scope="col">Ziel</th>
|
<th scope="col">Ziel</th>
|
||||||
|
<th scope="col"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody >
|
<tbody >
|
||||||
{% for wd in workdays %}
|
{% for wd in workdays %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{forloop.counter}}</td>
|
<td>{{wd.pk}}</td>
|
||||||
<td>{{wd.start|date:"d.m.Y H:i"}}</td>
|
<td>{{wd.start|date:"d.m.Y H:i"}}</td>
|
||||||
<td>{{wd.end|date:"d.m.Y H:i"}}</td>
|
<td>{{wd.end|date:"d.m.Y H:i"}}</td>
|
||||||
<td>{{wd.target}}</td>
|
<td>{{wd.target}}</td>
|
||||||
|
<td><a class="btn btn-secondary btn-sm " href="{% url 'adm-workday-update' wd.pk %}"><i class="fas fa-pen"></i></a> <a class="btn btn-sm " href="{% url 'adm-workday-delete' wd.pk %}"><i class="fas fa-trash"></i></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -203,7 +207,7 @@
|
||||||
<table class="table table-hover" id="user_absences" >
|
<table class="table table-hover" id="user_absences" >
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col"></th>
|
<th scope="col">ID</th>
|
||||||
<th scope="col">Art</th>
|
<th scope="col">Art</th>
|
||||||
<th scope="col">Start</th>
|
<th scope="col">Start</th>
|
||||||
<th scope="col">Ende</th>
|
<th scope="col">Ende</th>
|
||||||
|
|
@ -220,7 +224,7 @@
|
||||||
<tbody >
|
<tbody >
|
||||||
{% for ab in absences %}
|
{% for ab in absences %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{forloop.counter}}</td>
|
<td>{{ab.pk}}</td>
|
||||||
<td>{{ab.reason.name}}</td>
|
<td>{{ab.reason.name}}</td>
|
||||||
<td>{{ab.start|date:"d.m.Y"}}</td>
|
<td>{{ab.start|date:"d.m.Y"}}</td>
|
||||||
<td>{{ab.end|date:"d.m.Y"}}</td>
|
<td>{{ab.end|date:"d.m.Y"}}</td>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
{% extends "adm/adm_base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
{% if request.user.profile.agency.module_timemanagement %}
|
||||||
|
<div class="content-section col-7">
|
||||||
|
|
||||||
|
<h3>Arbeitstag für {{user.get_full_name}} erstellen</h3>
|
||||||
|
<hr>
|
||||||
|
<div class="col-6" style="margin-left: -10px;">
|
||||||
|
<form method="POST" class="">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{form.media}}
|
||||||
|
{{form|crispy}}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<a class="btn" href="{% url 'adm-user-single' user.pk %}">Abbrechen</a>
|
||||||
|
<button type="submit" class="btn btn-primary">Arbeitstag speichern</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
{% extends "adm/adm_base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
<div class="content-section col-12">
|
||||||
|
<h4>Arbeitstag von {{object.user.get_full_name}} am {{object.start|date:"d.m.Y"}} löschen?</h4>
|
||||||
|
<hr>
|
||||||
|
<form method="POST" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
<p>Achtung! Das Löschen kann nicht rückgängig gemacht werden. Der komplette Arbeitstag wird entfernt!</p>
|
||||||
|
<a class="btn btn-secondary" href="{% url 'adm-user-single' object.user.pk %}" name="action">Abbrechen</a>
|
||||||
|
<button style="float: right" class="btn btn-primary" type="submit" name="action">Arbeitstag löschen</button>
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
{% extends "adm/adm_base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
<div class="content-section col-12">
|
||||||
|
<h4>Arbeitstag von {{object.user.get_full_name}} am {{object.start|date:"d.m.Y"}} aktualisieren</h4>
|
||||||
|
<hr>
|
||||||
|
<form method="POST" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{form.media}}
|
||||||
|
{{form|crispy}}
|
||||||
|
<hr>
|
||||||
|
<h5>Pausen</h5>
|
||||||
|
<a class="btn btn-sm btn-primary" href="{% url 'adm-break-add' object.pk %}">+ Pause</a><br /><br />
|
||||||
|
{% if object.breaks.all|length > 0 %}
|
||||||
|
<table class="table table-hover" id="user_breaks" >
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"></th>
|
||||||
|
<th scope="col">Start</th>
|
||||||
|
<th scope="col">Ende</th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody >
|
||||||
|
{% for break in object.breaks.all %}
|
||||||
|
<tr>
|
||||||
|
<td>{{forloop.counter}}</td>
|
||||||
|
<td>{{break.start|date:"H:i"}}</td>
|
||||||
|
<td>{{break.end|date:"H:i"}}</td>
|
||||||
|
<td><a class="btn btn-secondary btn-sm " href="{% url 'adm-break-delete' break.pk %}"><i class="fas fa-trash"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
<p>Arbeitstag hat keine Pausen</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
<a class="btn btn-secondary" href="{% url 'adm-user-single' object.user.pk %}" name="action">Abbrechen</a>
|
||||||
|
<button style="float: right" class="btn btn-primary" type="submit" name="action">Speichern</button>
|
||||||
|
</form>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function(){
|
||||||
|
$('#user_breaks').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"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"pageLength": 10,
|
||||||
|
"buttons" : {
|
||||||
|
"className" : "btn-danger"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -17,5 +17,11 @@ urlpatterns = [
|
||||||
path('usersingle/<int:uspk>', AdmUserSingle.as_view(), name="adm-user-single"),
|
path('usersingle/<int:uspk>', AdmUserSingle.as_view(), name="adm-user-single"),
|
||||||
path('cron/<slug:code>', statisticCronJob, name="adm-cron"),
|
path('cron/<slug:code>', statisticCronJob, name="adm-cron"),
|
||||||
path('getorders/', getCSVRDOrders, name="getorders"),
|
path('getorders/', getCSVRDOrders, name="getorders"),
|
||||||
path('adm/addbill', AdmAddBill.as_view(), name="admbill-add")
|
path('adm/addbill', AdmAddBill.as_view(), name="admbill-add"),
|
||||||
|
path('wd/<int:pk>/update', AdmWorkdayUpdate.as_view(), name="adm-workday-update"),
|
||||||
|
path('wd/add/<int:uspk>', AdmWorkdayAdd.as_view(), name="adm-workday-add"),
|
||||||
|
path('wd/<int:pk>/delete', AdmWorkdayDelete.as_view(), name="adm-workday-delete"),
|
||||||
|
path('wd/break/<int:pk>/delete', AdmBreakDelete.as_view(), name="adm-break-delete"),
|
||||||
|
path('wd/<int:pk>/break/add', AdmAddBreak.as_view(), name="adm-break-add"),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
||||||
102
adm/views.py
102
adm/views.py
|
|
@ -13,9 +13,9 @@ import csv, os
|
||||||
from auditlog.models import LogEntry
|
from auditlog.models import LogEntry
|
||||||
import json
|
import json
|
||||||
from users.models import UserYearAbsenceInfo, UserTime
|
from users.models import UserYearAbsenceInfo, UserTime
|
||||||
from timemanagement.models import Workday, Absence
|
from timemanagement.models import Workday, Absence, Breaks
|
||||||
from recoverdir.models import *
|
from recoverdir.models import *
|
||||||
from .forms import AgencyBillForm
|
from .forms import AgencyBillForm, AdmWorkdayForm, AdmBreakAddForm
|
||||||
from datetime import date, timedelta, datetime
|
from datetime import date, timedelta, datetime
|
||||||
from organizer.models import QuickLinks, AGContacts, AGPassword
|
from organizer.models import QuickLinks, AGContacts, AGPassword
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
|
|
@ -547,8 +547,6 @@ def getLexOfficeBill(billid):
|
||||||
|
|
||||||
return returnvalue
|
return returnvalue
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def convert_size(size_bytes):
|
def convert_size(size_bytes):
|
||||||
if size_bytes == 0:
|
if size_bytes == 0:
|
||||||
return "0B"
|
return "0B"
|
||||||
|
|
@ -561,10 +559,98 @@ def convert_size(size_bytes):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
''' WORKDAY VIEWS
|
||||||
|
|
||||||
|
Hier sind alle Views für Arbeitstage und Pausen (Create, Update, Delete)
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
class AdmWorkdayAdd(CreateView):
|
||||||
|
model = Workday
|
||||||
|
template_name = "adm/adm_workday_add.html"
|
||||||
|
form_class = AdmWorkdayForm
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
wd_user = User.objects.get(pk=self.kwargs['uspk'])
|
||||||
|
wd = Workday(user=wd_user, agency=wd_user.profile.agency, start=form.cleaned_data['start'], end=form.cleaned_data['end'], target=form.cleaned_data["target"], freefield=form.cleaned_data["freefield"])
|
||||||
|
wd.save()
|
||||||
|
return HttpResponseRedirect(self.get_success_url())
|
||||||
|
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context.update({'active_link' : 'adm-users'})
|
||||||
|
context.update({'user' : User.objects.get(pk=self.kwargs['uspk'])})
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse('adm-user-single', kwargs={'uspk': self.kwargs['uspk']})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class AdmWorkdayUpdate(UpdateView):
|
||||||
|
model = Workday
|
||||||
|
form_class = AdmWorkdayForm
|
||||||
|
template_name = "adm/adm_workday_update.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context.update({'active_link' : 'adm-users'})
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse('adm-user-single', kwargs={'uspk': self.get_object().user.pk})
|
||||||
|
|
||||||
|
|
||||||
|
class AdmWorkdayDelete(DeleteView):
|
||||||
|
model = Workday
|
||||||
|
template_name = "adm/adm_workday_delete.html"
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse('adm-user-single', kwargs={'uspk': self.get_object().user.pk})
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context.update({'active_link' : 'adm-users'})
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class AdmBreakDelete(DeleteView):
|
||||||
|
model = Breaks
|
||||||
|
template_name = "adm/adm_break_delete.html"
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse('adm-workday-update', kwargs={'pk': self.get_object().workday.pk})
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context.update({'active_link' : 'adm-users'})
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class AdmAddBreak(CreateView):
|
||||||
|
model = Breaks
|
||||||
|
template_name = "adm/adm_break_add.html"
|
||||||
|
form_class = AdmBreakAddForm
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
wd = Workday.objects.get(pk=self.kwargs['pk'])
|
||||||
|
b = Breaks(user=wd.user, agency=wd.user.profile.agency, workday=wd, start=form.cleaned_data["start"], end=form.cleaned_data["end"])
|
||||||
|
b.save()
|
||||||
|
wd.breaks.add(b)
|
||||||
|
wd.save()
|
||||||
|
return HttpResponseRedirect(self.get_success_url())
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context.update({'active_link' : 'adm-users'})
|
||||||
|
context.update({'workday' : Workday.objects.get(pk=self.kwargs['pk'])})
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse('adm-workday-update', kwargs={'pk': self.kwargs['pk']})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
Hier sind alle Methoden gesammelt, die bei der Zeiterfassung eine Rolle spielen.
|
||||||
|
|
||||||
|
|
||||||
|
daterange()
|
||||||
|
- Gibt jeden Tag zwischen zwei Daten zurück
|
||||||
|
|
||||||
|
@param:
|
||||||
|
date1 - Startdatum
|
||||||
|
date2 - Enddatum
|
||||||
|
|
||||||
|
@return:
|
||||||
|
Array mit den entsprechenden Tagen
|
||||||
|
|
||||||
|
getIsAbsenceStartEndHalf()
|
||||||
|
- Gibt True zurücke, wenn der Anfang oder das Ende einer Abwesenheit nur ein halber Tag ist, ansonsten False
|
||||||
|
|
||||||
|
@param:
|
||||||
|
absence - Die zu prüfende Abwesenheit
|
||||||
|
|
||||||
|
@return:
|
||||||
|
True -> Ist nur ein halber Tag
|
||||||
|
False -> Ist ein ganzer Tag
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
# Gibt die Woche als Wochentage zurück
|
||||||
|
def daterange(date1, date2):
|
||||||
|
for n in range(int ((date2 - date1).days)+1):
|
||||||
|
yield date1 + timedelta(n)
|
||||||
|
|
||||||
|
|
||||||
|
# Gibt True zurück, wenn eine Tag einer Abwesenheit nur ein halber Tag ist
|
||||||
|
def getIsAbsenceStartEndHalf(absence):
|
||||||
|
if absence.startday_info == "1" or absence.startday_info == "2" or absence.endday_info == "1" or absence.endday_info == "2":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
from timemanagement.models import *
|
||||||
|
from digitaleagentur.timemanagement_utils import *
|
||||||
|
'''
|
||||||
|
|
||||||
|
Hier sind Funktion implementiert, die in verschiedenen Module benötigt werden
|
||||||
|
|
||||||
|
|
||||||
|
getAbsenceForOneDay - Gibt Abwesenheit eines Users für einen Tag zurück
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
# getAbsenceForOneDay
|
||||||
|
'''
|
||||||
|
|
||||||
|
Gibt eine Abwesenheit für einen übergebenen Tag zurück oder False, wenn keine Abwesenheit vorliegt.
|
||||||
|
|
||||||
|
@param:
|
||||||
|
- user (der entsprechende Nutzer)
|
||||||
|
- day (Tag, welcher auf Abwesenheiten geprüft werden soll)
|
||||||
|
|
||||||
|
'''
|
||||||
|
def getAbsenceForOneDay(user, day):
|
||||||
|
absencedays = Absence.objects.filter(agency=user.profile.agency, user=user, confirm_status=0) & (Absence.objects.filter(agency=user.profile.agency, user=user, start=day) | (Absence.objects.filter(agency=user.profile.agency, user=user, start__lt=day) & Absence.objects.filter(agency=user.profile.agency, user=user, end__gt=day)) | Absence.objects.filter(agency=user.profile.agency, user=user, end=day))
|
||||||
|
|
||||||
|
# Gibt es eine Abwesenheit an diesem Tag, welche einen halben Tag ist, dann gibt die Methode True zurück und bricht die Schleife ab!
|
||||||
|
for ab in absencedays:
|
||||||
|
if ab.startday_info == "1" or ab.startday_info == "2" or ab.endday_info == "1" or ab.endday_info == "2":
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Es gibt an diesem Tag keine Abwesenheit mit einem halben Tag
|
||||||
|
return False
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
# checkAbsenceWorkdayCollide()
|
||||||
|
|
||||||
|
|
||||||
|
Prüft, ob eine aktualisierte Abwesenheit Einfluss auf bereits bestehende Arbeitstage hat. Wenn zB nachträglich Arbeitstage eingetragen werden, dann würden diese hier angepasst werden.
|
||||||
|
|
||||||
|
Folgende Fälle werden berücksichtigt:
|
||||||
|
- Halber Tag der Abwesenheit verringert die Zielarbeitszeit dieses Tags auf die Hälfte
|
||||||
|
- Abwesenheit ist der komplette Tag, dann wird dieser Arbeitstag gelöscht, wenn es is_time false ist, sprich die Zeiterfassung soll nicht angefasst werden
|
||||||
|
- Abwesenheit ist kompletter Tag und die Abwesenheit soll Zeiterfassung beeinflussen (z.B. Gleitzeit) dann wird der Arbeitstag nicht verändert. Ist die Gleitzeit ein halber Tag, wird die Zielarbeitszeit halbiert.
|
||||||
|
'''
|
||||||
|
def checkAbsenceWorkdayCollide(absence):
|
||||||
|
# Alle einzelnen Tage der Abwesenheit werden durchgegangen:
|
||||||
|
for day in daterange(absence.start, absence.end):
|
||||||
|
# Arbeitstage an diesem Tag werden geladen
|
||||||
|
workdays = Workday.objects.filter(user=absence.user, start__day=absence.start.day, start__month=absence.start.month, start__year=absence.start.year)
|
||||||
|
|
||||||
|
# Wenn es Arbeitstage gibt, dann wird geprüft, ob die Abwesenheit diesen verändert hat.
|
||||||
|
for workday in workdays:
|
||||||
|
# Arbeitstag in Tag ohne Zeit umwandeln
|
||||||
|
# Wenn die Abwesenheit die Zeiterfassung NICHT ändert, muss diese ggf. geändert werden. Ansonsten bleibt sie gleich.
|
||||||
|
if absence.reason.is_time == False:
|
||||||
|
# Prüfung, ob der Tag halb ist oder nicht. Wenn ja, dann Zielarbeitszeit des Tages um die Hälfte reduzieren.
|
||||||
|
if (workday.start.day == absence.start.day and workday.start.month == absence.start.month and workday.start.year == absence.start.year) or (workday.end.day == absence.end.day and workday.end.month == absence.end.month and workday.end.year == absence.end.year):
|
||||||
|
if(getIsAbsenceStartEndHalf(absence)):
|
||||||
|
workday.target = workday.target / 2
|
||||||
|
workday.save()
|
||||||
|
# Ganzer Tag vorhanden, Arbeitstag wird gelöscht
|
||||||
|
else:
|
||||||
|
workday.delete()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -26,8 +26,8 @@ mysqlclient==2.0.1
|
||||||
Pillow==6.2.1
|
Pillow==6.2.1
|
||||||
pycparser==2.20
|
pycparser==2.20
|
||||||
python-bidi==0.4.2
|
python-bidi==0.4.2
|
||||||
python-dateutil==2.6.0
|
|
||||||
python-magic-bin==0.4.14
|
python-magic-bin==0.4.14
|
||||||
|
python-dateutil==2.6.0
|
||||||
pytz==2019.3
|
pytz==2019.3
|
||||||
requests==2.22.0
|
requests==2.22.0
|
||||||
requests-oauthlib==1.3.0
|
requests-oauthlib==1.3.0
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,6 @@ class AddAbsence(forms.ModelForm):
|
||||||
self.fields['activeyear'] = 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())
|
self.fields['userid'] = forms.CharField(initial="", required=False, widget=forms.HiddenInput())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UpdateAbsence(forms.ModelForm):
|
class UpdateAbsence(forms.ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="table_contacts" >
|
<tbody id="table_contacts" >
|
||||||
{% for da in days_this_month %}
|
{% for da in days_this_month %}
|
||||||
|
|
||||||
|
|
||||||
{% getabscenceday request.user request.user da as abday %}
|
{% getabscenceday request.user request.user da as abday %}
|
||||||
<tr id="da_{{da|date:"d-m-y"}}"
|
<tr id="da_{{da|date:"d-m-y"}}"
|
||||||
{% if da.weekday == 5 or da.weekday == 6 %}
|
{% if da.weekday == 5 or da.weekday == 6 %}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ from users.signals import save_newabsence
|
||||||
import locale
|
import locale
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
|
from digitaleagentur.utils import *
|
||||||
|
|
||||||
|
|
||||||
# Load freedays
|
# Load freedays
|
||||||
def loadingFreeDays(plz):
|
def loadingFreeDays(plz):
|
||||||
|
|
@ -514,7 +516,7 @@ def TimeAdd(request, team=0, pk=0):
|
||||||
form.fields["target"].initial = user.usertime.wd_sa
|
form.fields["target"].initial = user.usertime.wd_sa
|
||||||
elif(today.isoweekday() == 7):
|
elif(today.isoweekday() == 7):
|
||||||
form.fields["target"].initial = user.usertime.wd_so
|
form.fields["target"].initial = user.usertime.wd_so
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"active_link" : "timemanagement",
|
"active_link" : "timemanagement",
|
||||||
"form" : form,
|
"form" : form,
|
||||||
|
|
@ -589,6 +591,11 @@ def TimeAjax(request):
|
||||||
elif(today.isoweekday() == 7):
|
elif(today.isoweekday() == 7):
|
||||||
targettime = request.user.usertime.wd_so
|
targettime = request.user.usertime.wd_so
|
||||||
|
|
||||||
|
|
||||||
|
# Liegt eine halbe Abwesenheit vor, wird hier die Zielarbeitszeit halbiert
|
||||||
|
if(getAbsenceForOneDay(request.user, today) != False):
|
||||||
|
targettime = targettime / 2
|
||||||
|
|
||||||
wd = Workday(user=request.user, agency=request.user.profile.agency, start=timezone.now(), target=targettime)
|
wd = Workday(user=request.user, agency=request.user.profile.agency, start=timezone.now(), target=targettime)
|
||||||
wd.save()
|
wd.save()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ from channels_presence.signals import presence_changed
|
||||||
from organizer.models import *
|
from organizer.models import *
|
||||||
from chat.models import ChatMessage
|
from chat.models import ChatMessage
|
||||||
|
|
||||||
|
from digitaleagentur.utils import *
|
||||||
|
|
||||||
def loadingFreeDays(plz, year):
|
def loadingFreeDays(plz, year):
|
||||||
# Getting land
|
# Getting land
|
||||||
file_path = os.path.join(settings.STATIC_ROOT, 'users/extra/plz_short.csv')
|
file_path = os.path.join(settings.STATIC_ROOT, 'users/extra/plz_short.csv')
|
||||||
|
|
@ -640,6 +642,8 @@ def save_newabsence(sender, instance, **kwargs):
|
||||||
instance.holidays_normal_next = newdata[3][1]
|
instance.holidays_normal_next = newdata[3][1]
|
||||||
instance.holidays_rest_next = newdata[3][3]
|
instance.holidays_rest_next = newdata[3][3]
|
||||||
instance.save()
|
instance.save()
|
||||||
|
|
||||||
|
checkAbsenceWorkdayCollide(instance)
|
||||||
|
|
||||||
# NEUE ABWESENHEIT ERSTELLT
|
# NEUE ABWESENHEIT ERSTELLT
|
||||||
if(kwargs["created"]):
|
if(kwargs["created"]):
|
||||||
|
|
@ -710,8 +714,8 @@ def save_newabsence(sender, instance, **kwargs):
|
||||||
async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Abwesenheit | Sie wurden als Vertreter für " + instance.user.first_name + " " + instance.user.last_name + " eingetragen!"})
|
async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Abwesenheit | Sie wurden als Vertreter für " + instance.user.first_name + " " + instance.user.last_name + " eingetragen!"})
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("Absence-Object is no holiday...")
|
# Kein Urlaubsanspruch, dennoch prüfen ob bereits bestehende Arbeitstage involviert sind
|
||||||
|
checkAbsenceWorkdayCollide(instance)
|
||||||
post_save.connect(save_newabsence, sender=sender)
|
post_save.connect(save_newabsence, sender=sender)
|
||||||
|
|
||||||
# Neue Chatnachricht wurde verschickt - Hier Reaktion NUR auf PUSH!
|
# Neue Chatnachricht wurde verschickt - Hier Reaktion NUR auf PUSH!
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ from django.db.models.signals import m2m_changed
|
||||||
from django.contrib.auth.models import User, Group
|
from django.contrib.auth.models import User, Group
|
||||||
from users.signals import adjust_group_notifications_permission
|
from users.signals import adjust_group_notifications_permission
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from digitaleagentur.utils import *
|
||||||
from organizer.models import QuickLinks
|
from organizer.models import QuickLinks
|
||||||
from areas.models import Areas
|
from areas.models import Areas
|
||||||
from tasks.models import Tasks
|
from tasks.models import Tasks
|
||||||
|
|
@ -1637,8 +1637,13 @@ def cronactionsdaily(request, code):
|
||||||
if(weekday == 6):
|
if(weekday == 6):
|
||||||
targettworktime = user.usertime.wd_so
|
targettworktime = user.usertime.wd_so
|
||||||
|
|
||||||
|
day_half_found = False
|
||||||
|
if(getAbsenceForOneDay(user, yesterday) != False):
|
||||||
|
targettworktime = targettworktime / 2
|
||||||
|
day_half_found = True
|
||||||
|
|
||||||
# Es wird nur ein Arbeitstag erstellt, wenn KEINE Abwesenheiten vorliegen und der Nutzer an diesem Tag arbeiten muss
|
# Es wird nur ein Arbeitstag erstellt, wenn KEINE Abwesenheiten vorliegen und der Nutzer an diesem Tag arbeiten muss
|
||||||
if(workdays_yesterday == 0 and absencecheck(user, yesterday) == False and targettworktime > 0.0 and user.usertime.usetime_start < today):
|
if(workdays_yesterday == 0 and (absencecheck(user, yesterday) == False or day_half_found) and targettworktime > 0.0 and user.usertime.usetime_start < today):
|
||||||
workdaytemp = Workday(user=user, agency=user.profile.agency, start=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), end=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), target=targettworktime)
|
workdaytemp = Workday(user=user, agency=user.profile.agency, start=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), end=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), target=targettworktime)
|
||||||
workdaytemp.save()
|
workdaytemp.save()
|
||||||
except:
|
except:
|
||||||
|
|
@ -1680,7 +1685,6 @@ def cronactionsdaily(request, code):
|
||||||
#["htrampe@gmail.com"],
|
#["htrampe@gmail.com"],
|
||||||
fail_silently=True,
|
fail_silently=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
return JsonResponse(data)
|
return JsonResponse(data)
|
||||||
|
|
||||||
#import datetime
|
#import datetime
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue