NF Bereich 1

This commit is contained in:
holger.trampe 2020-10-05 17:19:06 +02:00
parent 0f13332892
commit 6ba4564f30
36 changed files with 982 additions and 21 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -42,6 +42,10 @@ MAILINFOKEY = "jka7sd8iukashdna78skduJAHDsu6dilaksdjba65a68iadbhjak"
# API KEY LEXOFFICE
LEX_API = "8f9ba01f-9e84-42c7-9548-48c254f14c19"
# KEYS FOR ENCRYPTED FILE FIELDS
DEFF_SALT = 'A-!GDtuKp?H/H5-UUatEh6ZcG/6h-VQf1OkDORRkK0(:(qCf//'
DEFF_PASSWORD = 'i8#vKXbrgHfdrPGns+O1n!s15bAF(3SE8tFNXuAGC0INHRo+EI'
DEFF_FETCH_URL_NAME = 'getdoc'
#ALLOWED_HOSTS = ['digitale-agentur.com', 'www.digitale-agentur.com', '127.0.0.1', '192.168.178.101','localhost', 'dev01.digitale-agentur.com', '10.0.2.2']
# FORWARD HEADERS
@ -204,9 +208,6 @@ MEDIA_URL = '/media/'
# CRISPY
CRISPY_TEMPLATE_PACK = 'bootstrap4'
# Bildspeicherpfad
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
# FOR COLORFIELD
GRAPPELLI_CLEAN_INPUT_TYPES = False

View File

