digitaleagenturnc/users/views.py

1542 lines
56 KiB
Python

from django.shortcuts import render, redirect, reverse
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.decorators import login_required
from django.conf import settings
from .usersforms import UsersAddNewUser, UsersAddProfileForm, UsersChangeProfil, AgencyUpdateForm, UsersPermForm, UserAreaTaskForm, SupportForm, NewAgencyForm, NewAgencyFormRD, FormRD
from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView, View, TemplateView
from django.contrib import messages
from django.contrib.auth.models import User, Permission
from django.db import models
from .models import Profile, Agency, UserTime, UserYearAbsenceInfo, AgencyBills, RegNotfallhilfe
from django.core.mail import send_mail
from django.http import HttpResponseRedirect,HttpResponse, JsonResponse
from areas.models import Areas
from tasks.models import Tasks
from organizer.models import QuickLinks
from .priomodel import Prio
from standards.models import Standards
from datetime import datetime
from django.utils import timezone
from django.utils import formats
from news.models import News
from cloud.models import DataFile
import requests
import json
import random
import string
from PIL import Image
from django.template.loader import render_to_string
from django.contrib.auth.forms import PasswordResetForm
from django.template.loader import render_to_string
from io import StringIO
from users.models import AgencyJob, AgencyGroup, AgencyNetwork
from django.contrib.auth.models import Group
from cloud.models import DataDir
from message.models import Message
from notificsys.models import UserNotification
from organizer.models import AGContacts, AGPassword
import sys, os
from asgiref.sync import async_to_sync
from channels_presence.models import Room
from channels_presence.models import Presence
import channels.layers
from datetime import date, timedelta
from timemanagement.models import Workday, Absence, Breaks
import base64
import filetype
from django.db.models.signals import m2m_changed
from django.contrib.auth.models import User, Group
from users.signals import adjust_group_notifications_permission
from django.core.exceptions import ObjectDoesNotExist
from organizer.models import QuickLinks
from areas.models import Areas
from tasks.models import Tasks
'''
Standardstruktur laden
4x Verbünde automatisch übernehmen --> Die 4 Verbünde aus der VVE Geschäftsstelle
'''
def loadPreStructure(agency):
########## VERMARKTEN
a_vermarkten = Areas(agency=agency, name="Vermarkten", color="#27ae60", desc="", created_area_by=None)
a_vermarkten.save()
a_vermarkten_tasks = ["Bewertungen", "Empfehlungsmanagement", "ERGO Mein Lokales Marketing", "Kampagnenmanagement", "Google My Business", "Hybride Agentur", "Social Media", "Zielgruppen"]
for l in a_vermarkten_tasks:
temp = Tasks(agency=agency, area=a_vermarkten, name=l)
temp.save()
# VERKAUFEN
a_verkaufen = Areas(agency=agency, name="Verkaufen", color="#8e44ad", desc="", created_area_by=None)
a_verkaufen.save()
a_verkaufen_tasks = ["Aktionen", "Antragsprozesse", "Cross-Selling", "Kooperationen", "Leads", "Skype-Beratung", "Telefon-Beratung", "Terminvorbereitung", "Verkaufsgespräch", "Terminnachbereitung", "Terminierung/KKM"]
for l in a_verkaufen_tasks:
temp = Tasks(agency=agency, area=a_verkaufen, name=l)
temp.save()
# VERWALTEN
a_verwalten = Areas(agency=agency, name="Verwalten", color="#f39c12", desc="", created_area_by=None)
a_verwalten.save()
a_verwalten_tasks = ["Agenturverwaltung", "Vertragsverwaltung", "EASY Anwendungen", "Host-Anwendungen", "Fremdverträge", "Kundenanschreiben", "Schaden und Leistung", "Textbaustein"]
for l in a_verwalten_tasks:
temp = Tasks(agency=agency, area=a_verwalten, name=l)
temp.save()
# BÜRPO INTERN
a_buerointern = Areas(agency=agency, name="Büroabläufe intern", color="#c0392b", desc="", created_area_by=None)
a_buerointern.save()
a_buero_tasks = ["Bestellungen", "Büroordnung", "Post", "Technik"]
for l in a_buero_tasks:
temp = Tasks(agency=agency, area=a_buerointern, name=l)
temp.save()
# AG-Netzwork Joins
# Join ID 8, 7, 6, 5
try:
agn_8 = AgencyNetwork.objects.get(pk=8)
agn_8.members.add(agency)
agn_7 = AgencyNetwork.objects.get(pk=7)
agn_7.members.add(agency)
agn_6 = AgencyNetwork.objects.get(pk=6)
agn_6.members.add(agency)
agn_5 = AgencyNetwork.objects.get(pk=5)
agn_5.members.add(agency)
except:
pass
# CREATE WELCOME NEWS
welcome_news = News(agency=agency, name="Herzlich Willkommen in der Digitalen Agentur", content='<p>Hallo lieber DA-Nutzer,</p><p>nicht erschrecken, wir haben für Sie schon einmal eine erste News mit allen wichtigen Informationen rund um diese Anwendung angelegt.&nbsp;</p><h4>Was bietet mir die Digitale Agentur für den Alltag?</h4><p>Bilder sagen mehr als tausend Worte - Videos sagen mehr als tausend Bilder. Hier haben wir für Sie unser Produktvideo verlinkt, um Ihnen die wesentlichen Funktionen noch einmal vorzustellen:</p><p><iframe frameborder="0" src="//www.youtube.com/embed/rGRZTZlHdEQ" width="640" height="360" class="note-video-clip"></iframe><br></p><h4>Womit fangen Sie nun am besten an?</h4><p>Damit Ihnen die ersten Schritte ein bisschen leichter fallen, haben wir für Sie eine Checkliste angelegt, die Ihnen die wichtigsten Einstellungen einmal zeigt. Die Checkliste erreichen Sie über den folgenden Link:&nbsp;<a href="https://digitale-agentur.com/article/erste-schritte/" target="_blank">digitale-agentur.com/article/erste-schritte/</a></p><h4>Wo kann ich mir Hilfe bei Fragen holen?</h4><p>Auf unserer Website finden Sie viele interessante und hilfreiche Kategorien und Artikel zur Arbeit mit der Anwendung. Wenn Sie also mal eine Frage haben oder sich inspirieren lassen wollen. Schauen Sie hier gerne vorbei:&nbsp;<a href="https://digitale-agentur.com/" target="_blank">digitale-agentur.com</a></p><p><span style="font-size: 1rem;">Bei inhaltlichen und technischen Fragen rund um die Anwendung klicken Sie einfach Links in der Navigation auf die Schaltfläche "Support", um Ihre Frage an unser Support-Team zu stellen.</span></p><p>Nun fürs erste aber genug - wir wünschen Ihnen viel Spaß und Erfolg mit der Digitalen Agentur!</p><p>Viele Grüße aus Hamburg ;)<br>Ihr DA-Team</p>')
welcome_news.save()
# ORGANIZER
hw = QuickLinks(agency=agency, name="Hilfe und Wiki", link="https://digitale-agentur.com")
hw.save()
vve = QuickLinks(agency=agency, name="myvve", link="https://myvve.de")
vve.save()
def randomString(stringLength=10):
"""Generate a random string of fixed length """
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(stringLength))
@login_required
def toUpdate(request):
# NO AGENVYJOBS
# CREATE DEFAULT
'''
Agenturleiter
Außendienst
Innendienst
Auszubildender
'''
agencyjobsobject = AgencyJob.objects.filter(agency__pk=request.user.profile.agency.pk)
if(len(agencyjobsobject) == 0):
defaultAgencyJobs = ['Agenturleiter', 'Außendienst', 'Innendienst', 'Auszubildender']
for ele in defaultAgencyJobs:
tempAgencyJob = AgencyJob(name=ele, agency=request.user.profile.agency)
tempAgencyJob.save()
agencygroups = AgencyGroup.objects.filter(agency__pk=request.user.profile.agency.pk)
if(len(agencygroups) == 0):
print("default groups not existing - creating")
# MITARBEITER
letters = string.ascii_lowercase
temgroup_mitarbeiter = Group(name=str(request.user.profile.agency.pk) + "_" + randomString(8))
temgroup_mitarbeiter.save()
temgroup_mitarbeiter_ag = AgencyGroup(savefordel=True, group=temgroup_mitarbeiter, agency=request.user.profile.agency, agencygroupname="Mitarbeiter")
temgroup_mitarbeiter_ag.save()
# VERWALTUNG
temgroup_verwaltung = Group(name=str(request.user.profile.agency.pk) + "_" + randomString(8))
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:
#print(temgroup_verwaltung_ag)
#print(temgroup_verwaltung_ag.group)
temgroup_verwaltung_ag.group.user_set.add(user)
temgroup_mitarbeiter_ag.group.user_set.add(user)
# ADDING ALL RIGHTS TO GROUP "VERWALTUNG"
perms = AgencyGroup._meta.permissions
for p in perms:
tempperm = Permission.objects.get(codename=p[0])
temgroup_verwaltung_ag.group.permissions.add(tempperm)
print("default groups created and users added")
else:
print("default groups existing")
# UPDATE - Notfallhilfe
# Gruppe Notfallhilfe 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")
# Notfallhilfe
letters = string.ascii_lowercase
temgroup_Notfallhilfe = Group(name=str(request.user.profile.agency.pk) + "_" + randomString(8))
temgroup_Notfallhilfe.save()
temgroup_Notfallhilfe_ag = AgencyGroup(savefordel=True, group=temgroup_Notfallhilfe, agency=request.user.profile.agency, agencygroupname="Notfallhilfe")
temgroup_Notfallhilfe_ag.save()
recoverdirmanagingperm = Permission.objects.get(codename='recoverdirmanager')
temgroup_Notfallhilfe_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)
ag_admingroup = list(AgencyGroup.objects.filter(agency=request.user.profile.agency, is_admin=True))[0]
perms = AgencyGroup._meta.permissions
for p in perms:
tempperm = Permission.objects.get(codename=p[0])
ag_admingroup.group.permissions.add(tempperm)
# INITIAL ROOT DIR
rootdir = DataDir.objects.filter(is_root=True, agency__pk=request.user.profile.agency.pk)
if(len(rootdir) == 0):
print("NO MAIN DIR FOUND - CREATE")
rootdir = DataDir(is_root=True, agency=request.user.profile.agency)
rootdir.save()
print("AGENCY ROOT DIR CREATED")
else:
print("MAIN ROOT DIR FOUND - FILESMODULE READY")
# CHECK IF AGENCY DIRS EXIST
path = settings.MEDIA_ROOT + "/agencydata/agency_" + str(request.user.profile.agency.pk)
if(os.path.isdir(path) == False):
# CREATE AGENCY DEFAULT DIRS
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk)))
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/profilepics"))
# DEF STANDARD DIR
defstandard = DataDir.objects.filter(is_defaultstandard=True, agency__pk=request.user.profile.agency.pk)
if(len(defstandard) == 0):
print("NO DEF STANDARD FOUND - CREATE")
rootdir = list(DataDir.objects.filter(is_root=True, agency__pk=request.user.profile.agency.pk))[0]
defstandard = DataDir(is_defaultstandard=True, agency=request.user.profile.agency, name="Standards Uploadbereich", parent_id=rootdir.pk)
defstandard.save()
print("AGENCY DEF STANDARD DIR CREATED")
else:
print("AGENCY DEF STANDARD DIR - FILESMODULE READY")
# CHANGE RIGHTS ORGNAIZER
admingroups = AgencyGroup.objects.filter(is_admin=True)
for a in admingroups:
a.group.permissions.add(Permission.objects.get(codename="moduleorganizer"))
a.group.permissions.add(Permission.objects.get(codename="agencynetwork"))
m2m_changed.connect(adjust_group_notifications_permission, sender=Group.permissions.through)
# USER TIME MODEL
usersofagency = User.objects.filter(profile__agency=request.user.profile.agency)
for u in usersofagency:
# CREATE USERTIME-OBJECT
if(len(UserTime.objects.filter(user=u)) == 0):
usertime_new = UserTime(user=u)
usertime_new.save()
else:
ut = UserTime.objects.get(user=u)
if(ut.loose_holidedate == "2020-" or ut.loose_holidedate == "2021-"):
ut.loose_holidedate = "30.04"
ut.save()
def onlyRD(request):
if request.method == "POST":
rdform = FormRD(request.POST)
if rdform.is_valid():
rd = RegNotfallhilfe()
rd.mail = rdform.cleaned_data.get('mail')
rd.name = rdform.cleaned_data.get('name')
rd.persnumber = rdform.cleaned_data.get("persnumber")
rd.mitgliedsnummer = rdform.cleaned_data.get("mitgliedsnummer")
rd.plz = rdform.cleaned_data.get("plz")
rd.stadt = rdform.cleaned_data.get("stadt")
rd.street = rdform.cleaned_data.get("street")
rd.data_to_vh = True
rd.rabatt = False
rd.save()
return render (request, 'users/rdorder_complete.html')
else:
messages.success(request, f'Bitte geben Sie korrekte Daten ein!')
context = {
"form" : FormRD(request.POST)
}
return render (request, 'users/register_rd.html',context)
else:
context = {
"form" : FormRD()
}
return render (request, 'users/register_rd.html',context)
'''
Neue Agentur UND Notfallhilfe bestellen
'''
from django.views.decorators.csrf import csrf_protect
@csrf_protect
def registerNewAgencyRD(request):
if request.method == "POST":
newagencyform = NewAgencyFormRD(request.POST)
if newagencyform.is_valid():
# Check Mail
email = newagencyform.cleaned_data.get('mail')
mailset = User.objects.filter(email=email)
if(len(mailset) == 0):
# AGENTURREGISTRIERUNG
newuser_name = newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name')
agency = Agency()
agency.name = newagencyform.cleaned_data.get("agencyname")
agency.vve = newagencyform.cleaned_data.get("vve")
agency.street = newagencyform.cleaned_data.get("street")
agency.city = newagencyform.cleaned_data.get("stadt")
agency.plz = newagencyform.cleaned_data.get("plz")
agency.save()
loadPreStructure(agency)
pr=Profile()
pr.agency=agency
user = ""
try:
user=User.objects.create_user(email, email, randomString(30))
except:
user = User.objects.get(username=email)
user.first_name = newagencyform.cleaned_data.get('first_name')
user.last_name = newagencyform.cleaned_data.get('last_name')
pr.user=user
pr.save()
user.profile = pr
user.save()
msg_html = render_to_string('users/register_mail.html', {'username': newuser_name})
# NOTFALLHILFE-DATEN SPEICHERN
rd = RegNotfallhilfe()
rd.mail = email
rd.name = newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name')
rd.persnumber = newagencyform.cleaned_data.get("persnumber")
rd.mitgliedsnummer = newagencyform.cleaned_data.get("vve")
rd.plz = newagencyform.cleaned_data.get("plz")
rd.stadt = newagencyform.cleaned_data.get("stadt")
rd.street = newagencyform.cleaned_data.get("street")
rd.data_to_vh = True
rd.rabatt = True
rd.save()
# E-Mail für Passwort-Setzung!
form = PasswordResetForm({'email': email})
if form.is_valid():
form.save(request=request,html_email_template_name='users/password_reset_mail.html')
return render (request, 'users/registercomplete.html')
else:
messages.success(request, f'Diese E-Mailadresse ist bereits vergeben!')
context = {
"form" : NewAgencyFormRD(request.POST)
}
return render (request, 'users/register_da_rd.html',context)
else:
messages.success(request, f'Bitte die korrekten Symbole aus dem Bild eingeben!')
context = {
"form" : NewAgencyForm(request.POST)
}
return render (request, 'users/register_da_rd.html',context)
else:
context = {
"form" : NewAgencyFormRD()
}
return render (request, 'users/register_da_rd.html',context)
'''
Neue Agentur registrieren
'''
def registerNewAgency(request):
if request.method == "POST":
newagencyform = NewAgencyForm(request.POST)
if newagencyform.is_valid():
# Check Mail
email = newagencyform.cleaned_data.get('mail')
mailset = User.objects.filter(email=email)
if(len(mailset) == 0):
newuser_name = newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name')
agency = Agency()
agency.name = newagencyform.cleaned_data.get("agencyname")
agency.vve = newagencyform.cleaned_data.get("vve")
agency.save()
loadPreStructure(agency)
pr=Profile()
pr.agency=agency
user = ""
try:
user=User.objects.create_user(email, email, randomString(30))
except:
user = User.objects.get(username=email)
user.first_name = newagencyform.cleaned_data.get('first_name')
user.last_name = newagencyform.cleaned_data.get('last_name')
pr.user=user
pr.save()
user.profile = pr
user.save()
msg_html = render_to_string('users/register_mail.html', {'username': newuser_name})
# E-Mail für Passwort-Setzung!
form = PasswordResetForm({'email': email})
if form.is_valid():
form.save(request=request,html_email_template_name='users/password_reset_mail.html')
return render (request, 'users/registercomplete.html')
'''
send_mail(
'Agenturanmeldung',
'Hallo ' + newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name') + '! Bitte setzen sie sich auf https://app.digitale-agentur.com/password-reset/ ein Passwort. Anschließend können Sie weitere Details Ihrer Agentur eingeben.',
'noreply@digitale-agentur.com',
[email],
html_message=msg_html,
fail_silently=True
)
'''
return render (request, 'users/registercomplete.html')
else:
messages.success(request, f'Diese E-Mailadresse ist bereits vergeben!')
context = {
"form" : NewAgencyForm(request.POST)
}
return render (request, 'users/register.html',context)
else:
messages.success(request, f'Bitte die korrekten Symbole aus dem Bild eingeben!')
context = {
"form" : NewAgencyForm(request.POST)
}
return render (request, 'users/register.html',context)
else:
context = {
"form" : NewAgencyForm()
}
return render (request, 'users/register.html',context)
class AgencyCreateView(CreateView):
model = User
fields = ['first_name', 'last_name','username', 'email']
success_url = '/register/done'
def form_valid(self, form):
# Send message to the site
messages.success(self.request, f'Agentur erstellt! Es wurde eine E-Mail verschickt mit weitere Infos zur Passworterstellung.')
# SAVE OBJECTS TO SIGNALE!
agency = Agency()
agency.name = self.request.POST.get("agency_name")
agency.save()
loadPreStructure(agency)
newuser_name = form.cleaned_data.get('first_name') + ' ' + form.cleaned_data.get('last_name')
form.instance.agency = agency
form.instance.parent = None
msg_html = render_to_string('users/register_mail.html', {'username': newuser_name})
# E-Mail für Passwort-Setzung!
send_mail(
'Agenturanmeldung',
'Hallo ' + form.cleaned_data.get('first_name') + ' ' + form.cleaned_data.get('last_name') + '! Bitte setzen sie sich auf https://app.digitale-agentur.com/password-reset/ ein Passwort. Anschließend können Sie weitere Details Ihrer Agentur eingeben.',
'noreply@digitale-agentur.com',
[form.cleaned_data.get('email')],
html_message=msg_html,
fail_silently=True
)
return super().form_valid(form)
@login_required
def dashboard(request):
# UPDATE FUNCTIONS BY NEW MODEL-CHANGES FOR COPIEN SOME DATA
toUpdate(request)
#storageinfo = sys.getfilesystemencoding()
context = {
'active_link' : 'dashboard',
#"systemencode" : storageinfo
}
# Adding active_link
# Loading only user same agency
# Change context and return for template-data
# # 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]
filterdate = datetime.now()
#news = News.objects.filter(agency__pk=request.user.profile.agency.pk).filter(go_online_on__let=filterdate).filter(go_offline_on__get=filterdate).order_by('-go_online_on')[:4]
news_all = 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') | News.objects.filter(agency__pk=request.user.profile.agency.pk).filter(go_online_on__lt=filterdate).filter(go_offline_on__isnull=True).order_by('-go_online_on')
# Maximal fünf News final zur Seite schicken!
news = []
for n in news_all:
if len(news) < 5:
news.append(n)
context.update({'active_link' : 'dashboard', 'standards_of_agency' : standards_of_agency, 'news' : news})
# GET ACUTAL ABSENCES
today = date.today()
acutal_absences = Absence.objects.filter(agency=request.user.profile.agency, end__gte=today, start__lte=today, confirm_status=0).order_by('user')
context.update({'acutal_absences' : acutal_absences})
return render (request, 'users/dashboard.html', context)
class UsersManagement(LoginRequiredMixin, ListView):
model = User
# Adding active_link
# Loading only user same agency
# Change context and return for template-data
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Get all Users of the Same Agency as logged user
users_of_agency = User.objects.filter(profile__agency__pk=self.request.user.profile.agency.pk).order_by('last_name')
context.update({'active_link' : 'usersmanagement', 'users_of_agency':users_of_agency})
return context
'''
Class AddNewUser()
Erstellt einen neuen Nutzer mit SIGNALS, Profile und Agency (des aktuellen Users mit Rechten)
'''
class UsersCreateUser(LoginRequiredMixin, CreateView):
model = User
fields = ['first_name', 'last_name', 'email']
success_url = '/settings/newuser/s2/'
# Adding active_link
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : 'settings'})
return context
def form_valid(self, form):
# Send message to the site
messages.success(self.request, f'Neuer Mitarbeiter angelegt!')
# SAVE OBJECTS TO SIGNALE!
form.instance.agency = self.request.user.profile.agency
form.instance.parent = None
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})
'''
if(self.request.POST.get("sendmailnewuser")):
send_mail(
self.request.user.profile.agency.name + ' Account',
'Hallo ' + form.cleaned_data.get('first_name') + ' ' + form.cleaned_data.get('last_name') + '! Bitte setzen sie sich auf https://app.digitale-agentur.com/password-reset/ ein Passwort.',
'noreply@digitale-agentur.com',
[form.cleaned_data.get('email')],
html_message=msg_html,
fail_silently=True,
)
'''
return super().form_valid(form)
# USER muss eingeloggt sein, um diese Seite zu sehen
@login_required
def profile(request):
if request.method == 'POST':
u_form = UsersChangeProfil(request.POST, instance=request.user)
if u_form.is_valid():
u_form.save()
prename = request.user.first_name
name = request.user.last_name
messages.success(request, f'Daten für {prename} {name} aktualisiert!')
# Daten neu laden und nicht die "Mächten sie die Daten speichern...?"
return redirect('users-dashboard')
else:
# Form in Klammern sind die aktuellen Daten :)
u_form = UsersChangeProfil(instance=request.user)
#p_form = UsersAddProfileForm(instance=request.user.profile)
context = {
'u_form' : u_form,
#'p_form' : p_form,
'active_link' : 'dashboard'
}
return render(request, 'users/profile.html', context)
# Hier andere Nutzer ändern, wenn man Usersmanagement darf!
class UserManagementUpdateForm(LoginRequiredMixin, UpdateView):
model = Profile
labels = {
"phoneland" : "Telefon",
"phonemobile" : "Mobil",
"compfunc" : "Agenturfunktion",
}
fields = ['phoneland','phonemobile','compfunc']
# Update der Zugrifssrechte eines Users
class UsersPermUpdateView(LoginRequiredMixin, View):
template_name = 'users/users_perm.html'
form_class = UsersPermForm
success_url = '/dashboard/usersman/'
# Form wird geladen; Checkboxen werden vorbereitet und hier rausgerendert.
def get(self,request,*args, **kwargs):
# User ist der hier Aufgerufene, bzw. das Profil!
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})
# Handle POST GTTP requests
def post(self, request, *args, **kwargs):
permissions_loaded = dict(request.POST.lists())
user_tochange = Profile.objects.get(pk=kwargs['pk']).user
# ITERATION Über alle Elemente gehen und Rechte entziehen (nicht vorhanden) oder adden (wenn vorhanden)
# Hat ein user ein Recht NICHT, ist es NICHT in permissions
# LOAD PERMISSIONS
temprof = Profile
for ele in temprof._meta.permissions:
tempperm = Permission.objects.get(codename=ele[0])
if ele[0] in permissions_loaded:
user_tochange.user_permissions.add(tempperm)
else:
# Eingeloggter User darf sich nicht selbst die Userverwaltungsrechte entziehen
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.')
else:
user_tochange.user_permissions.remove(tempperm)
user_tochange.save()
messages.success(request, f'Berechtigungen für {user_tochange.first_name} {user_tochange.last_name} aktualisiert!')
return HttpResponseRedirect('/dashboard/usersman/')
# Benutzerprofil wird aktualisiert
@login_required
def ProfileUpdateView(request, pk):
prof_user = User.objects.get(profile__pk=pk)
if request.method == 'POST':
profileform_form = UsersAddProfileForm(request.POST, request.FILES, instance=prof_user.profile)
#profileform_parents = UsersAddProfileFormParents(request.POST, instance=request.user)
prename = prof_user.first_name
name = prof_user.last_name
if profileform_form.is_valid():
profileform_form.save()
messages.success(request, f'Daten für {prename} {name} aktualisiert!')
return redirect('users-management')
else:
# Form in Klammern sind die aktuellen Daten :)
profileform_form = UsersAddProfileForm(instance=prof_user.profile)
# 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)
context = {
'prof_user' : prof_user,
'profileform_form' : profileform_form,
'active_link' : 'usersmanagement',
'possible_users' : possible_users
}
return render(request, 'users/profile_update.html', context)
'''
Set users Parent by AJAX
'''
@login_required
def setuserparent(request):
if request.method == 'GET':
if request.GET['action'] == 'adduserp':
userid = request.GET['objectid']
toadd = request.GET['userid']
toadd_user = User.objects.get(pk=toadd)
workinguser = User.objects.get(pk=userid)
username_clean = toadd_user.first_name + " " + toadd_user.last_name
workinguser.profile.parent = toadd_user
workinguser.save()
# Getting Remaining-Users
possible_users = User.objects.filter(profile__agency__pk=request.user.profile.agency.pk)
possible_users_js = list(possible_users.values())
# Cleaned out, that only data is neede will send to the side (first/last-name and id)
final_possible_users = {}
for ele in possible_users_js:
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
return JsonResponse({'userid' : userid, 'username_clean' : username_clean, 'remaining_users':possible_users_js})
else:
return HttpResponse("Request method is not a GET")
@login_required
def changeonlinestat(request):
if request.method == 'GET':
request.user.profile.onlinestatus = request.GET["newstat"]
request.user.save()
return JsonResponse({"newstat" : request.GET["newstat"]})
'''
# DELETE A USER
Hier wird das Profil gelöscht, aber damit auch der User. Zusätzlich werden
alle Standards, Bereiche und Tasks des zu löschenden Nutzers dem User
zugeschrieben, welcher eingeloggt ist. Das passiert VOR dem löschen!
'''
import csv
@login_required
def getDataFromToDelUser(request, pk):
if(request.method == "GET"):
user = User.objects.get(pk=pk)
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="DA-Export_'+ user.first_name + "_" + user.last_name + '.csv"'
writer = csv.writer(response)
# TASK: Hier besprechen, ob das Recht als Benutzermanager ausreicht!
if(request.user.has_perm("users.usermanager") and user.profile.agency == request.user.profile.agency):
user_absences = Absence.objects.filter(agency=request.user.profile.agency, user=user).order_by("-start")
for ab in user_absences:
status = "OK"
if(ab.confirm_status == 1 or ab.confirm_status == 2):
status = "Abgelehnt"
writer.writerow(['Abwesenheit', str(ab.start), str(ab.end), 'Grund: '+ab.reason.name, 'Status: '+status])
user_workdays = Workday.objects.filter(agency=request.user.profile.agency, user=user).order_by("-start")
for wd in user_workdays:
breaks = Breaks.objects.filter(agency=request.user.profile.agency, user=user, workday=wd)
breaks_string = ""
for b in breaks:
breaks_string += str(b.start) + " bis " + str(b.end) + ", "
writer.writerow(['Arbeitstag', str(wd.start), str(wd.end), 'Pausen: ' + breaks_string])
return response
else:
pass
class ProfileDeleteView(LoginRequiredMixin, DeleteView):
model = User
success_url = '/dasettings/main'
template_name = 'users/user_confirm_delete.html'
# Adding active_link
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Hier Daten zusammenstellen, damit alle Daten bzgl Vertrag nicht verloren gehen (Zeiterfassung, Urlaub und Abwesenheiten)
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="file.csv"'
writer = csv.writer(response)
writer.writerow(['1001', 'John', 'Domil', 'CA'])
writer.writerow(['1002', 'Amit', 'Mukharji', 'LA', '"Testing"'])
context.update({"response" : response})
print(response)
return context
def delete(self, request, *args, **kwargs):
user = User.objects.get(pk=kwargs['pk'])
logged_user = request.user
''' ALTER LÖSCHBEREICH - User wird einfach entfernt '''
'''
areas_fs = Areas.objects.filter(created_area_by=user)
for a in areas_fs:
a.created_area_by = logged_user
a.save()
# ACHTUNG! Bei Tasks heißt es leider auch created_area...
task_fs = Tasks.objects.filter(created_area_by=user)
for t in task_fs:
t.created_area_by = logged_user
t.save()
standards_fs = Standards.objects.filter(created_standard_by=user)
#print(standards_fs)
for a in standards_fs:
a.created_standard_by = logged_user
a.save()
standards_fs = Standards.objects.filter(last_modified_by=user)
for a in standards_fs:
a.last_modified_by = logged_user
a.save()
standards_fs = Standards.objects.filter(published_by=user)
for a in standards_fs:
a.published_by = logged_user
a.save()
'''
response = super(ProfileDeleteView, self).delete(request, *args, **kwargs)
name = user.first_name + " " + user.last_name
messages.success(request, f'Benutzer ' +name+ ' wurde gelöscht!')
return response
@login_required
def agency(request):
context = {
'active_link' : 'agencyinfo'
}
return render(request, 'users/agency.html', context)
class AgencyUpdateView(LoginRequiredMixin, UpdateView):
model = Agency
form_class = AgencyUpdateForm
template_name = 'users/agency_update.html'
success_url = '/dashboard/agencyinfo'
def get_context_data(self, **kwargs):
context = super(AgencyUpdateView, self).get_context_data(**kwargs)
context['active_link'] = 'agencyinfo'
return context
# PRIORISIERUNG
'''
Es werden alle Aufgabenbereiche den Bereichen der Agentur zugeordnet und ausgegeben.
'''
@login_required
def UsersPrio(request, pk):
user = User.objects.get(pk=pk)
if(user.profile.agency.pk != request.user.profile.agency.pk):
return HttpResponseRedirect('users-dashboard')
else:
prios = Prio.objects.filter(user__pk=pk)
areas = Areas.objects.filter(agency__pk=request.user.profile.agency.pk)
user_first_name = user.first_name
user_last_name = user.last_name
user_id = user.pk
context = {
'active_link' : '',
'areas' : areas,
'user_first_name' : user_first_name,
'user_last_name' : user_last_name,
'user_id' : user_id,
'prios' : prios
}
return render(request, 'users/users_prio.html', context)
'''
Ajax-Call für Prio.Updates seitens des Users
im Profil
'''
@login_required
def UsersPrioUpdate(request):
tempuser = User.objects.get(pk=request.GET['userid'])
if request.method == 'GET' and tempuser.profile.agency.pk == request.user.profile.agency.pk:
prio = Prio.objects.filter(user__pk=request.GET['userid']).filter(task__pk=request.GET['taskid'])
prio = list(prio)[0]
prio.prio = request.GET['value']
prio.save()
return HttpResponse("udated...")
else:
return HttpResponse("Request method is not a GET")
import re
def cleanhtml(raw_html):
cleanr = re.compile('<.*?>')
cleantext = re.sub(cleanr, '', raw_html)
return cleantext
# Searxh for Standards by name, content, creator - standards needs to be public!
@login_required
def GlobalSearch(request):
if request.method == 'GET':
searchfor = request.GET['searchstring']
ag = request.user.profile.agency.pk
res_standard = Standards.objects.filter(agency__pk=ag, public=True).filter(name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(content__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(area__name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(task__name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(created_standard_by__last_name__icontains=searchfor)|Standards.objects.filter(agency__pk=ag, public=True).filter(created_standard_by__first_name__icontains=searchfor)
res_news = News.objects.filter(agency__pk=ag).filter(name__icontains=searchfor) | News.objects.filter(agency__pk=ag).filter(content__icontains=searchfor) | News.objects.filter(agency__pk=ag).filter(created_by__last_name__icontains=searchfor)|News.objects.filter(agency__pk=ag).filter(created_by__first_name__icontains=searchfor)
res_pass = AGPassword.objects.filter(agency__pk=ag).filter(name__icontains=searchfor)
res_contacts = AGContacts.objects.filter(agency__pk=ag).filter(personname__icontains=searchfor) | AGContacts.objects.filter(agency__pk=ag).filter(name__icontains=searchfor)
res_areas = Areas.objects.filter(agency__pk=ag).filter(name__icontains=searchfor)
res_tasks = Tasks.objects.filter(agency__pk=ag).filter(name__icontains=searchfor) |Tasks.objects.filter(agency__pk=ag).filter(area__name__icontains=searchfor)
res_pers = User.objects.filter(profile__agency__pk=ag).filter(first_name__icontains=searchfor) | User.objects.filter(profile__agency__pk=ag).filter(last_name__icontains=searchfor)
links = QuickLinks.objects.filter(agency__pk=ag).filter(name__icontains=searchfor) | QuickLinks.objects.filter(agency__pk=ag).filter(link__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})
return HttpResponse(html)
else:
return HttpResponse("Request method is not a GET")
@login_required
def searchStandardRouter(request):
if request.method == 'GET':
return redirect('/standards/standard/'+request.GET['s_id']+'/single')
else:
return redirect('dashboard')
'''
Hier werden die Zuständigkeiten eines Benutzers über alle Bereiche/Aufgaben hinweg gesetzt.
Das Update erfolgt per Booleanfields.
'''
@login_required
def UsersAreaTaskUpdate(request, pk):
user = User.objects.get(pk=pk)
if request.user.profile.agency.pk != user.profile.agency.pk:
return redirect('dashboard')
else:
finaldata = {}
context = {
'active_link' : 'usersmanagement',
'user_id' : user.pk,
}
if request.method == 'POST':
form = request.POST
areatask_formdata = list(form)
# CRSF-Token löschen
del areatask_formdata[0]
# Formular übertragen
area_ids = []
task_ids = []
# Areas in Formular laden
for ar in areatask_formdata:
tempdata = ar.split("_")
if(tempdata[0] == 'area'):
area_ids.append(int(tempdata[1]))
elif(tempdata[0] == 'task'):
task_ids.append(int(tempdata[1]))
# Alle Areas und Tasks laden
areas = Areas.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
for area in areas:
if area.pk in area_ids:
area.usersfield.add(user)
else:
area.usersfield.remove(user)
area.save()
'''
Prüfen, ob ein User einem Aufgabenbereich hinzugeprdnet ist.
Ist er im Bereich, passiert nichts. Ist er nicht in diesem
Bereich, wird er dem usersfield der Aufgabe und der Tabelle
Prio hinzugeüfügt. Damit kann der User seine individuellen
Prios im Profil anpassen.
'''
for task in tasks:
if task.pk in task_ids:
prio_check = Prio.objects.filter(user__pk=pk, task=task)
if(len(prio_check) == 0):
prio = Prio(user=User.objects.get(pk=pk), task=task)
prio.save()
task.usersfield.add(user)
else:
task.usersfield.remove(user)
Prio.objects.filter(user__pk=pk).filter(task__pk=task.pk).delete()
task.save()
username_message = user.first_name + " " + user.last_name
messages.success(request, f'Zuständigkeiten für {username_message} aktualisiert!')
return redirect('users-management')
else:
form = UserAreaTaskForm(user)
user_first_name = user.first_name
user_last_name = user.last_name
user_id = user.pk
context = {
'active_link' : '',
'user_first_name' : user_first_name,
'user_last_name' : user_last_name,
'user_id' : user_id,
'form' : form
}
return render(request, 'users/users_areatasks.html', context)
@login_required
def support(request):
context = {
'active_link' : 'support',
'form' : SupportForm(request.user)
}
if request.method == 'POST':
form = request.POST
'''
fileblob = ""
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
filename = f.name
attachment_type = filetype.guess(f)
fileblob = str(base64.b64encode(f.read()))
fileblob = fileblob[1 : : ]
fileblob = fileblob[1 : : ]
fileblob = fileblob[:-1:]
attachments.append({str(filename) : "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
filename = f.name
attachment_type = filetype.guess(f)
fileblob = str(base64.b64encode(f.read()))
fileblob = fileblob[1 : : ]
fileblob = fileblob[1 : : ]
fileblob = fileblob[:-1:]
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
filename = f.name
attachment_type = filetype.guess(f)
fileblob = str(base64.b64encode(f.read()))
fileblob = fileblob[1 : : ]
fileblob = fileblob[1 : : ]
fileblob = fileblob[:-1:]
attachments.append({str(filename) : "data:" + attachment_type.mime + ";base64," + fileblob})
'''
#image = request.FILES
supportdata = dict(form)
# Data from Form to JSON-Format
name = str(supportdata['name'][0])
mail = str(supportdata['mail'][0])
problemconc = str(supportdata['problemconc'][0])
problem = str(supportdata['problem'][0])
# HEADERS CURL
headers = {'X-API-Key': 'F025A238EB74914E3653BA2989BFF7C4'}
subject = "Digitale Agentur: " + str(problemconc)
# TASK: Hier die Auswahl des DropDown in die API mit einbauen, damit das Ticket in das entsprechende Department läuft
# DataJSON
ostdata = {
"topicId" : str(supportdata['department'][0]),
"name": name,
"email": mail,
"subject": 'Digitale Agentur: '+problemconc,
"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
#"attachments" : attachments
}
json_data = json.dumps(ostdata)
r = requests.post("https://support.vh-solutions.de/api/http.php/tickets.json", data=json_data, headers=headers)
# IF request FAILED error-Message
if(r.status_code != 201):
messages.warning(request, f'Supportanfrage fehlgeschlagen!' + str(r))
else:
messages.success(request, f'Supportanfrage erfolgreich! Ihre Ticketnummer ist '+ str(r.json()) +'!')
return render(request, 'users/support_done.html', context)
else:
return render(request, 'users/support.html', context)
'''
Schickt eine E-Mail an den User inkl. Passwortlink zum zurücksetzen.
'''
def sendpassmail(request):
if(request.method == 'GET'):
userid = request.GET['userid']
tempuser = User.objects.get(pk=userid)
# E-Mail für Passwort-Setzung!
form = PasswordResetForm({'email': tempuser.email})
if form.is_valid():
form.save(request=request,html_email_template_name='users/password_reset_mail.html')
return render (request, 'users/registercomplete.html')
return JsonResponse({'message' : 0})
def datenschutz(request):
if request.user.is_authenticated:
return render(request, 'users/datenschutz.html')
else:
return render(request, 'users/datenschutz_p.html')
def impressum(request):
if request.user.is_authenticated:
return render(request, 'users/impressum.html')
else:
return render(request, 'users/impressum_p.html')
'''
ERROR HANDLER VIEWS
'''
def handler404(request, exception):
context = {}
response = render(request, "users/errors/404.html", context=context)
response.status_code = 404
return response
def handler500(request):
context = {}
response = render(request, "users/errors/500.html", context=context)
response.status_code = 500
return response
'''
CRONJOB FUNCTION
'''
# CRONJOBS ALLE 5 MINUTEN
def cronactions(request, code):
data = {}
if(code == settings.CRONAPIKEY):
# NEWS CHECKING
all_unnotifc_news = News.objects.filter(agnotify=False, go_online_on__lt=timezone.now())
allusers = User.objects.all()
for news in all_unnotifc_news:
targeturl = settings.BASE_URL + "news/news/" + str(news.pk) + "/single"
# NEW NEWS FOUND WHICH HAVE TO GO ONLINE NOW!
news.agnotify = True
news.save()
for user in allusers:
# SEMI-SIGNAL FOR NEWS GOING ONLINE
if(user.usernotifications.news_created_mail and news.agency == user.profile.agency):
notificationtext = "Neue Agenturnews: " + news.name
username = user.first_name + " " + user.last_name
msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext, 'linktarget' : targeturl})
send_mail(
'Agentur-Benachrichtigung',
'Hallo ' + user.first_name + ' ' + user.last_name + '! ' + notificationtext,
'noreply@digitale-agentur.com',
[user.email],
html_message=msg_html,
fail_silently=True
)
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.save()
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})
# LEXOFFICE TEST
# HEADERS CURL
'''
headers = {
'Authorization': 'Bearer 33bfb1b9-2994-4fd4-b447-1f4754a5c7cb',
'Content-Type': 'application/json',
'Accept': 'application/json',
}
# DataJSON
lexdata = {
"voucherDate": "2020-07-09T00:00:00.000+01:00",
"address" : {
"name" : "Agenturname XXX",
"countryCode" : "DE"
},
"totalPrice" : {
"currency" : "EUR",
},
"lineItems" : [
{
"type" : "custom",
"name" : "Monatsbeitrag",
"quantity" : 1,
"unitName" : "Stück",
"unitPrice" :
{
"currency" : "EUR",
"netAmount" : 10,
"taxRatePercentage" : 16
},
},
{
"type" : "custom",
"name" : "Abwesenheitsmodul",
"quantity" : 1,
"unitName" : "Stück",
"unitPrice" :
{
"currency" : "EUR",
"netAmount" : 10,
"taxRatePercentage" : 16
},
}
],
"taxConditions": {
"taxType": "net"
},
"shippingConditions": {
"shippingDate": "2020-07-09T00:00:00.000+01:00",
"shippingType": "service"
},
}
json_data = json.dumps(lexdata)
r = requests.get("https://api.lexoffice.io/v1/invoices/0f9b6a1d-1912-4a10-9926-7909e5580202", data=json_data, headers=headers)
print(r)
print(r.text)
'''
else:
print("API CODE FAILED")
data.update({"status" : "failed"})
return JsonResponse(data)
'''
LANDING PAGE
'''
class landingPage(TemplateView):
template_name = "users/landingpage.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
'''
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:05!
def cronactionsdaily(request, code):
data = {}
if(code == settings.CRONAPIKEY):
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!
'''
today = date.today()
for user in allusers:
# REST URLAUB BERECHNUNG
try:
usertimedata = UserTime.objects.get(user=user)
day_tocheck = usertimedata.loose_holidedate.split(".")[0]
month_tocheck = usertimedata.loose_holidedate.split(".")[1]
month = today.month
day = today.day
if month < 10:
month = "0" + str(month)
day = today.day
else:
month = month
if day < 10:
day = "0" + str(day)
else:
day = 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()
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()
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))
targettworktime = 0.0
# Mitarbeiter hat für den gestrigen Tag keine Zeiten erfasst, daher automatisch auf null wenn KEINE Abwesenheit eingetragen wurde
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
# Es wird nur ein Arbeitstag erstellt, wenn KEINE Abwesenheiten vorliegen und der Nutzer an diesem Tag arbeiten muss
if(workdays_yesterday == 0 and absencecheck(user, yesterday) == False and targettworktime > 0.0 and user.usertime.usetime_start <= today):
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)
workdaytemp.save()
# Erinnerungsmails/Push bei Vertretung verschicken
one_week_later = date.today() + timedelta(days=7)
repre_absence = Absence.objects.filter(representator=user, start=one_week_later, confirm_status=0)
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()
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 " + str(user.pk) : "ok"})
except ObjectDoesNotExist:
data.update({"status" + str(user.pk) : "no usertime found for " + user.get_full_name()})
else:
print("API CODE FAILED")
data.update({"status" : "failed"})
return JsonResponse(data)
'''
ABRECHNUNG CRON JOB
'''
from dateutil.relativedelta import *
def cronactionsbill(request, code):
data = {}
if(code == settings.CRONAPIKEY):
today = date.today()
# Check, ob Rechnungen bezahlt wurden
unpaid_bills = AgencyBills.objects.all()
for bill in unpaid_bills:
# Für jede Rechnung eine Anfrage an die LexOffice API und voucherStatus auslesen
headers = {
'Authorization': 'Bearer ' + settings.LEX_API,
'Content-Type': 'application/json',
'Accept': 'application/json',
}
json_data = {}
r = requests.get("https://api.lexoffice.io/v1/invoices/"+AgencyBills.objects.get(pk=bill.pk).lexid, data=json_data, headers=headers)
if(json.loads(r.text)["voucherStatus"] == "paid"):
bill.billstatus="paid"
bill.save()
else:
bill.billstatus="open"
bill.save()
# Monatliche Berechnung
# Alle Rechnungen laden, deren Letzter Tag HEUTE ist und bei ausgewähltem Paymentplan 1 eine neue Rechnung erstellen, Mailverschicke, Nutzeraccouns zählen und neue Rechnung in der Agentur hinterlegen
new_bills = AgencyBills.objects.filter(end=today)
for bill in new_bills:
if bill.agency.paymentplan == 1:
agency = bill.agency
month = today
next_month = today + relativedelta(months=1)
# USERCOUNT BERECHNEN
usercount = len(User.objects.filter(profile__agency=agency))
if(usercount < 4):
usercount = 0
else:
usercount = usercount - 3
# HEADERS CURL
headers = {
'Authorization': 'Bearer ' + settings.LEX_API,
'Content-Type': 'application/json',
'Accept': 'application/json',
}
plan = 1
start_date = month
start_date_string = month.strftime("%d.%m.%Y")
end_date = month + relativedelta(months=plan)
end_date_string= end_date.strftime("%d.%m.%Y")
voucher_date_today = date.today().strftime("%Y-%m-%d")
monthword = "Monat"
lexdata = {
"voucherDate": voucher_date_today + "T00:00:00.000+00:00",
"address" : {
"name" : agency.name,
"street": agency.street,
"zip": agency.plz,
"city": agency.city,
"countryCode" : "DE"
},
"totalPrice" : {
"currency" : "EUR",
},
"lineItems" : [
{
"type" : "custom",
"name" : "Digitale Agentur: Grundbetrag für " + str(plan) + " " + monthword,
"quantity" : 1,
"unitName" : "Stück",
"description" : "Zeitraum " + start_date_string + " - " + end_date_string,
"unitPrice" :
{
"currency" : "EUR",
"netAmount" : 21.00,
"taxRatePercentage" : 16
},
},
{
"type" : "custom",
"name" : "Digitale Agentur: Zusätzliche Nutzer",
"description" : "Zeitraum " + start_date_string + " - " + end_date_string,
"quantity" : usercount,
"unitName" : "Stück",
"unitPrice" :
{
"currency" : "EUR",
"netAmount" : 3,
"taxRatePercentage" : 16
},
}
],
"taxConditions": {
"taxType": "net"
},
"paymentConditions": {
"paymentTermLabel": "Bitte zahlen Sie innerhalb von 14 Tagen.",
"paymentTermDuration": 14,
},
"shippingConditions": {
#"shippingDate": voucher_date_today + "T00:00:00.000+00:00",
"shippingType": "none"
}
}
json_data = json.dumps(lexdata)
r = requests.post("https://api.lexoffice.io/v1/invoices/?finalize=true", data=json_data, headers=headers)
if(r.status_code == 201):
messages.success(request, f"Rechnung erstellt!")
# Response in JSON umwandeln
response_text = json.loads(r.text)
newbill_id = response_text["id"]
# OrganizationId berechnen, wenn noch nicht gesetzt
r = requests.get("https://api.lexoffice.io/v1/invoices/" + response_text["id"], data=json_data, headers=headers)
response_text = json.loads(r.text)
newbill = AgencyBills(agency=agency, lexid=newbill_id, billtype="invoice", billnumber=response_text["voucherNumber"], billstatus=response_text["voucherStatus"], start=start_date, end=end_date, plan=plan, usercount=usercount)
newbill.save()
mail_to_send = ""
if(agency.payment_address == ""):
mail_to_send = agency.agency_email
else:
mail_to_send = agency.payment_address
msg_html = render_to_string('users/newbill_mail.html', {})
send_mail('Digitale Agentur | Rechnung', 'Sehr geehrte Nutzer, es wurde eine Rechnung für Ihre digitale Agentur erstellt. Diese können Sie unter Einstellungen, Abrechnung einsehen.','noreply@digitale-agentur.com',[mail_to_send],html_message=msg_html,fail_silently=True)
data.update({"newBill_" + str(agency.pk) : newbill.lexid})
else:
data.update({"status" : "failed"})
return JsonResponse(data)
def sendMailNoti(notificationtext, user_touched, linktarget=""):
username = user_touched.first_name + " " + user_touched.last_name
msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext, 'linktarget' : linktarget})
send_mail(
'Agentur-Benachrichtigung',
'Hallo ' + user_touched.first_name + ' ' + user_touched.last_name + '! ' + notificationtext,
'noreply@digitale-agentur.com',
[user_touched.email],
html_message=msg_html,
fail_silently=True
)
def isAlive(request):
return JsonResponse({"status" : True})