Standard Gruppen weiter ausgebaut, Bug mit den Punkten im Editor gefixed

This commit is contained in:
holger.trampe 2021-01-15 18:13:25 +01:00
parent d75a95652c
commit 94ea27b615
12 changed files with 410 additions and 54 deletions

View File

@ -36,6 +36,13 @@ import json
from django.conf import settings # import the settings file
from PIL import Image
''' MAIL '''
from django.core.mail import EmailMessage
from django.core.mail import EmailMultiAlternatives
import io as BytesIO
import base64
from django.http import HttpResponse
def randomString(stringLength=10):
"""Generate a random string of fixed length """
letters = string.ascii_lowercase
@ -300,7 +307,7 @@ from django.http import HttpResponse
def GetBillPDF(request, pk):
bill = AgencyBills.objects.get(pk=pk)
# Sicherheitscheck, ob der angefragte User zur Agentur gehört und das Recht hat, Agenturinfos zu bearbeiten
if (bill.agency == request.user.profile.agency and request.user.has_perm("users.agencyinfo")) or request.user.is_staff:
if ((bill.agency == request.user.profile.agency and request.user.has_perm("users.agencyinfo")) or request.user.is_staff):
headers = {
'Authorization': 'Bearer ' + settings.LEX_API,
'Content-Type': 'application/json',
@ -1817,7 +1824,40 @@ class BillPlanUpdate(UpdateView):
mail_to_send = self.request.user.profile.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)
# 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"
}
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)
else:
messages.warning(self.request, f"Fehlercode "+str(r.status_code)+". Es wurde keine Rechnung erstellt. Bitte wenden Sie sich an den Support!")

BIN
dump.rdb

Binary file not shown.

View File

@ -36,6 +36,7 @@ $(document).ready(function() {
});
});
</script>
{% else %}
<h3>Das Modul News wurde in ihrer Agentur deaktiviert.</h3>
{% endif %}

View File

