implementatiom of hauptvertrag to the sucess main

This commit is contained in:
2026-08-27 00:17:45 +02:00
parent 54ca1ae70d
commit 7531bf6945
3 changed files with 197 additions and 8 deletions
+7 -4
View File
@@ -2206,7 +2206,7 @@ def build_module_config_string(package_list: list) -> str:
]
return " ".join(config_parts)
def background_booking_provisioning(app_instance, prov_id, subdomain, package_list, user_id, school_name, user_email, username):
def background_booking_provisioning(app_instance, prov_id, subdomain, package_list, user_id, school_name, user_email, username, address, price, software_name):
"""Hintergrund-Worker, der die Tenant-Bereitstellung über das Host-Watcher-Triggersystem auslöst."""
with app_instance.app_context():
req_client, req_col = _get_collection("instance_requests")
@@ -2280,8 +2280,11 @@ def background_booking_provisioning(app_instance, prov_id, subdomain, package_li
domain=domain,
username="admin",
password=admin_password,
invoice_pdf_path=f"/var/invoices/{subdomain}_invoice.pdf",
contract_pdf_path=f"/var/contracts/{subdomain}_contract.pdf"
school_name=school_name,
address=address,
price=price,
date=_utc_now_iso(),
software_name=software_name,
)
except Exception as mail_err:
print(f"[WARNING] E-Mail-Versand fehlgeschlagen: {mail_err}")
@@ -2523,7 +2526,7 @@ def booking_payment():
# Startet den asynchronen Provisioning-Thread
thread = threading.Thread(
target=background_booking_provisioning,
args=(app_obj, prov_id, subdomain, package_list, user_id, form_data["school_name"], user_email, username)
args=(app_obj, prov_id, subdomain, package_list, user_id, form_data["school_name"], user_email, username, form_data["address"], form_data["price"], form_data["software_name"])
)
thread.start()
print(f"[INFO] Background Provisioning Trigger gestartet für Subdomain: {subdomain}")
+188 -3
View File
@@ -2,6 +2,9 @@ from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
import time
import os
import tempfile
from fpdf import FPDF
def _build_smtp_client():
@@ -168,9 +171,177 @@ def send_password_reset_token(email: str, token: str) -> bool:
return send(email, subject, text_body=text_note, html_body=html_note)
def send_accreditation_email(recipient: str, domain: str, username: str, password: str, invoice_pdf_path: str, contract_pdf_path: str) -> bool:
"""Sends an accreditation email with login credentials and attached documents."""
def generate_main_contract_pdf(
school_name: str,
address: str,
price: str,
date: str,
software_name: str,
output_path: str
):
"""Generiert das komplette PDF des Hauptvertrages (HV) mit allen Paragraphen und dynamischen Feldern."""
pdf = FPDF()
pdf.add_page()
pdf.set_auto_page_break(auto=True, margin=15)
# Schriftart festlegen
pdf.set_font("Helvetica", size=10)
# --- TITEL ---
pdf.set_font("Helvetica", style="B", size=13)
pdf.cell(0, 6, "Vertrag über die Nutzung der Software-Lizenz", ln=True, align="C")
pdf.cell(0, 6, f"{software_name}", ln=True, align="C")
pdf.ln(6)
# --- PARTEIEN ---
pdf.set_font("Helvetica", size=10)
parties_text = (
"Zwischen\n\n"
"Invario UG\nAm Sportplatz 10, 83052 Bruckmühl\n"
"— Anbieter / Lizenzgeber —\n\n"
"und\n\n"
f"{school_name}\n{address}\n"
"— Auftraggeber / Schule —"
)
pdf.multi_cell(0, 5, parties_text)
pdf.ln(6)
# --- 1. VERTRAGSGEGENSTAND ---
pdf.set_font("Helvetica", style="B", size=10)
pdf.cell(0, 6, "1. Vertragsgegenstand", ln=True)
pdf.set_font("Helvetica", size=10)
pdf.multi_cell(0, 5,
f"(1) Der Anbieter stellt dem Auftraggeber die Software „{software_name}“ (nachfolgend „Software“) als webbasierte Anwendung im Wege des Software-as-a-Service (SaaS) zur Verfügung. Die Software wird auf der vom Anbieter genutzten Infrastruktur betrieben.\n"
"(2) Dieser Hauptvertrag wird durch folgende Dokumente ergänzt, die als integrale Bestandteile dieses Vertrages gelten:\n"
"a) Anlage 1: Allgemeine Geschäftsbedingungen (AGB) und Lizenzbedingungen (EULA) des Anbieters\n"
"b) Anlage 2: Auftragsverarbeitungsvertrag (AVV) gemäß Art. 28 DS-GVO nebst technischen und organisatorischen Maßnahmen (TOM)"
)
pdf.ln(4)
# --- 2. VERTRAGSBEGINN ---
pdf.set_font("Helvetica", style="B", size=10)
pdf.cell(0, 6, "2. Vertragsbeginn", ln=True)
pdf.set_font("Helvetica", size=10)
pdf.multi_cell(0, 5,
"(1) Dieser Vertrag kommt entweder mit dem Datum der beidseitigen Unterzeichnung dieses Dokumentes oder durch die Nutzung der integrierten digitalen Bestellfunktion im Invario-Portal durch einen hierzu autorisierten Vertreter des Auftraggebers zustande.\n"
"(2) Die Vertragslaufzeit beginnt mit der Bereitstellung der Zugangsdaten durch den Anbieter."
)
pdf.ln(4)
# --- 3. LAUFZEIT UND KÜNDIGUNG ---
pdf.set_font("Helvetica", style="B", size=10)
pdf.cell(0, 6, "3. Laufzeit und Kündigung", ln=True)
pdf.set_font("Helvetica", size=10)
pdf.multi_cell(0, 5,
"(1) Der Vertrag wird zunächst für die Dauer von zwölf (12) Monaten geschlossen (Mindestlaufzeit).\n"
"(2) Er verlängert sich automatisch um jeweils ein weiteres Jahr, sofern er nicht von einer Partei mit einer Frist von drei (3) Monaten zum Ende der jeweiligen Laufzeit gekündigt wird.\n"
"(3) Die Kündigung kann in Textform (z. B. per E-Mail) oder über die dafür vorgesehenen Funktionen im Invario-Portal erfolgen. Das Recht zur außerordentlichen Kündigung aus wichtigem Grund bleibt unberührt."
)
pdf.ln(4)
# --- 4. VERGÜTUNG UND BEZAHLUNG ---
pdf.set_font("Helvetica", style="B", size=10)
pdf.cell(0, 6, "4. Vergütung und Bezahlung", ln=True)
pdf.set_font("Helvetica", size=10)
pdf.multi_cell(0, 5,
f"(1) Für die Nutzung der Software zahlt der Auftraggeber eine jährliche Lizenzgebühr in Höhe von {price} EUR (zzgl. ggf. anfallender gesetzlicher Umsatzsteuer).\n"
"(2) Die Vergütung ist jeweils für ein Vertragsjahr im Voraus fällig.\n"
"(3) Der Rechnungsbetrag ist innerhalb von 30 Tagen nach Erhalt der Rechnung ohne Abzug zur Zahlung fällig."
)
pdf.ln(4)
# --- 5. NUTZUNG UND SUPPORT ---
pdf.set_font("Helvetica", style="B", size=10)
pdf.cell(0, 6, "5. Nutzung und Support", ln=True)
pdf.set_font("Helvetica", size=10)
pdf.multi_cell(0, 5,
"(1) Der Umfang der Lizenzeinräumung sowie die Nutzungsbeschränkungen richten sich nach den Bestimmungen der anliegenden EULA (Anlage 1).\n"
"(2) Der technische Support wird innerhalb der in den AGB (Anlage 1) definierten Servicezeiten über das integrierte Ticket-System oder per E-Mail erbracht."
)
pdf.ln(4)
# --- 6. DATENSCHUTZ UND DATENSICHERHEIT ---
pdf.set_font("Helvetica", style="B", size=10)
pdf.cell(0, 6, "6. Datenschutz und Datensicherheit", ln=True)
pdf.set_font("Helvetica", size=10)
pdf.multi_cell(0, 5,
"(1) Die Parteien verpflichten sich zur Einhaltung der datenschutzrechtlichen Bestimmungen. Die Details der Verarbeitung der personenbezogenen Daten werden im anliegenden AVV (Anlage 2) verbindlich geregelt.\n"
"(2) Der Anbieter sichert zu, dass die Speicherung und Verarbeitung der Daten des Auftraggebers ausschließlich in Rechenzentren mit Standort innerhalb der Bundesrepublik Deutschland erfolgt."
)
pdf.ln(4)
# --- 7. HAFTUNG ---
pdf.set_font("Helvetica", style="B", size=10)
pdf.cell(0, 6, "7. Haftung", ln=True)
pdf.set_font("Helvetica", size=10)
pdf.multi_cell(0, 5,
"(1) Die Haftung des Anbieters richtet sich nach den Regelungen in Ziffer 7 der Allgemeinen Geschäftsbedingungen (Anlage 1).\n"
"(2) Für Unterbrechungen der Verfügbarkeit durch höhere Gewalt, Störungen im Bereich außerhalb des Übergabepunktes (z. B. Internet-Backbone) sowie für unvorhersehbare Sicherheitslücken, die nach dem aktuellen Stand der Technik zum Zeitpunkt des Auftretens noch nicht abwehrbar waren (Zero-Day-Exploits), haftet the Anbieter nur nach Maßgabe der Haftungsregelungen in den AGB, es sei denn, ihn trifft ein Verschulden an der verzögerten Behebung. Gesetzliche Datenschutzpflichten und Meldepflichten bleiben unberührt."
)
pdf.ln(4)
# --- 8. SCHLUSSBESTIMMUNGEN ---
pdf.set_font("Helvetica", style="B", size=10)
pdf.cell(0, 6, "8. Schlussbestimmungen", ln=True)
pdf.set_font("Helvetica", size=10)
pdf.multi_cell(0, 5,
"(1) Änderungen und Ergänzungen dieses Vertrages bedürfen der Textform.\n"
"(2) Sollten einzelne Bestimmungen dieses Vertrages unwirksam oder undurchführbar sein oder werden, bleibt die Wirksamkeit der übrigen Bestimmungen hiervon unberührt. Anstelle der unwirksamen oder undurchführbaren Bestimmung gelten die gesetzlichen Vorschriften. Sofern es sich nicht um Allgemeine Geschäftsbedingungen handelt, verpflichten sich die Parteien, eine wirksame Regelung zu vereinbaren, die dem wirtschaftlichen Zweck der unwirksamen oder undurchführbaren Bestimmung möglichst nahekommt.\n"
"(3) Es gilt das Recht der Bundesrepublik Deutschland. Ausschließlicher Gerichtsstand für alle Streitigkeiten aus oder im Zusammenhang mit diesem Vertrag ist, soweit gesetzlich zulässig, der Sitz des Anbieters."
)
pdf.ln(6)
# --- UNTERSCHRIFTEN ---
pdf.set_font("Helvetica", style="B", size=10)
pdf.cell(0, 6, "Unterschriften und Einverständnis", ln=True)
pdf.set_font("Helvetica", size=9)
pdf.multi_cell(0, 4, "Mit der Unterzeichnung bestätigen die Parteien den Abschluss des Hauptvertrages inklusive der beigefügten Anlagen (AGB, EULA und AVV).")
pdf.ln(8)
# Unterschriften-Blöcke nebeneinander
pdf.set_font("Helvetica", size=9)
pdf.cell(95, 5, "Für den Auftraggeber", ln=False)
pdf.cell(95, 5, "Für den Anbieter", ln=True)
pdf.ln(8)
pdf.cell(95, 5, f"{date} ____________________________________", ln=False)
pdf.cell(95, 5, f"{date} ________________ ____________________", ln=True)
pdf.cell(95, 5, "(Verantwortlicher)", ln=False)
pdf.cell(95, 5, "(Simon Brieger)", ln=True)
# PDF speichern
pdf.output(output_path)
return output_path
def send_accreditation_email(
recipient: str,
domain: str,
username: str,
password: str,
school_name: str,
address: str,
price: str,
date: str,
software_name: str,
invoice_pdf_path: str = None
) -> bool:
"""Sends an accreditation email with login credentials and generated contract PDF."""
# 1. Temporären Pfad für das generierte PDF festlegen
contract_filename = f"Vertrag_{school_name.replace(' ', '_')}.pdf"
contract_pdf_path = os.path.join(tempfile.gettempdir(), contract_filename)
# 2. Hauptvertrag als PDF generieren
generate_main_contract_pdf(
school_name=school_name,
address=address,
price=price,
date=date,
software_name=software_name,
output_path=contract_pdf_path
)
# 3. E-Mail Inhalt vorbereiten
subject = "Ihre Zugangsdaten und Unterlagen für Invario"
text_note = (
@@ -204,4 +375,18 @@ def send_accreditation_email(recipient: str, domain: str, username: str, passwor
</div>
"""
return send(recipient, subject, text_body=text_note, html_body=html_note)
# 4. Anhänge zusammenstellen
attachments = [contract_pdf_path]
if invoice_pdf_path and os.path.exists(invoice_pdf_path):
attachments.append(invoice_pdf_path)
# 5. E-Mail versenden
result = send(recipient, subject, text_body=text_note, html_body=html_note, attachments=attachments)
# 6. Temporäre PDF-Datei nach dem Versand wieder löschen
try:
os.remove(contract_pdf_path)
except OSError:
pass
return result
+2 -1
View File
@@ -3,4 +3,5 @@ Flask-JWT-Extended>=4.6,<5.0
bleach>=6.1,<7.0
pymongo>=4.8,<5.0
gunicorn>=22.0,<23.0
requests
requests
fpdf2