From 43f31e0061f581613c7c7b51bfbcefabfbde2b89 Mon Sep 17 00:00:00 2001 From: AIIrondev Date: Wed, 26 Aug 2026 13:06:55 +0200 Subject: [PATCH] fix of the backend --- Website/main.py | 69 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/Website/main.py b/Website/main.py index 7f529b3..b39582b 100644 --- a/Website/main.py +++ b/Website/main.py @@ -2314,7 +2314,11 @@ def booking_payment(): if booking_flow not in BOOKING_FLOW_MAP: booking_flow = "payment" + is_json_request = "application/json" in request.headers.get("Accept", "") or request.is_json + if not packages_str: + if is_json_request: + return jsonify({"success": False, "error": "Keine Buchungsoption ausgewählt."}), 400 flash("Keine Buchungsoption ausgewählt.", "error") return redirect(url_for("preise")) @@ -2328,7 +2332,10 @@ def booking_payment(): selected_package_names.append(name) total_price += BOOKING_PRICE_MAP.get(pkg, 0.0) else: - flash(f"Ungültige Buchungsoption: {pkg}", "error") + err_msg = f"Ungültige Buchungsoption: {pkg}" + if is_json_request: + return jsonify({"success": False, "error": err_msg}), 400 + flash(err_msg, "error") return redirect(url_for("preise")) selected_package = ", ".join(selected_package_names) @@ -2336,14 +2343,19 @@ 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), + "school_number": _sanitize_text(request.values.get("school_number") or "", 60), "contact_email": _sanitize_text(request.values.get("contact_email") or "", 160).lower(), "contact_phone": _sanitize_text(request.values.get("contact_phone") or "", 60), + "billing_organization": _sanitize_text(request.values.get("billing_organization") or "", 160), "billing_street": _sanitize_text(request.values.get("billing_street") or "", 160), "billing_zip": _sanitize_text(request.values.get("billing_zip") or "", 20), "billing_city": _sanitize_text(request.values.get("billing_city") or "", 120), + "billing_reference": _sanitize_text(request.values.get("billing_reference") or "", 100), + "tenant_slug": _sanitize_text(request.values.get("tenant_slug") or "", 63).lower(), "notes": _sanitize_text(request.values.get("notes") or "", 600), "agreements_accepted": (request.values.get("agreements_accepted") or "").strip().lower() in {"1", "on", "true", "yes"}, } @@ -2367,27 +2379,39 @@ def booking_payment(): if request.method == "GET": return render_template("schnell_buchung.html", **review_data) - # --- POST Logic & Validation --- + # --- POST Validation --- required_fields = { "contact_person": "Ansprechpartner", - "school_name": "Schule/Einrichtung", - "contact_email": "E-Mail", + "school_name": "Name der Schule", + "school_number": "Dienststellennummer", + "contact_email": "Dienstliche E-Mail", + "billing_organization": "Einrichtung / Amt", "billing_street": "Straße", "billing_zip": "PLZ", "billing_city": "Ort", + "tenant_slug": "Gewünschte Schul-URL", } missing_labels = [label for key, label in required_fields.items() if not form_data.get(key)] if missing_labels: - flash(f"Bitte folgende Pflichtfelder ausfüllen: {', '.join(missing_labels)}.", "error") + err_msg = f"Bitte folgende Pflichtfelder ausfüllen: {', '.join(missing_labels)}." + if is_json_request: + return jsonify({"success": False, "error": err_msg}), 400 + flash(err_msg, "error") return render_template("schnell_buchung.html", **review_data) if not form_data["agreements_accepted"]: - flash("Bitte Nutzungsbedingungen, Lizenzvereinbarung und Datenschutzerklärung bestätigen.", "error") + err_msg = "Bitte Nutzungsbedingungen, Lizenzvereinbarung und Datenschutzerklärung bestätigen." + if is_json_request: + return jsonify({"success": False, "error": err_msg}), 400 + flash(err_msg, "error") return render_template("schnell_buchung.html", **review_data) if not _validate_email(form_data["contact_email"]): - flash("Bitte eine gültige E-Mail-Adresse angeben.", "error") + err_msg = "Bitte eine gültige E-Mail-Adresse angeben." + if is_json_request: + return jsonify({"success": False, "error": err_msg}), 400 + flash(err_msg, "error") return render_template("schnell_buchung.html", **review_data) assigned_admin = _select_booking_admin() @@ -2398,10 +2422,13 @@ def booking_payment(): 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']}\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 '-'}" ) @@ -2425,6 +2452,9 @@ def booking_payment(): finally: client.close() + if is_json_request: + return jsonify({"success": True, "redirect_url": url_for("user_chat")}), 200 + flash(f"Gesprächstermin für {selected_package} wurde an das Team gesendet.", "success") return redirect(url_for("user_chat")) @@ -2432,7 +2462,8 @@ def booking_payment(): if booking_flow == "payment": booking_number = f"BOOK-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}" - raw_base = form_data.get("school_name") or session.get("username") or booking_number + # 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 @@ -2447,7 +2478,10 @@ def booking_payment(): inst_check_client.close() if base in existing_subdomains: - flash("Die gewünschte Subdomain (aus dem Schulnamen) existiert bereits. Bitte wähle einen anderen Schulnamen.", "error") + err_msg = "Die gewünschte Subdomain existiert bereits. Bitte wähle eine andere Subdomain." + if is_json_request: + return jsonify({"success": False, "error": err_msg}), 400 + flash(err_msg, "error") return render_template("schnell_buchung.html", **review_data) subdomain = base[:63] @@ -2481,7 +2515,7 @@ def booking_payment(): user_id = session.get("user_id") user_email = session.get("email") or form_data.get("contact_email") - # Startet den asynchronen Thread. Wir übergeben nun direkt die 'package_list' + # 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) @@ -2489,13 +2523,24 @@ def booking_payment(): thread.start() print(f"[INFO] Background Provisioning Trigger gestartet für Subdomain: {subdomain}") + # Antworte AJAX-Aufrufen direkt mit JSON + if is_json_request: + return jsonify({ + "success": True, + "slug": subdomain, + "message": "Provisioning gestartet." + }), 200 + flash(f"Buchung für {selected_package} wurde erfasst. Die Instanz wird jetzt eingerichtet.", "success") return redirect(url_for("my_instance_management")) except Exception as e: print(f"[FATAL ERROR] In booking_payment Route:") traceback.print_exc() - flash("Buchungsanfrage konnte nicht gesendet werden. Ein unerwarteter Fehler ist aufgetreten.", "error") + err_msg = "Buchungsanfrage konnte nicht gesendet werden. Ein unerwarteter Fehler ist aufgetreten." + if is_json_request: + return jsonify({"success": False, "error": err_msg}), 500 + flash(err_msg, "error") return render_template("schnell_buchung.html", **review_data) @app.route('/instance_request/delete', methods=['POST'])