@ -5,8 +5,12 @@ from django.conf import settings
from django.conf.urls.static import static
from users.views import AgencyCreateView, registerNewAgency
from . import views
from .views import GetCryptFile
from django.contrib.auth.decorators import login_required
from rest_framework.authtoken.views import obtain_auth_token
from django_encrypted_filefield.constants import FETCH_URL_NAME
from django.conf.urls import url
urlpatterns = [
path('login/', auth_views.LoginView.as_view(template_name='users/login.html'), name='login'),
@ -35,6 +39,8 @@ urlpatterns = [
path('api/', include('api.urls', namespace='api')),
path('chat/', include('chat.urls'), name='chat'),
path('api-token-auth/', obtain_auth_token, name='api-token-auth'),
path('getdoc/<path:path>', GetCryptFile.as_view(), name=FETCH_URL_NAME),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -1,4 +1,106 @@
from django.shortcuts import render
from django.contrib.auth.mixins import AccessMixin
from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView
import requests
import magic
from django.conf import settings
from django.core.validators import URLValidator, ValidationError
from django.http import Http404, HttpResponse
from django.views.generic import View
import base64
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import os, six
def _get_setting(name):
setting_name = "DEFF_{}".format(name)
return os.getenv(setting_name, getattr(settings, setting_name, None))
def get_bytes(v):
if isinstance(v, six.string_types):
return bytes(v.encode("utf-8"))
if isinstance(v, bytes):
return v
raise TypeError(
"SALT & PASSWORD must be specified as strings that convert nicely to "
"bytes."
)
SALT = get_bytes(_get_setting("SALT"))
PASSWORD = get_bytes(_get_setting("PASSWORD"))
FETCH_URL_NAME = _get_setting("FETCH_URL_NAME")
class Cryptographer(object):
_fernet = Fernet(base64.urlsafe_b64encode(PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=SALT,
iterations=100000,
backend=default_backend()
).derive(PASSWORD)))
@classmethod
def encrypted(cls, content):
return cls._fernet.encrypt(content)
@classmethod
def decrypted(cls, content):
return cls._fernet.decrypt(content)
def registerdone(request):
return render (request, 'users/registercomplete.html')
class GetCryptFile(DetailView):
def get(self, request, *args, **kwargs):
if(self.request.user.has_perm("users.recoverdirmanager")):
path = kwargs.get("path")
# No path? You're boned. Move along.
if not path:
raise Http404
if self._is_url(path):
content = requests.get(path, stream=True).raw.read()
else:
# Normalise the path to strip out naughty attempts
path = os.path.normpath(path).replace(settings.MEDIA_URL, settings.MEDIA_ROOT, 1)
path = "media/" + path
# Evil path request!
#if not path.startswith(settings.MEDIA_ROOT):
# print("404 startswith")
# raise Http404
# The file requested doesn't exist locally. A legit 404
if not os.path.exists(path):
raise Http404
with open(path, "rb") as f:
content = f.read()
content = Cryptographer.decrypted(content)
return HttpResponse(content, content_type=magic.Magic(mime=True).from_buffer(content))
else:
return render(request, 'cloud/noentrie.html')
@staticmethod
def _is_url(path):
try:
URLValidator()(path)
return True
except ValidationError:
return False

BIN
media/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -1,6 +1,7 @@
from django import forms
from django.forms import ModelForm
from .models import PersLetter
from .models import *
from bootstrap_datepicker_plus import DatePickerInput
class PersLetterForm(forms.ModelForm):
@ -17,3 +18,78 @@ class PersLetterForm(forms.ModelForm):
super(PersLetterForm, self).__init__(*args, **kwargs)
self.fields['text'] = forms.CharField(label="Ihr persönlicher Text", widget=forms.Textarea(attrs={"rows":15, "cols":35}))
# NOTFALLORDNER FORMS
# 1 Handlungsleitfaden
class HLForm(forms.ModelForm):
class Meta:
model = Handlungsleitfaden
fields = ['rd_main','rd_prename','rd_postname','rd_street','rd_plz','rd_city','rd_tel','rd_mail','bvk_number','rv_name','rv_number','rv_tel_1','rv_tel_2']
labels = {
'rd_main' : "Zuständige RD",
'rd_prename': "Vorname RD Leiter",
'rd_postname' : "Nachname RD Leiter",
'rd_street' : "RD Straße",
'rd_plz' : "RD PLZ",
'rd_city' : "RD Stadt",
'rd_tel' : "RD Telefon",
'rd_mail' : "RD E-Mail",
'bvk_number' : "BVK Nummer",
'rv_name' : "Rechtsschutzversicherer",
'rv_number' : "Versicherungsnummer",
'rv_tel_1' : "Telefon 1",
'rv_tel_2' : "Telefon 2"
}
class RDContactF(forms.ModelForm):
class Meta:
model = RDContact
fields = ['rd_prename','rd_postname','rd_rel','rd_adresse','rd_tel']
labels = {
'rd_prename' : "Vorname",
'rd_postname' : "Nachname",
'rd_rel' : "Beziehung",
'rd_adresse' : "Adresse",
'rd_tel' : "Telefon"
}
class RDTrustPersonF(forms.ModelForm):
class Meta:
model = RDTrustPerson
fields = ['rd_prename','rd_postname','rd_company','rd_adresse','rd_tel']
labels = {
'rd_prename' : "Vorname",
'rd_postname' : "Nachname",
'rd_company' : "Firma",
'rd_adresse' : "Adresse",
'rd_tel' : "Telefon"
}
# DOCUMENTS
class DocumentForm(forms.ModelForm):
class Meta:
model = Documents
fields = ['document_desc', 'document_date', 'document_name','document', 'area']
labels = {
'document_desc' : "Dokumentbeschreibung",
'document_date' : "Datum",
"document_name" : "Dateiname",
'document' : "Dokument"
}
widgets = {
'document_date': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'})
}
def __init__(self, *args, **kwargs):
super(DocumentForm, self).__init__(*args, **kwargs)
self.fields['area'] = forms.CharField(initial="", required=False, widget=forms.HiddenInput())

View File

@ -7,6 +7,17 @@ from django_cryptography.fields import encrypt
# HISTORY
from simple_history.models import HistoricalRecords
from django_encrypted_filefield.fields import (
EncryptedFileField,
EncryptedImageField
)
# PATH FOR AGENCYPIC
def rd_path_agency(instance, filename):
# file will be uploaded to MEDIA_URL/agency_<id>/<subdirs>/<filename>
return 'agencydata/agency_{0}/rd/{1}'.format(instance.agency.pk, filename)
# Create your models here.
class PersLetter(models.Model):
@ -15,3 +26,52 @@ class PersLetter(models.Model):
text = encrypt(models.CharField(max_length=100000, blank=True, default="", null=True))
history = HistoricalRecords()
# Notfallordner Datenfelder
# Handlungsleitfaden
class Handlungsleitfaden(models.Model):
agency = models.ForeignKey(Agency, on_delete=models.CASCADE, null=True)
rd_main = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_prename = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_postname = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_street = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_plz = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_city = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_tel = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_mail = encrypt(models.EmailField(max_length=500, blank=True, default="", null=True))
bvk_number = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rv_name = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rv_number = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rv_tel_1 = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rv_tel_2 = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
history = HistoricalRecords()
# Contacts
class RDContact(models.Model):
agency = models.ForeignKey(Agency, on_delete=models.CASCADE, null=True)
rd_prename = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_postname = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_rel = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_adresse = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_tel = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
history = HistoricalRecords()
class RDTrustPerson(models.Model):
agency = models.ForeignKey(Agency, on_delete=models.CASCADE, null=True)
rd_prename = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_postname = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_company = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_adresse = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
rd_tel = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
history = HistoricalRecords()
class Documents(models.Model):
agency = models.ForeignKey(Agency, on_delete=models.CASCADE, null=True)
area = models.IntegerField(default=0)
document_desc = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
document_name = encrypt(models.CharField(max_length=500, blank=False, default="", null=False))
document_date = encrypt(models.DateField(default=timezone.now, blank=True, null=True))
document = EncryptedFileField(upload_to=rd_path_agency, blank=True)
history = HistoricalRecords()

View File

@ -0,0 +1,157 @@
{% if area_1_hl == None %}
<a class="btn btn-primary btn" href="{% url 'rd-a1-hl' %}"><i class="fas fa-plus"></i>&nbsp;Handlungsleitfaden</a>
{% else %}
<h4><a href="{% url 'rd-a1-hl-update' area_1_hl.pk %}">Handlungsleitfaden bearbeiten</a></h4>
{% endif %}
<hr>
<h4>Familie und Freunde
<a class="btn btn-primary btn mb-3" href="{% url 'rd-a1-addfamily' %}" style="float: right;"><i class="fas fa-plus"></i>&nbsp;Kontakt</a>
</h4>
<table class="table table-hover" id="a1_fc" >
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Beziehung</th>
<th scope="col">Adresse</th>
<th scope="col">Telefon</th>
<th scope="col">&nbsp;</th>
</tr>
</thead>
<tbody >
{% for familyc in area_1_fc %}
<tr>
<td>{{familyc.rd_prename}} {{familyc.rd_postname}}</td>
<td>{{familyc.rd_rel}}</td>
<td>{{familyc.rd_adresse}}</td>
<td>{{familyc.rd_tel}}</td>
<td>&nbsp;</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr>
<h4>Vertrauensperson
<a class="btn btn-primary btn mb-3" href="{% url 'rd-a1-addtrust' %}" style="float: right;"><i class="fas fa-plus"></i>&nbsp;Vertrauensperson</a>
</h4>
<table class="table table-hover" id="a1_trust" >
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Firma</th>
<th scope="col">Adresse</th>
<th scope="col">Telefon</th>
<th scope="col">&nbsp;</th>
</tr>
</thead>
<tbody >
{% for familyc in area_1_trust %}
<tr>
<td>{{familyc.rd_prename}} {{familyc.rd_postname}}</td>
<td>{{familyc.rd_company}}</td>
<td>{{familyc.rd_adresse}}</td>
<td>{{familyc.rd_tel}}</td>
<td>&nbsp;</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr>
<h4>Vorsorgedokumente
<a class="btn btn-primary btn mb-3" href="{% url 'rd-a1-adddoc' %}" style="float: right;"><i class="fas fa-plus"></i>&nbsp;Vorsorgedokument</a>
</h4>
<table class="table table-hover" id="a1_docs" >
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Datum</th>
<th scope="col">Beschreibung</th>
<th scope="col">&nbsp;</th>
</tr>
</thead>
<tbody >
{% for doc in area_1_doc %}
<tr>
<td><a href="{% url 'rd-a1-viewdoc' doc.pk %}" target="_blank">{{doc.document_name}}</a></td>
<td>{{doc.document_date|date:"d.m.Y"}}</td>
<td>{{doc.document_desc}}</td>
<td>
<a style="float: right" class="btn btn-secondary btn-sm mr-2 " href="{% url 'rd-a1-viewdoc' doc.pk %}" target="_blank"><i class="far fa-eye"></i></a>&nbsp;
<a style="float: right" class="btn btn-secondary btn-sm mr-2 " href="#"><small><i class="fas fa-pen"></i></small></a>&nbsp;
<a style="float: right" class="btn btn-secondary btn-sm mr-2 " href="#"><small><i class="fas fa-trash"></i></small></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<script type="text/javascript">
$(document).ready(function(){
$('#a1_docs').DataTable({
"language": {
"search" : "Suche",
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
"lengthMenu": "Zeige _MENU_ Einträge",
"zeroRecords": "Nichts gefunden",
"infoEmpty": "Keine Einträge",
"paginate": {
"first": "Erste",
"last": "Letzte",
"next": "Nächste",
"previous": "Zurück"
},
},
"pageLength": 50,
"buttons" : {
"className" : "btn-danger"
}
});
$('#a1_fc').DataTable({
"language": {
"search" : "Suche",
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
"lengthMenu": "Zeige _MENU_ Einträge",
"zeroRecords": "Nichts gefunden",
"infoEmpty": "Keine Einträge",
"paginate": {
"first": "Erste",
"last": "Letzte",
"next": "Nächste",
"previous": "Zurück"
},
},
"pageLength": 50,
"buttons" : {
"className" : "btn-danger"
}
});
$('#a1_trust').DataTable({
"language": {
"search" : "Suche",
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
"lengthMenu": "Zeige _MENU_ Einträge",
"zeroRecords": "Nichts gefunden",
"infoEmpty": "Keine Einträge",
"paginate": {
"first": "Erste",
"last": "Letzte",
"next": "Nächste",
"previous": "Zurück"
},
},
"pageLength": 50,
"buttons" : {
"className" : "btn-danger"
}
});
});
</script>

View File

@ -0,0 +1 @@
ZWEITE

View File

@ -0,0 +1 @@
DRIITTE

View File

@ -0,0 +1 @@
VIERTE

View File

@ -0,0 +1 @@
FÜNFTE

View File

@ -0,0 +1 @@
SECHSTE

View File

@ -0,0 +1 @@
SIEBTE

View File

@ -0,0 +1 @@
ACHTE

View File

@ -0,0 +1 @@
NEUNTE

View File

@ -0,0 +1,21 @@
{% extends "users/base.html" %}
{% block content %}
{% if request.user.profile.agency.module_recoverdir %}
<div class="content-section col-12">
<h3>Dokumentenansicht
<span style="float: right">
<a href="{% url 'recoverdir'%}" style="float: right" class="btn btn-secondary btn-sm "><small><i class="fas fa-chevron-circle-left"></i></small></a>
</span>
</h3>
<hr>
<h4>Beschreibung</h4>
<p>{{document.document_desc}}</p>
<p>Datum: {{document.document_date}}</p>
<hr>
<a href="{% url 'getdoc' document.document %}" target="_blank">Datei herunterladen</a>
<hr>
</div>
{% else %}
<h3>Auf dieses Modul haben Sie keinen Zugriff!</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,27 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_recoverdir %}
<div class="content-section col-9">
<h3>Vorsorgedokument hinzufügen</h3>
<hr>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.media}}
{{ form|crispy }}
<hr>
<a class="btn" href="{% url 'recoverdir' %} ">Abbrechen</a>
<button type="submit" class="btn btn-primary" style="float: right;">Vorsorgedokument speichern</button>&nbsp;
</form>
</div>
<script type="text/javascript">
$("#id_document").on("change", function(){
filename = $("#id_document")[0]['files'][0]['name'];
filetype = $("#id_document")[0]['files'][0]['type'];
$("#id_document_name").val(filename.split(".")[0]);
})
</script>
{% else %}
<h3>Das Modul Notfallordner wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,20 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_recoverdir %}
<div class="content-section col-9">
<h3>Familien/Freundekontakt bearbeiten</h3>
<hr>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.media}}
{{form|crispy}}
<hr>
<a class="btn" href="{% url 'recoverdir' %} ">Abbrechen</a>
<button type="submit" class="btn btn-primary" style="float: right;">Familien-/Freundekontakt speichern</button>&nbsp;
</form>
</div>
{% else %}
<h3>Das Modul Notfallordner wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,38 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_recoverdir %}
<div class="content-section col-9">
<h3>Handlungsleitfaden bearbeiten</h3>
<hr>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.media}}
<h4>Daten der Regionaldirektion</h4>
{{form.rd_main|as_crispy_field}}
{{form.rd_prename|as_crispy_field}}
{{form.rd_postname|as_crispy_field}}
{{form.rd_street|as_crispy_field}}
{{form.rd_plz|as_crispy_field}}
{{form.rd_city|as_crispy_field}}
{{form.rd_tel|as_crispy_field}}
{{form.rd_mail|as_crispy_field}}
<hr>
<h4>BVK Mitgliedsnummer</h4>
{{form.bvk_number|as_crispy_field}}
<hr>
<h4>Rechtsschutzersicherungsdaten</h4>
{{form.rv_name|as_crispy_field}}
{{form.rv_number|as_crispy_field}}
{{form.rv_tel_1|as_crispy_field}}
{{form.rv_tel_2|as_crispy_field}}
<hr>
<a class="btn" href="{% url 'recoverdir' %} ">Abbrechen</a>
<button type="submit" class="btn btn-primary" style="float: right;">Handlungsleitfaden speichern</button>&nbsp;
</form>
</div>
{% else %}
<h3>Das Modul Notfallordner wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,20 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_recoverdir %}
<div class="content-section col-9">
<h3>Vertraunsperson bearbeiten</h3>
<hr>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.media}}
{{form|crispy}}
<hr>
<a class="btn" href="{% url 'recoverdir' %} ">Abbrechen</a>
<button type="submit" class="btn btn-primary" style="float: right;">Vertrauensperson speichern</button>&nbsp;
</form>
</div>
{% else %}
<h3>Das Modul Notfallordner wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -33,7 +33,11 @@
<div class="col">
<div class="tab-content" id="rd_content">
<div class="tab-pane" id="t_rd" role="tabpanel" aria-labelledby="rd">
Notfallordner
<h5 class="mt-3">Notfallordner{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Hinterlegen Sie hier alle Dokumente und Informationen im Notfallordner." class="far fa-question-circle"></i></small>{% endif %}</h5>
<hr>
{% block rd_content %}
{% include "recoverdir/rd_rd.html" %}
{% endblock %}
</div>
<div class="tab-pane fade" id="t_infos" role="tabpanel" aria-labelledby="infos">

View File

@ -0,0 +1,257 @@
<style type="text/css">
.square_private_arrow {
float: right;
margin-right: 0px;
width: 65px;
height: 65px;
background-color: red;
color: #ffffff;
-webkit-clip-path:polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 25% 50%);
}
.square_company_arrow {
float: right;
margin-right: 0px;
width: 65px;
height: 65px;
background-color: black;
color: #ffffff;
-webkit-clip-path:polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 25% 50%);
}
.h2_in_arrow {
margin-left: 23px;
margin-top: 13px;
}
</style>
<div id="accordion">
<!-- 1. NOTFALLLEITFADEN -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#rd_1" aria-expanded="true" aria-controls="rd_1">
<h4 style="margin-top: 11px;">1. Notfallleitfaden & Vorsorgedokumente</h4>
</button>
<span style="float: right;">
<span class="square_private_arrow"><h2 class="h2_in_arrow">#1</h2></span>
</span>
</h5>
</div>
<div id="rd_1" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
{% block rd_area_1 %}
{% include "recoverdir/rd_areas/rd_area_1.html" %}
{% endblock %}
</div>
</div>
</div>
<!-- 2. ABSICHERUNG VERMÖGEN IMMOBILIEN -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#rd_2" aria-expanded="true" aria-controls="rd_2">
<h4 style="margin-top: 11px;">2. Absicherung, Vermögen & Immobilien</h4>
</button>
<span style="float: right;">
<span class="square_private_arrow"><h2 class="h2_in_arrow">#2</h2></span>
</span>
</h5>
</div>
<div id="rd_2" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
{% block rd_area_2 %}
{% include "recoverdir/rd_areas/rd_area_2.html" %}
{% endblock %}
</div>
</div>
</div>
<!-- 3. Verträge -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#rd_3" aria-expanded="true" aria-controls="rd_3">
<h4 style="margin-top: 11px;">3. Verträge</h4>
</button>
<span style="float: right;">
<span class="square_private_arrow"><h2 class="h2_in_arrow">#3</h2></span>
</span>
</h5>
</div>
<div id="rd_3" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
{% block rd_area_3 %}
{% include "recoverdir/rd_areas/rd_area_3.html" %}
{% endblock %}
</div>
</div>
</div>
<!-- 4. Digitale Konten -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#rd_4" aria-expanded="true" aria-controls="rd_4">
<h4 style="margin-top: 11px;">4. Digitale Konten & Passwörter</h4>
</button>
<span style="float: right;">
<span class="square_private_arrow"><h2 class="h2_in_arrow">#4</h2></span>
</span>
</h5>
</div>
<div id="rd_4" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
{% block rd_area_4 %}
{% include "recoverdir/rd_areas/rd_area_4.html" %}
{% endblock %}
</div>
</div>
</div>
<!-- GEWERBE -->
<!-- 5. Vorsorgedokumente -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#rd_5" aria-expanded="true" aria-controls="rd_5">
<h4 style="margin-top: 11px;">5. Gewerbe: Vorsorgedokumente</h4>
</button>
<span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#5</h2></span>
</span>
</h5>
</div>
<div id="rd_5" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
{% block rd_area_5 %}
{% include "recoverdir/rd_areas/rd_area_5.html" %}
{% endblock %}
</div>
</div>
</div>
<!-- 6. Vorsroge und Finanzen -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" 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>
</button>
<span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#6</h2></span>
</span>
</h5>
</div>
<div id="rd_6" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
{% block rd_area_6 %}
{% include "recoverdir/rd_areas/rd_area_6.html" %}
{% endblock %}
</div>
</div>
</div>
<!-- 7. Immobilien -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#rd_7" aria-expanded="true" aria-controls="rd_7">
<h4 style="margin-top: 11px;">7. Gewerbe: Immobilien</h4>
</button>
<span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#7</h2></span>
</span>
</h5>
</div>
<div id="rd_7" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
{% block rd_area_7 %}
{% include "recoverdir/rd_areas/rd_area_7.html" %}
{% endblock %}
</div>
</div>
</div>
<!-- 8. Verträge -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#rd_8" aria-expanded="true" aria-controls="rd_8">
<h4 style="margin-top: 11px;">8. Gewerbe: Verträge</h4>
</button>
<span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#8</h2></span>
</span>
</h5>
</div>
<div id="rd_8" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
{% block rd_area_8 %}
{% include "recoverdir/rd_areas/rd_area_8.html" %}
{% endblock %}
</div>
</div>
</div>
<!-- 9. Sonstiges -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#rd_9" aria-expanded="true" aria-controls="rd_9">
<h4 style="margin-top: 11px;">9. Sonstiges</h4>
</button>
<span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#9</h2></span>
</span>
</h5>
</div>
<div id="rd_9" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
{% block rd_area_9 %}
{% include "recoverdir/rd_areas/rd_area_9.html" %}
{% endblock %}
</div>
</div>
</div>
</div>