@ -133,7 +133,6 @@
var workingpass = "";
//GROUPS
function showGroupChangeModal(tochangeid){
console.log("HI!");
$("#changeGroupOfPass").modal("toggle");
$(".groupclass").attr("checked", false);
workingpass = tochangeid;

View File

@ -94,7 +94,7 @@
{% endif %}
{% if standard.authority_group.count > 0 or standard.executor_group.count > 0 or standard.representative_group.count > 0 %}
{% if standard.authority_group.count > 0 or standard.executor_group.count > 0 or standard.representative_group.count > 0 %}
<div class="card col-14 ml-1 mb-2" style="min-width: 110%">
<div class="card-body">
<h5 class="card-title">Gruppen</h5>
@ -103,7 +103,7 @@
{% if standard.executor_group.count > 0 %}
Ausführende<br />
{% for g in standard.executor_group.all %}
<span style="color: red">{{g.agencygroupname}}</span>{% if forloop.counter < standard.executor_group.count%}&nbsp;|&nbsp;{% endif %}
<a href="#" onclick="javascript:loadAGGroup({{g.pk}})">{{g.agencygroupname}}</a>{% if forloop.counter < standard.executor_group.count%}&nbsp;|&nbsp;{% endif %}
{% endfor %}
<br />
{% endif %}
@ -111,7 +111,7 @@
{% if standard.representative_group.count > 0 %}
Vertretende<br />
{% for g in standard.representative_group.all %}
<span style="color: red">{{g.agencygroupname}}</span>{% if forloop.counter < standard.representative_group.count%}&nbsp;|&nbsp;{% endif %}
<a href="#" onclick="javascript:loadAGGroup({{g.pk}})">{{g.agencygroupname}}</a>{% if forloop.counter < standard.representative_group.count%}&nbsp;|&nbsp;{% endif %}
{% endfor %}
<br />
{% endif %}
@ -120,7 +120,7 @@
{% if standard.authority_group.count > 0 %}
Verantwortliche<br />
{% for g in standard.authority_group.all %}
<span style="color: red">{{g.agencygroupname}}</span>{% if forloop.counter < standard.authority_group.count%}&nbsp;|&nbsp;{% endif %}
<a href="#" onclick="javascript:loadAGGroup({{g.pk}})">{{g.agencygroupname}}</a>{% if forloop.counter < standard.authority_group.count%}&nbsp;|&nbsp;{% endif %}
{% endfor %}
<br />
{% endif %}
@ -318,6 +318,31 @@
{% endfor %}
<!-- GRUPPEN MODAL -->
<div class="modal fade" id="showGroupMembers" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="" aria-hidden="true">
<div class="modal-dialog " role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Gruppenmitglieder der Gruppe <span id="aggroupname"></span></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Schließen">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<span id="message"></span>
<span id="groupmembers"></span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Schließen</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
function goToStandardMain(){
@ -329,6 +354,56 @@ function goToArea(name){
localStorage.setItem('activeTab', name);
location.href = "{% url 'standards' %}";
}
function loadAGGroup(agpk){
$.ajax({
url: "{% url 'standard-loadaggroupmembers' %}",
method : "GET",
data: {
aggroup : agpk
},
success: function (data) {
if(data["status"] == "ok"){
$("#aggroupname").html(data["aggroupname"]);
$("#groupmembers").html(data["members"]);
}
else{
$("#aggroupname").html("FEHLER");
$("#message").html(data["members"]);
}
}
});
$("#showGroupMembers").modal("toggle");
}
</script>
{% endblock content %}
{% endblock content %}

View File

@ -24,7 +24,7 @@ urlpatterns = [
path('standard/<int:pk>/task', views.StandardTask, name="standard-task"),
path('standardsagn/<int:pk>', views.StandardFromAgn, name="standard-agn"),
path('standardcopy/<int:pk>', views.CopyStandard, name="standard-copyagn"),
path('loadaggroupm/', views.LoadAGGroupMembers, name="standard-loadaggroupmembers"),
]

View File

@ -618,6 +618,40 @@ def StandardAdd(request, id=False):
return render(request, 'standards/standards_add.html', context)
'''
Gibt die Daten der Agenturgruppen zurück, welche in diesem Standard sind.
'''
@login_required
def LoadAGGroupMembers(request):
if request.method == "GET":
aggroupid = request.GET['aggroup']
try:
aggroup = AgencyGroup.objects.get(pk=aggroupid)
except:
return JsonResponse({"status" : "err", "message" : "Fehler! Diese Gruppe gibt es nicht."})
members_string = ""
if request.user.profile.agency == aggroup.agency:
members = User.objects.filter(groups__name=aggroup.group.name)
counter = 0
for member in members:
members_string += member.get_full_name()
counter += 1
if counter+1 <= len(members):
members_string += ", "
if counter == 0:
members_string = "Gruppe hat keine Mitglieder."
else:
return JsonResponse({"status" : "err", "message" : "Sie haben auf diese Gruppe keinen Zugriff!"})
return JsonResponse({"status" : "ok", "aggroupname" : aggroup.agencygroupname, "members" : members_string})
else:
return JsonResponse({"status" : "err", "message" : "Allgemeiner Fehler."})
# Funktion zum versenden einer Mail inkl. TEmplate
def sendMailNoti(notificationtext, user_touched, linktarget=""):
username = user_touched.first_name + " " + user_touched.last_name

View File

@ -579,7 +579,15 @@
{% endif %}
</div>
</div>
<!-- SUMMERNOTE ADDED CSS -->
<style type="text/css">
.note-editable li {
list-style-position: inside !important;
}
.card-body li {
list-style-position: inside !important;
}
</style>
<!-- CHAT BUTTON -->

View File

@ -124,7 +124,7 @@
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Roboto;font-size:18px;line-height:1;text-align:left;color:#000000;">
<p>Sehr geehrte Nutzer,</p>
<p>es wurde eine neue Rechnung für Ihre digitale Agentur erstellt. Sie können die Rechnung unter Einstellungen, Abrechnung einsehen.</p>
<p>es wurde eine neue Rechnung für Ihre digitale Agentur erstellt. Sie können die Rechnung unter Einstellungen, Abrechnung einsehen oder im Anhang herunterladen.</p>
<p>Mit freundlichen Grüßen</p>
<p>Ihr Team von Digitale Agentur</p>
</div>

View File

@ -0,0 +1,177 @@
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<title>
</title>
<!--[if !mso]><!-- -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!--<![endif]-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
#outlook a {
padding: 0;
}
body {
margin: 0;
padding: 0;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
table,
td {
border-collapse: collapse;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
img {
border: 0;
height: auto;
line-height: 100%;
outline: none;
text-decoration: none;
-ms-interpolation-mode: bicubic;
}
p {
display: block;
margin: 13px 0;
}
</style>
<!--[if mso]>
<xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
<![endif]-->
<!--[if lte mso 11]>
<style type="text/css">
.mj-outlook-group-fix { width:100% !important; }
</style>
<![endif]-->
<!--[if !mso]><!-->
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet" type="text/css">
<style type="text/css">
@import url(https://fonts.googleapis.com/css?family=Roboto:300,400,500,700);
</style>
<!--<![endif]-->
<style type="text/css">
@media only screen and (min-width:480px) {
.mj-column-per-100 {
width: 100% !important;
max-width: 100%;
}
}
</style>
<style type="text/css">
</style>
</head>
<body>
<div style="">
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div style="margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td style="font-size:0px;padding:10px 25px;word-break:break-word;">
<p style="border-top:solid 4px #5a5c69;font-size:1px;margin:0px auto;width:100%;">
</p>
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" style="border-top:solid 4px #5a5c69;font-size:1px;margin:0px auto;width:550px;" role="presentation" width="550px"
>
<tr>
<td style="height:0;line-height:0;">
&nbsp;
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Roboto;font-size:20px;line-height:1;text-align:left;color:#000000;">
<h2>Digitale Agentur | Rechnung RECHNUNGSNUMMER</h2>
</div>
</td>
</tr>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Roboto;font-size:18px;line-height:1;text-align:left;color:#000000;">
<p>Hallo VORNAME UND NACHNAME,</p> im Anhang erhalten Sie die Rechnung mit der Rechnungsnummer RECHNUNGSNUMMER für die Nutzung der Digitalen Agentur. <br /><br />Sollten Sie Fragen haben, melden Sie sich jederzeit per E-Mail an <a href href="mailto:support@digitale-agentur.com">support@digitale-agentur.com</a>. <p>Mit freundlichen Grüßen</p>
<p>Ihr Team von Digitale Agentur</p>
</div>
</td>
</tr>
<tr>
<td style="font-size:0px;padding:10px 25px;word-break:break-word;">
<p style="border-top:solid 4px #5a5c69;font-size:1px;margin:0px auto;width:100%;">
</p>
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" style="border-top:solid 4px #5a5c69;font-size:1px;margin:0px auto;width:550px;" role="presentation" width="550px"
>
<tr>
<td style="height:0;line-height:0;">
&nbsp;
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Roboto;font-size:12px;line-height:1;text-align:left;color:#000000;">Bitte antworten Sie nicht auf diese E-Mail. Diese Adresse ist nicht für den Empfang für E-Mails eingerichtet. Sie können uns über die E-Mail-Adresse support@digitale-agentur.com oder über das Support-Formular in Ihrer Digitalen Agentur kontaktieren.</div>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</div>
</body>
</html>

View File

@ -123,8 +123,9 @@
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Roboto;font-size:18px;line-height:1;text-align:left;color:#000000;">
<p>Hallo {{username}},</p> Ihre Agentur wurde erstellt. Sie können sich nun hier anmelden und Ihre Agentur gestalten:
<p> <a href="https://app.digitale-agentur.com">https://app.digitale-agentur.com</a> </p> <br /> Ihr Benutzername: {{ username_log }} <br /> Weitere Informationen erhalten Sie in unserem Wiki <a href="https://digitale-agentur.com/">https://digitale-agentur.com/</a> oder per E-Mail an support@digitale-agentur.com! </p>
<p>Hallo {{username}},</p> Ihre Agentur wurde erstellt. Sie können sich nun mit Ihrer E-Mailadresse hier anmelden und Ihre Agentur gestalten:
<p> <a href="https://app.digitale-agentur.com">https://app.digitale-agentur.com</a> </p>
<br /> Weitere Informationen erhalten Sie in unserem Wiki <a href="https://digitale-agentur.com/">https://digitale-agentur.com/</a> oder per E-Mail an support@digitale-agentur.com! </p>
<p>Mit freundlichen Grüßen</p>
<p>Ihr Team von Digitale Agentur</p>
</div>

View File

@ -58,6 +58,13 @@ 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
def getICSFile(request, ag):
if 'HTTP_AUTHORIZATION' in request.META:
auth = request.META['HTTP_AUTHORIZATION'].split()
@ -636,8 +643,6 @@ class AgencyCreateView(CreateView):
return super().form_valid(form)
#from django.core.mail import EmailMessage
#from django.core.mail import EmailMultiAlternatives
from auditlog.models import LogEntry
@ -665,26 +670,12 @@ def showUserLog(request, pk):
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)
'''
# BCC Mail with Object - NICHT DEN IMPORT VERGESSEN!!!
email = EmailMultiAlternatives(
'Subject',
'Bitte aktivieren Sie HTML in Ihrem Mailprogramm.',
'noreply@digitale-agentur.com',
['mail@holgertrampe.de'],
['htrampe@gmail.com'],
#reply_to=['noreply@digitale-agentur.com'],
headers={},
)
email.attach_alternative("<html><body><h1>Lobbt der Shit!</h1><hr></body></html>", "text/html")
email.send()
'''
#storageinfo = sys.getfilesystemencoding()
@ -1860,28 +1851,61 @@ def cronactionsbill(request, code):
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"]
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)
# 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})
mailstatus += "NEW BILL FOR AGENCY " + str(agency.pk)
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
# 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 += "NEW BILL FOR AGENCY " + str(agency.pk)
except:
mailstatus += "ERROR BY SENDING NEW MAIL TO " + str(agency.pk)
else:
data.update({"status" : "failed"})
@ -1892,11 +1916,8 @@ def cronactionsbill(request, code):
["htrampe@gmail.com", "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