Notfallordner PersSchreiben done

This commit is contained in:
holger.trampe 2020-10-02 23:41:53 +02:00
parent d7b73b832f
commit 633a7dadb6
28 changed files with 343 additions and 15 deletions

4
.gitignore vendored
View File

@ -26,6 +26,10 @@ standards/migrations/*
!standards/migrations/__init__.py
standards/__pycache__/*
recoverdir/migrations/*
!recoverdir/migrations/__init__.py
recoverdir/__pycache__/*
api/migrations/*
!api/migrations/__init__.py
api/__pycache__/*

View File

@ -10,7 +10,7 @@
<div class="card d-block mb-3 mr-2">
<div class="card-body">
<h5 class="card-title">Ihr Betrag</h5>
<p>Ihr monatlicher Nutzungsbeitrag setzt sich wie folgt zusammen:</p>
<p>Ihr monatlicher Nutzungsbetrag setzt sich wie folgt zusammen:</p>
<table style="width: 75%">
<tr>
<td>Grundbetrag (inkl. 3 Nutzer)</td><td>21,00 €</td>
@ -24,9 +24,9 @@
<td>Gesetzliche MwSt. (16%)</td><td>{{mwst|floatformat:2|intcomma}} €</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2"><hr></td>
</tr>
<tr class="mt-2">
<tr>
{% loadFinalMoney user as fm %}
<td><b>Monatlicher Bruttobetrag</b></td><td><b>{{fm|floatformat:2|intcomma}} €</b></td>
</tr>

View File

@ -35,9 +35,11 @@
<div id="agroup_{{aggroup.pk}}_card" class="collapse" aria-labelledby="agroup_{{aggroup.pk}}" data-parent="#groupAccordion">
<div class="card-body">
<h5>Gruppenrechte{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Gruppenrechte beeinflussen die Möglichkeiten der Mitarbeiter in einer Gruppe, z.B. dürfen nur Mitarbeiter in einer Gruppe mit dem Recht News entsprechend News erstellen, veröffentlichen und bearbeiten." class="far fa-question-circle"></i></small>{% endif %}</h5>
{% if aggroup.agencygroupname != "Notfallordner" %}
<div class="row">
<div class="col-4">
{% for perm in perms %}
{% if perm.help_text != "Notfallordner verwalten" %}
{% if forloop.counter|divisibleby:8 %}
</div>
<div class="col-4">
@ -51,10 +53,15 @@
<label class="custom-control-label" for="{{aggroup.pk}}_{{perm.name}}" >{{perm.help_text}}</label>
</div>
{% endif %}
{% endif %}
{% endfor %}
</div>
</div><!-- END ROW RIGHT -->
<hr>
{% else %}
Der Notfallordner ist für keine weiteren Rechte konfigurierbar.
<hr>
{% endif %}
<div col="10">
<h6>Mitarbeiter zur Gruppe <b>{{aggroup.agencygroupname}}</b> hinzufügen</h6>
<div class="input-group mb-3 col-5">
@ -98,10 +105,17 @@
</div>
</div>
{% if forloop.counter == 2 %}
{% if request.user.profile.agency.module_recoverdir %}
{% if forloop.counter == 3 %}
<hr>
{% endif %}
{% else %}
{% if forloop.counter == 2 %}
<hr>
{% endif %}
{% endif %}
{% endfor %}
</div>
</div>

View File

@ -163,7 +163,11 @@ def DASettings(request):
context.update({"agencyjobs" : AgencyJob.objects.filter(agency__pk=request.user.profile.agency.pk).order_by("name")})
# LOAD GROUPS
if request.user.profile.agency.module_recoverdir:
agencygroups = AgencyGroup.objects.filter(agency__pk=request.user.profile.agency.pk).order_by("agencygroupname").order_by("-savefordel")
else:
agencygroups = AgencyGroup.objects.filter(agency__pk=request.user.profile.agency.pk).order_by("agencygroupname").order_by("-savefordel").exclude(agencygroupname="Notfallordner")
context.update({"agencygroups" : agencygroups})
# LOAD AREAS

View File

@ -62,6 +62,7 @@ INSTALLED_APPS = [
'organizer.apps.OrganizerConfig',
'standards.apps.StandardsConfig',
'timemanagement.apps.TimemanagementConfig',
'recoverdir.apps.RecoverdirConfig',
'news.apps.NewsConfig',
'crispy_forms',
'colorful',

View File

@ -20,6 +20,7 @@ urlpatterns = [
path('organizer/', include('organizer.urls'), name="ql-management"),
path('cloud/', include('cloud.urls'), name="cloud-main"),
path('standards/', include('standards.urls'), name="standards"),
path('rd/', include('recoverdir.urls'), name="recoverdir"),
path('news/', include('news.urls'), name="dashboard"),
path('orga/', include('orga.urls'), name="orga"),
path('password-reset/', auth_views.PasswordResetView.as_view(template_name='users/password_reset.html', html_email_template_name='users/password_reset_mail.html'), name='password-reset'),

View File

@ -24,8 +24,6 @@
</ul>
<div class="tab-content" id="organizerTabscontent">
<div class="tab-pane fade show" id="quicklinks" role="tabpanel" aria-labelledby="quicklinks-tab">
<h5 class="mt-3">Quicklinks{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Verwalten Sie hier Links auf andere Webseiten." class="far fa-question-circle"></i></small>{% endif %}
{% if user|usergperm:"moduleorganizer" %} <span style="float: right; margin-top: -5px"><a class="btn btn-primary btn-sm" href="{% url 'ql-addql' %}"><i class="fas fa-plus"></i>&nbsp;Quicklink</a></span>{% endif %}

0
recoverdir/__init__.py Normal file
View File

3
recoverdir/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

5
recoverdir/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class RecoverdirConfig(AppConfig):
name = 'recoverdir'

19
recoverdir/forms.py Normal file
View File

@ -0,0 +1,19 @@
from django import forms
from django.forms import ModelForm
from .models import PersLetter
class PersLetterForm(forms.ModelForm):
class Meta:
model = PersLetter
fields = ['text']
labels = {
'text' : "Ihr persönlicher Text"
}
def __init__(self, *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}))

View File

18
recoverdir/models.py Normal file
View File

@ -0,0 +1,18 @@
from django.db import models
from django.contrib.auth.models import User
from users.models import Agency
from django.utils import timezone
from django_cryptography.fields import encrypt
# Create your models here.
class PersLetter(models.Model):
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
text = encrypt(models.CharField(max_length=100000, blank=True, default="", null=True))
class Updates(models.Model):
agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
byuser = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
updatedate = models.DateField(default=timezone.now)
updatetype = models.CharField(max_length=200, default="", blank=True, null=True)

View File

@ -0,0 +1,77 @@
{% extends "users/base.html" %}
{% load counter_tag %}
{% block content %}
{% if request.user.profile.agency.module_recoverdir %}
<div class="content-section col-12">
<h3>Notfallordner{% 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 Notfallordner <small><i onclick="javascript:$('#youtubevideoinformation').modal('toggle');" class="far fa-play-circle"></i></small>-->
</h3>
<hr>
<div class="row">
<div class="col-12">
<ul class="nav nav-tabs" id="rd_tabs" role="tablist" >
<li class="nav-item " >
<a class="nav-link active" id="rd" style="" data-toggle="tab" href="#t_rd" role="tab" aria-controls="t_rd" aria-selected="false"> Notfallordner</a>
</li>
<li class="nav-item " >
<a class="nav-link " id="infos" style="" data-toggle="tab" href="#t_info" role="tab" aria-controls="t_info" aria-selected="false">Wichtige Informationen</a>
</li>
<li class="nav-item " >
<a class="nav-link " id="updates" style="" data-toggle="tab" href="#t_updates" role="tab" aria-controls="t_updates" aria-selected="false"> Aktualisierungen</a>
</li>
<li class="nav-item " >
<a class="nav-link " id="pers" style="" data-toggle="tab" href="#t_pers" role="tab" aria-controls="t_pers" aria-selected="false"> Persönliches Schreiben</a>
</li>
<li class="nav-item ml-auto" >
<a class="nav-link" id="settings" data-toggle="tab" href="#t_settings" role="tab" aria-controls="t_settings" aria-selected="false">Einstellungen</a>
</li>
<li class="nav-item " >
<a class="nav-link" id="help" data-toggle="tab" href="#t_help" role="tab" aria-controls="t_help" aria-selected="false">Hilfe & Kontakt</a>
</li>
</div>
<div class="col">
<div class="tab-content" id="rd_content">
<div class="tab-pane show active" id="t_rd" role="tabpanel" aria-labelledby="rd">
Notfallordner
</div>
<div class="tab-pane fade" id="t_info" role="tabpanel" aria-labelledby="infos">
Wichtige Informationen
</div>
<div class="tab-pane fade" id="t_updates" role="tabpanel" aria-labelledby="updates">
<h5 class="mt-3">Aktualisierungen{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Hier sehen Sie alle Aktualisierungen, welche im Laufe der Zeit vorgenommen wurden." class="far fa-question-circle"></i></small>{% endif %}</h5>
<hr>
{% block notifications_content %}
{% include "recoverdir/rd_updates.html" %}
{% endblock %}
</div>
<div class="tab-pane fade" id="t_pers" role="tabpanel" aria-labelledby="pers">
{% block pers_content %}
{% include "recoverdir/rd_pers.html" %}
{% endblock %}
</div>
<div class="tab-pane fade" id="t_settings" role="tabpanel" aria-labelledby="settings">
Einstellungen
</div>
<div class="tab-pane fade" id="t_help" role="tabpanel" aria-labelledby="help">
Hilfe & Kontakt
</div>
</div>
</div>
</div>
{% else %}
Sie haben keinen Zugriff auf das Modul Notfallordner. Bitte wenden Sie sich an den Support!
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,20 @@
<h5 class="mt-3">Persönliches Schreiben{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Hinterlassen Sie hier eine persönliche Nachricht." class="far fa-question-circle"></i></small>{% endif %}
{% if persletter|length == 0 %}
<!-- -->
{% else %}
<span style="float: right">
<a style="float: right" class="btn btn-secondary btn-sm ml-2" href="{% url 'recoverdir-updatepl' persletter.0.pk %}"><small><i class="fas fa-pen"></i></small></a>
</span>
{% endif %}
</h5>
<hr>
{% if persletter|length == 0 %}
<a href="{% url 'recoverdir-addpl' %}">Erstellen Sie hier Ihr persönliches Schreiben.</a>
{% else %}
{{persletter.0.text.media}}
{{persletter.0.text|safe}}
<hr>
{% endif %}

View File

@ -0,0 +1,29 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_recoverdir %}
<div class="content-section col-9">
<h3>Persönlichen Brief erstellen</h3>
<hr>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{normalForm.media}}
{{ form|crispy }}
<hr>
<button type="submit" class="btn btn-primary">Persönlichen Brief speichern</button>&nbsp;
<a class="btn" href="{% url 'recoverdir' %} ">Abbrechen</a>
</form>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#id_text').summernote({
height: 400,
lang: "de-DE",
disableDragAndDrop: true
});
});
</script>
{% else %}
<h3>Das Modul Notfallordner wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,30 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_recoverdir %}
<div class="content-section col-9">
<h3>Persönlichen Brief aktualisieren</h3>
<hr>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{normalForm.media}}
{{ form|crispy }}
<hr>
<a class="btn" href="{% url 'recoverdir' %} ">Abbrechen</a>
<button style="float: right" type="submit" class="btn btn-primary">Persönlichen Brief speichern</button>&nbsp;
</form>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#id_text').summernote({
height: 400,
lang: "de-DE",
disableDragAndDrop: true
});
});
</script>
{% else %}
<h3>Das Modul Notfallordner wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

3
recoverdir/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

17
recoverdir/urls.py Normal file
View File

@ -0,0 +1,17 @@
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 .views import *
'''
Permissions definiert in models.py bei USERS und dann hier vor die View geschrieben!
'''
urlpatterns = [
path('', permission_required('users.recoverdirmanager')(RecoverDirManagement.as_view(template_name="recoverdir/rd_management.html")), name='recoverdir'),
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'),
]

47
recoverdir/views.py Normal file
View File

@ -0,0 +1,47 @@
from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView
from .models import *
from .forms import *
from django.urls import reverse_lazy
# Create your views here.
class RecoverDirManagement(LoginRequiredMixin, ListView):
model = PersLetter
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({
'active_link' : 'recoverdir',
'persletter' : PersLetter.objects.filter(agency=self.request.user.profile.agency)
})
return context
class RecoverDirAddPL(CreateView):
model = PersLetter
success_url = reverse_lazy('recoverdir')
form_class = PersLetterForm
template_name = "recoverdir/rd_pers_add.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
form.instance.user = self.request.user
return super().form_valid(form)
class RecoverDirUpdatePL(UpdateView):
model = PersLetter
success_url = reverse_lazy('recoverdir')
form_class = PersLetterForm
template_name = "recoverdir/rd_pers_update.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : 'recoverdir'})
return context

View File

@ -162,6 +162,7 @@ class UpdateWorkdayForm(forms.ModelForm):
self.fields['start'].required = True
self.fields['end'].required = True
# ADD WORKDAY FORM
class AddWorkdayForm(forms.ModelForm):
class Meta:

View File

@ -8,6 +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
admin.site.register(StandardComments)
admin.site.register(StandardCommentRate)
@ -32,3 +33,4 @@ admin.site.register(UserYearAbsenceInfo)
admin.site.register(ChatRoom)
admin.site.register(UserNotifications)
admin.site.register(AgencyBills)
admin.site.register(PersLetter)

View File

@ -133,6 +133,11 @@ class Agency(models.Model):
vve = models.CharField(default="", max_length=200, blank=True)
# RECOVERDIR
module_recoverdir = models.BooleanField(default=False)
def __str__(self):
return f'{self.name}'
@ -479,7 +484,8 @@ class AgencyGroup(models.Model):
('filesmanager', 'Dateien bearbeiten'),
('filedirmanager', 'Ordner bearbeiten'),
('filesviewer', 'Dateien lesen'),
('absencemanager', 'Abwesenheiten verwalten')
('absencemanager', 'Abwesenheiten verwalten'),
('recoverdirmanager', 'Notfallordner verwalten')
]
# SUBCLASS

View File

@ -176,7 +176,7 @@
<!--
TODO: Counter einfügen, der in der Navi zeigt, wie viele ausstehende Anträge es gibt
TASK: Counter einfügen, der in der Navi zeigt, wie viele ausstehende Anträge es gibt
-->
@ -206,6 +206,19 @@
</li>
{% endif %}
{% if request.user.profile.agency.module_recoverdir and request.user|usergperm:"recoverdirmanager" %}
{% if active_link == 'recoverdir' %}
<li class="nav-item active">
{% else%}
<li class="nav-item">
{%endif%}
<a class="nav-link " href="{% url 'recoverdir' %}" aria-expanded="true">
<i class="fas fa-medkit"></i>
<span>Notfallordner</span>
</a>
</li>
{% endif %}
<!-- Sidebar Toggler (Sidebar) -->
<!--
<div class="text-center d-none d-md-inline">

View File

@ -88,6 +88,7 @@ def toUpdate(request):
temgroup_verwaltung.save()
temgroup_verwaltung_ag = AgencyGroup(savefordel=True, is_admin=True, group=temgroup_verwaltung, agency=request.user.profile.agency, agencygroupname="Administratoren")
temgroup_verwaltung_ag.save()
print("default groups created...adding users...")
users_of_agency = User.objects.filter(profile__agency__pk=request.user.profile.agency.pk)
for user in users_of_agency:
@ -105,6 +106,21 @@ def toUpdate(request):
else:
print("default groups existing")
# UPDATE - Notfallordner
# Gruppe Notfallordner wird hinzugefügt, wenn die Anzahl der Gruppen savefordel=True zwei ist
if (len(AgencyGroup.objects.filter(agency=request.user.profile.agency, savefordel=True)) == 2):
print("missing recoverdir-group...adding")
# NOTFALLORDNER
letters = string.ascii_lowercase
temgroup_notfallordner = Group(name=str(request.user.profile.agency.pk) + "_" + randomString(8))
temgroup_notfallordner.save()
temgroup_notfallordner_ag = AgencyGroup(savefordel=True, group=temgroup_notfallordner, agency=request.user.profile.agency, agencygroupname="Notfallordner")
temgroup_notfallordner_ag.save()
recoverdirmanagingperm = Permission.objects.get(codename='recoverdirmanager')
temgroup_notfallordner_ag.group.permissions.add(recoverdirmanagingperm)
print("recoverdirgroup added and perms set")
# CHECK FOR ALL POSSIBLE RIGHTS ON ADMINGROUP
m2m_changed.disconnect(adjust_group_notifications_permission, sender=Group.permissions.through)