View File

@ -9,10 +9,13 @@
</tr>
</thead>
<tbody>
{% for plver in persletter.history.all %}
{% for ele in history %}
{% for plver in ele.history.all %}
<tr>
<td>Persönlicher Brief</td>
<td><a href="{% url 'recoverdir-plsingle' persletter.pk plver.pk %}">{{plver.history_date|date:"d.m.Y H:i"}}</a></td>
<td>
{% getClassOfObject plver as plver_typ %}
{{plver}} {{plver_typ}}</td>
<td>{{plver.history_date|date:"d.m.Y H:i"}}</td>
<td>
{% gethistoryuser plver.history_user_id as history_user %}
@ -24,6 +27,7 @@
</td>
<td>{% if plver.history_type == "~" %} Geändert {% elif plver.history_type == "+" %} Erstellt {% elif plver.history_type == "-"%} Gelöscht {% endif %}
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
@ -48,7 +52,8 @@
"pageLength": 50,
"buttons" : {
"className" : "btn-danger"
}
},
"order": [[ 1, "desc" ]]
});

View File

@ -1,6 +1,9 @@
from django.urls import path
from django.contrib.auth import views as auth_views
from django.contrib.auth.decorators import login_required, permission_required
from django_encrypted_filefield.constants import FETCH_URL_NAME
from .views import *
'''
Permissions definiert in models.py bei USERS und dann hier vor die View geschrieben!
@ -11,7 +14,10 @@ urlpatterns = [
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('pl/ver/<int:pk>/<int:rev>', permission_required('users.recoverdirmanager')(PLSingle.as_view(template_name="recoverdir/rd_persletter_single.html")), name='recoverdir-plsingle'),
path('aone/doc/add', permission_required('users.recoverdirmanager')(RDAoneAddDoc.as_view()), name='rd-a1-adddoc'),
path('aone/doc/<int:pk>', permission_required('users.recoverdirmanager')(RDAoneViewDoc.as_view()), name='rd-a1-viewdoc'),
path('aone/hl/add', permission_required('users.recoverdirmanager')(RDAoneAddHL.as_view()), name='rd-a1-hl'),
path('aone/hl/update/<int:pk>', permission_required('users.recoverdirmanager')(RDAoneUpdateHL.as_view()), name='rd-a1-hl-update'),
path('aone/fc/add', permission_required('users.recoverdirmanager')(RDAoneAddFC.as_view()), name='rd-a1-addfamily'),
path('aone/trust/add', permission_required('users.recoverdirmanager')(RDAoneAddTrust.as_view()), name='rd-a1-addtrust'),
]

View File

@ -4,6 +4,14 @@ from django.views.generic import CreateView, ListView, UpdateView, DetailView, D
from .models import *
from .forms import *
from django.urls import reverse_lazy
from django.contrib.auth.decorators import login_required
import os
import sys
from django.conf import settings
from django.http import JsonResponse, HttpResponse, Http404
from django_encrypted_filefield.views import FetchView
import string, random
from itertools import chain
# Create your views here.
class RecoverDirManagement(LoginRequiredMixin, ListView):
@ -19,6 +27,38 @@ class RecoverDirManagement(LoginRequiredMixin, ListView):
persletter = PersLetter.objects.filter(agency=self.request.user.profile.agency)[0]
context.update({'persletter' : persletter})
# Load Update-Historys
persletters = PersLetter.objects.filter(agency=self.request.user.profile.agency)
handlungsleitfaden = Handlungsleitfaden.objects.filter(agency=self.request.user.profile.agency)
contactfc = RDContact.objects.filter(agency=self.request.user.profile.agency)
contactstrust = RDTrustPerson.objects.filter(agency=self.request.user.profile.agency)
documents = Documents.objects.filter(agency=self.request.user.profile.agency, area=1)
finalupdatelist = chain(persletters, handlungsleitfaden, contactfc, contactstrust, documents)
context.update({"history" : finalupdatelist})
print(finalupdatelist)
# Bereich 1 - Handlungsleitfaden ########## ########## ########## ########## ########## ##########
# Handlungsleitfaden
hl = Handlungsleitfaden.objects.filter(agency=self.request.user.profile.agency)
if(len(hl) == 1):
hl = Handlungsleitfaden.objects.filter(agency=self.request.user.profile.agency)[0]
else:
hl = None
context.update({'area_1_hl' : hl})
# Familien-Freunde
context.update({'area_1_fc' : RDContact.objects.filter(agency=self.request.user.profile.agency)})
# Vertrauensperson
context.update({'area_1_trust' : RDTrustPerson.objects.filter(agency=self.request.user.profile.agency)})
# Dokumente
context.update({'area_1_doc' : Documents.objects.filter(agency=self.request.user.profile.agency, area=1).order_by('-document_date')})
return context
@ -63,6 +103,7 @@ class RecoverDirAddPL(CreateView):
# TASK: Hier Aktualisierung hinzufügen!
return super().form_valid(form)
class RecoverDirUpdatePL(UpdateView):
model = PersLetter
success_url = reverse_lazy('recoverdir')
@ -79,3 +120,108 @@ class RecoverDirUpdatePL(UpdateView):
return super().form_valid(form)
def randomString(stringLength=40):
"""Generate a random string of fixed length """
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(stringLength))
# NOTFALLORDNER ELEMENTE
# ABNSCHNITT 1
class RDAoneAddDoc(CreateView):
model = Documents
success_url = reverse_lazy('recoverdir')
form_class = DocumentForm
template_name = "recoverdir/rd_elements_forms/rd_area_1_adddoc.html"
def form_valid(self, form):
form.instance.agency = self.request.user.profile.agency
form.instance.area = 1
# Randomize File-Name keeping extension
file = self.request.FILES['document']
file_ext_arr = file.name.split(".")
file_ext = file_ext_arr[len(file_ext_arr)-1]
file.name = randomString() + "." + file_ext
form.instance.document = file
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : 'recoverdir'})
return context
# Einzeldokumentenanzeige
class RDAoneViewDoc(DetailView):
model = Documents
success_url = reverse_lazy('recoverdir')
template_name = 'recoverdir/rd_doc_single.html'
context_object_name = 'document'
# Handlungsleitfaden
# ABNSCHNITT 1
class RDAoneAddHL(CreateView):
model = Handlungsleitfaden
success_url = reverse_lazy('recoverdir')
form_class = HLForm
template_name = "recoverdir/rd_elements_forms/rd_area_1_addhl.html"
def form_valid(self, form):
form.instance.agency = self.request.user.profile.agency
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : 'recoverdir'})
return context
class RDAoneUpdateHL(UpdateView):
model = Handlungsleitfaden
success_url = reverse_lazy('recoverdir')
form_class = HLForm
template_name = "recoverdir/rd_elements_forms/rd_area_1_addhl.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : 'recoverdir'})
return context
class RDAoneAddFC(CreateView):
model = RDContact
success_url = reverse_lazy('recoverdir')
form_class = RDContactF
template_name = "recoverdir/rd_elements_forms/rd_area_1_addfc.html"
def form_valid(self, form):
form.instance.agency = self.request.user.profile.agency
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : 'recoverdir'})
return context
class RDAoneAddTrust(CreateView):
model = RDTrustPerson
success_url = reverse_lazy('recoverdir')
form_class = RDTrustPersonF
template_name = "recoverdir/rd_elements_forms/rd_area_1_addtrust.html"
def form_valid(self, form):
form.instance.agency = self.request.user.profile.agency
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : 'recoverdir'})
return context

View File

@ -29,3 +29,5 @@ channels-redis==3.0.1
filetype==1.0.7
python-dateutil==2.8.1
django-simple-history==2.11.0
django-encrypted-filefield==0.2.2
more-itertools==8.5.0

View File

@ -742,6 +742,10 @@ def gethistoryuser(userid):
last_user = None
return last_user
@register.simple_tag
def getClassOfObject(value):
return value.__class__.__name__

View File

@ -239,7 +239,7 @@ Gleitzeitkonto:
}
start = data["wd_starttime_complete"];
realTimeClock();
location.href = location.href;
//location.href = location.href;
}
});

View File

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

View File

@ -55,7 +55,7 @@
<tr>
<th scope="col">Titel</th>
<th scope="col">Bearbeitet von</th>
<th scope="col">Zuletzt bearbeitet am</th>
<th scope="col">Bearbeitet am</th>
</tr>
</thead>
{% for standard in standards_of_agency %}

View File

@ -156,8 +156,7 @@ SUPPORT_DEP = (
('12', 'Technischer Support'),
('13', 'Abrechnung'),
('14', 'Lob, Kritik und Anregung'),
)
)
class SupportForm(forms.Form):
def __init__(self, user, *args, **kwargs):