digitaleagenturnc/users/views.py

2093 lines
74 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 digitaleagentur.utils import *
from digitaleagentur.timemanagement_utils import *
from organizer.models import QuickLinks
from areas.models import Areas
from tasks.models import Tasks
''' ICS '''
from ics import Calendar, Event
import base64
from django.contrib.auth import authenticate
''' MAIL '''
from django.core.mail import EmailMessage
from django.core.mail import EmailMultiAlternatives
import io as BytesIO
import base64
from django.http import HttpResponse
# NC LOGIN
'''
A User has to be logged in in NC. If yes, we check the user-status and retrieving the userId. If the logged user by this session is the same we want to see in Django, than the user will logged in.
Double-Check: Logged-Session from NC (session-id cannot be hacked cause it is serverside) and we check userId local, django and NC
'''
import xmltodict, json
import urllib.request as urllib2
from django.contrib.auth import login, logout
from django.core.mail import send_mail
from django.views.generic import TemplateView
# Entry-Point for NC
def ncLogin(request, uid):
logout(request)
#print(uid)
user = User.objects.get(username=uid)
#if(getNCLoggedUserBySession(user.profile.nc_sid) == uid):
# login(request, user)
# return redirect('users-dashboard')
#return redirect('nclog', uid=uid)
return render(request, 'users/nclog.html',{'error' : "Bereite daten vor..." + getNCLoggedUserBySession(user.profile.nc_sid)})
def getICSFile(request, ag):
if 'HTTP_AUTHORIZATION' in request.META:
auth = request.META['HTTP_AUTHORIZATION'].split()
if len(auth) == 2:
if auth[0].lower() == "basic":
temp = base64.b64decode(auth[1] + "==")
username = temp.decode("utf-8").split(":")[0]
passwd = temp.decode("utf-8").split(":")[1]
user = authenticate(username=username, password=passwd)
if user is not None:
if user.is_active:
if user.profile.agency.pk == ag:
request.user = user
c = Calendar()
absencedays = Absence.objects.filter(agency=ag).exclude(confirm_status=2)
for ab in absencedays:
e = Event()
e.name = ab.user.first_name + " " + ab.user.last_name + " abwesend"
e.uid = "da-ab-" + str(ab.pk)
if ab.start < ab.end:
e.begin = ab.start
e.end = ab.end
else:
e.begin = ab.start
e.end = ab.start + timedelta(minutes=1)
e.allday = True
c.events.add(e)
return HttpResponse(c, content_type='text/calendar')
realm = ""
response = HttpResponse()
response.status_code = 401
response['WWW-Authenticate'] = 'Basic realm="%s"' % realm
return response
def getICSFileAll(request, ag):
if 'HTTP_AUTHORIZATION' in request.META:
auth = request.META['HTTP_AUTHORIZATION'].split()
if len(auth) == 2:
if auth[0].lower() == "basic":
temp = base64.b64decode(auth[1] + "==")
username = temp.decode("utf-8").split(":")[0]
passwd = temp.decode("utf-8").split(":")[1]
user = authenticate(username=username, password=passwd)
if user is not None:
if user.is_active:
if user.profile.agency.pk == ag and user.has_perm('users.absencemanager'):
request.user = user
c = Calendar()
absencedays = Absence.objects.filter(agency=ag).exclude(confirm_status=2)
for ab in absencedays:
e = Event()
e.name = ab.user.first_name + " " + ab.user.last_name + " | " + ab.reason.name
e.uid = "da-ab-" + str(ab.pk)
if ab.start < ab.end:
e.begin = ab.start
e.end = ab.end
else:
e.begin = ab.start
e.end = ab.start + timedelta(minutes=1)
e.allday = True
c.events.add(e)
return HttpResponse(c, content_type='text/calendar')
realm = ""
response = HttpResponse()
response.status_code = 401
response['WWW-Authenticate'] = 'Basic realm="%s"' % realm
return response
def getICSFileEx(request, code, ag):
if(request.method == "GET"):
#try:
agency = Agency.objects.get(pk=ag)
if agency != None and agency.agencycal_publicstatus == 1 and str(code) == str(agency.agencycalurl):
c = Calendar()
absencedays = Absence.objects.filter(agency=ag).exclude(confirm_status=2)
for ab in absencedays:
if ab.start != None and ab.end != None:
e = Event()
e.name = ab.user.first_name + " " + ab.user.last_name + " abwesend "
e.uid = "da-ab-" + str(ab.pk)
if ab.start < ab.end:
e.begin = ab.start
e.end = ab.end
else:
e.begin = ab.start
e.end = ab.start + timedelta(minutes=1)
#e.allday = True
c.events.add(e)
return HttpResponse(c, content_type='text/calendar')
else:
realm = ""
response = HttpResponse()
response.status_code = 400
return response
#except:
# realm = ""
# response = HttpResponse()
# response.status_code = 403
# return response
else:
realm = ""
response = HttpResponse()
response.status_code = 404
return response
def getICSFileExAll(request, code, ag):
if(request.method == "GET"):
#try:
agency = Agency.objects.get(pk=ag)
if agency != None and agency.agencycal_publicstatus == 1 and str(code) == str(agency.agencycalurl_all):
c = Calendar()
absencedays = Absence.objects.filter(agency=ag).exclude(confirm_status=2)
for ab in absencedays:
if ab.start != None and ab.end != None:
e = Event()
e.name = ab.user.first_name + " " + ab.user.last_name + " | " + ab.reason.name
e.uid = "da-ab-" + str(ab.pk)
if ab.start < ab.end:
e.begin = ab.start
e.end = ab.end
else:
e.begin = ab.start
e.end = ab.start + timedelta(minutes=1)
#e.allday = True
c.events.add(e)
return HttpResponse(c, content_type='text/calendar')
else:
realm = ""
response = HttpResponse()
response.status_code = 400
return response
#except:
# realm = ""
# response = HttpResponse()
# response.status_code = 403
# return response
else:
realm = ""
response = HttpResponse()
response.status_code = 404
return response
'''
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", "Videoberatung", "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", "Bestellungen", "Büroordnung", "Post", "Technik"]
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 = []
#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))
def randomStringNum(stringLength=20):
"""Generate a random string of fixed length """
lettersAndNumbers = string.ascii_lowercase + string.digits + string.ascii_uppercase
return ''.join(random.choice(lettersAndNumbers) for i in range(stringLength))
@login_required
def toUpdate(request):
# NO AGENVYJOBS
# CREATE DEFAULT
'''
Agenturleiter
Außendienst
Innendienst
Auszubildender
'''
if len(request.user.profile.agency.agencycalurl) == 0:
request.user.profile.agency.agencycalurl = randomStringNum(30)
request.user.profile.agency.agencycalurl_all = randomStringNum(30)
request.user.profile.agency.save()
print("CAL-URLS updated for " + str(request.user.profile.agency.pk))
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")
pass
# 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:
pass
#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")
pass
# 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)
from adm.models import AGBLog
def saveNewAGBLog(byuser, agname, usermail):
agblog = AGBLog(entry="Agentur von " + byuser + " mit Mail " + usermail + " am " + str(datetime.now()) + " für Agentur " + agname + " erstellt, AGBs und Vertragsdaten akzeptiert.")
agblog.save()
'''
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):
# AGENTUREGISTRIERUNG
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()
# LOG AGB SAVER
saveNewAGBLog(newuser_name, agency.name, email)
# 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})
# LOG AGB SAVER
saveNewAGBLog(newuser_name, agency.name, email)
# 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)
from auditlog.models import LogEntry
@login_required
def showUserLog(request, pk):
if (request.user.pk == pk):
logdata = LogEntry.objects.filter(object_pk=request.user.pk)[:50]
logdata_logins = []
for ele in reversed(logdata):
try:
datestring = json.loads(ele.changes)["last_login"][1]
datestring = datestring.split(".")[0]
logdata_logins.append(datetime.strptime(datestring, '%Y-%m-%d %H:%M:%S'))
except:
pass
context = {
'logdata' : logdata_logins
}
return render(request, 'users/userlog.html', context)
else:
context = {}
return render(request, 'users/userlog_forbidden.html', context)
@login_required
def dashboard(request):
# UPDATE FUNCTIONS BY NEW MODEL-CHANGES FOR COPIEN SOME DATA
toUpdate(request)
# Prüfung, ob bei UserTime das Users ein Start drin steht, ansonsten wird dort Einstellungsdatum eingetragen
if request.user.usertime.usetime_start == None and request.user.usertime.usetime == True:
request.user.usertime.usetime_start = request.user.usertime.startdate
request.user.usertime.save()
#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, delflag = False).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
# Gibt zurück, ob übergebener Nutzer einem anderen Nutzer im Organigramm als Parent zugeordnet ist
# TRUE - User hat keinen Parent und kann gelöscht werden
# FALSE - User hat Parent und kann nicht direkt gelöscht werden
def checkOrgaParent(user):
returnvalue = True
for u in User.objects.filter(profile__agency=user.profile.agency):
if u.profile.parent == user:
returnvalue = False
return returnvalue
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, *args, **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)
'''
# Standards des Users laden, um diese dann neu zuzuordnen - finaler Löschbutton wird erst angezeigt, wenn alle Standards durchgeklickt wurden (passiert mit AJAX in der HTML)
usersstandards = []
agencystandards = Standards.objects.filter(agency=self.request.user.profile.agency)
user_to_del = User.objects.get(pk=self.get_object().pk)
for s in agencystandards:
if s.created_standard_by == user_to_del or user_to_del in s.representative.all() or user_to_del in s.executor.all() or user_to_del in s.authority.all() :
usersstandards.append(s)
context.update({"standards_to_change" : usersstandards})
# Hier werden alle Nutzer der Agentur geladen und in ein Array gepackt, damit diese dann bei den Standards ausgewählt werden können.
usersofagency = User.objects.filter(profile__agency=user_to_del.profile.agency).exclude(pk=user_to_del.pk)
context.update({"usersofagency" : usersofagency})
context.update({"user_to_del" : user_to_del})
# Prüft, ob der Nutzer ein Parent im Organigramm ist. Gibt True oder False zurück. Das Template verhindert dann das löschen und informiert den Nutzer.
context.update({"orgaerror" : checkOrgaParent(kwargs["object"])})
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()
'''
# NC DELETE USER IN NC TOO!
headers = {
'Accept' : 'application/json',
'Access-Control-Allow-Headers' : 'OCS-APIRequest',
'OCS-APIRequest' : 'true'
}
r = requests.request("DELETE", settings.NEXTCLOUD_URL + "/ocs/v1.php/cloud/users/" + user.username,headers=headers, auth=(settings.NEXTCLOUD_USER_API, settings.NEXTCLOUD_PW_API))
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
# Saves a new User in parent of others Users.
@login_required
def UpdateUserOrga(request):
if(request.method == "GET"):
newuser = User.objects.get(pk=request.GET['userid'])
olduser = User.objects.get(pk=request.GET['useridold'])
if(newuser.profile.agency == request.user.profile.agency and request.user.has_perm("users.usermanager")):
for u in User.objects.filter(profile__agency=newuser.profile.agency):
if u.profile.parent != None and u.profile.parent == olduser and newuser != u:
u.profile.parent = newuser
u.save()
# der neue User ist der gleiche wie er selbst - hier den Chef setzen!
elif u == newuser:
u.profile.parent = User.objects.filter(profile__agency=newuser.profile.agency).order_by("pk")[0]
u.save()
success = True
else:
success = False
return JsonResponse({"success" : success})
@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) +")\nBrowser: " + request.META['HTTP_USER_AGENT'] + "\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()) +'!')
msg_html = render_to_string('users/supportanswer_mail.html', { 'name' : name, 'text' : problem, 'number' : str(r.json())})
send_mail("Re: Digitale Agentur: " + str(problemconc) + " [#" + str(r.json()) + "]","Hallo " + name + ", wir haben Ihre Anfrage unter der Ticketnummer " + str(r.json()) + " aufgenommen. Ihre Problembeschreibung: " + problem + " - Vielen Dank. Ihr Team der Digitalen Agentur ",'noreply@digitale-agentur.com',[mail],html_message=msg_html,fail_silently=True)
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! Zudem wird gecheckt, ob der Tag tatsächlich Urlaub ist.
'''
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):
for ab in absencedays:
if ab.reason.is_time == True:
returnstat = False
else:
returnstat = True
return returnstat
# CRONJOBS UM 00:05!
def cronactionsdaily(request, code):
data = {}
today = date.today()
mailstatus = "BEGIN CRONJOB DAILY" + str(today)
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!
'''
for user in allusers:
mailstatus += "\n USER: " + user.first_name + " " + user.last_name + " ID: (" + str(user.pk) + ")"
# 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
''' DAS IST UNNÖTIG '''
'''
if(str(day_tocheck) == str(day) and str(month_tocheck) == str(month)):
sourceyear = today.year
this_year = list(UserYearAbsenceInfo.objects.filter(year=sourceyear, user=user))[0]
next_year = list(UserYearAbsenceInfo.objects.filter(year=sourceyear+1, user=user))[0]
next_year.restdays = this_year.days - this_year.days_inuse
next_year.save()
'''
# Arbeitstage beenden
if(user.usertime.usetime):
try:
workdays = Workday.objects.filter(user=user, end=None, delflag = False)
for wd in workdays:
mailstatus += "\n WORKDAY AUTEND ID " + str(wd.pk)
wd.end = datetime(wd.start.year, wd.start.month, wd.start.day, 23, 59)
wd.save()
except:
mailstatus += "ERROR WORKDAYS AUTO END"
# AUTO ARBEITSTAGE HINZUFÜGEN
try:
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, delflag = False))
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
day_half_found = False
if(getAbsenceForOneDay(user, yesterday) != False):
targettworktime = targettworktime / 2
day_half_found = True
# 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 or day_half_found) and isfreedaycheck(user, yesterday) 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()
except:
mailstatus += "ERROR AUTO ADDING WORKDAYS"
try:
# 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 + "!"})
except:
mailstatus += "ERROR REMINDER ABSENCEMAIL"
data.update({"status " + str(user.pk) : "ok"})
except ObjectDoesNotExist:
data.update({"status" + str(user.pk) : "no usertime found for " + user.get_full_name()})
mailstatus += "USER HAS NO USERTIMEOBJECT USER-ID: " + str(user.pk)
else:
data.update({"status" : "failed"})
mailstatus += " END"
send_mail(
'DA-CRON: DAILY',
mailstatus,
'noreply@digitale-agentur.com',
["holger.trampe@vh-solutions.de", "info@digitale-agentur.com"],
fail_silently=True,
)
return JsonResponse(data)
#import datetime
from django.db.models.signals import post_save
from users.signals import save_newabsence
from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays, Absence
def recalculateAbsence(request, code):
data = {}
calcstat = "BEGIN RECALCULATE ABSENCE"
today = date.today()
year = today.year
post_save.disconnect(save_newabsence, sender=Absence)
if(code == settings.CRONAPIKEY):
for user in User.objects.all():
calcstat += "\n USER " + str(user.pk)
try:
abinfo_lastyear = UserYearAbsenceInfo.objects.get(user=user, year=str(int(year)-1))
abinfo_thisyear = UserYearAbsenceInfo.objects.get(user=user, year=year)
if(abinfo_lastyear.days_inuse > 0.0):
abinfo_thisyear.restdays = abinfo_lastyear.days - abinfo_lastyear.days_inuse
abinfo_thisyear.save()
calcstat += " DAYS UPDATED - NEW RESTDAYS: " + str(abinfo_thisyear.restdays)
for ab in Absence.objects.filter(user=user, start__year=year):
if(ab.reason.is_holiday):
calculateNewAbsenceDate(ab)
daysinuse_thisyear = 0.0
for ab in Absence.objects.filter(user=user, start__year=year):
daysinuse_thisyear += ab.holidays_normal
calcstat += " NEW DAYSINUSE THIS YEAR " + str(daysinuse_thisyear)
abinfo_thisyear.days_inuse = daysinuse_thisyear
abinfo_thisyear.save()
else:
calcstat += " NO DAYS IN 2020 USED "
except:
calcstat += "ERROR LASTYEAR/THISYEAR USER " + str(user.pk)
post_save.connect(save_newabsence, sender=Absence)
send_mail(
'RECALCULATING ABSENCE YEAR INFO PROTOCOLL',
calcstat,
'noreply@digitale-agentur.com',
["info@digitale-agentur.com"],
fail_silently=True,
)
return JsonResponse(data)
def calculateNewAbsenceDate(instance):
newdata = getFinalHolidayData(instance)
abinfo = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year))[0]
abinfo_lastyear = ""
abinfo_nextyear = ""
is_lastyear = False
abinfo_lastyear = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year-1))
if(len(abinfo_lastyear) > 0):
is_lastyear = True
abinfo_lastyear = abinfo_lastyear[0]
is_nextyear = False
abinfo_nextyear = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year+1))
if(len(abinfo_nextyear) > 0):
is_nextyear = True
abinfo_nextyear = abinfo_nextyear[0]
multiple_info_needays = False
if(hasattr(newdata[3], "__len__")):
multiple_info_needays = True
# Gleiches Jahr MIT Rest
if(multiple_info_needays and newdata[3][2] == False):
# Rest ist positiv, daher bleibt rest übrig, rest wird in absence gespeichert und vom rest des Jahres-Restes abgezogen
# Rest ist positiv, damit bleibt Rest übrig
if(newdata[3][0] > 0):
instance.holidays_rest = abinfo.restdays - newdata[3][0]
instance.save()
abinfo.restdays = newdata[3][0]
abinfo.save()
# Rest ist negativ
elif(newdata[3][0] < 0):
instance.holidays_rest = (abinfo.restdays - newdata[3][0]) - newdata[3][0]*(-1)
instance.holidays_normal = newdata[3][0]*(-1)
instance.save()
abinfo.restdays = 0
abinfo.days_inuse = abinfo.days_inuse + newdata[3][0]*(-1)
abinfo.save()
# Rest ist Urlaubsdauer
else:
instance.holidays_rest = abinfo.restdays
instance.save()
#abinfo.days_inuse = abinfo.days_inuse + abinfo.restdays
abinfo.restdays = 0
abinfo.save()
# Gleiches Jahr ohne Rest
elif(not multiple_info_needays):
abinfo.days_inuse = abinfo.days_inuse + newdata[3]
abinfo.save()
instance.holidays_normal = newdata[3]
instance.save()
# Mehrere Jahre
elif(multiple_info_needays and newdata[3][2] == True):
abinfo.days_inuse = abinfo.days_inuse + newdata[3][0]
abinfo.save()
abinfo_nextyear.days_inuse = abinfo_nextyear.days_inuse + newdata[3][1]
abinfo_nextyear.restdays = abinfo_nextyear.restdays - newdata[3][3]
abinfo_nextyear.save()
# Hier werden alle benötigten Tage von Vor- und Nächstem Jahr gespeichert
instance.holidays_normal = newdata[3][0]
instance.holidays_rest = 0
instance.holidays_normal_next = newdata[3][1]
instance.holidays_rest_next = newdata[3][3]
instance.save()
'''
ABRECHNUNG CRON JOB
'''
from dateutil.relativedelta import *
def cronactionsbill(request, code):
data = {}
today = date.today()
mailstatus = "BEGIN CRONJOB BILL " + str(today) + " - "
if(code == settings.CRONAPIKEY):
# Check, ob Rechnungen bezahlt wurden
unpaid_bills = AgencyBills.objects.all()
for bill in unpaid_bills:
try:
# 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()
mailstatus += "\n VOUCHERSTATUS BILL CHANGED TO PAID: " + str(bill.pk)
elif(json.loads(r.text)["voucherStatus"] == "voided"):
bill.billstatus="voided"
bill.save()
mailstatus += "\n VOUCHERSTATUS BILL CHANGED TO VOIDED: " + str(bill.pk)
else:
bill.billstatus="open"
bill.save()
except:
mailstatus += "\n VOUCHERSTATUS ERROR ON BILL " + str(bill.pk)
# Monatliche Berechnung
# Alle Rechnungen laden, deren Letzter Tag HEUTE ist und bei ausgewähltem Paymentplan 1 eine neue Rechnung erstellen, Mailverschicken, 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.paymentstatus == 0 and bill.agency.paymentplan == 1:
agency = bill.agency
month = today
# Einen Monat weiter und dann wieder einen Tag zurück
next_month = today + relativedelta(months=1)
next_month = next_month - relativedelta(days=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 + relativedelta(days=1)
start_date_string = start_date.strftime("%d.%m.%Y")
# Einen Monat weiter und dann wieder einen Tag zurück
end_date = month + relativedelta(months=1)
#end_date = end_date - relativedelta(days=1)
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" : 19
},
},
{
"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" : 19
},
}
],
"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)
# WIEDER RAUSNEHMEN
# NEUE RECHNUNG ALs ENTWURF
#r = requests.post("https://api.lexoffice.io/v1/invoices/", data=json_data, headers=headers)
# RICHTIGE RECHNUNG
r = requests.post("https://api.lexoffice.io/v1/invoices/?finalize=true", data=json_data, headers=headers)
if(r.status_code == 201):
try:
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 == None):
mail_to_send = agency.agency_email
else:
mail_to_send = agency.payment_address
# BCC Mail with Object - NICHT DEN IMPORT VERGESSEN!!!
email = EmailMultiAlternatives(
'Digitale Agentur | Rechnung ' + str(response_text["voucherNumber"]),
'Sehr geehrte Nutzer, hiermit erhalten Sie eine neue Rechnung für die Digitale Agentur. Ihr Team der Digitalen Agentur',
'noreply@digitale-agentur.com',
[mail_to_send],
['info@digitale-agentur.com'],
headers={},
)
headers = {
'Authorization': 'Bearer ' + settings.LEX_API,
'Content-Type': 'application/json',
'Accept': 'application/json',
}
lexdata = {
"renderType" : "pdf"
}
json_data = json.dumps(lexdata)
r_final = requests.get("https://api.lexoffice.io/v1/invoices/"+newbill_id+"/document", data=json_data, headers=headers)
json.loads(r_final.text)
base64String = requests.get("https://api.lexoffice.io/v1/files/"+json.loads(r_final.text)["documentFileId"]+"/", data=json_data, headers=headers)
content = base64.b64decode(base64String.text)
msg_html = render_to_string('users/newbill_mail.html', {})
email.attach_alternative(msg_html, "text/html")
email.attach('Rechnung_' + str(response_text["voucherNumber"]) + '.pdf', content, "application/pdf")
email.send()
#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})
mailstatus += "\n NEW BILL FOR AGENCY " + str(agency.pk)
except:
mailstatus += "\n ERROR BY SENDING NEW MAIL TO " + str(agency.pk)
else:
data.update({"status" : "failed"})
mailstatus += "\n END "
send_mail(
'DA-CRON: BILLS',
mailstatus,
'noreply@digitale-agentur.com',
["holger.trampe@vh-solutions.de", "info@digitale-agentur.com"],
fail_silently=True,
)
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})