Files

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)