Zeiterfassung bis auf Bearbeiten durch andere Mitarbeiter fertig für Betatest

This commit is contained in:
Holger Trampe 2020-07-29 13:45:34 +02:00
parent 51d7a746f7
commit 0de2a48c9e
7 changed files with 503 additions and 338 deletions

View File

@ -1,15 +1,16 @@
{% load counter_tag %} {% load counter_tag %}
<a href="{% url 'newuserfirst' %}"class="btn btn-primary active" data-toggle="tooltip" data-placement="top" title="Fügen Sie hier einen weiteren Mitarbeiter Ihrer Agentur hinzu."><i class="fas fa-plus"></i>&nbsp;Mitarbeiter</a> <a href="{% url 'newuserfirst' %}"class="btn btn-primary active" data-toggle="tooltip" data-placement="top" title="Fügen Sie hier einen weiteren Mitarbeiter Ihrer Agentur hinzu."><i class="fas fa-plus"></i>&nbsp;Mitarbeiter</a>
<hr> <hr>
<div class="row"> <div class="row">
<div class="table-responsive"> <div class="table-responsive">
<table class="table hover" id="usertableall"> <table class="table hover" id="usertableall">
<thead> <thead>
<tr> <tr>
<th scope="col">Vorname</th> <th scope="col">Vorname</th>
<th scope="col">Nachname</th> <th scope="col">Nachname</th>
<th scope="col">E-Mail</th> <th scope="col">E-Mail</th>
<th scope="col">Agenturfunktion</th> <th scope="col">Agenturfunktion</th>
<th scope="col">Gleitzeit</th>
<th scope="col">Letzter Login</th> <th scope="col">Letzter Login</th>
<th scope="col">Tätigkeit</th> <th scope="col">Tätigkeit</th>
<th scope="col">Telefon</th> <th scope="col">Telefon</th>
@ -21,21 +22,33 @@
{% for item in usersofagency %} {% for item in usersofagency %}
<tr> <tr>
<td><a href="{% url 'user_updateprofile' item.pk 0 %}">{{item.first_name }}</a></td> <td><a href="{% url 'user_updateprofile' item.pk 0 %}">{{item.first_name }}</a></td>
<td><a href="{% url 'user_updateprofile' item.pk 0 %}">{{ item.last_name }}</a></td> <td><a href="{% url 'user_updateprofile' item.pk 0 %}">{{ item.last_name }}</a></td>
<td>{{ item.email }}</td> <td>{{ item.email }}</td>
<td>{% if item.profile.func == None %}-{%else%}{{ item.profile.func }}{%endif%}</td> <td>{% if item.profile.func == None %}-{%else%}{{ item.profile.func }}{%endif%}</td>
<td>
{% if item.usertime.usetime %}
{% loadaccounttime item as actualaccounttime %}
{% if actualaccounttime.1 == 0 %}
<b><span style="color: green">+{{actualaccounttime.0}}</span></b>
{% else %}
<b><span style="color: red">-{{actualaccounttime.0}}</span></b>
{% endif %}
{% else %}
-
{% endif %}
</td>
<td>{% if item.last_login != Nonte %}{{ item.last_login }}{% endif %}</td> <td>{% if item.last_login != Nonte %}{{ item.last_login }}{% endif %}</td>
<td>{{ item.profile.compfunc }}</td> <td>{{ item.profile.compfunc }}</td>
<td>{{ item.profile.phoneland }}</td> <td>{{ item.profile.phoneland }}</td>
<td>{{ item.profile.phonemobile }}</td> <td>{{ item.profile.phonemobile }}</td>
<td> <td>
{% if item != request.user %} {% if item != request.user %}
<a href="{% url 'users-delete' item.pk %}" ><button class="btn btn-sm btn-secondary"><i class="fas fa-trash"></i></button></a> <a href="{% url 'users-delete' item.pk %}" ><button class="btn btn-sm btn-secondary"><i class="fas fa-trash"></i></button></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
@ -51,7 +64,7 @@
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
$('#usertableall').DataTable({ $('#usertableall').DataTable({
"order" : [], "order" : [],
"language": { "language": {
@ -71,9 +84,8 @@ $(document).ready(function(){
"className" : "btn-danger" "className" : "btn-danger"
} }
}); });
}); });
</script> </script>

View File

@ -17,3 +17,13 @@ six==1.13.0
sqlparse==0.3.0 sqlparse==0.3.0
urllib3==1.25.7 urllib3==1.25.7
webcolors==1.10 webcolors==1.10
django-summernote==0.8.11.6
django-mathfilters==1.0.0
django-cleanup==5.0.0
django-user-agents==0.4.0
djangorestframework==3.11.0
django-channels==0.7.0
django-channels-presence==1.0.0
django-cryptography==1.0
channels-redis==3.0.1
filetype==1.0.7

View File

@ -20,9 +20,7 @@
<!-- <!--
# TODO: Sichtbarkeit durch andere Nutzer absprechen? # TODO: Sichtbarkeit durch andere Nutzer absprechen?
# TODO: Bis wann darf rückwirkend eine Abwesenheit bearbeitet werden? Monatlich? Aktuell sieht man den Gleitzeitkontostand in der Mitarbeitertabelle, ein Bearbeiten muss ich nachschieben
# TODO: CronJob einmal umbauen
# TODO: Halber Tag mit Workday verbinden
--> -->
<div class="table-responsive "> <div class="table-responsive ">
@ -63,14 +61,129 @@
{% if abday.start == da%} {% if abday.start == da%}
{% if abday.startday_info == "1" %} {% if abday.startday_info == "1" %}
(nur Vormittags) (nur Vormittags)
{% for workday in workdays %}
{% if workday.start|date:"d-m-y" == da|date:"d-m-y" %}
<br />
{{workday.start|date:"H:i"}} - {{workday.end|date:"H:i"}},
{% getsumworkdayexcludebreak workday as sumworkday %}
{{ sumworkday }},
{% getsumbreak workday as sumbreakofday %}
{{sumbreakofday}} min. ({{workday.breaks.all|length}}),
{% getsumworkday workday as sumwd %}
{{sumwd}},
{% gettimeoveralldiff workday user as erg%}
{% if erg.1 == 0 %}
<span style="color: green">+{{erg.0}}</span>
{% elif erg.1 == 1 %}
<span>{{erg.0}}</span>
{% else %}
<span style="color: red">-{{erg.0}}</span>
{% endif %}
{% if breakmonthline < da %}
<button class="btn btn-secondary btn-sm ml-2" onclick="window.location.href='{% url 'tm-update' workday.pk %}'"><small><i class="fas fa-pen"></i></small></button>
<button class="btn btn-secondary btn-sm " onclick="javascript:$('#confirm-delete_{{workday.pk}}').modal('toggle')"><small><i class="fas fa-trash"></i></small></button>
{% endif %}
{% endif %}
{% endfor %}
{% elif abday.startday_info == "2" %} {% elif abday.startday_info == "2" %}
(nur Nachmittags) (nur Nachmittags)
{% for workday in workdays %}
{% if workday.start|date:"d-m-y" == da|date:"d-m-y" %}
<br />
{{workday.start|date:"H:i"}} - {{workday.end|date:"H:i"}}
{% getsumworkdayexcludebreak workday as sumworkday %}
{{ sumworkday }},
{% getsumbreak workday as sumbreakofday %}
{{sumbreakofday}} min. ({{workday.breaks.all|length}}),
{% getsumworkday workday as sumwd %}
{{sumwd}},
{% gettimeoveralldiff workday user as erg%}
{% if erg.1 == 0 %}
<span style="color: green">+{{erg.0}}</span>
{% elif erg.1 == 1 %}
<span>{{erg.0}}</span>
{% else %}
<span style="color: red">-{{erg.0}}</span>
{% endif %}
{% if breakmonthline < da %}
<button class="btn btn-secondary btn-sm ml-2" onclick="window.location.href='{% url 'tm-update' workday.pk %}'"><small><i class="fas fa-pen"></i></small></button>
<button class="btn btn-secondary btn-sm " onclick="javascript:$('#confirm-delete_{{workday.pk}}').modal('toggle')"><small><i class="fas fa-trash"></i></small></button>
{% endif %}
{% endif %}
{% endfor %}
{% endif %} {% endif %}
{% elif abday.end == da%} {% elif abday.end == da%}
{% if abday.endday_info == "1" %} {% if abday.endday_info == "1" %}
(nur Vormittags) (nur Vormittags)
{% for workday in workdays %}
{% if workday.start|date:"d-m-y" == da|date:"d-m-y" %}
<br />
{{workday.start|date:"H:i"}} - {{workday.end|date:"H:i"}}
{% getsumworkdayexcludebreak workday as sumworkday %}
{{ sumworkday }},
{% getsumbreak workday as sumbreakofday %}
{{sumbreakofday}} min. ({{workday.breaks.all|length}}),
{% getsumworkday workday as sumwd %}
{{sumwd}},
{% gettimeoveralldiff workday user as erg%}
{% if erg.1 == 0 %}
<span style="color: green">+{{erg.0}}</span>
{% elif erg.1 == 1 %}
<span>{{erg.0}}</span>
{% else %}
<span style="color: red">-{{erg.0}}</span>
{% endif %}
{% if breakmonthline < da %}
<button class="btn btn-secondary btn-sm ml-2" onclick="window.location.href='{% url 'tm-update' workday.pk %}'"><small><i class="fas fa-pen"></i></small></button>
<button class="btn btn-secondary btn-sm " onclick="javascript:$('#confirm-delete_{{workday.pk}}').modal('toggle')"><small><i class="fas fa-trash"></i></small></button>
{% endif %}
{% endif %}
{% endfor %}
{% elif abday.endday_info == "2" %} {% elif abday.endday_info == "2" %}
(nur Nachmittags) (nur Nachmittags)
{% for workday in workdays %}
{% if workday.start|date:"d-m-y" == da|date:"d-m-y" %}
<br />
{{workday.start|date:"H:i"}} - {{workday.end|date:"H:i"}}
{% getsumworkdayexcludebreak workday as sumworkday %}
{{ sumworkday }},
{% getsumbreak workday as sumbreakofday %}
{{sumbreakofday}} min. ({{workday.breaks.all|length}}),
{% getsumworkday workday as sumwd %}
{{sumwd}},
{% gettimeoveralldiff workday user as erg%}
{% if erg.1 == 0 %}
<span style="color: green">+{{erg.0}}</span>
{% elif erg.1 == 1 %}
<span>{{erg.0}}</span>
{% else %}
<span style="color: red">-{{erg.0}}</span>
{% endif %}
{% if breakmonthline < da %}
<button class="btn btn-secondary btn-sm ml-2" onclick="window.location.href='{% url 'tm-update' workday.pk %}'"><small><i class="fas fa-pen"></i></small></button>
<button class="btn btn-secondary btn-sm " onclick="javascript:$('#confirm-delete_{{workday.pk}}').modal('toggle')"><small><i class="fas fa-trash"></i></small></button>
{% endif %}
{% endif %}
{% endfor %}
{% endif %} {% endif %}
{% endif %} {% endif %}
@ -212,9 +325,10 @@
{% counterWDUp %} {% counterWDUp %}
{% if breakmonthline < da %}
<button class="btn btn-secondary btn-sm ml-2" onclick="window.location.href='{% url 'tm-update' workday.pk %}'"><small><i class="fas fa-pen"></i></small></button> <button class="btn btn-secondary btn-sm ml-2" onclick="window.location.href='{% url 'tm-update' workday.pk %}'"><small><i class="fas fa-pen"></i></small></button>
<button class="btn btn-secondary btn-sm " onclick="javascript:$('#confirm-delete_{{workday.pk}}').modal('toggle')"><small><i class="fas fa-trash"></i></small></button> <button class="btn btn-secondary btn-sm " onclick="javascript:$('#confirm-delete_{{workday.pk}}').modal('toggle')"><small><i class="fas fa-trash"></i></small></button>
{% endif %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</td> </td>

View File

@ -321,6 +321,7 @@ def TimeManagement(request, activemonth=False, activeyear=False):
# Hier werden nur die Arbeitstage gefiltert, die auch aktuell zur Ansicht stehen sollen # Hier werden nur die Arbeitstage gefiltert, die auch aktuell zur Ansicht stehen sollen
context = { context = {
"next_month" : next_month, "next_month" : next_month,
"breakmonthline" : date.today() - timedelta(days=30),
"prev_month" : prev_month, "prev_month" : prev_month,
"next_year" : next_year, "next_year" : next_year,
"prev_year" : prev_year, "prev_year" : prev_year,
@ -331,7 +332,7 @@ def TimeManagement(request, activemonth=False, activeyear=False):
"days_this_month" : get_datetime_range(int(active_year), int(activemonth)), "days_this_month" : get_datetime_range(int(active_year), int(activemonth)),
"workdays" : Workday.objects.filter(agency=request.user.profile.agency, user=request.user, start__month=activemonth, start__year=active_year).order_by("start").exclude(end=None), "workdays" : Workday.objects.filter(agency=request.user.profile.agency, user=request.user, start__month=activemonth, start__year=active_year).order_by("start").exclude(end=None),
"userhasworkdays" : user_has_workdays "userhasworkdays" : user_has_workdays
} }
return render(request, 'timemanagement/timemanagement_management.html', context) return render(request, 'timemanagement/timemanagement_management.html', context)

View File

@ -12,43 +12,43 @@
<title>Digitale Agentur</title> <title>Digitale Agentur</title>
<!-- Custom fonts for this template--> <!-- Custom fonts for this template-->
<link rel="canonical" href="https://www.digitale-agentur.com"> <link rel="canonical" href="https://www.digitale-agentur.com">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.js" type="text/javascript"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.js" type="text/javascript"></script>
<link href="{%static 'users/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css"> <link href="{%static 'users/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<!--<link href="{%static 'users/css/bootstrap.min.css' %}" rel="stylesheet">--> <!--<link href="{%static 'users/css/bootstrap.min.css' %}" rel="stylesheet">-->
<link href='https://fonts.googleapis.com/css?family=Roboto&display=swap' rel='stylesheet' type='text/css'> <link href='https://fonts.googleapis.com/css?family=Roboto&display=swap' rel='stylesheet' type='text/css'>
<!-- include summernote css/js --> <!-- include summernote css/js -->
<!--<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.15/dist/summernote.min.css" rel="stylesheet"> <!--<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.15/dist/summernote.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.15/dist/summernote.min.js"></script>--> <script src="https://cdn.jsdelivr.net/npm/summernote@0.8.15/dist/summernote.min.js"></script>-->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script>
<!-- <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>--> <!-- <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>-->
<!-- CROPPER --> <!-- CROPPER -->
<link href="{% static 'users/css/cropper.min.css' %}" type="text/css" rel="stylesheet"> <link href="{% static 'users/css/cropper.min.css' %}" type="text/css" rel="stylesheet">
<!-- DATATABLES --> <!-- DATATABLES -->
<link href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css" type="text/css" rel="stylesheet"> <link href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css" type="text/css" rel="stylesheet">
<link href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" type="text/css" rel="stylesheet"> <link href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" type="text/css" rel="stylesheet">
<!-- Custom styles for this template--> <!-- Custom styles for this template-->
<link href="{% static 'users/css/sb-admin-2.css' %}" type="text/css" rel="stylesheet"> <link href="{% static 'users/css/sb-admin-2.css' %}" type="text/css" rel="stylesheet">
<link href="{% static 'users/css/theme.css' %}" type="text/css" rel="stylesheet"> <link href="{% static 'users/css/theme.css' %}" type="text/css" rel="stylesheet">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote-bs4.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote-bs4.js"></script>
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote.css" rel="stylesheet" type="text/css"> <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="{% static 'summernote/lang/summernote-de-DE.min.js' %}"></script> <script type="text/javascript" src="{% static 'summernote/lang/summernote-de-DE.min.js' %}"></script>
@ -59,8 +59,8 @@
<div id="wrapper"> <div id="wrapper">
<!-- Sidebar --> <!-- Sidebar -->
<ul class=" bg-gray-900 sidebar sidebar-dark accordion fixed-top" id="accordionSidebar"> <ul class=" bg-gray-900 sidebar sidebar-dark accordion fixed-top" id="accordionSidebar">
<!-- Sidebar - Brand --> <!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="{% url 'users-dashboard' %}"> <a class="sidebar-brand d-flex align-items-center justify-content-center" href="{% url 'users-dashboard' %}">
@ -148,7 +148,7 @@
<i class="fas fa-envelope"></i> <i class="fas fa-envelope"></i>
<span>Mitteilungen <span>Mitteilungen
{% if gs > 0 %} {% if gs > 0 %}
<span class="badge badge-primary badge-counter" id="messcounter_badge" style="margin-right: 85px;"><span id="messcounter">{{gs}}</span></span>&nbsp; <span class="badge badge-primary badge-counter" id="messcounter_badge" style="margin-right: 85px;"><span id="messcounter">{{gs}}</span></span>&nbsp;
{% endif %} {% endif %}
</span> </span>
</a> </a>
@ -162,7 +162,7 @@
{% else%} {% else%}
<li class="nav-item"> <li class="nav-item">
{%endif%} {%endif%}
<a class="nav-link " href="{% url 'chat:chat-management' %}" aria-expanded="true"> <a class="nav-link " href="{% url 'chat:chat-management' %}" aria-expanded="true">
<i class="fas fa-comments"></i> <i class="fas fa-comments"></i>
<span>Chat&nbsp;<sup>BETA</sup></span> <span>Chat&nbsp;<sup>BETA</sup></span>
@ -205,7 +205,7 @@
<style scoped> <style scoped>
#bottom_info { #bottom_info {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
} }
</style> </style>
<div id="bottom_info"> <div id="bottom_info">
@ -214,7 +214,7 @@
<li class="nav-item active"> <li class="nav-item active">
{% else%} {% else%}
<li class="nav-item"> <li class="nav-item">
{%endif%} {%endif%}
<a class="nav-link " href="{% url 'dasettings' %}" aria-expanded="true" style="margin-top: -15px"> <a class="nav-link " href="{% url 'dasettings' %}" aria-expanded="true" style="margin-top: -15px">
<i class="fas fa-cog"></i> <i class="fas fa-cog"></i>
<span>Einstellungen</span> <span>Einstellungen</span>
@ -224,13 +224,13 @@
<li class="nav-item active"> <li class="nav-item active">
{% else%} {% else%}
<li class="nav-item"> <li class="nav-item">
{%endif%} {%endif%}
<a class="nav-link " href="{% url 'supportda' %}" aria-expanded="true" style="margin-top: -15px"> <a class="nav-link " href="{% url 'supportda' %}" aria-expanded="true" style="margin-top: -15px">
<i class="fas fa-question"></i> <i class="fas fa-question"></i>
<span>Support</span> <span>Support</span>
</a> </a>
</li> </li>
<div style="" class="sidebar-heading "> <div style="" class="sidebar-heading ">
<!--<span style="float: left"><small>poweder by&nbsp;</small><img src="{% static 'users/img/VVE-Logo.png' %}" width="27%" class="mb-2"></span>--> <!--<span style="float: left"><small>poweder by&nbsp;</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"> <img src="{% static 'users/img/VVE-Logo.png' %}" width="27%" class="mb-2">
@ -239,9 +239,9 @@
<a style="color: #999; text-decoration: none;" href="{% url 'impressumda' %}">Impressum</a> <a style="color: #999; text-decoration: none;" href="{% url 'impressumda' %}">Impressum</a>
</div> </div>
<div style="margin-top: 10px; margin-bottom: 5px;" class="sidebar-heading"> <div style="margin-top: 10px; margin-bottom: 5px;" class="sidebar-heading">
Version 0.9.1 Version 0.9.2
</div> </div>
</div> </div>
</ul> </ul>
<!-- End of Sidebar --> <!-- End of Sidebar -->
@ -267,7 +267,7 @@
<div id="content-wrapper"> <div id="content-wrapper">
<!-- Main Content --> <!-- Main Content -->
<!-- Topbar --> <!-- Topbar -->
<nav id="topnavbarmain" class="navbar navbar-expand navbar-light bg-white topbar fixed-top mb-4 static-top shadow" style="margin-left: 224px;"> <nav id="topnavbarmain" class="navbar navbar-expand navbar-light bg-white topbar fixed-top mb-4 static-top shadow" style="margin-left: 224px;">
<!-- Sidebar Toggle (Topbar) --> <!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3" onclick="javascript:toggleSidebar()"> <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3" onclick="javascript:toggleSidebar()">
<i class="fa fa-bars"></i> <i class="fa fa-bars"></i>
@ -276,7 +276,7 @@
<!-- Topbar Search --> <!-- Topbar Search -->
<form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search"> <form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group"> <div class="input-group">
<input list="searchres" placeholder="Agenturweite Suche..." id="search_string" onkeyup="javascript:startSearch(this.value)" class="form-control bg-light border-0 small" > <input list="searchres" placeholder="Agenturweite Suche..." id="search_string" onkeyup="javascript:startSearch(this.value)" class="form-control bg-light border-0 small" >
<!-- <!--
<input type="text" onkeyup="javascript:startSearch(this.value)" class="form-control bg-light border-0 small" placeholder="Suche..." aria-label="Suche" aria-describedby="basic-addon2" id="searchfield"> <input type="text" onkeyup="javascript:startSearch(this.value)" class="form-control bg-light border-0 small" placeholder="Suche..." aria-label="Suche" aria-describedby="basic-addon2" id="searchfield">
--> -->
@ -296,7 +296,7 @@
{% getUserIsRep request.user as repstring %} {% getUserIsRep request.user as repstring %}
{% if repstring != False %} {% if repstring != False %}
<div class="alert alert-info alert-dismissible" id="repholinfo" style="margin-bottom: -2px; text-align: center; display: none; float: right;"> <i class="fas fa-info-circle"></i>&nbsp; <div class="alert alert-info alert-dismissible" id="repholinfo" style="margin-bottom: -2px; text-align: center; display: none; float: right;"> <i class="fas fa-info-circle"></i>&nbsp;
{{repstring}} {{repstring}}
<button type="button" class="close" data-dismiss="alert" onclick="javascript:closeRepHolInfo()">&times;</button> <button type="button" class="close" data-dismiss="alert" onclick="javascript:closeRepHolInfo()">&times;</button>
</div> </div>
@ -316,7 +316,7 @@
{% endif %} {% endif %}
<!-- Topbar Navbar --> <!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto "> <ul class="navbar-nav ml-auto ">
{% if request.user.usertime.usetime and user.usertime.usetime_start != None %} {% if request.user.usertime.usetime and user.usertime.usetime_start != None %}
<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">
@ -325,7 +325,7 @@
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="alertsDropdown" id="timemanagement_clock" name="timemanagement_clock" aria-role="static"> <div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="alertsDropdown" id="timemanagement_clock" name="timemanagement_clock" aria-role="static">
<h6 class="dropdown-header text-white"> <h6 class="dropdown-header text-white">
Zeiterfassung Zeiterfassung
</h6> </h6>
<div> <div>
{% block timemanagement_content_realtime %} {% block timemanagement_content_realtime %}
@ -337,7 +337,7 @@
</li> </li>
{% endif %} {% endif %}
<!-- ALERT_AREA --> <!-- ALERT_AREA -->
<!-- Nav Item - Alerts --> <!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1"> <li class="nav-item dropdown no-arrow mx-1">
@ -363,9 +363,9 @@
border-radius: 50%; border-radius: 50%;
-webkit-box-shadow: 0px 0px 4px 5px {{onlinecolor}}; -webkit-box-shadow: 0px 0px 4px 5px {{onlinecolor}};
-moz-box-shadow: 0px 0px 4px 5px {{onlinecolor}}; -moz-box-shadow: 0px 0px 4px 5px {{onlinecolor}};
box-shadow: 0px 0px 4px 5px {{onlinecolor}}; box-shadow: 0px 0px 4px 5px {{onlinecolor}};
} }
</style> </style>
<div class="topbar-divider d-none d-sm-block"></div> <div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information --> <!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow"> <li class="nav-item dropdown no-arrow">
@ -376,19 +376,19 @@
</a> </a>
<!-- Dropdown - User Information --> <!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown"> <div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
<a class="dropdown-item" onclick="javascript:changeOnlineStatus(0)" href="#/"> <a class="dropdown-item" onclick="javascript:changeOnlineStatus(0)" href="#/">
<i class="fas fa-circle mr-2" style="color: green"></i> <i class="fas fa-circle mr-2" style="color: green"></i>
Online Online
</a> </a>
<a class="dropdown-item" onclick="javascript:changeOnlineStatus(1)" href="#/"> <a class="dropdown-item" onclick="javascript:changeOnlineStatus(1)" href="#/">
<i class="fas fa-circle mr-2" style="color: red"></i> <i class="fas fa-circle mr-2" style="color: red"></i>
Beschäftigt Beschäftigt
</a> </a>
<a class="dropdown-item" onclick="javascript:changeOnlineStatus(2)" href="#/"> <a class="dropdown-item" onclick="javascript:changeOnlineStatus(2)" href="#/">
<i class="fas fa-circle mr-2" style="color: yellow"></i> <i class="fas fa-circle mr-2" style="color: yellow"></i>
Abwesend Abwesend
</a> </a>
<a class="dropdown-item" onclick="javascript:changeOnlineStatus(3)" href="#/"> <a class="dropdown-item" onclick="javascript:changeOnlineStatus(3)" href="#/">
<i class="fas fa-circle mr-2" style="color: grey"></i> <i class="fas fa-circle mr-2" style="color: grey"></i>
Offline anzeigen Offline anzeigen
</a> </a>
@ -396,14 +396,14 @@
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<!--<a class="dropdown-item" onclick="userGoToSettings({{user.pk}})" href="{% url 'orga-single' user.pk %}">--> <!--<a class="dropdown-item" onclick="userGoToSettings({{user.pk}})" href="{% url 'orga-single' user.pk %}">-->
<a class="dropdown-item" onclick="userGoToSettings()" href="#/"> <a class="dropdown-item" onclick="userGoToSettings()" href="#/">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i> <i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Einstellungen Einstellungen
</a> </a>
<a class="dropdown-item" onclick="userGoToNotification()" href="#/"> <a class="dropdown-item" onclick="userGoToNotification()" href="#/">
<i class="fas fa-bell fa-sm fa-fw mr-2 text-gray-400"></i> <i class="fas fa-bell fa-sm fa-fw mr-2 text-gray-400"></i>
Benachrichtigungen Benachrichtigungen
</a> </a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item" href="{% url 'users-logout' %}"> <a class="dropdown-item" href="{% url 'users-logout' %}">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i> <i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
@ -416,12 +416,12 @@
<!-- End of Topbar --> <!-- End of Topbar -->
<!-- Begin Page Content --> <!-- Begin Page Content -->
<div class="container-fluid" > <div class="container-fluid" >
<div id="searchcontent" style="min-height: 100%; margin-top: 85px;"> <div id="searchcontent" style="min-height: 100%; margin-top: 85px;">
</div> </div>
<div id="maincontent" style="min-height: 100%; margin-top: 85px;" > <div id="maincontent" style="min-height: 100%; margin-top: 85px;" >
<!-- MESSAGES --> <!-- MESSAGES -->
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
@ -434,17 +434,17 @@
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% block content %} {% block content %}
{% endblock %} {% endblock %}
</div> </div>
<div style="height: 300px">&nbsp;</div> <div style="height: 300px">&nbsp;</div>
</div> <!-- End of Main Content CONTAINER FLUID--> </div> <!-- End of Main Content CONTAINER FLUID-->
<!-- End of Content Wrapper --> <!-- End of Content Wrapper -->
{% if active_link != 'chat' %} {% if active_link != 'chat' %}
{% if request.user.profile.agency.module_chat %} {% if request.user.profile.agency.module_chat %}
<div id="chat_alluserscontent" style="position: fixed; bottom: 75px; right: 36px; z-index: 999;"></div> <div id="chat_alluserscontent" style="position: fixed; bottom: 75px; right: 36px; z-index: 999;"></div>
<button id="chatButton" class="btn btn-primary" style="position: fixed; right: 36px; bottom: 30px;"><i class="far fa-comments"></i></button> <button id="chatButton" class="btn btn-primary" style="position: fixed; right: 36px; bottom: 30px;"><i class="far fa-comments"></i></button>
<!-- CHATAREA --> <!-- CHATAREA -->
<div id="dynamicchatwindow" class="col-4" style="position: fixed; bottom: 30px; right: 23px; display: none;z-index: 999;"> <div id="dynamicchatwindow" class="col-4" style="position: fixed; bottom: 30px; right: 23px; display: none;z-index: 999;">
<div class="card"> <div class="card">
@ -454,10 +454,10 @@
</div> </div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
</script> </script>
{% endif %} {% endif %}
<!-- CHATAREA END --> <!-- CHATAREA END -->
{% endif %} {% endif %}
</div> </div>
</div> </div>
@ -489,14 +489,14 @@
<script type="text/javascript" src="{%static 'users/vendor/jquery-easing/jquery.easing.min.js' %}"></script> <script type="text/javascript" src="{%static 'users/vendor/jquery-easing/jquery.easing.min.js' %}"></script>
<!-- DATABLES JS --> <!-- DATABLES JS -->
<script type="text/javascript" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script> <script type="text/javascript" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.20/js/dataTables.bootstrap4.min.js"></script> <script type="text/javascript" src="https://cdn.datatables.net/1.10.20/js/dataTables.bootstrap4.min.js"></script>
<!-- Custom scripts for all pages--> <!-- Custom scripts for all pages-->
<script type="text/javascript" src="{%static 'users/js/sb-admin-2.js' %}"></script> <script type="text/javascript" src="{%static 'users/js/sb-admin-2.js' %}"></script>
<!-- CUSTOM FONT --> <!-- CUSTOM FONT -->
<!--<link href="{% static 'users/css/custom.css' %}" rel="stylesheet">--> <!--<link href="{% static 'users/css/custom.css' %}" rel="stylesheet">-->
<!-- TABLE SORT --> <!-- TABLE SORT -->
<!--<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>--> <!--<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>-->
@ -509,14 +509,14 @@
<link href="{% static 'users/css/custom.css' %}" type="text/css" rel="stylesheet"> <link href="{% static 'users/css/custom.css' %}" type="text/css" rel="stylesheet">
</body> </body>
</html> </html>
{% if request.user.profile.showtooltips %} {% if request.user.profile.showtooltips %}
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function(){ $(document).ready(function(){
$('[data-toggle="tooltip"]').tooltip() $('[data-toggle="tooltip"]').tooltip()
}); });
</script> </script>
{% endif %} {% endif %}
@ -524,18 +524,18 @@
<script type="text/javascript"> <script type="text/javascript">
function userGoToSettings(){ function userGoToSettings(){
localStorage.setItem('activeTabSettings', "profil"); localStorage.setItem('activeTabSettings', "profil");
location.href = "{% url 'dasettings' %}" location.href = "{% url 'dasettings' %}"
} }
function userGoToNotification(){ function userGoToNotification(){
localStorage.setItem('activeTabSettings', "notifications"); localStorage.setItem('activeTabSettings', "notifications");
location.href = "{% url 'dasettings' %}" location.href = "{% url 'dasettings' %}"
} }
function clearSF(){ function clearSF(){
$("#searchcontent").empty(); $("#searchcontent").empty();
$("#searchcontent").hide(); $("#searchcontent").hide();
$("#maincontent").show(); $("#maincontent").show();
$("#search_string").val(""); $("#search_string").val("");
} }
@ -549,26 +549,26 @@ function clearSF(){
data:{ data:{
searchstring: searchstring searchstring: searchstring
}, },
success: function( data ) success: function( data )
{ {
$("#maincontent").hide(); $("#maincontent").hide();
$("#searchcontent").show(); $("#searchcontent").show();
$("#searchcontent").html(data); $("#searchcontent").html(data);
} }
}); });
} else { } else {
$("#searchcontent").empty(); $("#searchcontent").empty();
$("#searchcontent").hide(); $("#searchcontent").hide();
$("#maincontent").show(); $("#maincontent").show();
} }
} }
$(document).ready(function(){ $(document).ready(function(){
if($( window ).width() < 768) if($( window ).width() < 768)
{ {
$("#accordionSidebar").addClass("toggled"); $("#accordionSidebar").addClass("toggled");
$("#content-wrapper").css("margin-left" , "0px"); $("#content-wrapper").css("margin-left" , "0px");
$("#topnavbarmain").css("margin-left" , "0px"); $("#topnavbarmain").css("margin-left" , "0px");
@ -577,21 +577,21 @@ $(document).ready(function(){
}); });
// Toggle the side navigation // Toggle the side navigation
function toggleSidebar(){ function toggleSidebar(){
if(sidebar_hidden == false){ if(sidebar_hidden == false){
$("#accordionSidebar").addClass("toggled"); $("#accordionSidebar").addClass("toggled");
$("#content-wrapper").css("margin-left" , "105px"); $("#content-wrapper").css("margin-left" , "105px");
$("#topnavbarmain").css("margin-left" , "105px"); $("#topnavbarmain").css("margin-left" , "105px");
sidebar_hidden = true; sidebar_hidden = true;
} }
else{ else{
$("#accordionSidebar").removeClass("toggled"); $("#accordionSidebar").removeClass("toggled");
$("#content-wrapper").css("margin-left" , "0px"); $("#content-wrapper").css("margin-left" , "0px");
$("#topnavbarmain").css("margin-left" , "0px"); $("#topnavbarmain").css("margin-left" , "0px");
sidebar_hidden = false; sidebar_hidden = false;
} }
} }
@ -599,16 +599,16 @@ $( window ).resize(function() {
if($( window ).width() < 750) if($( window ).width() < 750)
{ {
$("#accordionSidebar").addClass("toggled"); $("#accordionSidebar").addClass("toggled");
$("#content-wrapper").css("margin-left" , "0px"); $("#content-wrapper").css("margin-left" , "0px");
$("#topnavbarmain").css("margin-left" , "0px"); $("#topnavbarmain").css("margin-left" , "0px");
sidebar_hidden = false; sidebar_hidden = false;
} }
else{ else{
$("#accordionSidebar").removeClass("toggled"); $("#accordionSidebar").removeClass("toggled");
$("#content-wrapper").css("margin-left" , "212px"); $("#content-wrapper").css("margin-left" , "212px");
$("#topnavbarmain").css("margin-left" , "224px"); $("#topnavbarmain").css("margin-left" , "224px");
sidebar_hidden = true; sidebar_hidden = true;
} }
}); });
/* /*
@ -624,8 +624,8 @@ function loadUnsendNotifications(){
data : { data : {
action : "checknotifications" action : "checknotifications"
}, },
success: function( data ) success: function( data )
{ {
$("#notification_items").html(""); $("#notification_items").html("");
notifications = data['unknownnotification']; notifications = data['unknownnotification'];
var i = 0; var i = 0;
@ -634,7 +634,7 @@ function loadUnsendNotifications(){
$("#notification_items").append('<span><a href="/'+notifications[i]['elelink']+'" id="notifyid_'+notifications[i]['not_id']+'" class="dropdown-item d-flex align-items-center"><div><div class="small text-gray-500">'+notifications[i]['date']+'</div>'+notifications[i]['text']+'</div></a></span>') $("#notification_items").append('<span><a href="/'+notifications[i]['elelink']+'" id="notifyid_'+notifications[i]['not_id']+'" class="dropdown-item d-flex align-items-center"><div><div class="small text-gray-500">'+notifications[i]['date']+'</div>'+notifications[i]['text']+'</div></a></span>')
i = i + 1; i = i + 1;
newunknownotificationscounter = newunknownotificationscounter + 1; newunknownotificationscounter = newunknownotificationscounter + 1;
} }
$("#notificationcounter").html(""); $("#notificationcounter").html("");
if(i > 0){$("#notificationcounter").html(i);} if(i > 0){$("#notificationcounter").html(i);}
@ -650,8 +650,8 @@ function loadUnviewnNotifications(){
data : { data : {
action : "oldnotifications" action : "oldnotifications"
}, },
success: function( data ) success: function( data )
{ {
notifications = data['oldnotifications']; notifications = data['oldnotifications'];
i = 0; i = 0;
$("#notification_items").html(""); $("#notification_items").html("");
@ -660,7 +660,7 @@ function loadUnviewnNotifications(){
$("#notification_items").append('<a href="/'+notifications[i]['elelink']+'" id="notifyid_'+notifications[i]['not_id']+'" class="dropdown-item d-flex align-items-center"><div><div class="small text-gray-500">'+notifications[i]['date']+'</div>'+notifications[i]['text']+'</div></a>') $("#notification_items").append('<a href="/'+notifications[i]['elelink']+'" id="notifyid_'+notifications[i]['not_id']+'" class="dropdown-item d-flex align-items-center"><div><div class="small text-gray-500">'+notifications[i]['date']+'</div>'+notifications[i]['text']+'</div></a>')
i = i + 1; i = i + 1;
} }
} }
} }
}); });
} }
@ -673,8 +673,8 @@ function changeNewNotToViewed(){
data : { data : {
action : "newnotificationsviewed" action : "newnotificationsviewed"
}, },
success: function( data ) success: function( data )
{ {
$("#notificationcounter").html(""); $("#notificationcounter").html("");
} }
}); });
@ -711,12 +711,12 @@ $(document).ready(function(){
} }
const mainwebsocket = new WebSocket(ws_string+window.location.host+"/ws/") const mainwebsocket = new WebSocket(ws_string+window.location.host+"/ws/")
mainwebsocket.onmessage = function(e) { mainwebsocket.onmessage = function(e) {
if(e["data"] != "presence_update") if(e["data"] != "presence_update")
{ {
//HANDLER FOR ALL PUSHNOTIFICATIONS //HANDLER FOR ALL PUSHNOTIFICATIONS
if(e["data"].split("__")[0] == "pushnotification"){ if(e["data"].split("__")[0] == "pushnotification"){
/* /*
Check for Chat-Message in CHatview or invisible-Browser Check for Chat-Message in CHatview or invisible-Browser
@ -727,7 +727,7 @@ $(document).ready(function(){
if(finalsplit[0] != "Chat"){ if(finalsplit[0] != "Chat"){
var notify = new Notification('Digitale Agentur', { var notify = new Notification('Digitale Agentur', {
body: e["data"].split("__")[1] body: e["data"].split("__")[1]
}); });
} }
else{ else{
{% if active_link == "chat" %} {% if active_link == "chat" %}
@ -751,20 +751,20 @@ $(document).ready(function(){
else{ else{
var notify = new Notification('Digitale Agentur', { var notify = new Notification('Digitale Agentur', {
body: e["data"].split("__")[1] body: e["data"].split("__")[1]
}); });
} }
} }
} }
} }
loadUnsendNotifications(); loadUnsendNotifications();
loadUnviewnNotifications(); loadUnviewnNotifications();
} }
else{ else{
{% if active_link == "chat" %} {% if active_link == "chat" %}
if(preventUpdatePresLive == false){ if(preventUpdatePresLive == false){
updatePresenceLive(); updatePresenceLive();
} }
{% endif %} {% endif %}
} }
@ -778,10 +778,10 @@ $(document).ready(function(){
//HEARTBEAT every minute //HEARTBEAT every minute
setInterval(function() setInterval(function()
{ {
mainwebsocket.send(JSON.stringify("heartbeat")); mainwebsocket.send(JSON.stringify("heartbeat"));
console.log("heartbeat is alive..."); console.log("heartbeat is alive...");
},60000); },60000);
}); });
@ -793,8 +793,8 @@ function changeOnlineStatus(newstat){
data : { data : {
newstat : newstat newstat : newstat
}, },
success: function( data ) success: function( data )
{ {
if(data["newstat"] == "0"){ if(data["newstat"] == "0"){
$("#userbaseprofilepicture").css({ $("#userbaseprofilepicture").css({
'-webkit-box-shadow' : '0px 0px 4px 5px green', '-webkit-box-shadow' : '0px 0px 4px 5px green',
@ -814,15 +814,15 @@ function changeOnlineStatus(newstat){
'-webkit-box-shadow' : '0px 0px 4px 5px orange', '-webkit-box-shadow' : '0px 0px 4px 5px orange',
'-moz-box-shadow': '0px 0px 4px 5px orange', '-moz-box-shadow': '0px 0px 4px 5px orange',
'box-shadow': '0px 0px 4px 5px orange' 'box-shadow': '0px 0px 4px 5px orange'
}) })
} }
else if(data["newstat"] == "3"){ else if(data["newstat"] == "3"){
$("#userbaseprofilepicture").css({ $("#userbaseprofilepicture").css({
'-webkit-box-shadow' : '0px 0px 4px 5px grey', '-webkit-box-shadow' : '0px 0px 4px 5px grey',
'-moz-box-shadow': '0px 0px 4px 5px grey', '-moz-box-shadow': '0px 0px 4px 5px grey',
'box-shadow': '0px 0px 4px 5px grey' 'box-shadow': '0px 0px 4px 5px grey'
}) })
} }
} }
}); });
} }
@ -836,7 +836,7 @@ window.onerror = function (msg, url, line) {
} else { } else {
// check if permission is already granted // check if permission is already granted
if (Notification.permission === 'granted') { if (Notification.permission === 'granted') {
// show notification here // show notification here
} else { } else {
// request permission from user // request permission from user
Notification.requestPermission().then(function(p) { Notification.requestPermission().then(function(p) {
@ -851,7 +851,7 @@ window.onerror = function (msg, url, line) {
}); });
} }
} }
$("#chatButton").click(function(){ $("#chatButton").click(function(){
@ -862,8 +862,8 @@ $("#chatButton").click(function(){
data : { data : {
action : "getloggedusers" action : "getloggedusers"
}, },
success: function( data ) success: function( data )
{ {
$("#chat_alluserscontent").fadeToggle(); $("#chat_alluserscontent").fadeToggle();
$("#chat_alluserscontent").html(data); $("#chat_alluserscontent").html(data);
} }
@ -872,7 +872,3 @@ $("#chatButton").click(function(){
</script> </script>

View File

@ -11,16 +11,16 @@
<title>Digitale Agentur</title> <title>Digitale Agentur</title>
<!-- Custom fonts for this template--> <!-- Custom fonts for this template-->
<link rel="canonical" href="https://www.digitale-agentur.com"> <link rel="canonical" href="https://www.digitale-agentur.com">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
<link href="{%static 'users/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css"> <link href="{%static 'users/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<!--<link href="{%static 'users/css/bootstrap.min.css' %}" rel="stylesheet">--> <!--<link href="{%static 'users/css/bootstrap.min.css' %}" rel="stylesheet">-->
<link href='https://fonts.googleapis.com/css?family=Roboto&display=swap' rel='stylesheet' type='text/css'> <link href='https://fonts.googleapis.com/css?family=Roboto&display=swap' rel='stylesheet' type='text/css'>
@ -34,37 +34,37 @@
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script>
<!-- <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>--> <!-- <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>-->
<!-- CROPPER --> <!-- CROPPER -->
<link href="{% static 'users/css/cropper.min.css' %}" rel="stylesheet"> <link href="{% static 'users/css/cropper.min.css' %}" rel="stylesheet">
<!-- DATATABLES --> <!-- DATATABLES -->
<link href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css" rel="stylesheet"> <link href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" rel="stylesheet"> <link href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" rel="stylesheet">
<!-- Custom styles for this template--> <!-- Custom styles for this template-->
<link href="{% static 'users/css/sb-admin-2.css' %}" rel="stylesheet"> <link href="{% static 'users/css/sb-admin-2.css' %}" rel="stylesheet">
<link href="{% static 'users/css/theme.css' %}" rel="stylesheet"> <link href="{% static 'users/css/theme.css' %}" rel="stylesheet">
<link href="{% static 'users/css/custom.css' %}" rel="stylesheet"> <link href="{% static 'users/css/custom.css' %}" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote-bs4.js"></script> <script src="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote-bs4.js"></script>
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote.css" rel="stylesheet">
<script src="{% static 'summernote/lang/summernote-de-DE.min.js' %}"></script> <script src="{% static 'summernote/lang/summernote-de-DE.min.js' %}"></script>
<style type="text/css"> <style type="text/css">
.background-image { .background-image {
background-image: url('{% static 'users/img/registerbackground.jpg' %}'); background-image: url('{% static 'users/img/registerbackground.jpg' %}');
background-size: cover; /* Resize the background image to cover the entire container */ background-size: cover; /* Resize the background image to cover the entire container */
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
filter: blur(8px); filter: blur(8px);
@ -85,7 +85,7 @@
<ul class=" bg-gray-900 navbar sidebar-dark accordion fixed-top" id="accordionSidebar"> <ul class=" bg-gray-900 navbar sidebar-dark accordion fixed-top" id="accordionSidebar">
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="{% url 'users-dashboard' %}"> <a class="sidebar-brand d-flex align-items-center justify-content-center" href="{% url 'users-dashboard' %}">
<div class="sidebar-brand-text mx-3" style="text-align: left;"> <div class="sidebar-brand-text mx-3" style="text-align: left;">
<img src="{% static 'users/img/logo.png' %}" style="float: left;" width="7%" class=""> <img src="{% static 'users/img/logo.png' %}" style="float: left;" width="7%" class="">
<img src="{% static 'users/img/VVE-Logo.png' %}" style="float: right;" width="2.5%" class=""> <img src="{% static 'users/img/VVE-Logo.png' %}" style="float: right;" width="2.5%" class="">
@ -94,13 +94,13 @@
</ul> </ul>
<style type="text/css"> <style type="text/css">
#logincard { #logincard {
width: 35%; width: 35%;
min-width: 500px !important; min-width: 500px !important;
margin-top: 4%; margin-top: 4%;
} }
</style> </style>
{% block content %} {% block content %}
{% endblock %} {% endblock %}
</body> </body>
</html> </html>

View File

@ -56,10 +56,10 @@ def randomString(stringLength=10):
@login_required @login_required
def toUpdate(request): def toUpdate(request):
# NO AGENVYJOBS # NO AGENVYJOBS
# CREATE DEFAULT # CREATE DEFAULT
''' '''
Agenturleiter Agenturleiter
Außendienst Außendienst
Innendienst Innendienst
@ -97,25 +97,25 @@ def toUpdate(request):
temgroup_mitarbeiter_ag.group.user_set.add(user) temgroup_mitarbeiter_ag.group.user_set.add(user)
# ADDING ALL RIGHTS TO GROUP "VERWALTUNG" # ADDING ALL RIGHTS TO GROUP "VERWALTUNG"
perms = AgencyGroup._meta.permissions perms = AgencyGroup._meta.permissions
for p in perms: for p in perms:
tempperm = Permission.objects.get(codename=p[0]) tempperm = Permission.objects.get(codename=p[0])
temgroup_verwaltung_ag.group.permissions.add(tempperm) temgroup_verwaltung_ag.group.permissions.add(tempperm)
print("default groups created and users added") print("default groups created and users added")
else: else:
print("default groups existing") print("default groups existing")
# CHECK FOR ALL POSSIBLE RIGHTS ON ADMINGROUP # CHECK FOR ALL POSSIBLE RIGHTS ON ADMINGROUP
m2m_changed.disconnect(adjust_group_notifications_permission, sender=Group.permissions.through) m2m_changed.disconnect(adjust_group_notifications_permission, sender=Group.permissions.through)
ag_admingroup = list(AgencyGroup.objects.filter(agency=request.user.profile.agency, is_admin=True))[0] ag_admingroup = list(AgencyGroup.objects.filter(agency=request.user.profile.agency, is_admin=True))[0]
perms = AgencyGroup._meta.permissions perms = AgencyGroup._meta.permissions
for p in perms: for p in perms:
tempperm = Permission.objects.get(codename=p[0]) tempperm = Permission.objects.get(codename=p[0])
ag_admingroup.group.permissions.add(tempperm) ag_admingroup.group.permissions.add(tempperm)
# INITIAL ROOT DIR # INITIAL ROOT DIR
rootdir = DataDir.objects.filter(is_root=True, agency__pk=request.user.profile.agency.pk) rootdir = DataDir.objects.filter(is_root=True, agency__pk=request.user.profile.agency.pk)
@ -123,7 +123,7 @@ def toUpdate(request):
print("NO MAIN DIR FOUND - CREATE") print("NO MAIN DIR FOUND - CREATE")
rootdir = DataDir(is_root=True, agency=request.user.profile.agency) rootdir = DataDir(is_root=True, agency=request.user.profile.agency)
rootdir.save() rootdir.save()
print("AGENCY ROOT DIR CREATED") print("AGENCY ROOT DIR CREATED")
else: else:
print("MAIN ROOT DIR FOUND - FILESMODULE READY") print("MAIN ROOT DIR FOUND - FILESMODULE READY")
@ -135,7 +135,7 @@ def toUpdate(request):
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/files")) os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/files"))
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/agencystats")) os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/agencystats"))
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/agencystats/profilepics")) os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/agencystats/profilepics"))
# DEF STANDARD DIR # DEF STANDARD DIR
defstandard = DataDir.objects.filter(is_defaultstandard=True, agency__pk=request.user.profile.agency.pk) defstandard = DataDir.objects.filter(is_defaultstandard=True, agency__pk=request.user.profile.agency.pk)
@ -161,7 +161,7 @@ def toUpdate(request):
# USER TIME MODEL # USER TIME MODEL
usersofagency = User.objects.filter(profile__agency=request.user.profile.agency) usersofagency = User.objects.filter(profile__agency=request.user.profile.agency)
for u in usersofagency: for u in usersofagency:
# CREATE USERTIME-OBJECT # CREATE USERTIME-OBJECT
if(len(UserTime.objects.filter(user=u)) == 0): if(len(UserTime.objects.filter(user=u)) == 0):
usertime_new = UserTime(user=u) usertime_new = UserTime(user=u)
@ -182,19 +182,19 @@ Templates: welcomeusers.html und base.html
''' '''
def registerNewAgency(request): def registerNewAgency(request):
if request.method == "POST": if request.method == "POST":
newagencyform = NewAgencyForm(request.POST) newagencyform = NewAgencyForm(request.POST)
if newagencyform.is_valid(): if newagencyform.is_valid():
# Check Mail # Check Mail
email = newagencyform.cleaned_data.get('mail') email = newagencyform.cleaned_data.get('mail')
mailset = User.objects.filter(email=email) mailset = User.objects.filter(email=email)
if(len(mailset) == 0): if(len(mailset) == 0):
newuser_name = newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name') newuser_name = newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name')
agency = Agency() agency = Agency()
agency.name = newagencyform.cleaned_data.get("agencyname") agency.name = newagencyform.cleaned_data.get("agencyname")
agency.vve = newagencyform.cleaned_data.get("vve") agency.vve = newagencyform.cleaned_data.get("vve")
agency.save() agency.save()
@ -212,9 +212,9 @@ def registerNewAgency(request):
user.profile = pr user.profile = pr
user.save() user.save()
msg_html = render_to_string('users/register_mail.html', {'username': newuser_name}) msg_html = render_to_string('users/register_mail.html', {'username': newuser_name})
# E-Mail für Passwort-Setzung! # E-Mail für Passwort-Setzung!
form = PasswordResetForm({'email': email}) form = PasswordResetForm({'email': email})
if form.is_valid(): if form.is_valid():
form.save(request=request,html_email_template_name='users/password_reset_mail.html') form.save(request=request,html_email_template_name='users/password_reset_mail.html')
@ -225,10 +225,10 @@ def registerNewAgency(request):
'Agenturanmeldung', 'Agenturanmeldung',
'Hallo ' + newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name') + '! Bitte setzen sie sich auf https://digitale-agentur.com/password-reset/ ein Passwort. Anschließend können Sie weitere Details Ihrer Agentur eingeben.', 'Hallo ' + newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name') + '! Bitte setzen sie sich auf https://digitale-agentur.com/password-reset/ ein Passwort. Anschließend können Sie weitere Details Ihrer Agentur eingeben.',
'noreply@digitale-agentur.com', 'noreply@digitale-agentur.com',
[email], [email],
html_message=msg_html, html_message=msg_html,
fail_silently=True fail_silently=True
) )
''' '''
return render (request, 'users/registercomplete.html') return render (request, 'users/registercomplete.html')
@ -238,7 +238,7 @@ def registerNewAgency(request):
"form" : NewAgencyForm(request.POST) "form" : NewAgencyForm(request.POST)
} }
return render (request, 'users/register.html',context) return render (request, 'users/register.html',context)
else: else:
messages.success(request, f'Es ist ein Fehler aufgetreten.') messages.success(request, f'Es ist ein Fehler aufgetreten.')
@ -258,39 +258,39 @@ class AgencyCreateView(CreateView):
fields = ['first_name', 'last_name','username', 'email'] fields = ['first_name', 'last_name','username', 'email']
success_url = '/register/done' success_url = '/register/done'
def form_valid(self, form): def form_valid(self, form):
# Send message to the site # Send message to the site
messages.success(self.request, f'Agentur erstellt! Es wurde eine E-Mail verschickt mit weitere Infos zur Passworterstellung.') messages.success(self.request, f'Agentur erstellt! Es wurde eine E-Mail verschickt mit weitere Infos zur Passworterstellung.')
# SAVE OBJECTS TO SIGNALE! # SAVE OBJECTS TO SIGNALE!
agency = Agency() agency = Agency()
agency.name = self.request.POST.get("agency_name") agency.name = self.request.POST.get("agency_name")
agency.save() agency.save()
newuser_name = form.cleaned_data.get('first_name') + ' ' + form.cleaned_data.get('last_name') newuser_name = form.cleaned_data.get('first_name') + ' ' + form.cleaned_data.get('last_name')
form.instance.agency = agency form.instance.agency = agency
form.instance.parent = None form.instance.parent = None
msg_html = render_to_string('users/register_mail.html', {'username': newuser_name}) msg_html = render_to_string('users/register_mail.html', {'username': newuser_name})
# E-Mail für Passwort-Setzung! # E-Mail für Passwort-Setzung!
send_mail( send_mail(
'Agenturanmeldung', 'Agenturanmeldung',
'Hallo ' + form.cleaned_data.get('first_name') + ' ' + form.cleaned_data.get('last_name') + '! Bitte setzen sie sich auf https://digitale-agentur.com/password-reset/ ein Passwort. Anschließend können Sie weitere Details Ihrer Agentur eingeben.', 'Hallo ' + form.cleaned_data.get('first_name') + ' ' + form.cleaned_data.get('last_name') + '! Bitte setzen sie sich auf https://digitale-agentur.com/password-reset/ ein Passwort. Anschließend können Sie weitere Details Ihrer Agentur eingeben.',
'noreply@digitale-agentur.com', 'noreply@digitale-agentur.com',
[form.cleaned_data.get('email')], [form.cleaned_data.get('email')],
html_message=msg_html, html_message=msg_html,
fail_silently=True fail_silently=True
) )
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)
#storageinfo = sys.getfilesystemencoding() #storageinfo = sys.getfilesystemencoding()
context = { context = {
'active_link' : 'dashboard', 'active_link' : 'dashboard',
#"systemencode" : storageinfo #"systemencode" : storageinfo
} }
@ -298,8 +298,8 @@ def dashboard(request):
# Loading only user same agency # Loading only user same agency
# Change context and return for template-data # Change context and return for template-data
# # Get all Users of the Same Agency as logged user # # Get all Users of the Same Agency as logged user
standards_of_agency = Standards.objects.filter(agency__pk=request.user.profile.agency.pk).filter(public=True).exclude(area=None).exclude(task=None).order_by('-last_modified_on')[:5] standards_of_agency = Standards.objects.filter(agency__pk=request.user.profile.agency.pk).filter(public=True).exclude(area=None).exclude(task=None).order_by('-last_modified_on')[:5]
filterdate = datetime.now() filterdate = datetime.now()
news = News.objects.filter(agency__pk=request.user.profile.agency.pk).filter(go_online_on__lt=filterdate).filter(go_offline_on__gt=filterdate).order_by('-go_online_on')[:4] news = News.objects.filter(agency__pk=request.user.profile.agency.pk).filter(go_online_on__lt=filterdate).filter(go_offline_on__gt=filterdate).order_by('-go_online_on')[:4]
@ -331,19 +331,19 @@ class UsersCreateUser(LoginRequiredMixin, CreateView):
model = User model = User
fields = ['first_name', 'last_name', 'email'] fields = ['first_name', 'last_name', 'email']
success_url = '/settings/newuser/s2/' success_url = '/settings/newuser/s2/'
# Adding active_link # Adding active_link
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context.update({'active_link' : 'settings'}) context.update({'active_link' : 'settings'})
return context return context
def form_valid(self, form): def form_valid(self, form):
# Send message to the site # Send message to the site
messages.success(self.request, f'Neuer Mitarbeiter angelegt!') messages.success(self.request, f'Neuer Mitarbeiter angelegt!')
# SAVE OBJECTS TO SIGNALE! # SAVE OBJECTS TO SIGNALE!
form.instance.agency = self.request.user.profile.agency form.instance.agency = self.request.user.profile.agency
form.instance.parent = None form.instance.parent = None
newuser_name = form.cleaned_data.get('first_name') + " " + form.cleaned_data.get('last_name') newuser_name = form.cleaned_data.get('first_name') + " " + form.cleaned_data.get('last_name')
msg_html = render_to_string('users/newusers_email.html', {'username': newuser_name}) msg_html = render_to_string('users/newusers_email.html', {'username': newuser_name})
''' '''
@ -355,7 +355,7 @@ class UsersCreateUser(LoginRequiredMixin, CreateView):
[form.cleaned_data.get('email')], [form.cleaned_data.get('email')],
html_message=msg_html, html_message=msg_html,
fail_silently=True, fail_silently=True,
) )
''' '''
return super().form_valid(form) return super().form_valid(form)
@ -364,14 +364,14 @@ class UsersCreateUser(LoginRequiredMixin, CreateView):
def profile(request): def profile(request):
if request.method == 'POST': if request.method == 'POST':
u_form = UsersChangeProfil(request.POST, instance=request.user) u_form = UsersChangeProfil(request.POST, instance=request.user)
if u_form.is_valid(): if u_form.is_valid():
u_form.save() u_form.save()
prename = request.user.first_name prename = request.user.first_name
name = request.user.last_name name = request.user.last_name
messages.success(request, f'Daten für {prename} {name} aktualisiert!') messages.success(request, f'Daten für {prename} {name} aktualisiert!')
# Daten neu laden und nicht die "Mächten sie die Daten speichern...?" # Daten neu laden und nicht die "Mächten sie die Daten speichern...?"
return redirect('users-dashboard') return redirect('users-dashboard')
else: else:
# Form in Klammern sind die aktuellen Daten :) # Form in Klammern sind die aktuellen Daten :)
@ -387,16 +387,16 @@ def profile(request):
# Hier andere Nutzer ändern, wenn man Usersmanagement darf! # Hier andere Nutzer ändern, wenn man Usersmanagement darf!
class UserManagementUpdateForm(LoginRequiredMixin, UpdateView): class UserManagementUpdateForm(LoginRequiredMixin, UpdateView):
model = Profile model = Profile
labels = { labels = {
"phoneland" : "Telefon", "phoneland" : "Telefon",
"phonemobile" : "Mobil", "phonemobile" : "Mobil",
"compfunc" : "Agenturfunktion", "compfunc" : "Agenturfunktion",
} }
fields = ['phoneland','phonemobile','compfunc'] fields = ['phoneland','phonemobile','compfunc']
# Update der Zugrifssrechte eines Users # Update der Zugrifssrechte eines Users
class UsersPermUpdateView(LoginRequiredMixin, View): class UsersPermUpdateView(LoginRequiredMixin, View):
template_name = 'users/users_perm.html' template_name = 'users/users_perm.html'
form_class = UsersPermForm form_class = UsersPermForm
success_url = '/dashboard/usersman/' success_url = '/dashboard/usersman/'
@ -405,11 +405,11 @@ class UsersPermUpdateView(LoginRequiredMixin, View):
# Form wird geladen; Checkboxen werden vorbereitet und hier rausgerendert. # Form wird geladen; Checkboxen werden vorbereitet und hier rausgerendert.
def get(self,request,*args, **kwargs): def get(self,request,*args, **kwargs):
# User ist der hier Aufgerufene, bzw. das Profil! # User ist der hier Aufgerufene, bzw. das Profil!
user_tochange = Profile.objects.get(pk=kwargs['pk']).user user_tochange = Profile.objects.get(pk=kwargs['pk']).user
return render (request, self.template_name, {'form':self.form_class(user_tochange), 'active_link': 'usersmanagement', 'user_tochange': user_tochange}) return render (request, self.template_name, {'form':self.form_class(user_tochange), 'active_link': 'usersmanagement', 'user_tochange': user_tochange})
# Handle POST GTTP requests # Handle POST GTTP requests
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
permissions_loaded = dict(request.POST.lists()) permissions_loaded = dict(request.POST.lists())
user_tochange = Profile.objects.get(pk=kwargs['pk']).user user_tochange = Profile.objects.get(pk=kwargs['pk']).user
# ITERATION Über alle Elemente gehen und Rechte entziehen (nicht vorhanden) oder adden (wenn vorhanden) # ITERATION Über alle Elemente gehen und Rechte entziehen (nicht vorhanden) oder adden (wenn vorhanden)
@ -418,14 +418,14 @@ class UsersPermUpdateView(LoginRequiredMixin, View):
temprof = Profile temprof = Profile
for ele in temprof._meta.permissions: for ele in temprof._meta.permissions:
tempperm = Permission.objects.get(codename=ele[0]) tempperm = Permission.objects.get(codename=ele[0])
if ele[0] in permissions_loaded: if ele[0] in permissions_loaded:
user_tochange.user_permissions.add(tempperm) user_tochange.user_permissions.add(tempperm)
else: else:
# Eingeloggter User darf sich nicht selbst die Userverwaltungsrechte entziehen # Eingeloggter User darf sich nicht selbst die Userverwaltungsrechte entziehen
if user_tochange == request.user and ele[0]=='usermanager': if user_tochange == request.user and ele[0]=='usermanager':
messages.warning(request, f'Benutzerverwaltungsrechte für {user_tochange.first_name} {user_tochange.last_name} kann nicht entfernt werden.') messages.warning(request, f'Benutzerverwaltungsrechte für {user_tochange.first_name} {user_tochange.last_name} kann nicht entfernt werden.')
else: else:
user_tochange.user_permissions.remove(tempperm) user_tochange.user_permissions.remove(tempperm)
user_tochange.save() user_tochange.save()
messages.success(request, f'Berechtigungen für {user_tochange.first_name} {user_tochange.last_name} aktualisiert!') messages.success(request, f'Berechtigungen für {user_tochange.first_name} {user_tochange.last_name} aktualisiert!')
return HttpResponseRedirect('/dashboard/usersman/') return HttpResponseRedirect('/dashboard/usersman/')
@ -434,7 +434,7 @@ class UsersPermUpdateView(LoginRequiredMixin, View):
@login_required @login_required
def ProfileUpdateView(request, pk): def ProfileUpdateView(request, pk):
prof_user = User.objects.get(profile__pk=pk) prof_user = User.objects.get(profile__pk=pk)
if request.method == 'POST': if request.method == 'POST':
profileform_form = UsersAddProfileForm(request.POST, request.FILES, instance=prof_user.profile) profileform_form = UsersAddProfileForm(request.POST, request.FILES, instance=prof_user.profile)
#profileform_parents = UsersAddProfileFormParents(request.POST, instance=request.user) #profileform_parents = UsersAddProfileFormParents(request.POST, instance=request.user)
@ -442,25 +442,25 @@ def ProfileUpdateView(request, pk):
name = prof_user.last_name name = prof_user.last_name
if profileform_form.is_valid(): if profileform_form.is_valid():
profileform_form.save() profileform_form.save()
messages.success(request, f'Daten für {prename} {name} aktualisiert!') messages.success(request, f'Daten für {prename} {name} aktualisiert!')
return redirect('users-management') return redirect('users-management')
else: else:
# Form in Klammern sind die aktuellen Daten :) # Form in Klammern sind die aktuellen Daten :)
profileform_form = UsersAddProfileForm(instance=prof_user.profile) profileform_form = UsersAddProfileForm(instance=prof_user.profile)
# Nur User, die im Organigramm auch sichtbar sein, können ausgewählt werden # Nur User, die im Organigramm auch sichtbar sein, können ausgewählt werden
possible_users = User.objects.filter(profile__agency__pk=prof_user.profile.agency.pk).filter(profile__visible=True) possible_users = User.objects.filter(profile__agency__pk=prof_user.profile.agency.pk).filter(profile__visible=True)
context = { context = {
'prof_user' : prof_user, 'prof_user' : prof_user,
'profileform_form' : profileform_form, 'profileform_form' : profileform_form,
'active_link' : 'usersmanagement', 'active_link' : 'usersmanagement',
'possible_users' : possible_users 'possible_users' : possible_users
} }
return render(request, 'users/profile_update.html', context) return render(request, 'users/profile_update.html', context)
''' '''
@ -471,13 +471,13 @@ def ProfileUpdateView(request, pk):
@login_required @login_required
def setuserparent(request): def setuserparent(request):
if request.method == 'GET': if request.method == 'GET':
if request.GET['action'] == 'adduserp': if request.GET['action'] == 'adduserp':
userid = request.GET['objectid'] userid = request.GET['objectid']
toadd = request.GET['userid'] toadd = request.GET['userid']
toadd_user = User.objects.get(pk=toadd) toadd_user = User.objects.get(pk=toadd)
workinguser = User.objects.get(pk=userid) workinguser = User.objects.get(pk=userid)
username_clean = toadd_user.first_name + " " + toadd_user.last_name username_clean = toadd_user.first_name + " " + toadd_user.last_name
workinguser.profile.parent = toadd_user workinguser.profile.parent = toadd_user
workinguser.save() workinguser.save()
# Getting Remaining-Users # Getting Remaining-Users
possible_users = User.objects.filter(profile__agency__pk=request.user.profile.agency.pk) possible_users = User.objects.filter(profile__agency__pk=request.user.profile.agency.pk)
@ -486,14 +486,14 @@ def setuserparent(request):
final_possible_users = {} final_possible_users = {}
for ele in possible_users_js: for ele in possible_users_js:
final_possible_users.update({'first_name':ele['first_name'],'last_name':ele['last_name'],'id':ele['id']}) final_possible_users.update({'first_name':ele['first_name'],'last_name':ele['last_name'],'id':ele['id']})
# Counter for remaining users to show/hide "Keine Mitarbeiter"-Div # Counter for remaining users to show/hide "Keine Mitarbeiter"-Div
return JsonResponse({'userid' : userid, 'username_clean' : username_clean, 'remaining_users':possible_users_js}) return JsonResponse({'userid' : userid, 'username_clean' : username_clean, 'remaining_users':possible_users_js})
else: else:
return HttpResponse("Request method is not a GET") return HttpResponse("Request method is not a GET")
@login_required @login_required
def changeonlinestat(request): def changeonlinestat(request):
if request.method == 'GET': if request.method == 'GET':
request.user.profile.onlinestatus = request.GET["newstat"] request.user.profile.onlinestatus = request.GET["newstat"]
request.user.save() request.user.save()
return JsonResponse({"newstat" : request.GET["newstat"]}) return JsonResponse({"newstat" : request.GET["newstat"]})
@ -511,9 +511,9 @@ class ProfileDeleteView(LoginRequiredMixin, DeleteView):
model = User model = User
success_url = '/dasettings/main' success_url = '/dasettings/main'
template_name = 'users/user_confirm_delete.html' template_name = 'users/user_confirm_delete.html'
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
user = User.objects.get(pk=kwargs['pk']) user = User.objects.get(pk=kwargs['pk'])
logged_user = request.user logged_user = request.user
areas_fs = Areas.objects.filter(created_area_by=user) areas_fs = Areas.objects.filter(created_area_by=user)
@ -549,8 +549,8 @@ class ProfileDeleteView(LoginRequiredMixin, DeleteView):
return response return response
@login_required @login_required
def agency(request): def agency(request):
context = { context = {
'active_link' : 'agencyinfo' 'active_link' : 'agencyinfo'
} }
return render(request, 'users/agency.html', context) return render(request, 'users/agency.html', context)
@ -563,7 +563,7 @@ class AgencyUpdateView(LoginRequiredMixin, UpdateView):
success_url = '/dashboard/agencyinfo' success_url = '/dashboard/agencyinfo'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(AgencyUpdateView, self).get_context_data(**kwargs) context = super(AgencyUpdateView, self).get_context_data(**kwargs)
context['active_link'] = 'agencyinfo' context['active_link'] = 'agencyinfo'
return context return context
@ -571,19 +571,19 @@ class AgencyUpdateView(LoginRequiredMixin, UpdateView):
# PRIORISIERUNG # PRIORISIERUNG
''' '''
Es werden alle Aufgabenbereiche den Bereichen der Agentur zugeordnet und ausgegeben. Es werden alle Aufgabenbereiche den Bereichen der Agentur zugeordnet und ausgegeben.
''' '''
@login_required @login_required
def UsersPrio(request, pk): def UsersPrio(request, pk):
user = User.objects.get(pk=pk) user = User.objects.get(pk=pk)
if(user.profile.agency.pk != request.user.profile.agency.pk): if(user.profile.agency.pk != request.user.profile.agency.pk):
return HttpResponseRedirect('users-dashboard') return HttpResponseRedirect('users-dashboard')
else: else:
prios = Prio.objects.filter(user__pk=pk) prios = Prio.objects.filter(user__pk=pk)
areas = Areas.objects.filter(agency__pk=request.user.profile.agency.pk) areas = Areas.objects.filter(agency__pk=request.user.profile.agency.pk)
user_first_name = user.first_name user_first_name = user.first_name
user_last_name = user.last_name user_last_name = user.last_name
user_id = user.pk user_id = user.pk
@ -598,7 +598,7 @@ def UsersPrio(request, pk):
return render(request, 'users/users_prio.html', context) return render(request, 'users/users_prio.html', context)
''' '''
Ajax-Call für Prio.Updates seitens des Users Ajax-Call für Prio.Updates seitens des Users
im Profil im Profil
@ -645,7 +645,7 @@ def GlobalSearch(request):
res_files = DataFile.objects.filter(agency__pk=ag).filter(name__icontains=searchfor) res_files = DataFile.objects.filter(agency__pk=ag).filter(name__icontains=searchfor)
html = render_to_string('users/searchres.html', {'links': links, 'res_standard': res_standard, 'res_areas': res_areas, 'res_tasks': res_tasks, 'res_pers': res_pers, 'res_news' : res_news, 'res_pass' : res_pass, 'res_contacts' : res_contacts, 'res_files' : res_files, 'user' : request.user}) html = render_to_string('users/searchres.html', {'links': links, 'res_standard': res_standard, 'res_areas': res_areas, 'res_tasks': res_tasks, 'res_pers': res_pers, 'res_news' : res_news, 'res_pass' : res_pass, 'res_contacts' : res_contacts, 'res_files' : res_files, 'user' : request.user})
return HttpResponse(html) return HttpResponse(html)
@ -657,7 +657,7 @@ def searchStandardRouter(request):
if request.method == 'GET': if request.method == 'GET':
return redirect('/standards/standard/'+request.GET['s_id']+'/single') return redirect('/standards/standard/'+request.GET['s_id']+'/single')
else: else:
return redirect('dashboard') return redirect('dashboard')
''' '''
Hier werden die Zuständigkeiten eines Benutzers über alle Bereiche/Aufgaben hinweg gesetzt. Hier werden die Zuständigkeiten eines Benutzers über alle Bereiche/Aufgaben hinweg gesetzt.
@ -669,14 +669,14 @@ def UsersAreaTaskUpdate(request, pk):
user = User.objects.get(pk=pk) user = User.objects.get(pk=pk)
if request.user.profile.agency.pk != user.profile.agency.pk: if request.user.profile.agency.pk != user.profile.agency.pk:
return redirect('dashboard') return redirect('dashboard')
else: else:
finaldata = {} finaldata = {}
context = { context = {
'active_link' : 'usersmanagement', 'active_link' : 'usersmanagement',
'user_id' : user.pk, 'user_id' : user.pk,
} }
if request.method == 'POST': if request.method == 'POST':
form = request.POST form = request.POST
areatask_formdata = list(form) areatask_formdata = list(form)
@ -693,22 +693,22 @@ def UsersAreaTaskUpdate(request, pk):
area_ids.append(int(tempdata[1])) area_ids.append(int(tempdata[1]))
elif(tempdata[0] == 'task'): elif(tempdata[0] == 'task'):
task_ids.append(int(tempdata[1])) task_ids.append(int(tempdata[1]))
# Alle Areas und Tasks laden # Alle Areas und Tasks laden
areas = Areas.objects.filter(agency__pk=user.profile.agency.pk) areas = Areas.objects.filter(agency__pk=user.profile.agency.pk)
tasks = Tasks.objects.filter(agency__pk=user.profile.agency.pk) tasks = Tasks.objects.filter(agency__pk=user.profile.agency.pk)
# Prüfen, ob der User in Area ist oder nicht und ihn ggf. hinzufügen/entfernen # Prüfen, ob der User in Area ist oder nicht und ihn ggf. hinzufügen/entfernen
for area in areas: for area in areas:
if area.pk in area_ids: if area.pk in area_ids:
area.usersfield.add(user) area.usersfield.add(user)
else: else:
area.usersfield.remove(user) area.usersfield.remove(user)
area.save() area.save()
''' '''
Prüfen, ob ein User einem Aufgabenbereich hinzugeprdnet ist. Prüfen, ob ein User einem Aufgabenbereich hinzugeprdnet ist.
Ist er im Bereich, passiert nichts. Ist er nicht in diesem Ist er im Bereich, passiert nichts. Ist er nicht in diesem
Bereich, wird er dem usersfield der Aufgabe und der Tabelle Bereich, wird er dem usersfield der Aufgabe und der Tabelle
Prio hinzugeüfügt. Damit kann der User seine individuellen Prio hinzugeüfügt. Damit kann der User seine individuellen
@ -728,7 +728,7 @@ def UsersAreaTaskUpdate(request, pk):
task.save() task.save()
username_message = user.first_name + " " + user.last_name username_message = user.first_name + " " + user.last_name
messages.success(request, f'Zuständigkeiten für {username_message} aktualisiert!') messages.success(request, f'Zuständigkeiten für {username_message} aktualisiert!')
return redirect('users-management') return redirect('users-management')
else: else:
form = UserAreaTaskForm(user) form = UserAreaTaskForm(user)
user_first_name = user.first_name user_first_name = user.first_name
@ -747,7 +747,7 @@ def UsersAreaTaskUpdate(request, pk):
@login_required @login_required
def support(request): def support(request):
context = { context = {
'active_link' : 'support', 'active_link' : 'support',
'form' : SupportForm(request.user) 'form' : SupportForm(request.user)
} }
@ -758,35 +758,35 @@ def support(request):
attachments=[] #myfile is the key of a multi value dictionary, values are the uploaded files attachments=[] #myfile is the key of a multi value dictionary, values are the uploaded files
for f in request.FILES.getlist('attachment_1'): #myfile is the name of your html file button for f in request.FILES.getlist('attachment_1'): #myfile is the name of your html file button
filename = f.name filename = f.name
attachment_type = filetype.guess(f) attachment_type = filetype.guess(f)
fileblob = str(base64.b64encode(f.read())) fileblob = str(base64.b64encode(f.read()))
fileblob = fileblob[1 : : ] fileblob = fileblob[1 : : ]
fileblob = fileblob[1 : : ] fileblob = fileblob[1 : : ]
fileblob = fileblob[:-1:] fileblob = fileblob[:-1:]
attachments.append({str(filename) : "data:" + attachment_type.mime + ";base64," + fileblob}) attachments.append({str(filename) : "data:" + attachment_type.mime + ";base64," + fileblob})
fileblob = "data:" + attachment_type.mime + ";base64," + fileblob fileblob = "data:" + attachment_type.mime + ";base64," + fileblob
for f in request.FILES.getlist('attachment_2'): #myfile is the name of your html file button for f in request.FILES.getlist('attachment_2'): #myfile is the name of your html file button
filename = f.name filename = f.name
attachment_type = filetype.guess(f) attachment_type = filetype.guess(f)
fileblob = str(base64.b64encode(f.read())) fileblob = str(base64.b64encode(f.read()))
fileblob = fileblob[1 : : ] fileblob = fileblob[1 : : ]
fileblob = fileblob[1 : : ] fileblob = fileblob[1 : : ]
fileblob = fileblob[:-1:] fileblob = fileblob[:-1:]
attachments.append({str(filename) : "data:" + attachment_type.mime + ";base64," + fileblob}) attachments.append({str(filename) : "data:" + attachment_type.mime + ";base64," + fileblob})
for f in request.FILES.getlist('attachment_2'): #myfile is the name of your html file button for f in request.FILES.getlist('attachment_2'): #myfile is the name of your html file button
filename = f.name filename = f.name
attachment_type = filetype.guess(f) attachment_type = filetype.guess(f)
fileblob = str(base64.b64encode(f.read())) fileblob = str(base64.b64encode(f.read()))
fileblob = fileblob[1 : : ] fileblob = fileblob[1 : : ]
fileblob = fileblob[1 : : ] fileblob = fileblob[1 : : ]
fileblob = fileblob[:-1:] fileblob = fileblob[:-1:]
attachments.append({str(filename) : "data:" + attachment_type.mime + ";base64," + fileblob}) attachments.append({str(filename) : "data:" + attachment_type.mime + ";base64," + fileblob})
''' '''
#image = request.FILES #image = request.FILES
supportdata = dict(form) supportdata = dict(form)
# Data from Form to JSON-Format # Data from Form to JSON-Format
name = str(supportdata['name'][0]) name = str(supportdata['name'][0])
mail = str(supportdata['mail'][0]) mail = str(supportdata['mail'][0])
problemconc = str(supportdata['problemconc'][0]) problemconc = str(supportdata['problemconc'][0])
problem = str(supportdata['problem'][0]) problem = str(supportdata['problem'][0])
@ -794,31 +794,31 @@ def support(request):
# HEADERS CURL # HEADERS CURL
headers = {'X-API-Key': 'F025A238EB74914E3653BA2989BFF7C4'} headers = {'X-API-Key': 'F025A238EB74914E3653BA2989BFF7C4'}
subject = "Digitale Agentur: " + str(problemconc) subject = "Digitale Agentur: " + str(problemconc)
# DataJSON # DataJSON
ostdata = { ostdata = {
"topicId" : '12', "topicId" : '12',
"name": name, "name": name,
"email": mail, "email": mail,
"subject": 'Digitale Agentur: '+problemconc, "subject": 'Digitale Agentur: '+problemconc,
"ip": "1.1.1.1", "ip": "1.1.1.1",
"message": "*****************************\nAgentur: "+ request.user.profile.agency.name +" (ID: "+ str(request.user.profile.agency.pk) +")\nBenutzer: "+request.user.first_name+" "+request.user.last_name+" (ID: "+ str(request.user.pk) +")\n*******************************\n\n" + problem "message": "*****************************\nAgentur: "+ request.user.profile.agency.name +" (ID: "+ str(request.user.profile.agency.pk) +")\nBenutzer: "+request.user.first_name+" "+request.user.last_name+" (ID: "+ str(request.user.pk) +")\n*******************************\n\n" + problem
#"attachments" : attachments #"attachments" : attachments
} }
json_data = json.dumps(ostdata) json_data = json.dumps(ostdata)
r = requests.post("https://support.vh-solutions.de/api/http.php/tickets.json", data=json_data, headers=headers) r = requests.post("https://support.vh-solutions.de/api/http.php/tickets.json", data=json_data, headers=headers)
# IF request FAILED error-Message # IF request FAILED error-Message
if(r.status_code != 201): if(r.status_code != 201):
messages.warning(request, f'Supportanfrage fehlgeschlagen!' + str(r)) messages.warning(request, f'Supportanfrage fehlgeschlagen!' + str(r))
else: else:
messages.success(request, f'Supportanfrage erfolgreich! Ihre Ticketnummer ist '+ str(r.json()) +'!') messages.success(request, f'Supportanfrage erfolgreich! Ihre Ticketnummer ist '+ str(r.json()) +'!')
return render(request, 'users/support_done.html', context) return render(request, 'users/support_done.html', context)
else: else:
return render(request, 'users/support.html', context) return render(request, 'users/support.html', context)
''' '''
@ -827,23 +827,23 @@ Schickt eine E-Mail an den User inkl. Passwortlink zum zurücksetzen.
''' '''
def sendpassmail(request): def sendpassmail(request):
if(request.method == 'GET'): if(request.method == 'GET'):
userid = request.GET['userid'] userid = request.GET['userid']
tempuser = User.objects.get(pk=userid) tempuser = User.objects.get(pk=userid)
# E-Mail für Passwort-Setzung! # E-Mail für Passwort-Setzung!
form = PasswordResetForm({'email': tempuser.email}) form = PasswordResetForm({'email': tempuser.email})
if form.is_valid(): if form.is_valid():
form.save(request=request,html_email_template_name='users/password_reset_mail.html') form.save(request=request,html_email_template_name='users/password_reset_mail.html')
return render (request, 'users/registercomplete.html') return render (request, 'users/registercomplete.html')
return JsonResponse({'message' : 0}) return JsonResponse({'message' : 0})
def datenschutz(request): def datenschutz(request):
if request.user.is_authenticated: if request.user.is_authenticated:
return render(request, 'users/datenschutz.html') return render(request, 'users/datenschutz.html')
else: else:
return render(request, 'users/datenschutz_p.html') return render(request, 'users/datenschutz_p.html')
def impressum(request): def impressum(request):
if request.user.is_authenticated: if request.user.is_authenticated:
return render(request, 'users/impressum.html') return render(request, 'users/impressum.html')
else: else:
@ -876,37 +876,37 @@ def handler500(request):
# CRONJOBS ALLE 5 MINUTEN # CRONJOBS ALLE 5 MINUTEN
def cronactions(request, code): def cronactions(request, code):
data = {} data = {}
if(code == settings.CRONAPIKEY): if(code == settings.CRONAPIKEY):
# NEWS CHECKING # NEWS CHECKING
all_unnotifc_news = News.objects.filter(agnotify=False, go_online_on__lt=timezone.now()) all_unnotifc_news = News.objects.filter(agnotify=False, go_online_on__lt=timezone.now())
allusers = User.objects.all() allusers = User.objects.all()
for news in all_unnotifc_news: for news in all_unnotifc_news:
targeturl = settings.BASE_URL + "news/news/" + str(news.pk) + "/single" targeturl = settings.BASE_URL + "news/news/" + str(news.pk) + "/single"
# NEW NEWS FOUND WHICH HAVE TO GO ONLINE NOW! # NEW NEWS FOUND WHICH HAVE TO GO ONLINE NOW!
news.agnotify = True news.agnotify = True
news.save() news.save()
for user in allusers: for user in allusers:
# SEMI-SIGNAL FOR NEWS GOING ONLINE # SEMI-SIGNAL FOR NEWS GOING ONLINE
if(user.usernotifications.news_created_mail and news.agency == user.profile.agency): if(user.usernotifications.news_created_mail and news.agency == user.profile.agency):
notificationtext = "Neue Agenturnews: " + news.name notificationtext = "Neue Agenturnews: " + news.name
username = user.first_name + " " + user.last_name username = user.first_name + " " + user.last_name
msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext, 'linktarget' : targeturl}) msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext, 'linktarget' : targeturl})
send_mail( send_mail(
'Agentur-Benachrichtigung', 'Agentur-Benachrichtigung',
'Hallo ' + user.first_name + ' ' + user.last_name + '! ' + notificationtext, 'Hallo ' + user.first_name + ' ' + user.last_name + '! ' + notificationtext,
'noreply@digitale-agentur.com', 'noreply@digitale-agentur.com',
[user.email], [user.email],
html_message=msg_html, html_message=msg_html,
fail_silently=True fail_silently=True
) )
if(user.usernotifications.news_created_push and news.agency == user.profile.agency): if(user.usernotifications.news_created_push and news.agency == user.profile.agency):
newnotification = UserNotification(touser=user, notificationtext="Neue Agenturnews: " + news.name, notificationtype="agencynews", elementid=news.pk) newnotification = UserNotification(touser=user, notificationtext="Neue Agenturnews: " + news.name, notificationtype="agencynews", elementid=news.pk)
newnotification.save() newnotification.save()
channel_layer = channels.layers.get_channel_layer() channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__News | Neue Agenturnews: " + news.name}) async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__News | Neue Agenturnews: " + news.name})
# LEXOFFICE TEST # LEXOFFICE TEST
# HEADERS CURL # HEADERS CURL
''' '''
@ -915,41 +915,41 @@ def cronactions(request, code):
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept': 'application/json', 'Accept': 'application/json',
} }
# DataJSON # DataJSON
lexdata = { lexdata = {
"voucherDate": "2020-07-09T00:00:00.000+01:00", "voucherDate": "2020-07-09T00:00:00.000+01:00",
"address" : { "address" : {
"name" : "Agenturname XXX", "name" : "Agenturname XXX",
"countryCode" : "DE" "countryCode" : "DE"
}, },
"totalPrice" : { "totalPrice" : {
"currency" : "EUR", "currency" : "EUR",
}, },
"lineItems" : [ "lineItems" : [
{ {
"type" : "custom", "type" : "custom",
"name" : "Monatsbeitrag", "name" : "Monatsbeitrag",
"quantity" : 1, "quantity" : 1,
"unitName" : "Stück", "unitName" : "Stück",
"unitPrice" : "unitPrice" :
{ {
"currency" : "EUR", "currency" : "EUR",
"netAmount" : 10, "netAmount" : 10,
"taxRatePercentage" : 16 "taxRatePercentage" : 16
}, },
}, },
{ {
"type" : "custom", "type" : "custom",
"name" : "Abwesenheitsmodul", "name" : "Abwesenheitsmodul",
"quantity" : 1, "quantity" : 1,
"unitName" : "Stück", "unitName" : "Stück",
"unitPrice" : "unitPrice" :
{ {
"currency" : "EUR", "currency" : "EUR",
"netAmount" : 10, "netAmount" : 10,
"taxRatePercentage" : 16 "taxRatePercentage" : 16
}, },
} }
], ],
"taxConditions": { "taxConditions": {
@ -959,96 +959,128 @@ def cronactions(request, code):
"shippingDate": "2020-07-09T00:00:00.000+01:00", "shippingDate": "2020-07-09T00:00:00.000+01:00",
"shippingType": "service" "shippingType": "service"
}, },
} }
json_data = json.dumps(lexdata) json_data = json.dumps(lexdata)
r = requests.get("https://api.lexoffice.io/v1/invoices/0f9b6a1d-1912-4a10-9926-7909e5580202", data=json_data, headers=headers) r = requests.get("https://api.lexoffice.io/v1/invoices/0f9b6a1d-1912-4a10-9926-7909e5580202", data=json_data, headers=headers)
print(r) print(r)
print(r.text) print(r.text)
''' '''
else: else:
print("API CODE FAILED") print("API CODE FAILED")
data.update({"status" : "failed"}) data.update({"status" : "failed"})
return JsonResponse(data) return JsonResponse(data)
'''
Gibt False zurück, wenn der User an diesem Tag KEINE Abwesenheiten hat, ansonsten True!
'''
def absencecheck(user, daytocheck):
returnstat = False
absencedays = Absence.objects.filter(agency=user.profile.agency, user=user, confirm_status=0) & (Absence.objects.filter(agency=user.profile.agency, user=user, start=daytocheck) | (Absence.objects.filter(agency=user.profile.agency, user=user, start__lt=daytocheck) & Absence.objects.filter(agency=user.profile.agency, user=user, end__gt=daytocheck)) | Absence.objects.filter(agency=user.profile.agency, user=user, end=daytocheck))
if(len(absencedays) > 0):
returnstat = True
return returnstat
# CRONJOBS UM 00:01! # CRONJOBS UM 00:01!
def cronactionsdaily(request, code): def cronactionsdaily(request, code):
data = {} data = {}
if(code == settings.CRONAPIKEY): if(code == settings.CRONAPIKEY):
allusers = User.objects.all() allusers = User.objects.all()
'''
''' Pro User gibt es das Feld loose_holiday in der UserTime-Info. Ist dieser Tag vorbei, muss die Differenz der days_inuse des VORJHARES in den Rest das AKTUELLEN JAHRES gespeichert werden!
'''
Pro User gibt es das Feld loose_holiday in der UserTime-Info. Ist dieser Tag vorbei, muss die Differenz der days_inuse des VORJHARES in den Rest das AKTUELLEN JAHRES gespeichert werden! today = date.today()
for user in allusers:
# REST URLAUB BERECHNUNG
usertimedata = UserTime.objects.get(user=user)
day_tocheck = usertimedata.loose_holidedate.split(".")[0]
month_tocheck = usertimedata.loose_holidedate.split(".")[1]
month = today.month
if month < 10:
month = "0" + str(month)
day = today.day
if day < 10:
day = "0" + str(day)
''' # Restetag erreicht, Reste ins nächste Jahr übertragen
today = date.today() if(str(day_tocheck) == str(day) and str(month_tocheck) == str(month)):
for user in allusers: sourceyear = today.year
# REST URLAUB BERECHNUNG this_year = list(UserYearAbsenceInfo.objects.filter(year=sourceyear, user=user))[0]
usertimedata = UserTime.objects.get(user=user) next_year = list(UserYearAbsenceInfo.objects.filter(year=sourceyear+1, user=user))[0]
next_year.restdays = this_year.days - this_year.days_inuse
next_year.save()
day_tocheck = usertimedata.loose_holidedate.split(".")[0] # ARBEITSTAGE BEENDEN
month_tocheck = usertimedata.loose_holidedate.split(".")[1] # Benutzer hat Zeiterfassung aktiv
if(user.usertime.usetime):
workdays = Workday.objects.filter(user=user, end=None)
for wd in workdays:
wd.end = datetime(wd.start.year, wd.start.month, wd.start.day, 23, 59)
wd.save()
month = today.month yesterday = date.today() - timedelta(days=1)
weekday = yesterday.weekday()
workdays_yesterday = len(Workday.objects.filter(user=user, start__day=yesterday.day, start__month=yesterday.month, start__year=yesterday.year))
# Mitarbeiter hat für den gestrigen Tag keine Zeiten erfasst, daher automatisch auf null wenn KEINE Abwesenheit eingetragen wurde
if month < 10: if(workdays_yesterday == 0 and absencecheck(user, yesterday) == False):
month = "0" + str(month) targettworktime = 0.0
if(weekday == 0):
targettworktime = user.usertime.wd_mo
if(weekday == 1):
targettworktime = user.usertime.wd_tu
if(weekday == 2):
targettworktime = user.usertime.wd_we
if(weekday == 3):
targettworktime = user.usertime.wd_th
if(weekday == 4):
targettworktime = user.usertime.wd_fr
if(weekday == 5):
targettworktime = user.usertime.wd_sa
if(weekday == 6):
targettworktime = user.usertime.wd_so
day = today.day workdaytemp = Workday(user=user, agency=user.profile.agency, start=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), end=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), target=targettworktime)
if day < 10: workdaytemp.save()
day = "0" + str(day)
# Restetag erreicht, Reste ins nächste Jahr übertragen
if(str(day_tocheck) == str(day) and str(month_tocheck) == str(month)):
sourceyear = today.year
this_year = list(UserYearAbsenceInfo.objects.filter(year=sourceyear, user=user))[0]
next_year = list(UserYearAbsenceInfo.objects.filter(year=sourceyear+1, user=user))[0]
next_year.restdays = this_year.days - this_year.days_inuse
next_year.save()
# ARBEITSTAGE BEENDEN # Erinnerungsmails/Push bei Vertretung verschicken
# Benutzer hat Zeiterfassung aktiv one_week_later = date.today() + timedelta(days=7)
if(user.usertime.usetime): repre_absence = Absence.objects.filter(representator=user, start=one_week_later, confirm_status=0)
workdays = Workday.objects.filter(user=user, end=None)
for wd in workdays:
wd.end = datetime(wd.start.year, wd.start.month, wd.start.day, 23, 59)
wd.save()
# Erinnerungsmails/Push bei Vertretung verschicken for r in repre_absence:
one_week_later = date.today() + timedelta(days=7) if(r.representator.usernotifications.absence_user_is_rep_reminder_mail):
repre_absence = Absence.objects.filter(representator=user, start=one_week_later, confirm_status=0) sendMailNoti(" in einer Woche startet Ihre Vertretung für " + r.user.first_name + " " + r.user.last_name + "!", user)
for r in repre_absence:
if(r.representator.usernotifications.absence_user_is_rep_reminder_mail):
sendMailNoti(" in einer Woche startet Ihre Vertretung für " + r.user.first_name + " " + r.user.last_name + "!", user)
if(r.representator.usernotifications.absence_user_is_rep_reminder_push):
newnotification = UserNotification(touser=user, notificationtext="Erinnerung für Abwesenheitsvertretung!", notificationtype="", elementid=r.pk)
newnotification.save()
channel_layer = channels.layers.get_channel_layer() if(r.representator.usernotifications.absence_user_is_rep_reminder_push):
async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Abwesenheit | In einer Woche startet Ihre Vertretung für " + r.user.first_name + " " + r.user.last_name + "!"}) newnotification = UserNotification(touser=user, notificationtext="Erinnerung für Abwesenheitsvertretung!", notificationtype="", elementid=r.pk)
newnotification.save()
data.update({"status" : "ok"})
channel_layer = channels.layers.get_channel_layer()
else: async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Abwesenheit | In einer Woche startet Ihre Vertretung für " + r.user.first_name + " " + r.user.last_name + "!"})
print("API CODE FAILED") data.update({"status" : "ok"})
data.update({"status" : "failed"})
return JsonResponse(data) else:
print("API CODE FAILED")
data.update({"status" : "failed"})
return JsonResponse(data)
def sendMailNoti(notificationtext, user_touched, linktarget=""): def sendMailNoti(notificationtext, user_touched, linktarget=""):
username = user_touched.first_name + " " + user_touched.last_name username = user_touched.first_name + " " + user_touched.last_name
msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext, 'linktarget' : linktarget}) msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext, 'linktarget' : linktarget})
send_mail( send_mail(
'Agentur-Benachrichtigung', 'Agentur-Benachrichtigung',
'Hallo ' + user_touched.first_name + ' ' + user_touched.last_name + '! ' + notificationtext, 'Hallo ' + user_touched.first_name + ' ' + user_touched.last_name + '! ' + notificationtext,
'noreply@digitale-agentur.com', 'noreply@digitale-agentur.com',
[user_touched.email], [user_touched.email],
html_message=msg_html, html_message=msg_html,
fail_silently=True fail_silently=True
) )