feat: Implement booking package and flow mappings with review page

This commit is contained in:
2026-05-22 23:40:22 +02:00
parent df30cee1a2
commit beb9cb34f4
3 changed files with 229 additions and 26 deletions
+74 -15
View File
@@ -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"))