Modulcommit Zeiterfassung
This commit is contained in:
parent
fe4115df40
commit
f45e761dea
|
|
@ -5,6 +5,16 @@ from users.models import AgencyGroup, Agency, Profile, AgencyJob, AgencyNetwork,
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from bootstrap_datepicker_plus import DatePickerInput
|
from bootstrap_datepicker_plus import DatePickerInput
|
||||||
|
|
||||||
|
class AgencyTimeManagement(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Agency
|
||||||
|
|
||||||
|
fields = ['module_timemanagement_ze']
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
'module_timemanagement_ze' : "Zeiterfassung aktivieren"
|
||||||
|
}
|
||||||
|
|
||||||
class AgencyOrganigrammForm(forms.ModelForm):
|
class AgencyOrganigrammForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Agency
|
model = Agency
|
||||||
|
|
@ -97,7 +107,7 @@ class AgencyModulsForm(forms.ModelForm):
|
||||||
'module_files' : "Dateien",
|
'module_files' : "Dateien",
|
||||||
'module_organigramm' : "Organigramm",
|
'module_organigramm' : "Organigramm",
|
||||||
'module_messages' : "Mitteilungen",
|
'module_messages' : "Mitteilungen",
|
||||||
'module_timemanagement' : "Zeiterfassung",
|
'module_timemanagement' : "Abwesenheits- und Zeiterfassung",
|
||||||
}
|
}
|
||||||
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_timemanagement']
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,26 +2,65 @@
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
{% load counter_tag %}
|
{% load counter_tag %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="content-section col-8">
|
<div class="content-section col-9">
|
||||||
<h3>Agenturverbund {{agn.name}} beitreten</h3>
|
<h3>Agenturverbund {{agn.name}} beitreten</h3>
|
||||||
<hr>
|
<hr>
|
||||||
<h4>Verbundinfos</h4>
|
|
||||||
{% getsumofallag agn.pk as agsum %}
|
<div class="card">
|
||||||
{% getsumofallstandards agn.pk as ag_standardsum %}
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Verbundinfos</h5>
|
||||||
|
{% getsumofallag agn.pk as agsum %}
|
||||||
|
{% getsumofallstandards agn.pk as ag_standardsum %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row mt-3">
|
|
||||||
<div class="col-8">
|
|
||||||
<h6><b>Gründeragentur</b> {{agn.creator_agency.name }}</h6>
|
<h6><b>Gründeragentur</b> {{agn.creator_agency.name }}</h6>
|
||||||
<h6><b>Gegründet von</b> {{agn.creator.first_name }} {{agn.creator.last_name }}</h6>
|
<h6><b>Gegründet von</b> {{agn.creator.first_name }} {{agn.creator.last_name }}</h6>
|
||||||
<h6><b>Grüdungsdatum</b> {{agn.created_on }}</h6>
|
<h6><b>Grüdungsdatum</b> {{agn.created_on }}</h6>
|
||||||
<h6><b>Agenturen</b> {{agsum}}</h6>
|
<h6><b>Agenturen</b> {{agsum}}</h6>
|
||||||
<h6><b>Standards</b> {{agn.standards.all|length}}</h6>
|
<h6><b>Standards</b> {{agn.standards.all|length}}</h6>
|
||||||
<h6><b>Letzte Aktivität</b> {{agn.lastactivity}}</h6>
|
<h6><b>Letzte Aktivität</b> {{agn.lastactivity}}</h6>
|
||||||
</div>
|
|
||||||
</div>
|
{% if agn.publicjoin %}
|
||||||
{% if agn.publicjoin %}
|
<hr>
|
||||||
Das Beitreten zu diesem Verbund ist öffentlich. Sie können daher sofort nach Beitritt die geteilten Informationen einsehen, aber selber keine Informationen in den Verbund teilen.
|
Das Beitreten zu diesem Verbund ist öffentlich. Sie können daher sofort nach Beitritt die geteilten Informationen einsehen, aber selber keine Informationen in den Verbund teilen.
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<hr>
|
||||||
|
<h5>Agenturen im Verbund</h5>
|
||||||
|
<b>Verwaltende Agenturen:</b>
|
||||||
|
{% for a in agn.adminagencys.all %}
|
||||||
|
{{a.name}}{% if forloop.counter < agn.adminagencys.all|length %},{% endif %}{% endfor %}
|
||||||
|
<br />
|
||||||
|
<a href="#\" onclick="javascript:showHiddenAgencys()" style=""><b>Mitgliedsagenturen betrachten</b></a>
|
||||||
|
<span id="agencys_of_ag" style="display: none;">
|
||||||
|
<br />
|
||||||
|
{% for a in agn.members.all %}
|
||||||
|
{{a.name}}{% if forloop.counter < agn.members.all|length %},{% endif %}{% endfor %}{% if agn.sharemembers.all|length > 0 %}, {% endif %}{% for a in agn.sharemembers.all %}{{a.name}}{% if forloop.counter < agn.sharemembers.all|length %},
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var hidden_ag = true;
|
||||||
|
|
||||||
|
function showHiddenAgencys(){
|
||||||
|
if(hidden_ag){
|
||||||
|
$("#agencys_of_ag").show();
|
||||||
|
hidden_ag = false;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$("#agencys_of_ag").hide();
|
||||||
|
hidden_ag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
Möchten Sie diesem Verbund beitreten?
|
Möchten Sie diesem Verbund beitreten?
|
||||||
<br />
|
<br />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
{% 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 %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
function updateTmSettings(){
|
||||||
|
$.ajax(
|
||||||
|
{
|
||||||
|
type: "GET",
|
||||||
|
url: "{% url 'modsettings-tm' %}",
|
||||||
|
data:{
|
||||||
|
aze: $("#id_module_timemanagement_ze").prop('checked')
|
||||||
|
},
|
||||||
|
success: function( data )
|
||||||
|
{
|
||||||
|
location.href = location.href;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -17,7 +17,13 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{formfield.label_tag}}</td>
|
<td>{{formfield.label_tag}}</td>
|
||||||
<td>{{formfield}}</td>
|
<td>{{formfield}}</td>
|
||||||
<td>{% if formfield.name == 'module_organigramm' %}<button type="button" class="btn btn-sm btn-primary" onclick="javascript:$('#modulesettings_{{formfield.name}}').modal('toggle');"><i class="fas fa-cog"></i></button>{% endif %}</td>
|
<td>
|
||||||
|
{% if formfield.name == 'module_organigramm' %}
|
||||||
|
<button type="button" class="btn btn-sm btn-primary" onclick="javascript:$('#modulesettings_{{formfield.name}}').modal('toggle');"><i class="fas fa-cog"></i></button>
|
||||||
|
{% elif formfield.name == 'module_timemanagement' %}
|
||||||
|
<button type="button" class="btn btn-sm btn-primary" onclick="javascript:$('#modulesettings_{{formfield.name}}').modal('toggle');"><i class="fas fa-cog"></i></button>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -28,7 +34,7 @@
|
||||||
|
|
||||||
{% for formfield in modulform %}
|
{% for formfield in modulform %}
|
||||||
<div class="modal fade" id="modulesettings_{{formfield.name}}" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="" aria-hidden="true">
|
<div class="modal fade" id="modulesettings_{{formfield.name}}" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="" aria-hidden="true">
|
||||||
<div class="modal-dialog " role="document">
|
<div class="modal-dialog modal-lg " role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">Moduleinstellungen {{formfield.label_tag}}</h5>
|
<h5 class="modal-title">Moduleinstellungen {{formfield.label_tag}}</h5>
|
||||||
|
|
@ -37,18 +43,27 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
{% if formfield.name != 'module_organigramm' %}
|
{% if formfield.name == 'module_organigramm' %}
|
||||||
Keine Einstellungen vorhanden.
|
{% block modulesettings_organigramm %}
|
||||||
|
{% include "dasettings/modulesettings_organigramm.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
{% elif formfield.name == 'module_timemanagement' %}
|
||||||
|
{% block modulesettings_tm %}
|
||||||
|
{% include "dasettings/modulesettings_timemanagement.html" %}
|
||||||
|
{% endblock %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% block modulesettings_organigramm %}
|
Keine Einstellungen vorhanden.
|
||||||
{% include "dasettings/modulesettings_organigramm.html" %}
|
|
||||||
{% endblock %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if formfield.name == 'module_organigramm' %}
|
{% if formfield.name == 'module_organigramm' %}
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-danger" data-dismiss="modal">Schließen</button>
|
<button type="button" class="btn btn-danger" data-dismiss="modal">Schließen</button>
|
||||||
<button id="" type="button" onclick="javascript:updateOrganigrammSettings()" class="btn btn-success" data-dismiss="modal" >Speichern</button>
|
<button id="" type="button" onclick="javascript:updateOrganigrammSettings()" class="btn btn-success" data-dismiss="modal" >Speichern</button>
|
||||||
</div>
|
</div>
|
||||||
|
{% elif formfield.name == 'module_timemanagement' %}
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-danger" data-dismiss="modal">Schließen</button>
|
||||||
|
<button id="" type="button" onclick="javascript:updateTmSettings()" class="btn btn-success" data-dismiss="modal" >Speichern</button>
|
||||||
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|
|
||||||
|
|
@ -24,4 +24,5 @@ urlpatterns = [
|
||||||
path('managnag/deli/<int:pk>', permission_required('users.agencynetwork')(views.DelAgInv), name='delinvite'),
|
path('managnag/deli/<int:pk>', permission_required('users.agencynetwork')(views.DelAgInv), name='delinvite'),
|
||||||
#path('managnag/delfromagn/<int:agn>/<int:ag>', permission_required('users.agencynetwork')(views.DelFromAgn), name='delagfromagn'),
|
#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/orga/', views.ModSettingsOrga, name="modsettings-orga"),
|
||||||
|
path('modsettings/tm/', views.ModSettingsTm, name="modsettings-tm"),
|
||||||
]
|
]
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.http import HttpResponseRedirect,HttpResponse, JsonResponse
|
from django.http import HttpResponseRedirect,HttpResponse, JsonResponse
|
||||||
from .forms import UsersSelfChangeForm, UsersNotificationForm, AgencyGroupPerms, AgencyModulsForm, UserNewUserForm, UserProfileForm, AgencyNetworkForm, AgencyOrganigrammForm, UserTimeForm
|
from .forms import UsersSelfChangeForm, UsersNotificationForm, AgencyGroupPerms, AgencyModulsForm, UserNewUserForm, UserProfileForm, AgencyNetworkForm, AgencyOrganigrammForm, UserTimeForm, AgencyTimeManagement
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth import update_session_auth_hash
|
from django.contrib.auth import update_session_auth_hash
|
||||||
from django.contrib.auth.forms import PasswordChangeForm
|
from django.contrib.auth.forms import PasswordChangeForm
|
||||||
|
|
@ -21,6 +21,7 @@ from tasks.models import Tasks
|
||||||
import webcolors
|
import webcolors
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from standards.models import Standards
|
from standards.models import Standards
|
||||||
|
from timemanagement.models import AbsenceReason
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
import re
|
import re
|
||||||
|
|
@ -68,6 +69,12 @@ def getAllForms(request, context):
|
||||||
modsettings_organigramm = AgencyOrganigrammForm(instance=request.user.profile.agency)
|
modsettings_organigramm = AgencyOrganigrammForm(instance=request.user.profile.agency)
|
||||||
context.update({'modsettings_organigramm' : modsettings_organigramm})
|
context.update({'modsettings_organigramm' : modsettings_organigramm})
|
||||||
|
|
||||||
|
#Modulsettings ABWESENHEIT- UND ZEITERFASSUNG
|
||||||
|
modsettings_tm = AgencyTimeManagement(instance=request.user.profile.agency)
|
||||||
|
context.update({'modsettings_tm' : modsettings_tm})
|
||||||
|
context.update({"modsettings_tm_abcat" : AbsenceReason.objects.filter(agency=request.user.profile.agency).order_by("-name") })
|
||||||
|
|
||||||
|
|
||||||
# USER FOR USERTABLE
|
# USER FOR USERTABLE
|
||||||
users = User.objects.filter(profile__agency__pk=request.user.profile.agency.pk)
|
users = User.objects.filter(profile__agency__pk=request.user.profile.agency.pk)
|
||||||
return context
|
return context
|
||||||
|
|
@ -858,7 +865,7 @@ def AgencyNetworkAjaxSettings(request):
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def ModSettingsOrga(request):
|
def ModSettingsOrga(request):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET' and request.user.has_perm("modulesconfig"):
|
||||||
if(request.GET['dynorga'] == "true"):
|
if(request.GET['dynorga'] == "true"):
|
||||||
ag = request.user.profile.agency
|
ag = request.user.profile.agency
|
||||||
ag.dynamicprofile = True
|
ag.dynamicprofile = True
|
||||||
|
|
@ -869,4 +876,19 @@ def ModSettingsOrga(request):
|
||||||
ag.save()
|
ag.save()
|
||||||
return JsonResponse({})
|
return JsonResponse({})
|
||||||
else:
|
else:
|
||||||
return JsonResponse({})
|
return JsonResponse({})
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def ModSettingsTm(request):
|
||||||
|
if request.method == 'GET' and request.user.has_perm("modulesconfig"):
|
||||||
|
if(request.GET['aze'] == "true"):
|
||||||
|
ag = request.user.profile.agency
|
||||||
|
ag.module_timemanagement_ze = True
|
||||||
|
ag.save()
|
||||||
|
else:
|
||||||
|
ag = request.user.profile.agency
|
||||||
|
ag.module_timemanagement_ze = False
|
||||||
|
ag.save()
|
||||||
|
return JsonResponse({})
|
||||||
|
else:
|
||||||
|
return JsonResponse({})
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Generated by Django 3.0.4 on 2020-04-30 23:06
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('users', '0023_auto_20200430_2306'),
|
||||||
|
('timemanagement', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='AbsenceReason',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('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)),
|
||||||
|
('agency', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.Agency')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Absence',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('start', models.DateTimeField(blank=True, default=None, null=True)),
|
||||||
|
('end', models.DateTimeField(blank=True, default=None, null=True)),
|
||||||
|
('start_ishalf', models.BooleanField(default=False)),
|
||||||
|
('end_ishalf', models.BooleanField(default=False)),
|
||||||
|
('info', models.TextField(blank=True, default='', verbose_name='Abwesenheitsbegründung')),
|
||||||
|
('confirm_status', models.IntegerField(default=0)),
|
||||||
|
('confirm_info', models.TextField(blank=True, default='', verbose_name='Begründung')),
|
||||||
|
('agency', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.Agency')),
|
||||||
|
('reason', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='timemanagement.AbsenceReason')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Generated by Django 3.0.4 on 2020-05-01 00:20
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('users', '0023_auto_20200430_2306'),
|
||||||
|
('timemanagement', '0002_absence_absencereason'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='FreeDays',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('day', models.DateTimeField(blank=True, default=None, null=True)),
|
||||||
|
('name', models.CharField(default='', max_length=200)),
|
||||||
|
('year', models.IntegerField(default=0)),
|
||||||
|
('agency', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.Agency')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -17,3 +17,31 @@ class Breaks(models.Model):
|
||||||
start = models.DateTimeField(default=None, null=True, blank=True)
|
start = models.DateTimeField(default=None, null=True, blank=True)
|
||||||
end = models.DateTimeField(default=None, null=True, blank=True)
|
end = models.DateTimeField(default=None, null=True, blank=True)
|
||||||
|
|
||||||
|
class AbsenceReason(models.Model):
|
||||||
|
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
|
||||||
|
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)
|
||||||
|
|
||||||
|
class Absence(models.Model):
|
||||||
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
|
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
|
||||||
|
start = models.DateTimeField(default=None, null=True, blank=True)
|
||||||
|
end = models.DateTimeField(default=None, null=True, blank=True)
|
||||||
|
start_ishalf = models.BooleanField(default=False)
|
||||||
|
end_ishalf = models.BooleanField(default=False)
|
||||||
|
reason = models.ForeignKey("AbsenceReason", on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
|
info = models.TextField(blank=True, verbose_name='Abwesenheitsbegründung', default="")
|
||||||
|
confirm_status = models.IntegerField(default=0)
|
||||||
|
confirm_info = models.TextField(blank=True, verbose_name='Begründung', default="")
|
||||||
|
|
||||||
|
class FreeDays(models.Model):
|
||||||
|
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
|
||||||
|
day = models.DateTimeField(default=None, null=True, blank=True)
|
||||||
|
name = models.CharField(default="", max_length=200)
|
||||||
|
year = models.IntegerField(default=0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@
|
||||||
<th scope="col">Arbeitszeit</th>
|
<th scope="col">Arbeitszeit</th>
|
||||||
<th scope="col">Pausen</th>
|
<th scope="col">Pausen</th>
|
||||||
<th scope="col">Gesamtzeit</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>
|
<th scope="col"> </th>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -46,11 +48,15 @@
|
||||||
{{sumwd}}
|
{{sumwd}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
DROPDOWN
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-secondary btn-sm ml-2" onclick="javascript:$('#confirm-delete_{{workday.pk}}').modal('toggle')"><small><i class="fas fa-trash"></i></small></button>
|
<button class="btn btn-secondary btn-sm ml-2" onclick="javascript:$('#confirm-delete_{{workday.pk}}').modal('toggle')"><small><i class="fas fa-trash"></i></small></button>
|
||||||
<button class="btn btn-secondary btn-sm " href=""><small><i class="fas fa-pen"></i></small></button>
|
<button class="btn btn-secondary btn-sm " href=""><small><i class="fas fa-pen"></i></small></button>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -127,6 +133,6 @@ $(document).ready(function(){
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h3>Das Modul Zeiterfassung wurde in ihrer Agentur deaktiviert.</h3>
|
<h3>Das Modul Abwesenheits- und Zeiterfassung wurde in ihrer Agentur deaktiviert oder die Zeiterfassung wurde im Modul deaktiviert.</h3>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
{% extends "users/base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
{% load counter_tag %}
|
||||||
|
{% if request.user.profile.agency.module_timemanagement_ze %}
|
||||||
|
<div class="content-section col-12">
|
||||||
|
<h3>Abwesenheiten <small><i data-toggle="tooltip" data-placement="top" title="Bearbeiten Sie hier Ihre Abwesenheiten." class="far fa-question-circle"></i></small></h3>
|
||||||
|
<hr>
|
||||||
|
{{freedays}}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* DATATABLES */
|
||||||
|
.paginate_button {
|
||||||
|
padding: 0px !important;
|
||||||
|
border: 0px !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
/*
|
||||||
|
$('#table_timemanagement').DataTable({
|
||||||
|
"language": {
|
||||||
|
"search" : "Suche",
|
||||||
|
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
|
||||||
|
"lengthMenu": "Zeige _MENU_ Einträge",
|
||||||
|
"zeroRecords": "Nichts gefunden",
|
||||||
|
"infoEmpty": "Keine Einträge",
|
||||||
|
"paginate": {
|
||||||
|
"first": "Erste",
|
||||||
|
"last": "Letzte",
|
||||||
|
"next": "Nächste",
|
||||||
|
"previous": "Zurück"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"buttons" : {
|
||||||
|
"className" : "btn-danger"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{% else %}
|
||||||
|
<h3>Das Modul Abwesenheits- und Zeiterfassung wurde in ihrer Agentur deaktiviert.</h3>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from django.contrib.auth.decorators import login_required, permission_required
|
from django.contrib.auth.decorators import login_required, permission_required
|
||||||
from .views import TimeManagement, TimeAjax
|
from .views import TimeManagement, TimeAjax, AbsenceManagmenet
|
||||||
'''
|
'''
|
||||||
Permissions definiert in models.py bei USERS und dann hier vor die View geschrieben!
|
Permissions definiert in models.py bei USERS und dann hier vor die View geschrieben!
|
||||||
'''
|
'''
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', TimeManagement, name='tm-management'),
|
path('', TimeManagement, name='tm-management'),
|
||||||
|
path('abs/', AbsenceManagmenet, name='tma-management'),
|
||||||
path('ajax/', TimeAjax, name='tm-ajax'),
|
path('ajax/', TimeAjax, name='tm-ajax'),
|
||||||
#path('newsadd/', permission_required('users.modulenews')(views.NewsAdd), name='news-add'),
|
#path('newsadd/', permission_required('users.modulenews')(views.NewsAdd), name='news-add'),
|
||||||
#path('newsupdate/<int:id>/', permission_required('users.modulenews')(views.NewsUpdate), name='news-update'),
|
#path('newsupdate/<int:id>/', permission_required('users.modulenews')(views.NewsUpdate), name='news-update'),
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,49 @@ from django.contrib.auth.decorators import login_required
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from .models import Workday, Breaks
|
from .models import Workday, Breaks
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
import requests, csv, os
|
||||||
|
from django.templatetags.static import static
|
||||||
|
from django.conf import settings
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
def loadingFreeDays(plz):
|
||||||
|
# Getting land
|
||||||
|
|
||||||
|
file_path = os.path.join(settings.STATIC_ROOT, 'users/extra/plz_short.csv')
|
||||||
|
|
||||||
|
land = False
|
||||||
|
|
||||||
|
with open(file_path, 'rt') as csvfile:
|
||||||
|
filecsv = csv.reader(csvfile, delimiter=';')
|
||||||
|
for row in filecsv:
|
||||||
|
if row[1] == plz:
|
||||||
|
land = row[6]
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(land != False):
|
||||||
|
# CALCULATE FREEDAYS AS JSON
|
||||||
|
year = today = date.today().year
|
||||||
|
|
||||||
|
|
||||||
|
URL = "https://feiertage-api.de/api/"
|
||||||
|
PARAMS = {'jahr':year,'nur_land':land}
|
||||||
|
r = requests.get(url = URL, params = PARAMS)
|
||||||
|
return r.json()
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def AbsenceManagmenet(request):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"active_link" : "abscence",
|
||||||
|
"freedays" : loadingFreeDays(request.user.profile.agency.plz)
|
||||||
|
}
|
||||||
|
return render(request, 'timemanagement/tm_ab_management.html', context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def TimeManagement(request):
|
def TimeManagement(request):
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ from django.contrib.auth.models import Permission
|
||||||
from message.models import Message
|
from message.models import Message
|
||||||
from cloud.models import DataFile
|
from cloud.models import DataFile
|
||||||
from organizer.models import AGContacts
|
from organizer.models import AGContacts
|
||||||
from timemanagement.models import Workday, Breaks
|
from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays
|
||||||
|
|
||||||
admin.site.register(StandardComments)
|
admin.site.register(StandardComments)
|
||||||
admin.site.register(StandardCommentRate)
|
admin.site.register(StandardCommentRate)
|
||||||
|
|
@ -24,4 +24,5 @@ admin.site.register(DataFile)
|
||||||
admin.site.register(UserTime)
|
admin.site.register(UserTime)
|
||||||
admin.site.register(Workday)
|
admin.site.register(Workday)
|
||||||
admin.site.register(Breaks)
|
admin.site.register(Breaks)
|
||||||
|
admin.site.register(AbsenceReason)
|
||||||
|
admin.site.register(FreeDays)
|
||||||
|
|
|
||||||
|
|
@ -99,8 +99,14 @@ class Agency(models.Model):
|
||||||
module_messages = models.BooleanField(default=True)
|
module_messages = models.BooleanField(default=True)
|
||||||
|
|
||||||
# KOSTENPFLICHTIGE MODULE
|
# KOSTENPFLICHTIGE MODULE
|
||||||
|
|
||||||
|
# Abwesenheits- und Zeiterfassung
|
||||||
|
# Modul aktiv/deaktiviert
|
||||||
module_timemanagement = models.BooleanField(default=False)
|
module_timemanagement = models.BooleanField(default=False)
|
||||||
module_timemanagement_price = models.FloatField(default=5.0, max_length=9, blank=True)
|
module_timemanagement_price = models.FloatField(default=10.0, max_length=9, blank=True)
|
||||||
|
# Zeiterfassung Ja/Nein
|
||||||
|
module_timemanagement_ze = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
|
||||||
# Steckbrief dynamisch aus Standard
|
# Steckbrief dynamisch aus Standard
|
||||||
dynamicprofile = models.BooleanField(default=True)
|
dynamicprofile = models.BooleanField(default=True)
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,40 @@ from django.conf import settings
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from standards.models import Standards
|
from standards.models import Standards
|
||||||
from django.contrib.auth.signals import user_logged_in
|
from django.contrib.auth.signals import user_logged_in
|
||||||
from timemanagement.models import Workday, Breaks
|
from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays
|
||||||
from datetime import date
|
from datetime import date
|
||||||
import datetime
|
import datetime, json
|
||||||
|
from django.utils import timezone
|
||||||
|
import requests, csv, os
|
||||||
|
from django.templatetags.static import static
|
||||||
|
from django.conf import settings
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
def loadingFreeDays(plz):
|
||||||
|
# Getting land
|
||||||
|
|
||||||
|
file_path = os.path.join(settings.STATIC_ROOT, 'users/extra/plz_short.csv')
|
||||||
|
|
||||||
|
land = False
|
||||||
|
|
||||||
|
with open(file_path, 'rt') as csvfile:
|
||||||
|
filecsv = csv.reader(csvfile, delimiter=';')
|
||||||
|
for row in filecsv:
|
||||||
|
if row[1] == plz:
|
||||||
|
land = row[6]
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(land != False):
|
||||||
|
# CALCULATE FREEDAYS AS JSON
|
||||||
|
year = today = date.today().year
|
||||||
|
|
||||||
|
|
||||||
|
URL = "https://feiertage-api.de/api/"
|
||||||
|
PARAMS = {'jahr':year,'nur_land':land}
|
||||||
|
r = requests.get(url = URL, params = PARAMS)
|
||||||
|
return r.json()
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
# CHECK SOMETHING WHEN USER LOGGED IN
|
# CHECK SOMETHING WHEN USER LOGGED IN
|
||||||
@receiver(signal=user_logged_in, sender=User)
|
@receiver(signal=user_logged_in, sender=User)
|
||||||
|
|
@ -31,7 +62,40 @@ def checkForWorkDays(sender, user, request, **kwargs):
|
||||||
if(b.end == None):
|
if(b.end == None):
|
||||||
b.end = datetime.datetime(d.start.year, d.start.month, d.start.day, 23, 59, 00)
|
b.end = datetime.datetime(d.start.year, d.start.month, d.start.day, 23, 59, 00)
|
||||||
b.save()
|
b.save()
|
||||||
|
|
||||||
|
# CHECK SOMETHING WHEN USER LOGGED IN
|
||||||
|
@receiver(signal=user_logged_in, sender=User)
|
||||||
|
def checkDefaultAbsenceReasons(sender, user, request, **kwargs):
|
||||||
|
|
||||||
|
ar = AbsenceReason.objects.filter(agency=user.profile.agency)
|
||||||
|
|
||||||
|
if(len(ar) == 0):
|
||||||
|
new_ar_holidays = AbsenceReason(agency=user.profile.agency, name="Urlaub", need_confirm=True, need_rep=True, is_holiday=True)
|
||||||
|
new_ar_holidays.save()
|
||||||
|
|
||||||
|
new_ar_specialholidays = AbsenceReason(agency=user.profile.agency, name="Sonderurlaub", need_confirm=True, need_rep=True, is_holiday=False)
|
||||||
|
new_ar_specialholidays.save()
|
||||||
|
|
||||||
|
new_ar_ill = AbsenceReason(agency=user.profile.agency, name="Krankheit", need_confirm=False, need_rep=False, is_holiday=False)
|
||||||
|
new_ar_ill.save()
|
||||||
|
|
||||||
|
new_ar_school = AbsenceReason(agency=user.profile.agency, name="Berufsschule", need_confirm=False, need_rep=False, is_holiday=False)
|
||||||
|
new_ar_school.save()
|
||||||
|
|
||||||
|
@receiver(signal=user_logged_in, sender=User)
|
||||||
|
def checkAllFreeDaysLoaded(sender, user, request, **kwargs):
|
||||||
|
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
|
# Deletes all Notifications added to to delete news
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -162,6 +162,19 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if request.user.profile.agency.module_timemanagement %}
|
{% if request.user.profile.agency.module_timemanagement %}
|
||||||
|
{% if active_link == 'abscence' %}
|
||||||
|
<li class="nav-item active">
|
||||||
|
{% else%}
|
||||||
|
<li class="nav-item">
|
||||||
|
{%endif%}
|
||||||
|
<a class="nav-link " href="{% url 'tma-management' %}" aria-expanded="true">
|
||||||
|
<i class="fas fa-umbrella-beach"></i>
|
||||||
|
<span>Abwesenheiten</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if request.user.profile.agency.module_timemanagement_ze %}
|
||||||
{% if active_link == 'timemanagement' %}
|
{% if active_link == 'timemanagement' %}
|
||||||
<li class="nav-item active">
|
<li class="nav-item active">
|
||||||
{% else%}
|
{% else%}
|
||||||
|
|
@ -267,7 +280,7 @@
|
||||||
</style>
|
</style>
|
||||||
<!-- Topbar Navbar -->
|
<!-- Topbar Navbar -->
|
||||||
<ul class="navbar-nav ml-auto ">
|
<ul class="navbar-nav ml-auto ">
|
||||||
{% if request.user.profile.agency.module_timemanagement %}
|
{% if request.user.profile.agency.module_timemanagement_ze %}
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
<li class="nav-item dropdown no-arrow mx-1">
|
||||||
<a class="nav-link dropdown-toggle" onclick="" id="timemanagement_realtime" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<a class="nav-link dropdown-toggle" onclick="" id="timemanagement_realtime" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
<i class="far fa-clock"></i>
|
<i class="far fa-clock"></i>
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ from organizer.models import AGContacts, AGPassword
|
||||||
import socket
|
import socket
|
||||||
import sys, os
|
import sys, os
|
||||||
|
|
||||||
|
|
||||||
def randomString(stringLength=10):
|
def randomString(stringLength=10):
|
||||||
"""Generate a random string of fixed length """
|
"""Generate a random string of fixed length """
|
||||||
letters = string.ascii_lowercase
|
letters = string.ascii_lowercase
|
||||||
|
|
@ -258,9 +259,9 @@ class AgencyCreateView(CreateView):
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def dashboard(request):
|
def dashboard(request):
|
||||||
|
|
||||||
|
|
||||||
# UPDATE FUNCTIONS BY NEW MODEL-CHANGES FOR COPIEN SOME DATA
|
# UPDATE FUNCTIONS BY NEW MODEL-CHANGES FOR COPIEN SOME DATA
|
||||||
toUpdate(request)
|
toUpdate(request)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue