118 lines
4.8 KiB
Python
118 lines
4.8 KiB
Python
"""
|
|
app/tenant/locations/routes.py
|
|
Location management: list, create, edit, set primary, switch.
|
|
"""
|
|
import logging
|
|
from flask import Blueprint, render_template, redirect, url_for, flash, request, session, g
|
|
from flask_login import login_required, current_user
|
|
from app.extensions import db
|
|
from app.models.salon import Location
|
|
from app.decorators import require_role, tenant_feature_required, demo_readonly
|
|
from app.tenant.utils import log_tenant_action, plan_limit_check
|
|
|
|
logger = logging.getLogger(__name__)
|
|
locations_bp = Blueprint("locations", __name__, url_prefix="/locations")
|
|
|
|
|
|
@locations_bp.route("/")
|
|
@login_required
|
|
@require_role("tenant_admin", "tenant_manager")
|
|
def index():
|
|
locs = Location.query.filter_by(tenant_id=g.tenant.id).order_by(
|
|
Location.is_primary.desc(), Location.name).all()
|
|
return render_template("tenant/locations/index.html", locations=locs)
|
|
|
|
|
|
@locations_bp.route("/switch/<int:location_id>")
|
|
@login_required
|
|
@require_role("tenant_admin", "tenant_manager")
|
|
def switch(location_id):
|
|
loc = Location.query.filter_by(
|
|
id=location_id, tenant_id=g.tenant.id, is_active=True).first_or_404()
|
|
session["active_location_id"] = loc.id
|
|
logger.info("Location switched: location=%s tenant=%s user=%s",
|
|
loc.id, g.tenant.id, current_user.get_id())
|
|
flash(f"Switched to {loc.name}.", "info")
|
|
return redirect(request.referrer or url_for("dashboard.index"))
|
|
|
|
|
|
@locations_bp.route("/new", methods=["GET", "POST"])
|
|
@login_required
|
|
@require_role("tenant_admin")
|
|
@demo_readonly
|
|
def create():
|
|
allowed, err = plan_limit_check("location")
|
|
if not allowed:
|
|
flash(err, "warning")
|
|
return redirect(url_for("locations.index"))
|
|
|
|
if request.method == "POST":
|
|
name = request.form.get("name", "").strip()
|
|
if not name:
|
|
return render_template("tenant/locations/form.html",
|
|
mode="create", error="Name is required.")
|
|
allowed, err = plan_limit_check("location")
|
|
if not allowed:
|
|
return render_template("tenant/locations/form.html",
|
|
mode="create", error=err)
|
|
loc = Location(
|
|
tenant_id=g.tenant.id, name=name,
|
|
address=request.form.get("address", "").strip() or None,
|
|
phone=request.form.get("phone", "").strip() or None,
|
|
email=request.form.get("email", "").strip() or None,
|
|
timezone=request.form.get("timezone", "America/New_York"),
|
|
is_active=True, is_primary=False,
|
|
)
|
|
db.session.add(loc)
|
|
db.session.flush()
|
|
log_tenant_action("location.create", "location", loc.id, {"name": name})
|
|
db.session.commit()
|
|
flash(f"Location \'{name}\' created.", "success")
|
|
return redirect(url_for("locations.index"))
|
|
return render_template("tenant/locations/form.html", mode="create")
|
|
|
|
|
|
@locations_bp.route("/<int:location_id>/edit", methods=["GET", "POST"])
|
|
@login_required
|
|
@require_role("tenant_admin")
|
|
@demo_readonly
|
|
def edit(location_id):
|
|
loc = Location.query.filter_by(
|
|
id=location_id, tenant_id=g.tenant.id).first_or_404()
|
|
if request.method == "POST":
|
|
name = request.form.get("name", "").strip()
|
|
if not name:
|
|
return render_template("tenant/locations/form.html",
|
|
mode="edit", location=loc, error="Name is required.")
|
|
old_name = loc.name
|
|
loc.name = name
|
|
loc.address = request.form.get("address", "").strip() or None
|
|
loc.phone = request.form.get("phone", "").strip() or None
|
|
loc.email = request.form.get("email", "").strip() or None
|
|
loc.timezone = request.form.get("timezone", loc.timezone)
|
|
loc.is_active = request.form.get("is_active") == "1"
|
|
if request.form.get("is_primary") == "1" and not loc.is_primary:
|
|
Location.query.filter_by(tenant_id=g.tenant.id, is_primary=True).update({"is_primary": False})
|
|
loc.is_primary = True
|
|
log_tenant_action("location.edit", "location", loc.id,
|
|
{"old_name": old_name, "new_name": name})
|
|
db.session.commit()
|
|
flash(f"Location \'{name}\' updated.", "success")
|
|
return redirect(url_for("locations.index"))
|
|
return render_template("tenant/locations/form.html", mode="edit", location=loc)
|
|
|
|
|
|
@locations_bp.route("/<int:location_id>/set-primary", methods=["POST"])
|
|
@login_required
|
|
@require_role("tenant_admin")
|
|
@demo_readonly
|
|
def set_primary(location_id):
|
|
loc = Location.query.filter_by(
|
|
id=location_id, tenant_id=g.tenant.id, is_active=True).first_or_404()
|
|
Location.query.filter_by(tenant_id=g.tenant.id, is_primary=True).update({"is_primary": False})
|
|
loc.is_primary = True
|
|
log_tenant_action("location.set_primary", "location", loc.id)
|
|
db.session.commit()
|
|
flash(f"\'{loc.name}\' set as primary.", "success")
|
|
return redirect(url_for("locations.index"))
|