Files
MyPOS/app/tenant/locations/routes.py
T
2026-05-07 12:17:19 -04:00

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"))