changes to he pdf sending

This commit is contained in:
2026-08-27 13:24:51 +02:00
parent 708274bd8f
commit cb6627bd3d
2 changed files with 81 additions and 70 deletions
+47 -40
View File
@@ -2206,7 +2206,19 @@ 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, address, price, software_name):
def background_booking_provisioning(
app_instance,
prov_id,
subdomain,
package_list,
user_id,
school_name,
user_email,
username,
address,
price,
software_name="Invario Inventarsystem"
):
"""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")
@@ -2214,7 +2226,7 @@ def background_booking_provisioning(app_instance, prov_id, subdomain, package_li
# 1. Status auf "in_progress" setzen
req_col.update_one({"_id": ObjectId(prov_id)}, {"$set": {"provision_status": "in_progress"}})
# 2. Naechsten Port und Admin-Passwort ermitteln
# 2. Nächsten Port und Admin-Passwort ermitteln
inst_client_check, inst_col_check = _get_collection("instances")
try:
existing_instances = list(inst_col_check.find({}, {"https_port": 1, "port": 1}))
@@ -2232,7 +2244,7 @@ def background_booking_provisioning(app_instance, prov_id, subdomain, package_li
# Generiere den korrekten Modul-String
module_config_str = build_module_config_string(package_list)
# 3. Trigger-Datei fuer den Host-Watcher schreiben
# 3. Trigger-Datei für den Host-Watcher schreiben
os.makedirs(TRIGGER_DIR, exist_ok=True)
trigger_file = os.path.join(TRIGGER_DIR, f"{subdomain}.json")
@@ -2248,13 +2260,13 @@ def background_booking_provisioning(app_instance, prov_id, subdomain, package_li
with open(trigger_file, "w") as f:
json.dump(trigger_payload, f)
print(f"[INFO] Trigger-Datei fuer Host-Watcher erstellt: {trigger_file} mit Payload: {trigger_payload}")
print(f"[INFO] Trigger-Datei für Host-Watcher erstellt: {trigger_file} mit Payload: {trigger_payload}")
# 4. Instanz-Eintrag in der Datenbank registrieren
domain = f"{subdomain}.invario-software.de"
instance_doc = {
"owner_id": user_id,
"owner_username": username, # <--- HIER HINZUGEFÜGT
"owner_username": username,
"school_name": school_name,
"subdomain": subdomain,
"domain": domain,
@@ -2272,9 +2284,11 @@ def background_booking_provisioning(app_instance, prov_id, subdomain, package_li
finally:
inst_client.close()
# 5. Bestaetigungs-E-Mail versenden
# 5. Bestätigungs-E-Mail inkl. Vertrag & Anhängen versenden
try:
if user_email:
formatted_date = datetime.today().strftime('%d.%m.%Y')
send_accreditation_email(
recipient=user_email,
domain=domain,
@@ -2283,9 +2297,10 @@ def background_booking_provisioning(app_instance, prov_id, subdomain, package_li
school_name=school_name,
address=address,
price=price,
date=_utc_now_iso(),
software_name=software_name,
date=formatted_date,
software_name=software_name
)
except Exception as mail_err:
print(f"[WARNING] E-Mail-Versand fehlgeschlagen: {mail_err}")
@@ -2302,10 +2317,10 @@ def background_booking_provisioning(app_instance, prov_id, subdomain, package_li
"updated_at": _utc_now_iso()
}}
)
print(f"[SUCCESS] Provisioning-Trigger erfolgreich gesendet fuer {subdomain}")
print(f"[SUCCESS] Provisioning-Trigger erfolgreich gesendet für {subdomain}")
except Exception as e:
print(f"[ERROR] Async Provisioning fehlgeschlagen fuer {subdomain}:")
print(f"[ERROR] Async Provisioning fehlgeschlagen für {subdomain}:")
traceback.print_exc()
req_col.update_one({"_id": ObjectId(prov_id)}, {"$set": {"provision_status": "failed", "last_error": str(e)}})
finally:
@@ -2350,7 +2365,6 @@ def booking_payment():
flow_config = BOOKING_FLOW_MAP[booking_flow]
# Auslesen aller Formularfelder (inkl. tenant_slug und Rechnungsdaten)
form_data = {
"contact_person": _sanitize_text(request.values.get("contact_person") or "", 120),
"school_name": _sanitize_text(request.values.get("school_name") or "", 160),
@@ -2426,21 +2440,8 @@ def booking_payment():
assigned_admin_display_name = assigned_admin.get("display_name") if assigned_admin else ""
assigned_admin_email = (assigned_admin.get("email") if assigned_admin else "") or BOOKING_ADMIN_EMAIL_FALLBACK
message = (
f"{flow_config['message_prefix']} {selected_package} {flow_config['message_suffix']}\n"
f"Ansprechpartner: {form_data['contact_person']}\n"
f"Schule: {form_data['school_name']} (Dienstst.-Nr: {form_data['school_number']})\n"
f"E-Mail: {form_data['contact_email']}\n"
f"Telefon: {form_data['contact_phone'] or '-'}\n"
f"Schulträger/Amt: {form_data['billing_organization']}\n"
f"Rechnungsadresse: {form_data['billing_street']}, {form_data['billing_zip']} {form_data['billing_city']}\n"
f"Kassenzeichen: {form_data['billing_reference'] or '-'}\n"
f"Gewünschte Subdomain: {form_data['tenant_slug']}\n"
f"Notizen: {form_data['notes'] or '-'}"
)
try:
# FLOW 1: Beratung / Gesprächs-Buchung
# FLOW 1: Consultation / Chat
if booking_flow == "consultation":
client, col = _get_collection("chat_messages")
try:
@@ -2449,7 +2450,7 @@ def booking_payment():
"username": session.get("username"),
"sender": session.get("display_name") or session.get("username"),
"sender_role": "user",
"message": message,
"message": f"Gesprächswunsch bezüglich: {selected_package}",
"created_at": _utc_now_iso(),
"booking_flow": booking_flow,
"booking_package": package_raw,
@@ -2465,18 +2466,16 @@ def booking_payment():
flash(f"Gesprächstermin für {selected_package} wurde an das Team gesendet.", "success")
return redirect(url_for("user_chat"))
# FLOW 2: Kostenpflichtige Direkt-Buchung mit Provisioning via Watcher
# FLOW 2: Direktbuchung mit Provisioning via Host-Watcher
if booking_flow == "payment":
booking_number = f"BOOK-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}"
# Schul-URL aus dem Formular bevorzugen
raw_base = form_data.get("tenant_slug") or form_data.get("school_name") or session.get("username") or booking_number
base = _slugify_subdomain(raw_base).lower()[:51]
# Prüfung auf doppelte Subdomains via MongoDB 'instances' Collection
inst_check_client, inst_check_col = _get_collection("instances")
inst_check_client, inst_col_check = _get_collection("instances")
try:
existing_docs = list(inst_check_col.find({}, {"subdomain": 1}))
existing_docs = list(inst_col_check.find({}, {"subdomain": 1}))
existing_subdomains = [d.get("subdomain") for d in existing_docs if d.get("subdomain")]
except Exception as e:
print(f"[WARNING] Konnte bestehende Subdomains nicht prüfen: {e}")
@@ -2523,29 +2522,37 @@ def booking_payment():
username = session.get("username")
user_email = session.get("email") or form_data.get("contact_email")
address_process = f"{form_data['billing_street']}, {form_data['billing_zip']} {form_data['billing_city']}"
price_str = f"{total_price:.2f}".replace('.', ',')
# Startet den asynchronen Provisioning-Thread
# Startet den asynchronen Provisioning-Thread mit exakten Parametern
thread = threading.Thread(
target=background_booking_provisioning,
args=(app_obj, prov_id, subdomain, package_list, user_id, form_data["school_name"], user_email, username, address_process, total_price, selected_package)
args=(
app_obj,
prov_id,
subdomain,
package_list,
user_id,
form_data["school_name"],
user_email,
username,
address_process,
price_str,
selected_package
)
)
thread.start()
print(f"[INFO] Background Provisioning Trigger gestartet für Subdomain: {subdomain}")
# ANPASSUNG FÜR BESSERE WARTEZEIT:
# Wir geben Metadaten mit, wie lange das Setup ca. dauern wird.
if is_json_request:
return jsonify({
"success": True,
"slug": subdomain,
"message": "Instanz wird eingerichtet...",
"estimated_seconds": 45, # Erwartete Dauer in Sekunden (anpassbar)
"status_poll_interval_ms": 3000 # Wie oft soll das Frontend fragen? (3 Sek)
"estimated_seconds": 45,
"status_poll_interval_ms": 3000
}), 200
# Falls es KEIN AJAX-Request war:
# Wir hängen den Parameter "wait_for_slug" an, damit die "my_instance_management"-Seite weiß,
# dass sie sofort ein Lade-Overlay für diesen spezifischen Tenant öffnen muss.
flash(f"Buchung für {selected_package} wurde erfasst. Deine Instanz wird jetzt automatisch eingerichtet.", "success")
return redirect(url_for("my_instance_management", wait_for_slug=subdomain))