Abwesenheit und Chat
This commit is contained in:
parent
a00710e04c
commit
15348b2d25
|
|
@ -1,3 +1,4 @@
|
|||
{% load counter_tag %}
|
||||
{% if roomdata.creator == user %}
|
||||
<h4 id="chattitle">Gespräch mit {{roomdata.chatmember_single.first_name}} {{roomdata.chatmember_single.last_name}}</h4>
|
||||
{% else %}
|
||||
|
|
@ -8,43 +9,57 @@
|
|||
<div class="card" >
|
||||
<div class="card-body scroll" id="chatcontentcomplete">
|
||||
|
||||
<div id="roomstart" style="min-width: 100%; text-align: center;">
|
||||
|
||||
<small>Unterhaltung gestartet am {{roomdata.chatroom_createddate}}</small>
|
||||
|
||||
<div id="roomstart" style="min-width: 100%; text-align: center;">
|
||||
<small>Unterhaltung gestartet am {{roomdata.chatroom_createddate}}</small>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
|
||||
<div id="chatmessages">
|
||||
{% for message in roomdata.messages.all %}
|
||||
|
||||
{% if forloop.counter0 == 0 %}
|
||||
{% setMessageDayInfo message %}
|
||||
{% else %}
|
||||
{% getMessageDayInfo message as newday %}
|
||||
{% if newday == True %}
|
||||
<div style="" class="chatmessageele_breaker col-12 mb-3">
|
||||
<div class="col-12 mb-3" style="text-align: center;">
|
||||
<hr>
|
||||
<small>{{message.sendtime|date:"d.m.Y"}}</small>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% for message in roomdata.messages.all %}
|
||||
{% if message.author == request.user %}
|
||||
<div style="" class="chatmessageele_me col-7 mb-3 ">
|
||||
<div class='icon-container ml-2 mt-1 ' style="float: right;">
|
||||
<img class="img-profile roundimg" src="{{ message.author.profile.get_photo_url }}">
|
||||
</div>
|
||||
<h6 class="mt-3"><small>{{message.author.first_name}} {{message.author.last_name}}, {{message.sendtime}}</small></h6>
|
||||
</div>
|
||||
<h6 class="mt-3"><small>{{message.sendtime|date:"H:m"}}</small></h6>
|
||||
<div style="text-align: left;" class="mt-1">
|
||||
<span style="float: right !important; font-size: 1.0em;">
|
||||
{{message.content}}
|
||||
</span>
|
||||
</div>
|
||||
{{message.content}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div style="" class="chatmessageele_other col-7 mb-3">
|
||||
<div class='icon-container mr-2 mt-1 ' style="float: left;">
|
||||
<img class="img-profile roundimg" src="{{ message.author.profile.get_photo_url }}">
|
||||
</div>
|
||||
<h6 class="mt-3"><small>{{message.author.first_name}} {{message.author.last_name}}, {{message.sendtime}}</small></h6>
|
||||
<div style="text-align: left;" class="mt-1">
|
||||
<span style="float: left !important; font-size: 1.0em;">
|
||||
{{message.content}}
|
||||
</span>
|
||||
<div class='icon-container mr-2 mt-1 ' style="float: left;">
|
||||
<img class="img-profile roundimg" src="{{ message.author.profile.get_photo_url }}">
|
||||
</div>
|
||||
<h6 class="mt-3"><small>{{message.author.first_name}} {{message.author.last_name}}, {{message.sendtime|date:"H:m"}}</small></h6>
|
||||
<div style="text-align: left;" class="mt-1">
|
||||
<span style="float: left !important; font-size: 1.0em;">
|
||||
{{message.content}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
|
||||
{% endfor %}
|
||||
|
||||
<!-- SINGLE MESSAGE -->
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div class='icon-container mr-2 mt-1 ' style="float: left;">
|
||||
<img class="img-profile roundimg" src="{{ newmessage.author.profile.get_photo_url }}">
|
||||
</div>
|
||||
<h6 class="mt-3"><small>{{newmessage.author.first_name}} {{newmessage.author.last_name}}, {{newmessage.sendtime}}</small></h6>
|
||||
<h6 class="mt-3"><small>{{newmessage.author.first_name}} {{newmessage.author.last_name}}, {{newmessage.sendtime|date:"H:m"}}</small></h6>
|
||||
<div style="text-align: left;" class="mt-1">
|
||||
<span style="float: left !important; font-size: 1.0em;">
|
||||
{{newmessage.content}}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div class='icon-container ml-2 mt-1 ' style="float: right;">
|
||||
<img class="img-profile roundimg" src="{{ newmessage.author.profile.get_photo_url }}">
|
||||
</div>
|
||||
<h6 class="mt-3"><small>{{newmessage.author.first_name}} {{newmessage.author.last_name}}, {{newmessage.sendtime}}</small></h6>
|
||||
<h6 class="mt-3"><small>{{newmessage.sendtime|date:"H:m"}}</small></h6>
|
||||
<div style="text-align: left;" class="mt-1">
|
||||
<span style="float: right !important; font-size: 1.0em;">
|
||||
{{newmessage.content}}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,15 @@
|
|||
position: absolute;
|
||||
}
|
||||
|
||||
.chatmessageele_breaker
|
||||
{
|
||||
float: right;
|
||||
}
|
||||
.chatmessageele_me
|
||||
{
|
||||
padding: 5px;
|
||||
border-radius: 15px;
|
||||
background-color: #f8f9fc;
|
||||
background-color: #cfe6f4;
|
||||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
|
|
@ -38,10 +42,10 @@
|
|||
{
|
||||
padding: 5px;
|
||||
border-radius: 15px;
|
||||
background-color: #858796;
|
||||
background-color: #f8f9fc;
|
||||
float: left;
|
||||
text-align: left;
|
||||
color: #ffffff;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.scroll {
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ a.disabled {
|
|||
</div></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-success" data-dismiss="modal">Beenden</button>
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Beenden</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from users.models import AgencyGroup, Agency, Profile, AgencyJob, AgencyNetwork,
|
|||
from PIL import Image
|
||||
from bootstrap_datepicker_plus import DatePickerInput
|
||||
from django.utils.translation import gettext as _
|
||||
from timemanagement.models import AbsenceReason
|
||||
|
||||
class AgencyTimeManagement(forms.ModelForm):
|
||||
class Meta:
|
||||
|
|
@ -71,15 +72,16 @@ class UserTimeForm(forms.ModelForm):
|
|||
"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",
|
||||
#"wd_mo" : "Montag",
|
||||
#"wd_tu" : "Dienstag",
|
||||
#"wd_we" : "Mittwoch",
|
||||
#"wd_th" : "Donnerstag",
|
||||
#"wd_fr" : "Freitag",
|
||||
}
|
||||
fields = ["startdate", "wd_mo", "wd_tu", "wd_we", "wd_th", "wd_fr", "holiday", "loose_holidedate", "holiday_start", ]
|
||||
#fields = ["startdate", "wd_mo", "wd_tu", "wd_we", "wd_th", "wd_fr", "holiday", "loose_holidedate", "holiday_start", ]
|
||||
fields = ["startdate", "holiday", "loose_holidedate", "holiday_start", ]
|
||||
widgets = {
|
||||
'loose_holidedate': DatePickerInput(options={"format":'DD.MM.', "locale":'de'}),
|
||||
'loose_holidedate': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'}),
|
||||
"startdate" : DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'})
|
||||
}
|
||||
|
||||
|
|
@ -117,15 +119,17 @@ class AgencyModulsForm(forms.ModelForm):
|
|||
'module_files' : "Dateien",
|
||||
'module_organigramm' : "Organigramm",
|
||||
'module_messages' : "Mitteilungen",
|
||||
'module_timemanagement' : "Abwesenheits- und Zeiterfassung",
|
||||
'module_chat' : "Chat",
|
||||
#'module_timemanagement' : "Abwesenheits- und Zeiterfassung",
|
||||
'module_timemanagement' : "Abwesenheitsplanung",
|
||||
}
|
||||
fields = ['module_news','module_organizer','module_files','module_organigramm', 'module_messages', 'module_timemanagement']
|
||||
fields = ['module_news','module_organizer','module_files','module_organigramm', 'module_messages', 'module_chat', 'module_timemanagement']
|
||||
|
||||
# RAUSNHEMEN WENN DEV DONE
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AgencyModulsForm, self).__init__(*args, **kwargs)
|
||||
self.fields['module_timemanagement'].widget.attrs['readonly'] = True
|
||||
self.fields['module_timemanagement'].widget.attrs['disabled'] = True
|
||||
#self.fields['module_timemanagement'].widget.attrs['readonly'] = True
|
||||
#self.fields['module_timemanagement'].widget.attrs['disabled'] = True
|
||||
|
||||
|
||||
# NEW USER FORM
|
||||
|
|
@ -187,3 +191,15 @@ class UserProfileForm(forms.ModelForm):
|
|||
except:
|
||||
print("no photo")
|
||||
|
||||
|
||||
class AbsenceReasonForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = AbsenceReason
|
||||
labels = {
|
||||
"name" : "Bezeichnung",
|
||||
"need_confirm" : "Muss bestätigt werden",
|
||||
"need_rep" : "Muss vertreten werden",
|
||||
"is_holiday" : "Geht vom Urlaub ab",
|
||||
"color" : "Farbe"
|
||||
}
|
||||
fields = ["name", "need_confirm", "need_rep", "is_holiday", "color"]
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{% extends "users/base.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% block content %}
|
||||
{% if request.user.profile.agency.module_timemanagement %}
|
||||
<div class="content-section col-6">
|
||||
<h3>Abwesenheitskategorie anlegen</h3>
|
||||
<hr>
|
||||
<form method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr>
|
||||
<button type="submit" class="btn btn-primary">Abwesenheitskategorie anlegen</button>
|
||||
<a class="btn" href="{% url 'dasettings' %} ">Abbrechen</a>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
<h3>Das Modul Abwesenheitsplanung wurden in ihrer Agentur deaktiviert.</h3>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{% extends "users/base.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% block content %}
|
||||
{% if request.user.profile.agency.module_timemanagement %}
|
||||
<div class="content-section">
|
||||
<div class="media">
|
||||
<div class="media-body">
|
||||
<h2 class="account-heading">Abwesenheitskategorie {{ object.name }} löschen?</h2>
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary">Abwesenheitskategorie löschen</button>
|
||||
<a href="{% url 'dasettings' %}" class="btn">Abbrechen</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
<h3>Das Modul Abwesenheitsplanung wurden in ihrer Agentur deaktiviert.</h3>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{% extends "users/base.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% block content %}
|
||||
{% if request.user.profile.agency.module_timemanagement %}
|
||||
<div class="content-section col-6">
|
||||
<h3>Abwesenheitskategorie aktualisieren</h3>
|
||||
<hr>
|
||||
<form method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr>
|
||||
<button type="submit" class="btn btn-primary">Abwesenheitskategorie aktualisieren</button>
|
||||
<a class="btn" href="{% url 'dasettings' %} ">Abbrechen</a>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
<h3>Das Modul Abwesenheitsplanung wurden in ihrer Agentur deaktiviert.</h3>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{% extends "users/base.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% block content %}
|
||||
{% if request.user.profile.agency.module_timemanagement %}
|
||||
<div class="content-section col-6">
|
||||
<h3>Freien Tag anlegen</h3>
|
||||
<hr>
|
||||
<form method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{form.media}}
|
||||
{{ form|crispy }}
|
||||
<hr>
|
||||
<button type="submit" class="btn btn-primary">Freien Tag anlegen</button>
|
||||
<a class="btn" href="{% url 'tm-managemenetfreedays' %} ">Abbrechen</a>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
<h3>Das Modul Abwesenheitsplanung wurden in ihrer Agentur deaktiviert.</h3>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
{% extends "users/base.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% block content %}
|
||||
{% if request.user.profile.agency.module_timemanagement %}
|
||||
<div class="content-section">
|
||||
<div class="media">
|
||||
<div class="media-body">
|
||||
<h2 class="account-heading">Freien Tag {{ object.name }} am {{ object.day|date:"d. F Y"}} löschen?</h2>
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Für das Speichern der Bilder enctype -->
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary">Freien Tag löschen</button>
|
||||
<a href="{% url 'tm-managemenetfreedays' %}" class="btn">Abbrechen</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
<h3>Das Modul Abwesenheitsplanung wurden in ihrer Agentur deaktiviert.</h3>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
{% extends "users/base.html" %}
|
||||
{% load counter_tag %}
|
||||
{% block content %}
|
||||
<div class="content-section col-12">
|
||||
|
||||
<h3>Feiertage und Schließtage</i></b>{% if request.user.profile.showtooltips %} <small><i data-toggle="tooltip" data-placement="top" title="Erstellen Sie hier Feiertage und Tage, an denen Ihre Agentur generell geschlossen hat." class="far fa-question-circle"></i></small>{% endif %}
|
||||
<a class="btn btn-primary btn-sm" href="{% url 'tm-freedayadd' %}" style="float: right;"><i class="fas fa-plus"></i> Freier Tag</a>
|
||||
</h3>
|
||||
<hr>
|
||||
<div class="content-section col-12">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover" id="fdtable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Tag</th>
|
||||
<!--<th scope="col">Logo</th> -->
|
||||
{% if user|usergperm:"moduleorganizer" %}
|
||||
<th scope="col"> </th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="table_freedays">
|
||||
{% for fd in freedays %}
|
||||
<tr>
|
||||
<td>{{ fd.name }}</td>
|
||||
<td>{{ fd.day|date:"d. F Y" }}</td>
|
||||
<td>
|
||||
{% if user|usergperm:"moduleorganizer" %}
|
||||
<a style="float: right" class="btn btn-secondary btn-sm ml-2" href="{% url 'freeday-delete' fd.pk %}">
|
||||
<small><i class="fas fa-trash"></i></small>
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" tabindex="-1" role="dialog" id="freedays_initloadinginfo" data-backdrop="static">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Feiertage laden</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Sie haben das Modul Abwesenheitsplanung aktiviert. Sollen die Feiertage automatisch für die Postleitzahl {{request.user.profile.agency.plz}} geladen werden?</p>
|
||||
<small>Sie können Feiertage auch nachträglich laden und verändern.</small>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" onclick="javascript:loadFreeDays()">Feiertage laden</button>
|
||||
<button type="button" class="btn " data-dismiss="modal">Abbrechen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" tabindex="-1" role="dialog" id="plz_error" data-backdrop="static">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Postleitzahl nicht gefunden</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Die Postleitzahl Ihrer Agentur konnte nicht gefunden. Bitte gehen Sie in den Bereich Einstellungen auf den Reiter Agentur, um dort eine gültige Postleizahl zu hinterlegen.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Schließen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
$(document).ready(function(){
|
||||
{% if init_freedays %}
|
||||
$("#freedays_initloadinginfo").modal("toggle");
|
||||
{% endif %}
|
||||
$('#fdtable').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"
|
||||
},
|
||||
},
|
||||
"aaSorting": [],
|
||||
"buttons" : {
|
||||
"className" : "btn-danger"
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
function loadFreeDays()
|
||||
{
|
||||
$("#freedays_initloadinginfo").modal("hide");
|
||||
$.ajax(
|
||||
{
|
||||
type: "GET",
|
||||
url: "{% url 'dasettings-ajax' %}",
|
||||
data:{
|
||||
action : "initloadfreedays",
|
||||
},
|
||||
success: function( data )
|
||||
{
|
||||
if(data["success"]){
|
||||
window.location.href = "{% url 'tm-managemenetfreedays' %}";
|
||||
}
|
||||
else{
|
||||
$("#plz_error").modal("toggle");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
/* DATATABLES */
|
||||
.paginate_button {
|
||||
padding: 0px !important;
|
||||
border: 0px !important;
|
||||
}
|
||||
</style>
|
||||
{% endblock content %}
|
||||
|
|
@ -1,11 +1,45 @@
|
|||
{% load crispy_forms_tags %}
|
||||
<form method="POST" enctype="multipart/form-data" name="updateModSettingsTM">
|
||||
{% csrf_token %}
|
||||
{{modsettings_tm|crispy}}
|
||||
</form>
|
||||
{% for ab in modsettings_tm_abcat %}
|
||||
{{ab.name}}<br />
|
||||
{% endfor %}
|
||||
{% load counter_tag %}
|
||||
<h4 >Abwesenheitskategorien{% if request.user.profile.showtooltips %} <small><i data-toggle="tooltip" data-placement="top" title="Bearbeiten Sie hier Ihre Abwesenheitskategorien." class="far fa-question-circle"></i></small>{% endif %}
|
||||
<a class="btn btn-primary btn-sm" href="{% url 'abcat-add' %}" style="float: right;"><i class="fas fa-plus"></i> Kategorie</a>
|
||||
</h4>
|
||||
<small> </small>
|
||||
<table class="table table-hover mt-1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Bezeichnung</th>
|
||||
<th scope="col">Muss bestätigt werden</th>
|
||||
<th scope="col">Muss vertreten werden</th>
|
||||
<th scope="col">Urlaubstag</th>
|
||||
<th scope="col"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for ab in modsettings_tm_abcat %}
|
||||
<tr>
|
||||
<td><b>{{ab.name}}</b></td>
|
||||
<td>{% if ab.need_confirm %} Bedarf Bestätigung {% else %} Ohne Bestätigung {% endif %}</td>
|
||||
<td>{% if ab.need_rep %} Muss vertreten werden {% else %} Ohne Vertretung {% endif %}</td>
|
||||
<td>{% if ab.is_holiday %} Urlaub {% endif %}</td>
|
||||
<td>
|
||||
{% if user|usergperm:"moduleorganizer" %}
|
||||
<a style="float: right" class="btn btn-secondary btn-sm ml-2" href="{% url 'abcat-delete' ab.pk %}">
|
||||
<small>
|
||||
<i class="fas fa-trash"></i></small></a>
|
||||
|
||||
<a style="float: right" class="btn btn-secondary btn-sm " href="{% url 'abcat-update' ab.pk %}">
|
||||
<small>
|
||||
<i class="fas fa-pen"></i>
|
||||
</small></a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<small>Abwesenheitskategorien legen fest, wie sich eine Abwesenheit bzgl. Bestätigung durch einen Mitarbeiter mit entsprechenden Rechten und eines Vertretes verhält.</small>
|
||||
<hr>
|
||||
<a class="btn btn-primary mb-2" href="{% url 'tm-managemenetfreedays' %}">Feiertage bearbeiten</a>
|
||||
<script type="text/javascript">
|
||||
function updateTmSettings(){
|
||||
$.ajax(
|
||||
|
|
|
|||
|
|
@ -164,20 +164,22 @@
|
|||
<form method="POST" enctype="multipart/form-data" name="usertime_basic">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="form_type" value="contract">
|
||||
|
||||
<!--
|
||||
<p>Arbeitszeiten <small><i data-toggle="tooltip" data-placement="top" title="Legen Sie fest, an welchen Tagen dieser Mitarbeiter wie viele Stunden arbeitet." class="far fa-question-circle"></i></small></p>
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<tr>
|
||||
<td>{{usertime_form.wd_mo|as_crispy_field}}</td>
|
||||
<td>{{usertime_form.wd_tu|as_crispy_field}}</td>
|
||||
<td>{{usertime_form.wd_we|as_crispy_field}}</td>
|
||||
<td>{{usertime_form.wd_th|as_crispy_field}}</td>
|
||||
<td>{{usertime_form.wd_fr|as_crispy_field}}</td>
|
||||
<td>usertime_form.wd_mo|as_crispy_field</td>
|
||||
<td>usertime_form.wd_tu|as_crispy_field</td>
|
||||
<td>usertime_form.wd_we|as_crispy_field</td>
|
||||
<td>usertime_form.wd_th|as_crispy_field</td>
|
||||
<td>usertime_form.wd_fr|as_crispy_field</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<hr style="margin-top: -20px;">
|
||||
</div>
|
||||
<hr style="margin-top: -20px;">
|
||||
|
||||
-->
|
||||
<div class="col-5" >
|
||||
<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}}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from django.urls import path
|
|||
from django.contrib.auth import views as auth_views
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from . import views
|
||||
from .views import FreeDayDeleteView, AbsenceReasonDeleteView, AbsenceReasonUpdateView, AbsenceReasonAddView
|
||||
from .views import NewUserFirstStep, UserProfileUpdate, UserChangeMain
|
||||
'''
|
||||
Permissions definiert in models.py bei USERS und dann hier vor die View geschrieben!
|
||||
|
|
@ -25,4 +26,11 @@ urlpatterns = [
|
|||
#path('managnag/delfromagn/<int:agn>/<int:ag>', permission_required('users.agencynetwork')(views.DelFromAgn), name='delagfromagn'),
|
||||
path('modsettings/orga/', views.ModSettingsOrga, name="modsettings-orga"),
|
||||
path('modsettings/tm/', views.ModSettingsTm, name="modsettings-tm"),
|
||||
path('freedaysmn/', views.FreeDaysManagemenet, name="tm-managemenetfreedays"),
|
||||
path('freedaysmn/<int:initload>', views.FreeDaysManagemenet, name="tm-initload"),
|
||||
path('freedayadd/', views.FreeDayAdd, name="tm-freedayadd"),
|
||||
path('freedaydel/<int:pk>', FreeDayDeleteView.as_view(), name="freeday-delete"),
|
||||
path('abcatdel/<int:pk>', AbsenceReasonDeleteView.as_view(), name="abcat-delete"),
|
||||
path('abcatupdate/<int:pk>', AbsenceReasonUpdateView.as_view(), name="abcat-update"),
|
||||
path('abcatadd/', AbsenceReasonAddView.as_view(), name="abcat-add"),
|
||||
]
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
from django.shortcuts import render, redirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpResponseRedirect,HttpResponse, JsonResponse
|
||||
from .forms import UsersSelfChangeForm, UsersNotificationForm, AgencyGroupPerms, AgencyModulsForm, UserNewUserForm, UserProfileForm, AgencyNetworkForm, AgencyOrganigrammForm, UserTimeForm, AgencyTimeManagement
|
||||
from .forms import UsersSelfChangeForm, UsersNotificationForm, AgencyGroupPerms, AgencyModulsForm, UserNewUserForm, UserProfileForm, AgencyNetworkForm, AgencyOrganigrammForm, UserTimeForm, AgencyTimeManagement, AbsenceReasonForm
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import update_session_auth_hash
|
||||
from django.contrib.auth.forms import PasswordChangeForm
|
||||
|
|
@ -19,12 +19,18 @@ from users.models import Profile
|
|||
from areas.models import Areas
|
||||
from tasks.models import Tasks
|
||||
import webcolors
|
||||
from datetime import datetime
|
||||
import datetime
|
||||
from datetime import date
|
||||
from standards.models import Standards
|
||||
from timemanagement.models import AbsenceReason
|
||||
from timemanagement.models import AbsenceReason, FreeDays
|
||||
from django.core.mail import send_mail
|
||||
from django.conf import settings
|
||||
import re
|
||||
import re, os, csv, requests
|
||||
from django.templatetags.static import static
|
||||
from django.db.models import DateField
|
||||
from django.views.generic import DeleteView, UpdateView
|
||||
from timemanagement.forms import AddFreeDayForm
|
||||
from django.urls import reverse_lazy
|
||||
|
||||
def randomString(stringLength=10):
|
||||
"""Generate a random string of fixed length """
|
||||
|
|
@ -177,22 +183,138 @@ def SettingsAgency(request, context):
|
|||
context['agencyform'] = AgencyUpdateForm(instance=request.user.profile.agency)
|
||||
return render(request, 'dasettings/settings.html', context)
|
||||
|
||||
from django.db.models import F, Func, Value
|
||||
|
||||
@login_required
|
||||
def FreeDaysManagemenet(request, initload=0):
|
||||
if(initload==1):
|
||||
context = {
|
||||
'active_link' : 'dasettings',
|
||||
'init_freedays' : True
|
||||
}
|
||||
return render(request, 'dasettings/freedays_management.html', context)
|
||||
else:
|
||||
context = {
|
||||
'active_link' : 'dasettings',
|
||||
'freedays' : FreeDays.objects.filter(agency=request.user.profile.agency).order_by("-day")
|
||||
}
|
||||
return render(request, 'dasettings/freedays_management.html', context)
|
||||
|
||||
@login_required
|
||||
def FreeDayAdd(request):
|
||||
if request.POST:
|
||||
freedayform = AddFreeDayForm(request.POST, instance=request.user.profile.agency)
|
||||
if freedayform.is_valid():
|
||||
|
||||
fd = FreeDays(agency=request.user.profile.agency, day=freedayform.cleaned_data['day'], year=freedayform.cleaned_data['day'].year, name=freedayform.cleaned_data['name']).save()
|
||||
|
||||
messages.success(request, f'Freier Tag hinzugefügt')
|
||||
context = {
|
||||
"active_link" : "dasettings",
|
||||
}
|
||||
return redirect("tm-managemenetfreedays")
|
||||
else:
|
||||
messages.success(request, f'Fehler beim hinzufügen!')
|
||||
return redirect("tm-managemenetfreedays")
|
||||
else:
|
||||
context = {
|
||||
"active_link" : "dasettings",
|
||||
"form" : AddFreeDayForm()
|
||||
}
|
||||
return render(request, 'dasettings/freedays_add.html', context)
|
||||
|
||||
class FreeDayDeleteView(LoginRequiredMixin, DeleteView):
|
||||
model = FreeDays
|
||||
success_url = reverse_lazy('tm-managemenetfreedays')
|
||||
template_name = 'dasettings/freedays_confirm_delete.html'
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
response = super(FreeDayDeleteView, self).delete(request, *args, **kwargs)
|
||||
messages.success(request, f'Freier Tag wurde gelöscht!')
|
||||
return response
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(FreeDayDeleteView, self).get_context_data(**kwargs)
|
||||
context['active_link'] = 'dasettings'
|
||||
return context
|
||||
|
||||
|
||||
class AbsenceReasonDeleteView(LoginRequiredMixin, DeleteView):
|
||||
model = AbsenceReason
|
||||
success_url = reverse_lazy('dasettings')
|
||||
template_name = 'dasettings/absencereason_confirm_delete.html'
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
response = super(AbsenceReasonDeleteView, self).delete(request, *args, **kwargs)
|
||||
messages.success(request, f'Abwesenheitskategorie wurde gelöscht!')
|
||||
return response
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(AbsenceReasonDeleteView, self).get_context_data(**kwargs)
|
||||
context['active_link'] = 'dasettings'
|
||||
return context
|
||||
|
||||
class AbsenceReasonAddView(LoginRequiredMixin, CreateView):
|
||||
model = AbsenceReason
|
||||
success_url = reverse_lazy('dasettings')
|
||||
form_class = AbsenceReasonForm
|
||||
template_name = 'dasettings/absencereason_add.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({'active_link' : 'dasettings'})
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
# Send message to the site
|
||||
messages.success(self.request, f'Abwesenheitskategorie angelegt!')
|
||||
# SAVE OBJECTS TO SIGNALE!
|
||||
form.instance.agency = self.request.user.profile.agency
|
||||
return super().form_valid(form)
|
||||
|
||||
class AbsenceReasonUpdateView(LoginRequiredMixin, UpdateView):
|
||||
model = AbsenceReason
|
||||
template_name = 'dasettings/absencereason_update.html'
|
||||
success_url = reverse_lazy('dasettings')
|
||||
form_class = AbsenceReasonForm
|
||||
|
||||
def form_valid(self, form):
|
||||
# Send message to the site
|
||||
messages.success(self.request, f'Abwesenheitskategorie aktualisiert!')
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(AbsenceReasonUpdateView, self).get_context_data(**kwargs)
|
||||
context['active_link'] = 'dasettings'
|
||||
return context
|
||||
|
||||
@login_required
|
||||
def SettingsAgencyModuls(request, context):
|
||||
if request.POST.get("form_type") == "agencymodform":
|
||||
agencymoduleform = AgencyModulsForm(request.POST, instance=request.user.profile.agency)
|
||||
if agencymoduleform.is_valid():
|
||||
agencymoduleform.save()
|
||||
|
||||
agencymoduleform.save()
|
||||
|
||||
# Check, if Timemanagement is deactivate, to deactivate Zeiterfassung
|
||||
if(request.user.profile.agency.module_timemanagement == False):
|
||||
ag = request.user.profile.agency
|
||||
ag.module_timemanagement_ze = False
|
||||
|
||||
if(request.user.has_perm("users.modulesconfig")):
|
||||
FreeDays.objects.filter(agency=request.user.profile.agency).delete()
|
||||
|
||||
ag.save()
|
||||
|
||||
context['modulform'] = AgencyModulsForm(instance=request.user.profile.agency)
|
||||
messages.success(request, f'Moduleinstellungen aktualisiert!')
|
||||
return render(request, 'dasettings/settings.html', context)
|
||||
temp_freedays = FreeDays.objects.filter(agency=request.user.profile.agency)
|
||||
|
||||
if(request.user.profile.agency.module_timemanagement and len(temp_freedays) == 0):
|
||||
messages.success(request, f'Moduleinstellungen aktualisiert! Bitte prüfen Sie Ihre Feiertagseinstellungen')
|
||||
return redirect('tm-initload', 1)
|
||||
else:
|
||||
context['modulform'] = AgencyModulsForm(instance=request.user.profile.agency)
|
||||
messages.success(request, f'Moduleinstellungen aktualisiert!')
|
||||
return render(request, 'dasettings/settings.html', context)
|
||||
else:
|
||||
context['modulform'] = AgencyModulsForm(instance=request.user.profile.agency)
|
||||
messages.success(request, f'Fehler beim aktualisieren! Bitte wenden Sie sich an den Support.')
|
||||
|
|
@ -517,11 +639,64 @@ def SettingsAjaxRouter(request):
|
|||
else:
|
||||
data = {"userfullname" : tempuser.first_name + " " + tempuser.last_name}
|
||||
success = False
|
||||
elif request.method == 'GET' and request.GET['action'] == "initloadfreedays" :
|
||||
if(request.user.has_perm('users.modulesconfig')):
|
||||
temp_freedays = FreeDays.objects.filter(agency=request.user.profile.agency)
|
||||
|
||||
if(len(temp_freedays) == 0):
|
||||
tempdays_thisyear = loadingFreeDays(request.user.profile.agency.plz, date.today().year)
|
||||
tempdays_lastyear = loadingFreeDays(request.user.profile.agency.plz, date.today().year - 1)
|
||||
tempdays_nextyear = loadingFreeDays(request.user.profile.agency.plz, date.today().year + 1)
|
||||
|
||||
if(tempdays_thisyear != False):
|
||||
|
||||
for k in tempdays_lastyear.keys():
|
||||
tempdate = tempdays_lastyear[k]["datum"].split("-")
|
||||
FreeDays(agency=request.user.profile.agency, name=k, day=datetime.datetime(int(tempdate[0]),int(tempdate[1]),int(tempdate[2])), year=date.today().year-1).save()
|
||||
|
||||
for k in tempdays_thisyear.keys():
|
||||
tempdate = tempdays_thisyear[k]["datum"].split("-")
|
||||
FreeDays(agency=request.user.profile.agency, name=k, day=datetime.datetime(int(tempdate[0]),int(tempdate[1]),int(tempdate[2])), year=date.today().year).save()
|
||||
|
||||
for k in tempdays_nextyear.keys():
|
||||
tempdate = tempdays_nextyear[k]["datum"].split("-")
|
||||
FreeDays(agency=request.user.profile.agency, name=k, day=datetime.datetime(int(tempdate[0]),int(tempdate[1]),int(tempdate[2])), year=date.today().year+1).save()
|
||||
messages.success(request, f'Feiertage erfolgreich gespeichert!')
|
||||
success = True
|
||||
else:
|
||||
success = False
|
||||
else:
|
||||
data = {"userfullname" : tempuser.first_name + " " + tempuser.last_name}
|
||||
success = False
|
||||
else:
|
||||
success = False
|
||||
return JsonResponse({"success" : success, "data" : data})
|
||||
|
||||
|
||||
def loadingFreeDays(plz, year):
|
||||
# Getting land
|
||||
file_path = os.path.join(settings.STATIC_ROOT, 'users/extra/plz_short.csv')
|
||||
|
||||
land = False
|
||||
|
||||
with open(file_path, 'rt') as csvfile:
|
||||
filecsv = csv.reader(csvfile, delimiter=';')
|
||||
for row in filecsv:
|
||||
|
||||
if str(row[1]) == str(plz):
|
||||
land = row[6]
|
||||
break;
|
||||
|
||||
|
||||
|
||||
if(land != False):
|
||||
URL = "https://feiertage-api.de/api/"
|
||||
PARAMS = {'jahr':year,'nur_land':land}
|
||||
r = requests.get(url = URL, params = PARAMS)
|
||||
return r.json()
|
||||
else:
|
||||
return False
|
||||
|
||||
'''
|
||||
UserProfileUpdate
|
||||
|
||||
|
|
@ -577,6 +752,7 @@ def UserProfileUpdate(request, pk, newuser=0):
|
|||
elif(request.POST["form_type"] == "contract"):
|
||||
|
||||
formtosave = UserTimeForm(request.POST, instance=UserTime.objects.get(user=usertochange))
|
||||
|
||||
if(formtosave.is_valid()):
|
||||
messages.success(request, f'Vertragsdaten gespeichert!')
|
||||
formtosave.save()
|
||||
|
|
@ -865,7 +1041,6 @@ def DelAgInv(request, pk):
|
|||
|
||||
@login_required
|
||||
def DelFromAgn(request, agn, ag):
|
||||
|
||||
return redirect('managagn', agn)
|
||||
|
||||
@login_required
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -15,6 +15,7 @@ from datetime import datetime, timedelta
|
|||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
|
||||
############################################## DEV #####################################
|
||||
BASE_URL = "https://dev01.digitale-agentur.com/"
|
||||
CRONAPIKEY = "gCddsaz6NOnE9QbXZM5LasdEk122D"
|
||||
|
|
|
|||
|
|
@ -37,8 +37,7 @@
|
|||
<small>
|
||||
<i class="fas fa-pen"></i>
|
||||
</small></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@
|
|||
<div class="col-12">
|
||||
<ul class="nav nav-tabs" id="area_tabs" role="tablist" >
|
||||
{% for area in areas %}
|
||||
<li class="nav-item " >
|
||||
<!--<a class="nav-link " id="{{area.id}}" style="opacity:0.8;background-color: {{area.color}}; color: #FFFFFF" data-toggle="tab" href="#t_{{area.id}}" role="tab" aria-controls="t_{{area.id}}" aria-selected="false">{{area.name}}</a>-->
|
||||
<a class="nav-link " id="{{area.id}}" style="" data-toggle="tab" href="#t_{{area.id}}" role="tab" aria-controls="t_{{area.id}}" aria-selected="false">{{area.name}}</a>
|
||||
<li class="nav-item " >
|
||||
<a class="nav-link " id="{{area.id}}" style="border-bottom: 3px solid {{area.color}}; margin-bottom: -4px;" data-toggle="tab" href="#t_{{area.id}}" role="tab" aria-controls="t_{{area.id}}" aria-selected="false">{{area.name}}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if agencynetworks|length > 0 %}
|
||||
|
|
@ -26,7 +25,7 @@
|
|||
{% endif %}
|
||||
|
||||
<li class="nav-item {% if agencynetworks|length == 0 %}ml-auto{% endif %}">
|
||||
<a class="nav-link" id="userown" data-toggle="tab" href="#t_userown" role="tab" aria-controls="t_userown" aria-selected="false">Eigene Standards</a>
|
||||
<a class="nav-link" id="userown" data-toggle="tab" href="#t_userown" role="tab" aria-controls="t_userown" aria-selected="false">Eigene Standards</a>
|
||||
</li>
|
||||
{% if perms.users.standardmanager %}
|
||||
<li class="nav-item" style="float: left">
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -454,4 +454,23 @@ def getonlinestatuscolor(user):
|
|||
elif(user.profile.onlinestatus == 3):
|
||||
maincolor = "grey"
|
||||
|
||||
return maincolor
|
||||
return maincolor
|
||||
|
||||
tempday = False
|
||||
|
||||
@register.simple_tag
|
||||
def setMessageDayInfo(info):
|
||||
global tempday
|
||||
tempday = info.sendtime.day
|
||||
return ""
|
||||
|
||||
@register.simple_tag
|
||||
def getMessageDayInfo(info):
|
||||
global tempday
|
||||
|
||||
if info.sendtime.day > tempday:
|
||||
tempday = info.sendtime.day
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
from bootstrap_datepicker_plus import DatePickerInput
|
||||
from django import forms
|
||||
from django.forms import ModelForm
|
||||
from .models import Absence, AbsenceReason
|
||||
from .models import Absence, AbsenceReason, FreeDays
|
||||
from users.models import UserFullName
|
||||
|
||||
class AddAbsence(forms.ModelForm):
|
||||
|
|
@ -62,4 +62,26 @@ class ConfirmAbsenceForm(forms.ModelForm):
|
|||
|
||||
def __init__(self, *arg, **kwargs):
|
||||
super(ConfirmAbsenceForm, self).__init__(*arg, **kwargs)
|
||||
self.fields['confirm_info'].widget.attrs['rows'] = 3
|
||||
self.fields['confirm_info'].widget.attrs['rows'] = 3
|
||||
|
||||
|
||||
# NEW USER FORM
|
||||
class AddFreeDayForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = FreeDays
|
||||
labels = {
|
||||
"day" : "Datum",
|
||||
"name" : "Bezeichnung"
|
||||
}
|
||||
|
||||
fields = [
|
||||
"name", "day"
|
||||
]
|
||||
widgets = {
|
||||
'day': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'}),
|
||||
}
|
||||
|
||||
def __init__(self, *arg, **kwargs):
|
||||
super(AddFreeDayForm, self).__init__(*arg, **kwargs)
|
||||
self.fields['name'].required = True
|
||||
self.fields['day'].required = True
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from django.db import models
|
|||
from django.contrib.auth.models import User
|
||||
from users.models import Agency
|
||||
from django.core.exceptions import ValidationError
|
||||
from colorful.fields import RGBColorField
|
||||
|
||||
# Create your models here.
|
||||
class Workday(models.Model):
|
||||
|
|
@ -23,7 +24,8 @@ class AbsenceReason(models.Model):
|
|||
name = models.CharField(default="", max_length=200)
|
||||
need_confirm = models.BooleanField(default=True)
|
||||
need_rep = models.BooleanField(default=True)
|
||||
is_holiday = models.BooleanField(default=True)
|
||||
is_holiday = models.BooleanField(default=True)
|
||||
color = RGBColorField(colors=['#FFB900', '#E74856', '#0078D7', '#0099BC', '#7A7574'], default='#0099BC', blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.name}'
|
||||
|
|
@ -31,8 +33,8 @@ class AbsenceReason(models.Model):
|
|||
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 = models.DateField(default=None, null=True, blank=True)
|
||||
end = models.DateField(default=None, null=True, blank=True)
|
||||
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)
|
||||
|
|
@ -53,7 +55,7 @@ class Absence(models.Model):
|
|||
|
||||
class FreeDays(models.Model):
|
||||
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
|
||||
day = models.DateTimeField(default=None, null=True, blank=True)
|
||||
day = models.DateField(default=None, null=True, blank=True)
|
||||
name = models.CharField(default="", max_length=200)
|
||||
year = models.IntegerField(default=0)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ Informationen: {{absence.info}}<br />
|
|||
{{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>
|
||||
<button type="button" class="btn btn-primary" onclick="javascript:noconfirmAbsence({{absence.pk}})">Ablehnen</button>
|
||||
<button type="button" class="btn" onclick="javascript:confirmAbsence({{absence.pk}})">Annehmen</button>
|
||||
</div>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
{% if isfree %}
|
||||
<!-- FREEDAYS -->
|
||||
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_free" style="background-color: #e74a3b" data-toggle="tooltip" data-placement="top" title="{{isfreename}}">
|
||||
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_free" style="background-color: #9C9C9C" data-toggle="tooltip" data-placement="top" title="{{isfreename}}">
|
||||
{% elif da.weekday == 5 or da.weekday == 6 %}
|
||||
<!-- WEEKEND -->
|
||||
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_free" style="background-color: #d3d3d3">
|
||||
|
|
@ -46,9 +46,9 @@
|
|||
class="partialfilling"
|
||||
style="background-size: 50% 100%"
|
||||
{% else %}
|
||||
style="background-color: #36b9cc"
|
||||
style="background-color: {{abday.reason.color}}"
|
||||
{% 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 %} ">
|
||||
data-toggle="tooltip" data-placement="top" title="{{abday.reason.name}} {% if abday.representator != None %} | Vertreter {{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 %}
|
||||
|
|
@ -58,8 +58,8 @@
|
|||
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 %} ">
|
||||
style="background-color: {{abday.reason.color}}"
|
||||
{% endif %} data-toggle="tooltip" data-placement="top" title="Abwesend {% if abday.representator != None %} | Vertreter {{abday.representator.first_name}} {{abday.representator.last_name}} {% endif %} ">
|
||||
{% endif %}
|
||||
{% elif abday.confirm_status == 1 %}
|
||||
{% if user|usergperm:"absencemanager" %}
|
||||
|
|
@ -145,12 +145,12 @@
|
|||
{% getsomemonths as months %}
|
||||
{% for m in months %}
|
||||
<button class="btn
|
||||
{% if forloop.counter == activemonth %} btn-secondary {% else %} btn-primary {% endif %}
|
||||
{% if forloop.counter == activemonth %} btn-primary {% else %} btn-secondary {% 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>
|
||||
<button type="button" class="btn btn-primary " data-dismiss="modal">Schließen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -190,6 +190,7 @@ document.getElementById("id_reason").addEventListener("change", function(){
|
|||
rid : reasonid
|
||||
},
|
||||
success : function(data){
|
||||
//CHANGE REPRESENTOR
|
||||
if(data["isreq"]){
|
||||
$("#id_representator").prop('required',true);
|
||||
$("label[for*='id_representator']").html("Vertreter*");
|
||||
|
|
@ -198,6 +199,16 @@ document.getElementById("id_reason").addEventListener("change", function(){
|
|||
$("#id_representator").prop('required',false);
|
||||
$("label[for*='id_representator']").html("Vertreter");
|
||||
}
|
||||
//CHANGE HOLIDAYCOUNT
|
||||
if(data["isholiday"] == false){
|
||||
$("#noholidays_container").show();
|
||||
$("#restholidays_container").hide();
|
||||
}
|
||||
else{
|
||||
$("#noholidays_container").hide();
|
||||
$("#restholidays_container").show();
|
||||
recalculateChoosenDaysAfterInit();
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
|
@ -261,7 +272,6 @@ else{
|
|||
user_has_right = false;
|
||||
}
|
||||
|
||||
|
||||
function recalculateChoosenDays(){
|
||||
seldates = [];
|
||||
userid = "";
|
||||
|
|
@ -276,17 +286,84 @@ function recalculateChoosenDays(){
|
|||
$("#div_id_end").show();
|
||||
$("#div_id_end_ishalf").show();
|
||||
|
||||
$("#startAbsenceProgress").modal("toggle");
|
||||
$("#id_start").data("DateTimePicker").date(date_start);
|
||||
$("#id_end").data("DateTimePicker").date(date_end);
|
||||
$("#id_start").data("DateTimePicker").date(date_start);
|
||||
$("#id_end").data("DateTimePicker").date(date_end);
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "{% url 'tm-ajax' %}",
|
||||
data:{
|
||||
action : "getrestholidays",
|
||||
userid : userid,
|
||||
startdate : date_start.getFullYear() + "__" + (date_start.getMonth()+1) + "__" + date_start.getDate(),
|
||||
enddate : date_end.getFullYear() + "__" + (date_end.getMonth()+1) + "__" + date_end.getDate(),
|
||||
start_half : $("#id_start_ishalf").prop("checked"),
|
||||
end_half : $("#id_end_ishalf").prop("checked"),
|
||||
},
|
||||
success : function(data){
|
||||
|
||||
$("#restholidays").html(data["restholiday"])
|
||||
$("#startAbsenceProgress").modal("show");
|
||||
|
||||
if(seldates.length == 1){
|
||||
$("#div_id_end").hide();
|
||||
$("#div_id_end_ishalf").hide();
|
||||
}
|
||||
if(seldates.length == 1){
|
||||
$("#div_id_end").hide();
|
||||
$("#div_id_end_ishalf").hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function recalculateChoosenDaysAfterInit(){
|
||||
|
||||
new_start = $("#id_start").datepicker().val();
|
||||
new_end = $("#id_end").datepicker().val();
|
||||
|
||||
new_start = new_start.split(".");
|
||||
new_end = new_end.split(".");
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "{% url 'tm-ajax' %}",
|
||||
data:{
|
||||
action : "getrestholidays",
|
||||
userid : userid,
|
||||
startdate : new_start[2] + "__" + new_start[1] + "__" + new_start[0],
|
||||
enddate : new_end[2] + "__" + new_end[1] + "__" + new_end[0],
|
||||
start_half : $("#id_start_ishalf").prop("checked"),
|
||||
end_half : $("#id_end_ishalf").prop("checked"),
|
||||
},
|
||||
success : function(data){
|
||||
|
||||
$("#restholidays").html(data["restholiday"])
|
||||
//$("#startAbsenceProgress").modal("show");
|
||||
|
||||
if(seldates.length == 1){
|
||||
$("#div_id_end").hide();
|
||||
$("#div_id_end_ishalf").hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
/*
|
||||
CHANGE LISTENER
|
||||
*/
|
||||
$("#id_start").blur(function(){
|
||||
recalculateChoosenDaysAfterInit();
|
||||
})
|
||||
|
||||
$("#id_end").blur(function(){
|
||||
recalculateChoosenDaysAfterInit();
|
||||
})
|
||||
|
||||
$("#id_start_ishalf").change(function(){
|
||||
recalculateChoosenDaysAfterInit();
|
||||
})
|
||||
|
||||
$("#id_end_ishalf").change(function(){
|
||||
recalculateChoosenDaysAfterInit();
|
||||
})
|
||||
|
||||
|
||||
$( function() {
|
||||
$( "#timetable_team" ).selectable({
|
||||
filter: 'td',
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
<div class="content-section col-12">
|
||||
<h3>Zeiterfassung <small><i data-toggle="tooltip" data-placement="top" title="Bearbeiten Sie hier Ihre Zeiterfassung." class="far fa-question-circle"></i></small></h3>
|
||||
<hr>
|
||||
|
||||
<div class="table-responsive ">
|
||||
<table class="table table-hover" id="table_timemanagement" >
|
||||
<thead>
|
||||
|
|
@ -17,10 +16,8 @@
|
|||
<th scope="col">Pausen</th>
|
||||
<th scope="col">Gesamtzeit</th>
|
||||
<th scope="col">Abwesenheit</th>
|
||||
<th scope="col">Gleitzeit in h</th>
|
||||
|
||||
<th scope="col">Gleitzeit in h</th>
|
||||
<th scope="col"> </th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="table_contacts" >
|
||||
|
|
@ -74,8 +71,8 @@
|
|||
Möchten Sie wirklich den Arbeitstag am {{workday.start|date:"d.m"}} löschen?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-danger" id="dodel_{{workday.pk}}" >Löschen</button>
|
||||
<button type="button" class="btn btn-success" data-dismiss="modal">Abbrechen</button>
|
||||
<button class="btn btn-primary" id="dodel_{{workday.pk}}" >Löschen</button>
|
||||
<button type="button" class="btn" data-dismiss="modal">Abbrechen</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@
|
|||
|
||||
});
|
||||
</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">
|
||||
|
|
@ -66,8 +65,8 @@
|
|||
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>
|
||||
<button class="btn btn-primary" id="ab_{{ab.pk}}" >Löschen</button>
|
||||
<button type="button" class="btn" data-dismiss="modal">Abbrechen</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -70,9 +70,6 @@
|
|||
<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">
|
||||
|
|
@ -86,6 +83,31 @@
|
|||
<div class="modal-body">
|
||||
<h5>Abwesenheit für <b><span id="username_abscence"></span></b> beantragen</h5>
|
||||
<hr>
|
||||
<div id="restholidays_container">
|
||||
<!--<h6>Verbleibender Urlaub <span id="holidayyear">: <span id="restholidays">Lade...</span></h6>
|
||||
|
||||
Drei Zahlen berechnet Resturlaub, Verbleibender aktuelles Jahr, Nächstes Jahr
|
||||
|
||||
Drei zahlen in Info-Icon, berechnet aus Resturlaub und aktuelles Jahr die Zahl zeigen!
|
||||
|
||||
Runterklappdinger für Jahresaufteilung
|
||||
|
||||
Beim ändern von Urlaubstagen
|
||||
|
||||
2020 2021 2022
|
||||
30 32 30
|
||||
|
||||
Agentur: 30
|
||||
|
||||
Abwesenheiten - Meine Abwesenheiten, Übersicht über aktuelle Tage, Resturlaub in Jahren usw.
|
||||
Bezug zu Urlaubsjahren mit Daten für Resturlaubsberechnung
|
||||
-->
|
||||
<h6>Resturlaub Urlaub 2019: <span id="restholidays">Lade...</span></h6>
|
||||
</div>
|
||||
<div id="noholidays_container" style="display: none;">
|
||||
<h6>Abwesenheitsgrund ohne Urlaubsanspruch</h6>
|
||||
</div>
|
||||
<hr>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="form_type" value="absenceform">
|
||||
{% csrf_token %}
|
||||
|
|
@ -94,7 +116,7 @@
|
|||
</div>
|
||||
<div class="modal-footer">
|
||||
<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" data-dismiss="modal">Abbrechen</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -135,7 +157,7 @@
|
|||
</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>
|
||||
<button type="button" class="btn btn" data-dismiss="modal">Abbrechen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -362,4 +384,38 @@ $('#absencetabs a').on('click', function (e) {
|
|||
{% else %}
|
||||
<h3>Das Modul Abwesenheits- und Zeiterfassung wurde in ihrer Agentur deaktiviert.</h3>
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
{% if missinguserdata|length > 0 %}
|
||||
<div class="modal fade" tabindex="-1" role="dialog" data-backdrop="static" id="missingdatainfo">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Fehlende Mitarbeiterinformationen</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Zur Berechnung der Abwesenheiten und Urlaub müssen alle Mitarbeiter ein Einstellungsdatum haben. Dies fehlt bei folgenden Mitarbeitern:</p>
|
||||
{% for m in missinguserdata %}
|
||||
{{m.first_name}} {{m.last_name}}<br />
|
||||
{% endfor %}
|
||||
<br />
|
||||
Bitte ergänzen Sie das Datum, da sonst keine Urlaubstage berechnet werden können.
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Schließen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
$("#missingdatainfo").modal("toggle");
|
||||
})
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{% endblock content %}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ import calendar
|
|||
from .forms import AddAbsence, ConfirmAbsenceForm
|
||||
from django.contrib import messages
|
||||
from users.models import UserFullName
|
||||
|
||||
from users.models import UserTime
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
def loadingFreeDays(plz):
|
||||
|
|
@ -143,11 +144,20 @@ def AbsenceManagmenet(request, activemonth=False, activeyear=False):
|
|||
else:
|
||||
prevyear = activeyear
|
||||
|
||||
missinguserdata = []
|
||||
#CHECK, ob alle nötigen Infos zur Urlaubsberechnung vorliegen
|
||||
for user in User.objects.filter(profile__agency=request.user.profile.agency):
|
||||
tempTime = UserTime.objects.get(user=user)
|
||||
|
||||
if(tempTime.startdate == None):
|
||||
missinguserdata.append(user)
|
||||
|
||||
context = {
|
||||
"active_link" : "abscence",
|
||||
"usersofagency" : User.objects.filter(profile__agency=request.user.profile.agency).order_by("-last_name"),
|
||||
"days_this_month" : get_datetime_range(activeyear,activemonth),
|
||||
"nextmonth" : nextmonth,
|
||||
"missinguserdata" : missinguserdata,
|
||||
"prevmonth" : prevmonth,
|
||||
"nextyear" : nextyear,
|
||||
"prevyear" : prevyear,
|
||||
|
|
@ -294,12 +304,21 @@ def TimeAjax(request):
|
|||
prevyear = activeyear - 1
|
||||
else:
|
||||
prevyear = activeyear
|
||||
|
||||
missinguserdata = []
|
||||
#CHECK, ob alle nötigen Infos zur Urlaubsberechnung vorliegen
|
||||
for user in User.objects.filter(profile__agency=request.user.profile.agency):
|
||||
tempTime = UserTime.objects.get(user=user)
|
||||
|
||||
if(tempTime.startdate == None):
|
||||
missinguserdata.append(user)
|
||||
|
||||
|
||||
context = {
|
||||
"active_link" : "abscence",
|
||||
"usersofagency" : User.objects.filter(profile__agency=request.user.profile.agency).order_by("-last_name"),
|
||||
"days_this_month" : get_datetime_range(activeyear,activemonth),
|
||||
"activemonth" : activemonth,
|
||||
"missinguserdata" : missinguserdata,
|
||||
"activeyear" : activeyear,
|
||||
"nextmonth" : nextmonth,
|
||||
"prevmonth" : prevmonth,
|
||||
|
|
@ -314,7 +333,8 @@ def TimeAjax(request):
|
|||
if(reason.agency == request.user.profile.agency):
|
||||
data = {
|
||||
"success" : True,
|
||||
"isreq" : reason.need_rep
|
||||
"isreq" : reason.need_rep,
|
||||
"isholiday" : reason.is_holiday
|
||||
}
|
||||
else:
|
||||
data = {
|
||||
|
|
@ -357,6 +377,67 @@ def TimeAjax(request):
|
|||
"activemonth" : request.GET["activemonth"],
|
||||
"activeyear" : request.GET["activeyear"]
|
||||
}
|
||||
elif request.GET["action"] == "getrestholidays":
|
||||
user = User.objects.get(pk=request.GET["userid"])
|
||||
usertimedata = UserTime.objects.get(user=user)
|
||||
today = date.today()
|
||||
if(user.profile.agency == request.user.profile.agency and request.user.has_perm("users.absencemanager")):
|
||||
|
||||
# Alle Abwesenheiten laden, die bestätigt oder angefragt sind UND Urlaub sind
|
||||
absences = Absence.objects.filter(user=user, confirm_status=0, reason__is_holiday=True) | Absence.objects.filter(user=user, confirm_status=1, reason__is_holiday=True)
|
||||
|
||||
start_day = request.GET["startdate"].split("__")
|
||||
start_day_ob = datetime.date(int(start_day[0]), int(start_day[1]), int(start_day[2]))
|
||||
|
||||
end_day = request.GET["enddate"].split("__")
|
||||
end_day_obj = datetime.date(int(end_day[0]), int(end_day[1]), int(end_day[2]))
|
||||
|
||||
start_half = True
|
||||
if request.GET["start_half"] == "false":
|
||||
start_half = False
|
||||
|
||||
end_half = True
|
||||
if request.GET["end_half"] == "false":
|
||||
end_half = False
|
||||
|
||||
|
||||
# USER HAS NO ABSENCE
|
||||
if(len(absences) == 0):
|
||||
# Hier Urlaubstage bei Einstellung mit berücksichtigen
|
||||
if(start_day_ob.year == usertimedata.startdate.year):
|
||||
|
||||
data = {
|
||||
"restholiday" : calculateHolidays(request, usertimedata.holiday_start + usertimedata.holiday, start_day_ob, end_day_obj, start_half, end_half)
|
||||
}
|
||||
# Hier Einstellungstage irrelevant und da noch keine Abwesenheiten eingetragen wurden, einfach aus Profil laden
|
||||
else:
|
||||
data = {
|
||||
"restholiday" : calculateHolidays(request, usertimedata.holiday, start_day_ob, end_day_obj, start_half, end_half)
|
||||
}
|
||||
# ABSENCE-Data found, calculating rest-Days
|
||||
else:
|
||||
finalholidays = 0
|
||||
|
||||
# Besteht noch Anspruch aus Einstellungsjahr?
|
||||
if(start_day_ob.year == usertimedata.startdate.year):
|
||||
finalholidays += usertimedata.holiday_start + usertimedata.holiday
|
||||
# Hier Einstellungstage irrelevant und da noch keine Abwesenheiten eingetragen wurden, einfach normal
|
||||
else:
|
||||
finalholidays += usertimedata.holiday
|
||||
|
||||
# Berechne pro Abwesenheits die verbrauchen Urlaubstage
|
||||
for absence in absences:
|
||||
finalholidays -= calculatingHolidaysByAbsence(request, absence)
|
||||
|
||||
data = {
|
||||
"restholiday" : calculateHolidays(request, finalholidays, start_day_ob, end_day_obj, start_half, end_half)
|
||||
}
|
||||
# REQUEST USER NO RIGHTS
|
||||
else:
|
||||
data = {
|
||||
"success" : False
|
||||
}
|
||||
# GET REQUEST ACTION UNKNOWN
|
||||
else:
|
||||
data = {
|
||||
"success" : False
|
||||
|
|
@ -365,3 +446,77 @@ def TimeAjax(request):
|
|||
return JsonResponse(data)
|
||||
|
||||
|
||||
'''
|
||||
|
||||
Gibt einen Integer zurück, welcher die Urlaubstage von Start zu Enddatum auf der Grundlage von Freitagen berechnet.
|
||||
Berücksichtigt sowohl Wochenende als auch in der Agentur hinterlegte Freitage/Schließtage
|
||||
|
||||
'''
|
||||
@login_required
|
||||
def calculateHolidays(request, restdays, start, end, start_half, end_half):
|
||||
allfreedays = FreeDays.objects.filter(agency=request.user.profile.agency)
|
||||
if(end == start):
|
||||
if(start_half):
|
||||
return restdays - 0.5
|
||||
else:
|
||||
return restdays - 1
|
||||
else:
|
||||
if(end < start):
|
||||
return False
|
||||
else:
|
||||
counter = 0
|
||||
if(start_half):
|
||||
counter -= 0.5
|
||||
if(end_half):
|
||||
counter -= 0.5
|
||||
|
||||
weekdays = [6,7]
|
||||
freedaycounter = 0
|
||||
for dt in daterange(start, end):
|
||||
|
||||
if dt.isoweekday() not in weekdays:
|
||||
counter += 1
|
||||
for freeday in allfreedays.all():
|
||||
if(dt == freeday.day):
|
||||
freedaycounter += 1
|
||||
|
||||
|
||||
return restdays - counter + freedaycounter
|
||||
|
||||
@login_required
|
||||
def calculatingHolidaysByAbsence(request, absence):
|
||||
# Freitage laden, die innerhalb der gewünschten Abwesenheit liegen
|
||||
allfreedays = FreeDays.objects.filter(agency=request.user.profile.agency, day__gt=absence.start, day__lt=absence.end)
|
||||
finalholidayinabsence = 0
|
||||
|
||||
# Start und Ende gleich, nur ein Tag. Checken, ob Halber Tag
|
||||
if(absence.start == absence.end):
|
||||
if(absence.start_ishalf):
|
||||
finalholidayinabsence = 0.5
|
||||
else:
|
||||
finalholidayinabsence = 1
|
||||
return finalholidayinabsence
|
||||
|
||||
else:
|
||||
if(absence.start_ishalf):
|
||||
finalholidayinabsence -= 0.5
|
||||
if(absence.end_ishalf):
|
||||
finalholidayinabsence -= 0.5
|
||||
|
||||
weekdays = [6,7]
|
||||
freedaycounter = 0
|
||||
for dt in daterange(absence.start, absence.end):
|
||||
|
||||
if dt.isoweekday() not in weekdays:
|
||||
finalholidayinabsence += 1
|
||||
for freeday in allfreedays.all():
|
||||
# FREEDAY FOUND
|
||||
if(dt == freeday.day):
|
||||
freedaycounter += 1
|
||||
|
||||
return finalholidayinabsence - freedaycounter
|
||||
|
||||
# Gibt die Woche als Wochentage zurück
|
||||
def daterange(date1, date2):
|
||||
for n in range(int ((date2 - date1).days)+1):
|
||||
yield date1 + timedelta(n)
|
||||
|
|
@ -268,7 +268,7 @@ class UserTime(models.Model):
|
|||
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))
|
||||
startdate = models.DateTimeField(default=None, blank=True, null=True)
|
||||
startdate = models.DateField(default=None, blank=True, null=True)
|
||||
|
||||
|
||||
'''
|
||||
|
|
|
|||
|
|
@ -25,38 +25,43 @@ from datetime import date
|
|||
import channels.layers
|
||||
from asgiref.sync import async_to_sync
|
||||
|
||||
def loadingFreeDays(plz):
|
||||
def loadingFreeDays(plz, year):
|
||||
# Getting land
|
||||
|
||||
file_path = os.path.join(settings.STATIC_ROOT, 'users/extra/plz_short.csv')
|
||||
|
||||
land = False
|
||||
|
||||
with open(file_path, 'rt') as csvfile:
|
||||
filecsv = csv.reader(csvfile, delimiter=';')
|
||||
filecsv = csv.reader(csvfile, delimiter=';')
|
||||
for row in filecsv:
|
||||
if row[1] == plz:
|
||||
|
||||
if str(row[1]) == str(plz):
|
||||
land = row[6]
|
||||
break;
|
||||
|
||||
|
||||
if(land != False):
|
||||
# CALCULATE FREEDAYS AS JSON
|
||||
year = today = date.today().year
|
||||
|
||||
|
||||
URL = "https://feiertage-api.de/api/"
|
||||
PARAMS = {'jahr':year,'nur_land':land}
|
||||
r = requests.get(url = URL, params = PARAMS)
|
||||
r = requests.get(url = URL, params = PARAMS)
|
||||
return r.json()
|
||||
else:
|
||||
return False
|
||||
|
||||
# CHECK SOMETHING WHEN USER LOGGED IN
|
||||
@receiver(signal=user_logged_in, sender=User)
|
||||
def checkForWorkDays(sender, user, request, **kwargs):
|
||||
def checkForFreeDays(sender, user, request, **kwargs):
|
||||
user.profile.onlinestatus = 0
|
||||
user.save()
|
||||
today = date.today()
|
||||
|
||||
if len(FreeDays.objects.filter(agency=user.profile.agency, year=today.year+2)) == 0:
|
||||
tempdays = loadingFreeDays(user.profile.agency.plz, today.year+2)
|
||||
if(tempdays != False):
|
||||
for k in tempdays.keys():
|
||||
tempdate = tempdays[k]["datum"].split("-")
|
||||
FreeDays(agency=user.profile.agency, name=k, day=datetime.datetime(int(tempdate[0]),int(tempdate[1]),int(tempdate[2])), year=date.today().year+2).save()
|
||||
|
||||
'''
|
||||
wd = Workday.objects.filter(user=user, end=None, start__day__lte=today.day)
|
||||
for d in wd:
|
||||
d.end = datetime.datetime(d.start.year, d.start.month, d.start.day, 23, 59, 00)
|
||||
|
|
@ -65,7 +70,7 @@ def checkForWorkDays(sender, user, request, **kwargs):
|
|||
if(b.end == None):
|
||||
b.end = datetime.datetime(d.start.year, d.start.month, d.start.day, 23, 59, 00)
|
||||
b.save()
|
||||
|
||||
'''
|
||||
# CHECK SOMETHING WHEN USER LOGGED IN
|
||||
@receiver(signal=user_logged_in, sender=User)
|
||||
def checkDefaultAbsenceReasons(sender, user, request, **kwargs):
|
||||
|
|
@ -87,25 +92,6 @@ def checkDefaultAbsenceReasons(sender, user, request, **kwargs):
|
|||
|
||||
|
||||
|
||||
|
||||
@receiver(signal=user_logged_in, sender=User)
|
||||
def checkAllFreeDaysLoaded(sender, user, request, **kwargs):
|
||||
pass
|
||||
'''
|
||||
allFreeDays = FreeDays.objects.filter(agency=user.profile.agency, year=date.today().year)
|
||||
# NO DAYS FOR THIS YEAR
|
||||
if(len(allFreeDays) == 0):
|
||||
tempdays = loadingFreeDays(user.profile.agency.plz)
|
||||
for k in tempdays.keys():
|
||||
tempdate = tempdays[k]["datum"].split("-")
|
||||
FreeDays(agency=user.profile.agency, name=k, day=datetime.datetime(int(tempdate[0]),int(tempdate[1]),int(tempdate[2])), year=date.today().year).save()
|
||||
'''
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Deletes all Notifications added to to delete news
|
||||
@receiver(pre_delete, sender=News)
|
||||
def del_news_notifications(sender, instance, **kwargs):
|
||||
|
|
|
|||
|
|
@ -57,10 +57,9 @@
|
|||
|
||||
<!-- Page Wrapper -->
|
||||
<div id="wrapper">
|
||||
<!-- Sidebar -->
|
||||
|
||||
<ul class=" bg-gray-900 sidebar sidebar-dark accordion fixed-top" id="accordionSidebar">
|
||||
|
||||
|
||||
<!-- Sidebar -->
|
||||
<ul class=" bg-gray-900 sidebar sidebar-dark accordion fixed-top" id="accordionSidebar">
|
||||
<!-- Sidebar - Brand -->
|
||||
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="{% url 'users-dashboard' %}">
|
||||
<i class="fas fa-laptop"></i>
|
||||
|
|
@ -229,7 +228,7 @@
|
|||
</a>
|
||||
</li>
|
||||
|
||||
<div style="" class="sidebar-heading">
|
||||
<div style="" class="sidebar-heading ">
|
||||
<!--<span style="float: left"><small>poweder by </small><img src="{% static 'users/img/VVE-Logo.png' %}" width="27%" class="mb-2"></span>-->
|
||||
<img src="{% static 'users/img/VVE-Logo.png' %}" width="27%" class="mb-2">
|
||||
<br />
|
||||
|
|
@ -258,8 +257,14 @@
|
|||
<div id="content-wrapper">
|
||||
<!-- Main Content -->
|
||||
<!-- Topbar -->
|
||||
<div class="alert alert-info alert-dismissible" style="margin-bottom: -2px; text-align: center;"> <i class="fas fa-info-circle"></i>
|
||||
Sie vertreten bis zum XXXX Darius Hannemann.
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
</div>
|
||||
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
||||
|
||||
|
||||
|
||||
<!-- Sidebar Toggle (Topbar) -->
|
||||
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3" onclick="javascript:toggleSidebar()">
|
||||
<i class="fa fa-bars"></i>
|
||||
|
|
@ -464,9 +469,7 @@
|
|||
|
||||
|
||||
<link href="{% static 'users/css/custom.css' %}" type="text/css" rel="stylesheet">
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue