Bug Cronjob

This commit is contained in:
holger.trampe 2020-10-07 11:40:58 +02:00
parent 6b94978115
commit 746e797ac6
20 changed files with 277 additions and 20 deletions

View File

@ -156,9 +156,19 @@ AUTH_PASSWORD_VALIDATORS = [
{ {
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
}, },
#{
# 'NAME' : "passwords.auth_password_validators.ComplexityValidator",
#}
] ]
PASSWORD_COMPLEXITY = { # You can omit any or all of these for no limit for that particular set
"UPPER": 1, # Uppercase
"LOWER": 1, # Lowercase
"LETTERS": 1, # Either uppercase or lowercase letters
"DIGITS": 1, # Digits
"SPECIAL": 1, # Not alphanumeric, space or punctuation character
"WORDS": 0 # Words (alphanumeric sequences separated by a whitespace or punctuation character)
}
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/ # https://docs.djangoproject.com/en/2.2/topics/i18n/

View File

@ -2,6 +2,9 @@ from django import forms
from django.forms import ModelForm from django.forms import ModelForm
from .models import * from .models import *
from bootstrap_datepicker_plus import DatePickerInput from bootstrap_datepicker_plus import DatePickerInput
from django.contrib.auth.password_validation import validate_password
from django.core import validators
from passwords.validators import *
class PersLetterForm(forms.ModelForm): class PersLetterForm(forms.ModelForm):
@ -18,6 +21,22 @@ class PersLetterForm(forms.ModelForm):
super(PersLetterForm, self).__init__(*args, **kwargs) super(PersLetterForm, self).__init__(*args, **kwargs)
self.fields['text'] = forms.CharField(label="Ihr persönlicher Text", widget=forms.Textarea(attrs={"rows":15, "cols":35})) self.fields['text'] = forms.CharField(label="Ihr persönlicher Text", widget=forms.Textarea(attrs={"rows":15, "cols":35}))
class LoginRDForm(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['pass'] = forms.CharField(widget=forms.PasswordInput, label="Passwort", required=True)
class RecoverDirSettingForm(forms.ModelForm):
class Meta:
model = RecoverDirSetting
fields = ['logpass']
def __init__(self, *args, **kwargs):
super(RecoverDirSettingForm, self).__init__(*args, **kwargs)
self.fields['logpass'] = forms.CharField(widget=forms.PasswordInput, label="Passwort", required=True, validators=[dictionary_words, complexity, validate_length])
self.fields['logpass_check'] = forms.CharField(widget=forms.PasswordInput, label="Passwort wiederholen", required=True,validators=[dictionary_words, complexity, validate_length])
# Notfallhilfe FORMS # Notfallhilfe FORMS
# 1 Handlungsleitfaden # 1 Handlungsleitfaden

View File

@ -18,6 +18,12 @@ def rd_path_agency(instance, filename):
return 'agencydata/agency_{0}/rd/{1}'.format(instance.agency.pk, filename) return 'agencydata/agency_{0}/rd/{1}'.format(instance.agency.pk, filename)
# MAIN RECOVERDIR PASSWORD AND CONFIG
class RecoverDirSetting(models.Model):
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
logpass = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
recoverkey = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
# Create your models here. # Create your models here.
class PersLetter(models.Model): class PersLetter(models.Model):

View File

@ -1,7 +1,6 @@
<h4>Personal, interne und externe Partner inkl. Funktionen usw. <h4>Personal, interne und externe Partner inkl. Funktionen usw.
<a class="btn btn-primary btn btn-sm mb-3" href="{% url 'rd-a5-addpersonal' %}" style="float: right;"><i class="fas fa-plus"></i>&nbsp;Personal</a> <a class="btn btn-primary btn btn-sm mb-3" href="{% url 'rd-a5-addpersonal' %}" style="float: right;"><i class="fas fa-plus"></i>&nbsp;Personal</a>
</h4> </h4>
<small>Beim externen Aufrufen der Notfallhilfe werden alle aktuell angelegten Mitarbeiter inkl. Kontaktdaten angezeigt. Erstellen Sie daher hier Mitarbeiter, die nicht in der digitalen Agentur angelegt sind.</small>
<hr> <hr>
<table class="table table-hover" id="a5_personal" > <table class="table table-hover" id="a5_personal" >
<thead> <thead>
@ -29,6 +28,17 @@
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
{% for us in users_of_agency %}
<tr>
<td>{{us.get_full_name}}</td>
<td>{{us.profile.func|default:""}}</td>
<td>
Intern
</td>
<td>
</td>
</tr>
{% endfor %}
</tbody> </tbody>
</table> </table>
<hr> <hr>
@ -101,7 +111,8 @@ $(document).ready(function(){
"pageLength": 50, "pageLength": 50,
"buttons" : { "buttons" : {
"className" : "btn-danger" "className" : "btn-danger"
} },
"order": [[ 1, "desc" ]]
}); });
}); });

View File

@ -0,0 +1,26 @@
{% extends "users/base.html" %}
{% load counter_tag %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_recoverdir %}
<div class="content-section col-12">
<h3>Notfallhilfe{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Legen Sie hier die wichtigsten Dokumente für sich und Ihre Agentur an." class="far fa-question-circle"></i></small>{% endif %}
<!-- TASK: Video für Notfallhilfe <small><i onclick="javascript:$('#youtubevideoinformation').modal('toggle');" class="far fa-play-circle"></i></small>-->
</h3>
<hr>
<div class="col-6">
Bitte melden Sie sich mit dem Passwort für die Notfallhilfe an!
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.media}}
{{form|crispy}}
<hr>
<button type="submit" class="btn btn-primary" style="float: right;">Anmelden</button>&nbsp;
</form>
</div>
</div>
{% else %}
Sie haben keinen Zugriff auf das Modul Notfallhilfe. Bitte wenden Sie sich an den Support!
{% endif %}
{% endblock content %}

View File

@ -5,6 +5,7 @@
<div class="content-section col-12"> <div class="content-section col-12">
<h3>Notfallhilfe{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Legen Sie hier die wichtigsten Dokumente für sich und Ihre Agentur an." class="far fa-question-circle"></i></small>{% endif %} <h3>Notfallhilfe{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Legen Sie hier die wichtigsten Dokumente für sich und Ihre Agentur an." class="far fa-question-circle"></i></small>{% endif %}
<!-- TASK: Video für Notfallhilfe <small><i onclick="javascript:$('#youtubevideoinformation').modal('toggle');" class="far fa-play-circle"></i></small>--> <!-- TASK: Video für Notfallhilfe <small><i onclick="javascript:$('#youtubevideoinformation').modal('toggle');" class="far fa-play-circle"></i></small>-->
<a style="float: right" class="btn btn-secondary btn-sm mr-2 " href="{% url 'closerecoverdir' %}"><i class="fas fa-lock"></i></a>
</h3> </h3>
<hr> <hr>
<div class="row"> <div class="row">
@ -63,7 +64,10 @@
</div> </div>
<div class="tab-pane fade" id="t_settings" role="tabpanel" aria-labelledby="settings"> <div class="tab-pane fade" id="t_settings" role="tabpanel" aria-labelledby="settings">
Einstellungen <h5 class="mt-3">Einstellungen{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Verwalten Sie hier die Einstellungen für den Zugang zur Notfallhilfe." class="far fa-question-circle"></i></small>{% endif %}</h5>
{% block settings_content %}
{% include "recoverdir/rd_viewsettings.html" %}
{% endblock %}
</div> </div>
<div class="tab-pane fade" id="t_help" role="tabpanel" aria-labelledby="help"> <div class="tab-pane fade" id="t_help" role="tabpanel" aria-labelledby="help">

View File

@ -125,7 +125,7 @@
<div class="card-header" id="headingOne"> <div class="card-header" id="headingOne">
<h5 class="mb-0"> <h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(5)" data-toggle="collapse" data-target="#rd_5" aria-expanded="true" aria-controls="rd_5"> <button class="btn btn-link tabelement" onclick="javascript:newTabOpen(5)" data-toggle="collapse" data-target="#rd_5" aria-expanded="true" aria-controls="rd_5">
<h4 style="margin-top: 11px;">5. Gewerbe: Vorsorgedokumente</h4> <h4 style="margin-top: 11px;">5. Vorsorgedokumente</h4>
</button> </button>
<span style="float: right;"> <span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#5</h2></span> <span class="square_company_arrow"><h2 class="h2_in_arrow">#5</h2></span>
@ -147,7 +147,7 @@
<div class="card-header" id="headingOne"> <div class="card-header" id="headingOne">
<h5 class="mb-0"> <h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(6)" data-toggle="collapse" data-target="#rd_6" aria-expanded="true" aria-controls="rd_6"> <button class="btn btn-link tabelement" onclick="javascript:newTabOpen(6)" data-toggle="collapse" data-target="#rd_6" aria-expanded="true" aria-controls="rd_6">
<h4 style="margin-top: 11px;">6. Gewerbe: Vorsorge und Finanzen</h4> <h4 style="margin-top: 11px;">6. Vorsorge und Finanzen</h4>
</button> </button>
<span style="float: right;"> <span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#6</h2></span> <span class="square_company_arrow"><h2 class="h2_in_arrow">#6</h2></span>
@ -169,7 +169,7 @@
<div class="card-header" id="headingOne"> <div class="card-header" id="headingOne">
<h5 class="mb-0"> <h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(7)" data-toggle="collapse" data-target="#rd_7" aria-expanded="true" aria-controls="rd_7"> <button class="btn btn-link tabelement" onclick="javascript:newTabOpen(7)" data-toggle="collapse" data-target="#rd_7" aria-expanded="true" aria-controls="rd_7">
<h4 style="margin-top: 11px;">7. Gewerbe: Immobilien</h4> <h4 style="margin-top: 11px;">7. Immobilien</h4>
</button> </button>
<span style="float: right;"> <span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#7</h2></span> <span class="square_company_arrow"><h2 class="h2_in_arrow">#7</h2></span>
@ -191,7 +191,7 @@
<div class="card-header" id="headingOne"> <div class="card-header" id="headingOne">
<h5 class="mb-0"> <h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(8)" data-toggle="collapse" data-target="#rd_8" aria-expanded="true" aria-controls="rd_8"> <button class="btn btn-link tabelement" onclick="javascript:newTabOpen(8)" data-toggle="collapse" data-target="#rd_8" aria-expanded="true" aria-controls="rd_8">
<h4 style="margin-top: 11px;">8. Gewerbe: Verträge</h4> <h4 style="margin-top: 11px;">8. Verträge</h4>
</button> </button>
<span style="float: right;"> <span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#8</h2></span> <span class="square_company_arrow"><h2 class="h2_in_arrow">#8</h2></span>

View File

@ -0,0 +1,21 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_recoverdir %}
<div class="content-section col-9">
<h3>Einstellungen verwalten</h3>
<hr>
<form method="POST" enctype="multipart/form-data">
<small>Beachten Sie bitte, dass dieses Passwort allen Personen sicher zugänglich gemacht werden muss, die auf die Notfallhilfe zugreifen können! Zusätzlich benötigen diese Personen den Sicherheitssschlüssel. Dieser wird automatisch generiert und kann nicht geändert werden. Sie finden den Sicherheitsschlüssel unter Notfallhilfe, Einstellungen.</small>
{% csrf_token %}
{{normalForm.media}}
{{ form|crispy }}
<hr>
<a class="btn" href="{% url 'recoverdir' %} ">Abbrechen</a>
<button type="submit" class="btn btn-primary" style="float: right;">Einstellungen speichern</button>&nbsp;
</form>
</div>
{% else %}
<h3>Das Modul Notfallhilfe wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -61,6 +61,9 @@
{% elif hisotryelementinfo.1 == 11 %} {% elif hisotryelementinfo.1 == 11 %}
<a href="{% url 'recoverdir-personalhistory-single' ele.pk rdele.pk %}">{{hisotryelementinfo.0}}</a> <a href="{% url 'recoverdir-personalhistory-single' ele.pk rdele.pk %}">{{hisotryelementinfo.0}}</a>
{% elif hisotryelementinfo.1 == 20 %}
<a href="{% url 'recoverdir-elsehistory-single' ele.pk rdele.pk %}">{{hisotryelementinfo.0}}</a>
{% endif %} {% endif %}
</td> </td>
<td>{{rdele.history_date|date:"d.m.Y H:i"}}</td> <td>{{rdele.history_date|date:"d.m.Y H:i"}}</td>

View File

@ -0,0 +1,20 @@
<hr>
<table>
<tr>
<td>Sicherheitsschlüssel (nicht veränderbar):</td><td><b>{{rd_settings.recoverkey}}</b></td>
</tr>
<tr>
<td>Passwort für die Notfallhilfe:</td><td><span id="pw_hidden">***************</span><span id="pw" style="display: none;"><b>{{rd_settings.logpass}}</b></span></td>
<td>
<button style="float: right" class="btn btn-secondary btn-sm mr-2 " onclick="javascript:showPW()"><i class="far fa-eye"></i></button>&nbsp;
<a style="float: right" class="btn btn-secondary btn-sm mr-2 " href="{% url 'recoverdir-updatesettings' rd_settings.pk %}"><small><i class="fas fa-pen"></i></small></a>&nbsp;
</td>
</tr>
</tr>
</table>
<script type="text/javascript">
function showPW(){
$("#pw_hidden").toggle();
$("#pw").toggle();
}
</script>

View File

@ -12,6 +12,13 @@ Permissions definiert in models.py bei USERS und dann hier vor die View geschrie
urlpatterns = [ urlpatterns = [
path('', permission_required('users.recoverdirmanager')(RecoverDirManagement.as_view(template_name="recoverdir/rd_management.html")), name='recoverdir'), path('', permission_required('users.recoverdirmanager')(RecoverDirManagement.as_view(template_name="recoverdir/rd_management.html")), name='recoverdir'),
# SETTINGS
path('rdsettings/', permission_required('users.recoverdirmanager')(RecoverDirAddSettings.as_view()), name='recoverdir-addsettings'),
path('rdsettings/update/<int:pk>', permission_required('users.recoverdirmanager')(RecoverDirUpdateSettings.as_view()), name='recoverdir-updatesettings'),
path('rdlogin/', permission_required('users.recoverdirmanager')(RecoverDirLog.as_view()), name='recoverdir-login'),
path('close/', permission_required('users.recoverdirmanager')(CloseRecoverDir), name='closerecoverdir'),
# Persönliches Schreiben # Persönliches Schreiben
path('addpl/', permission_required('users.recoverdirmanager')(RecoverDirAddPL.as_view(template_name="recoverdir/rd_pers_add.html")), name='recoverdir-addpl'), path('addpl/', permission_required('users.recoverdirmanager')(RecoverDirAddPL.as_view(template_name="recoverdir/rd_pers_add.html")), name='recoverdir-addpl'),
path('updatepl/<int:pk>', permission_required('users.recoverdirmanager')(RecoverDirUpdatePL.as_view(template_name="recoverdir/rd_pers_update.html")), name='recoverdir-updatepl'), path('updatepl/<int:pk>', permission_required('users.recoverdirmanager')(RecoverDirUpdatePL.as_view(template_name="recoverdir/rd_pers_update.html")), name='recoverdir-updatepl'),

View File

@ -1,9 +1,11 @@
from django.shortcuts import render from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView, FormView
from .models import * from .models import *
from .forms import * from .forms import *
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.shortcuts import redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
import os import os
import sys import sys
@ -12,11 +14,27 @@ from django.http import JsonResponse, HttpResponse, Http404
from django_encrypted_filefield.views import FetchView from django_encrypted_filefield.views import FetchView
import string, random import string, random
from itertools import chain from itertools import chain
from django.contrib.auth.password_validation import *
from datetime import datetime
from django.contrib.auth.models import User
# Create your views here. # Create your views here.
class RecoverDirManagement(LoginRequiredMixin, ListView): class RecoverDirManagement(LoginRequiredMixin, ListView):
model = PersLetter model = PersLetter
# First Method!
def dispatch(self, request, *args, **kwargs):
# Check, if initial config exist and user has rights
if(len(RecoverDirSetting.objects.filter(agency=self.request.user.profile.agency)) == 0 and self.request.user.has_perm('users.recoverdirmanager')):
# Settings not found
return redirect('recoverdir-addsettings')
# TASK: Hier noch einstellen, dass der Nutzer weniger als 30 Minuten nicht inaktiv war!
elif(self.request.user.profile.rd_login == None and self.request.user.has_perm('users.recoverdirmanager')):
return redirect('recoverdir-login')
else:
return super(RecoverDirManagement, self).get(request)
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' : 'recoverdir'}) context.update({'active_link' : 'recoverdir'})
@ -60,7 +78,9 @@ class RecoverDirManagement(LoginRequiredMixin, ListView):
finalupdatelist = chain(persletters, handlungsleitfaden, contactfc, contactstrust, handlungsleitfadenvf, depistvollmacht, ergodigi, onlinebank, streamingabo, digitalaccount, personal, onlinebank6, elseele) finalupdatelist = chain(persletters, handlungsleitfaden, contactfc, contactstrust, handlungsleitfadenvf, depistvollmacht, ergodigi, onlinebank, streamingabo, digitalaccount, personal, onlinebank6, elseele)
context.update({"history" : finalupdatelist}) context.update({"history" : finalupdatelist})
users_of_agency = User.objects.filter(profile__agency=self.request.user.profile.agency)
context.update({"users_of_agency" : users_of_agency})
# DOCUMENTS NOT WORKING Weil das "alte" nicht gespeichert wird sondern lediglich der Datensatz # DOCUMENTS NOT WORKING Weil das "alte" nicht gespeichert wird sondern lediglich der Datensatz
#documents = Documents.objects.filter(agency=self.request.user.profile.agency, area=1) #documents = Documents.objects.filter(agency=self.request.user.profile.agency, area=1)
@ -117,8 +137,93 @@ class RecoverDirManagement(LoginRequiredMixin, ListView):
# A9 # A9
context.update({'area_9_doc' : Documents.objects.filter(agency=self.request.user.profile.agency, area=9).order_by('-document_date')}) context.update({'area_9_doc' : Documents.objects.filter(agency=self.request.user.profile.agency, area=9).order_by('-document_date')})
# Load Settings
context.update({'rd_settings' : RecoverDirSetting.objects.filter(agency=self.request.user.profile.agency)[0]})
return context return context
def CloseRecoverDir(request):
request.user.profile.rd_login = None
request.user.profile.save()
return redirect('recoverdir')
class RecoverDirLog(FormView):
template_name = "recoverdir/rd_elements_forms/rd_mainlogin.html"
form_class = LoginRDForm
success_url = reverse_lazy('recoverdir')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({
'active_link' : 'recoverdir',
'form' : LoginRDForm()
})
return context
def form_valid(self, form):
# Load Settings-Data
settings = RecoverDirSetting.objects.filter(agency=self.request.user.profile.agency)[0]
if form.cleaned_data.get("pass") == settings.logpass and self.request.user.has_perm("users.recoverdirmanager") and settings.agency == self.request.user.profile.agency:
self.request.user.profile.rd_login = datetime.now()
self.request.user.profile.save()
else:
messages.warning(self.request, f'Passwort nicht korrekt!')
return super().form_valid(form)
class RecoverDirAddSettings(CreateView):
model = RecoverDirSetting
success_url = reverse_lazy('recoverdir')
form_class = RecoverDirSettingForm
template_name = "recoverdir/rd_settings.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({
'active_link' : 'recoverdir',
})
return context
def form_valid(self, form):
form.instance.agency = self.request.user.profile.agency
# Initial Recover-Key
if(len(RecoverDirSetting.objects.filter(agency=self.request.user.profile.agency)) == 0 and self.request.user.has_perm('users.recoverdirmanager')):
form.instance.recoverkey = randomStringRecoverKey()
if(form.cleaned_data.get('logpass') == form.cleaned_data.get('logpass_check')):
messages.warning(self.request, f'Daten gespeichert!')
else:
messages.warning(self.request, f'Die Passwörter stimmen nicht überein. Bitte neu eingeben!')
return redirect('recoverdir-addsettings')
return super().form_valid(form)
class RecoverDirUpdateSettings(UpdateView):
model = RecoverDirSetting
success_url = reverse_lazy('recoverdir')
form_class = RecoverDirSettingForm
template_name = "recoverdir/rd_settings.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({
'active_link' : 'recoverdir',
})
return context
def form_valid(self, form):
# Initial Recover-Key
if(form.cleaned_data.get('logpass') == form.cleaned_data.get('logpass_check')):
messages.warning(self.request, f'Daten gespeichert!')
else:
messages.warning(self.request, f'Die Passwörter stimmen nicht überein. Bitte neu eingeben!')
return redirect('recoverdir-addsettings')
return super().form_valid(form)
class RecoverDirAddPL(CreateView): class RecoverDirAddPL(CreateView):
model = PersLetter model = PersLetter
success_url = reverse_lazy('recoverdir') success_url = reverse_lazy('recoverdir')
@ -160,6 +265,18 @@ def randomString(stringLength=40):
letters = string.ascii_lowercase letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(stringLength)) return ''.join(random.choice(letters) for i in range(stringLength))
def randomStringRecoverKey():
letters = string.ascii_uppercase
key = ""
for run in range(10):
key += ''.join(random.choice(letters) for i in range(5))
if(run < 9):
key += "-"
return key
# Notfallhilfe ELEMENTE # Notfallhilfe ELEMENTE
# ABNSCHNITT 1 # ABNSCHNITT 1
@ -1070,7 +1187,7 @@ class ElseSingleHistory(DetailView):
shown_element = he shown_element = he
context.update({ context.update({
'ele' : shown_element, 'else' : shown_element,
'history' : True 'history' : True
}) })
return context return context

View File

@ -31,3 +31,4 @@ python-dateutil==2.8.1
django-simple-history==2.11.0 django-simple-history==2.11.0
django-encrypted-filefield==0.2.2 django-encrypted-filefield==0.2.2
more-itertools==8.5.0 more-itertools==8.5.0
django-passwords==0.3.12

View File

@ -799,7 +799,7 @@ def getHistoryClassOfObject(value):
finalclass[0] = "Personal und Partner" finalclass[0] = "Personal und Partner"
finalclass[1] = 11 finalclass[1] = 11
# ELSE # ELSE
elif(objectClass == 'HistoricalElse'): elif(objectClass == 'HistoricalRDElse'):
finalclass[0] = "Sonstiges" finalclass[0] = "Sonstiges"
finalclass[1] = 20 finalclass[1] = 20

View File

@ -8,7 +8,7 @@ from cloud.models import DataFile
from organizer.models import AGContacts from organizer.models import AGContacts
from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays, Absence from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays, Absence
from chat.models import ChatRoom from chat.models import ChatRoom
from recoverdir.models import PersLetter, Documents, Handlungsleitfaden, RDContact from recoverdir.models import PersLetter, Documents, Handlungsleitfaden, RDContact, RecoverDirSetting
from simple_history.admin import SimpleHistoryAdmin from simple_history.admin import SimpleHistoryAdmin
@ -39,4 +39,5 @@ admin.site.register(AgencyBills)
admin.site.register(PersLetter, SimpleHistoryAdmin) admin.site.register(PersLetter, SimpleHistoryAdmin)
admin.site.register(Documents, SimpleHistoryAdmin) admin.site.register(Documents, SimpleHistoryAdmin)
admin.site.register(Handlungsleitfaden) admin.site.register(Handlungsleitfaden)
admin.site.register(RDContact) admin.site.register(RDContact)
admin.site.register(RecoverDirSetting)

View File

@ -262,6 +262,9 @@ class Profile(models.Model):
''' '''
onlinestatus = models.IntegerField(default=0) onlinestatus = models.IntegerField(default=0)
# RECOVER DIR LAST LOGIN FIELD - AFTER LOGIN SET TO NONE
rd_login = models.DateTimeField(null=True, blank=True, default=None)
def __str__(self): def __str__(self):
return f'{self.user.last_name}' return f'{self.user.last_name}'

View File

@ -59,12 +59,14 @@ def loadingFreeDays(plz, year):
@receiver(signal=user_logged_out, sender=User) @receiver(signal=user_logged_out, sender=User)
def checkForFreeDays(sender, user, request, **kwargs): def checkForFreeDays(sender, user, request, **kwargs):
user.profile.onlinestatus = 3 user.profile.onlinestatus = 3
user.profile.rd_login = None
user.save() user.save()
# CHECK SOMETHING WHEN USER LOGGED IN # CHECK SOMETHING WHEN USER LOGGED IN
@receiver(signal=user_logged_in, sender=User) @receiver(signal=user_logged_in, sender=User)
def checkDefaultAbsenceReasons(sender, user, request, **kwargs): def checkDefaultAbsenceReasons(sender, user, request, **kwargs):
user.profile.onlinestatus = 0 user.profile.onlinestatus = 0
user.profile.rd_login = None
user.save() user.save()
ar = AbsenceReason.objects.filter(agency=user.profile.agency) ar = AbsenceReason.objects.filter(agency=user.profile.agency)
if(len(ar) == 0): if(len(ar) == 0):

View File

@ -47,7 +47,7 @@ import filetype
from django.db.models.signals import m2m_changed from django.db.models.signals import m2m_changed
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from users.signals import adjust_group_notifications_permission from users.signals import adjust_group_notifications_permission
from django.core.exceptions import ObjectDoesNotExist
def randomString(stringLength=10): def randomString(stringLength=10):
"""Generate a random string of fixed length """ """Generate a random string of fixed length """
@ -1079,16 +1079,22 @@ def cronactionsdaily(request, code):
today = date.today() today = date.today()
for user in allusers: for user in allusers:
# REST URLAUB BERECHNUNG # REST URLAUB BERECHNUNG
try: try:
usertimedata = UserTime.objects.get(user=user) usertimedata = UserTime.objects.get(user=user)
day_tocheck = usertimedata.loose_holidedate.split(".")[0] day_tocheck = usertimedata.loose_holidedate.split(".")[0]
month_tocheck = usertimedata.loose_holidedate.split(".")[1] month_tocheck = usertimedata.loose_holidedate.split(".")[1]
month = today.month month = today.month
day = today.day
if month < 10: if month < 10:
month = "0" + str(month) month = "0" + str(month)
day = today.day day = today.day
else:
month = month
if day < 10: if day < 10:
day = "0" + str(day) day = "0" + str(day)
else:
day = day
# Restetag erreicht, Reste ins nächste Jahr übertragen # Restetag erreicht, Reste ins nächste Jahr übertragen
if(str(day_tocheck) == str(day) and str(month_tocheck) == str(month)): if(str(day_tocheck) == str(day) and str(month_tocheck) == str(month)):
sourceyear = today.year sourceyear = today.year
@ -1144,10 +1150,10 @@ def cronactionsdaily(request, code):
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__Abwesenheit | In einer Woche startet Ihre Vertretung für " + r.user.first_name + " " + r.user.last_name + "!"}) 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 + "!"})
data.update({"status" : "ok"})
except: data.update({"status " + str(user.pk) : "ok"})
pass except ObjectDoesNotExist:
data.update({"status" + str(user.pk) : "no usertime found for " + user.get_full_name()})
else: else:
print("API CODE FAILED") print("API CODE FAILED")
data.update({"status" : "failed"}) data.update({"status" : "failed"})