From beb9cb34f4b0b9d10c3fcd250f02346595531d53 Mon Sep 17 00:00:00 2001 From: Aiirondev Date: Fri, 22 May 2026 23:40:22 +0200 Subject: [PATCH] feat: Implement booking package and flow mappings with review page --- Website/main.py | 89 +++++++++++++--- Website/templates/preise.html | 31 ++++-- Website/templates/schnell_buchung.html | 135 +++++++++++++++++++++++++ 3 files changed, 229 insertions(+), 26 deletions(-) create mode 100644 Website/templates/schnell_buchung.html diff --git a/Website/main.py b/Website/main.py index 5dab6ba..6351ec0 100644 --- a/Website/main.py +++ b/Website/main.py @@ -30,6 +30,34 @@ app.config["SESSION_COOKIE_SAMESITE"] = "Strict" app.config["SESSION_COOKIE_SECURE"] = os.environ.get("SESSION_COOKIE_SECURE", "0") == "1" app.config["PREFERRED_URL_SCHEME"] = "https" if os.environ.get("SESSION_COOKIE_SECURE") == "1" else "http" +BOOKING_PACKAGE_MAP = { + "starter_package": "Starter-Paket", + "advanced_package": "Advanced-Paket", + "inventarsystem": "Inventarsystem", + "buecherei": "Bücherei", + "terminverwaltung": "Terminverwaltung", + "emailversand": "E-Mail Versand", + "schultraeger": "Schulträger Angebot", + "telefonsupport": "Telefonsupport 20/Monat", +} + +BOOKING_FLOW_MAP = { + "consultation": { + "title": "Buchung als Gesprächstermin prüfen", + "intro": "Bitte prüfen Sie die Angaben noch einmal. Nach Ihrer Bestätigung wird die Anfrage als Gesprächstermin an das Team gesendet.", + "confirm_label": "Gesprächstermin bestätigen", + "message_prefix": "Ich möchte für das Paket", + "message_suffix": "einen Gesprächstermin vereinbaren. Bitte kontaktieren Sie mich für die nächsten Schritte.", + }, + "payment": { + "title": "Buchung vor dem Zahlungsschritt prüfen", + "intro": "Bitte prüfen Sie die Angaben noch einmal. Nach Ihrer Bestätigung wird die Buchung per POST an /booking/payment übermittelt.", + "confirm_label": "Jetzt kostenpflichtig buchen", + "message_prefix": "Ich möchte das Paket", + "message_suffix": "kostenpflichtig buchen. Bitte prüfen Sie die Angaben und senden Sie mir die nächsten Schritte.", + }, +} + @app.after_request def set_security_headers(response): @@ -1808,24 +1836,48 @@ def preise(): @login_required def book_option_package(): package_raw = _sanitize_text(request.form.get("package") or "", 40).lower() - package_map = { - "starter_package": "Starter-Paket", - "advanced_package": "Advanced-Paket", - "inventarsystem": "Inventarsystem", - "buecherei": "Bücherei", - "terminverwaltung": "Terminverwaltung", - "emailversand": "E-Mail Versand", - "schultraeger": "Schulträger Angebot", - "telefonsupport": "Telefonsupport 20/Monat", - } - selected_package = package_map.get(package_raw) + booking_flow = _sanitize_text(request.form.get("flow") or "payment", 24).lower() + if booking_flow not in BOOKING_FLOW_MAP: + booking_flow = "payment" + + selected_package = BOOKING_PACKAGE_MAP.get(package_raw) if not selected_package: flash("Ungültige Buchungsoption ausgewählt.", "error") return redirect(url_for("preise")) + return redirect(url_for("booking_payment", package=package_raw, flow=booking_flow)) + + +@app.route('/booking/payment', methods=['GET', 'POST']) +@login_required +def booking_payment(): + package_raw = _sanitize_text((request.values.get("package") or ""), 40).lower() + booking_flow = _sanitize_text((request.values.get("flow") or "payment"), 24).lower() + if booking_flow not in BOOKING_FLOW_MAP: + booking_flow = "payment" + + selected_package = BOOKING_PACKAGE_MAP.get(package_raw) + if not selected_package: + flash("Ungültige Buchungsoption ausgewählt.", "error") + return redirect(url_for("preise")) + + flow_config = BOOKING_FLOW_MAP[booking_flow] + review_data = { + "package": selected_package, + "package_key": package_raw, + "flow": booking_flow, + "title": flow_config["title"], + "intro": flow_config["intro"], + "confirm_label": flow_config["confirm_label"], + "username": session.get("username"), + "display_name": session.get("display_name") or session.get("username"), + } + + if request.method == "GET": + return render_template("schnell_buchung.html", **review_data) + message = ( - f"Ich möchte das Paket {selected_package} buchen. " - "Bitte kontaktieren Sie mich für die nächsten Schritte." + f"{flow_config['message_prefix']} {selected_package} {flow_config['message_suffix']}" ) client = None @@ -1838,16 +1890,23 @@ def book_option_package(): "sender_role": "user", "message": message, "created_at": _utc_now_iso(), + "booking_flow": booking_flow, + "booking_package": package_raw, } ) except PyMongoError: flash("Buchungsanfrage konnte nicht gesendet werden.", "error") - return redirect(url_for("preise")) + return redirect(url_for("booking_payment", package=package_raw, flow=booking_flow)) finally: if client: client.close() - flash(f"Buchungsanfrage für Paket {selected_package} wurde an den Admin gesendet.", "success") + success_text = ( + f"Gesprächstermin für {selected_package} wurde an das Team gesendet." + if booking_flow == "consultation" + else f"Buchung für {selected_package} wurde an den Admin gesendet." + ) + flash(success_text, "success") return redirect(url_for("user_chat")) diff --git a/Website/templates/preise.html b/Website/templates/preise.html index c8c7309..f2f8058 100644 --- a/Website/templates/preise.html +++ b/Website/templates/preise.html @@ -483,7 +483,7 @@
150 € - / Jahr + / Jahr ab 400 Schüler

Ein spezialisiertes Modul für Bibliotheken und Medienzentren mit Ausleihprozessen, Medienbeständen und historischer Transparenz.

@@ -520,37 +520,46 @@

Buchung bestätigen

-

Möchten Sie dieses Paket wirklich anfragen?

-

Ein Administrator wird sich innerhalb von ca. 48 Stunden über das Portal mit Ihnen in Verbindung setzen. Dort wird dann ein Termin ausgemacht, um die Buchung persönlich vor Ort zu besprechen oder einen direkten Start zu vereinbaren.

+

Möchten Sie dieses Paket jetzt direkt buchen oder zuerst einen Gesprächstermin vereinbaren?

+

In beiden Fällen werden Ihre Angaben noch einmal geprüft, bevor die Buchung per POST an /booking/payment gesendet wird.

- + +