188 lines
6.2 KiB
Python
Executable File
188 lines
6.2 KiB
Python
Executable File
"""Profile routes with dynamic WordPress field synchronization.
|
|
|
|
Sprint 6.6: Dynamic fields from WordPress schema.
|
|
Sprint 10: Admin-configurable field visibility.
|
|
"""
|
|
|
|
import logging
|
|
|
|
from flask import Blueprint, flash, g, redirect, render_template, request, url_for
|
|
|
|
from customer_portal.models import get_db
|
|
from customer_portal.models.settings import PortalSettings
|
|
from customer_portal.services.wordpress_api import WordPressAPI
|
|
from customer_portal.web.routes.auth import login_required
|
|
|
|
bp = Blueprint("profile", __name__)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@bp.route("/")
|
|
@login_required
|
|
def show():
|
|
"""Display profile with dynamic fields from WordPress schema."""
|
|
customer = g.customer
|
|
db = get_db()
|
|
|
|
# Get field configuration from admin settings
|
|
field_config = PortalSettings.get_field_config(db)
|
|
|
|
# Fetch schema from WordPress (only if custom fields are enabled)
|
|
schema = {"core_fields": [], "custom_fields": [], "editable": {}}
|
|
if field_config.get("custom_fields_visible"):
|
|
try:
|
|
schema = WordPressAPI.get_schema()
|
|
except Exception as e:
|
|
logger.error(f"Failed to fetch schema: {e}")
|
|
|
|
# Get current custom field values
|
|
custom_fields = customer.get_custom_fields()
|
|
|
|
return render_template(
|
|
"profile/show.html",
|
|
customer=customer,
|
|
schema=schema,
|
|
custom_fields=custom_fields,
|
|
field_config=field_config,
|
|
)
|
|
|
|
|
|
@bp.route("/edit", methods=["GET", "POST"])
|
|
@login_required
|
|
def edit():
|
|
"""Edit profile with dynamic fields."""
|
|
customer = g.customer
|
|
db = get_db()
|
|
|
|
# Get field configuration from admin settings
|
|
field_config = PortalSettings.get_field_config(db)
|
|
|
|
# Fetch schema from WordPress (only if custom fields are enabled)
|
|
schema = {"core_fields": [], "custom_fields": [], "editable": {}}
|
|
if field_config.get("custom_fields_visible"):
|
|
try:
|
|
schema = WordPressAPI.get_schema()
|
|
except Exception as e:
|
|
logger.error(f"Failed to fetch schema: {e}")
|
|
|
|
if request.method == "POST":
|
|
# Sprint 12: All updates go to custom_fields
|
|
custom_fields = customer.get_custom_fields()
|
|
|
|
# Update core fields (now stored in custom_fields)
|
|
if request.form.get("phone") is not None:
|
|
custom_fields["phone"] = request.form.get("phone", "").strip()
|
|
|
|
if request.form.get("address_street") is not None:
|
|
custom_fields["address_street"] = request.form.get(
|
|
"address_street", ""
|
|
).strip()
|
|
|
|
if request.form.get("address_city") is not None:
|
|
custom_fields["address_city"] = request.form.get("address_city", "").strip()
|
|
|
|
if request.form.get("address_zip") is not None:
|
|
custom_fields["address_zip"] = request.form.get("address_zip", "").strip()
|
|
|
|
# Update custom fields based on schema
|
|
schema_custom_fields = schema.get("custom_fields", [])
|
|
|
|
for field in schema_custom_fields:
|
|
field_name = field.get("name")
|
|
if not field_name:
|
|
continue
|
|
|
|
form_value = request.form.get(f"custom_{field_name}")
|
|
if form_value is not None:
|
|
# Handle different field types
|
|
field_type = field.get("type", "text")
|
|
if field_type == "checkbox":
|
|
custom_fields[field_name] = form_value in {"on", "1"}
|
|
else:
|
|
custom_fields[field_name] = form_value.strip()
|
|
|
|
customer.set_custom_fields(custom_fields)
|
|
db.commit()
|
|
|
|
logger.info(f"Profile updated for customer {customer.id}")
|
|
flash("Profil erfolgreich aktualisiert.", "success")
|
|
return redirect(url_for("profile.show"))
|
|
|
|
# GET: Show edit form
|
|
custom_fields = customer.get_custom_fields()
|
|
|
|
return render_template(
|
|
"profile/edit.html",
|
|
customer=customer,
|
|
schema=schema,
|
|
custom_fields=custom_fields,
|
|
field_config=field_config,
|
|
)
|
|
|
|
|
|
@bp.route("/sync", methods=["POST"])
|
|
@login_required
|
|
def sync_from_wordpress():
|
|
"""Sync custom fields from latest booking.
|
|
|
|
Fetches the most recent booking and syncs any custom field values
|
|
that are missing in the customer profile.
|
|
"""
|
|
customer = g.customer
|
|
db = get_db()
|
|
|
|
try:
|
|
# Get latest booking
|
|
bookings = WordPressAPI.get_bookings(customer.email)
|
|
if not bookings:
|
|
flash("Keine Buchungen zum Synchronisieren gefunden.", "info")
|
|
return redirect(url_for("profile.show"))
|
|
|
|
# Get most recent booking (first in list, sorted by date desc)
|
|
latest_booking = bookings[0]
|
|
booking_id = latest_booking.get("id")
|
|
|
|
if booking_id:
|
|
synced = WordPressAPI.sync_customer_fields_from_booking(
|
|
customer, booking_id
|
|
)
|
|
db.commit()
|
|
|
|
if synced:
|
|
synced_names = list(synced.keys())
|
|
flash(f"Felder synchronisiert: {', '.join(synced_names)}", "success")
|
|
else:
|
|
flash("Alle Felder sind bereits aktuell.", "info")
|
|
else:
|
|
flash("Buchungs-ID nicht gefunden.", "warning")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Sync failed for customer {customer.id}: {e}")
|
|
flash(
|
|
"Synchronisation fehlgeschlagen. Bitte versuchen Sie es spaeter.", "error"
|
|
)
|
|
|
|
return redirect(url_for("profile.show"))
|
|
|
|
|
|
@bp.route("/settings", methods=["GET", "POST"])
|
|
@login_required
|
|
def settings():
|
|
"""Manage notification and communication settings."""
|
|
customer = g.customer
|
|
db = get_db()
|
|
|
|
if request.method == "POST":
|
|
# Update notification settings
|
|
customer.email_notifications = request.form.get("email_notifications") == "on"
|
|
customer.email_reminders = request.form.get("email_reminders") == "on"
|
|
customer.email_invoices = request.form.get("email_invoices") == "on"
|
|
customer.email_marketing = request.form.get("email_marketing") == "on"
|
|
db.commit()
|
|
|
|
logger.info(f"Settings updated for customer {customer.id}")
|
|
flash("Einstellungen erfolgreich gespeichert.", "success")
|
|
return redirect(url_for("profile.settings"))
|
|
|
|
return render_template("profile/settings.html", customer=customer)
|