import json import traceback from flask import request, flash, redirect, url_for, render_template, jsonify from . import main from .. import db from ..models import Brand, Item, Area, RoomFunction, Room from ..utils.load import eager_load_room_relationships @main.route('/settings', methods=['GET', 'POST']) def settings(): if request.method == 'POST': form = request.form try: state = json.loads(form['formState']) except Exception: flash("Invalid form state submitted. JSON decode failed.", "danger") traceback.print_exc() return redirect(url_for('main.settings')) try: with db.session.begin(): # Sync each table and grab temp ID maps brand_map = Brand.sync_from_state(state.get("brands", [])) type_map = Item.sync_from_state(state.get("types", [])) section_map = Area.sync_from_state(state.get("sections", [])) function_map = RoomFunction.sync_from_state(state.get("functions", [])) # Fix up room foreign keys based on real IDs submitted_rooms = [] for room in state.get("rooms", []): room = dict(room) # shallow copy sid = room.get("section_id") fid = room.get("function_id") if sid is not None: sid_key = str(sid) if sid_key in section_map: room["section_id"] = section_map[sid_key] if fid is not None: fid_key = str(fid) if fid_key in function_map: room["function_id"] = function_map[fid_key] submitted_rooms.append(room) Room.sync_from_state( submitted_rooms=submitted_rooms, section_map=section_map, function_map=function_map ) flash("Changes saved.", "success") except Exception as e: flash(f"Error saving changes: {e}", "danger") return redirect(url_for('main.settings')) # === GET === brands = db.session.query(Brand).order_by(Brand.name).all() types = db.session.query(Item).order_by(Item.description).all() sections = db.session.query(Area).order_by(Area.name).all() functions = db.session.query(RoomFunction).order_by(RoomFunction.description).all() rooms = eager_load_room_relationships(db.session.query(Room).order_by(Room.name)).all() return render_template('settings.html', title="Settings", brands=[b.serialize() for b in brands], types=[{"id": t.id, "name": t.description} for t in types], sections=[s.serialize() for s in sections], functions=[f.serialize() for f in functions], rooms=[r.serialize() for r in rooms] ) @main.route("/api/settings", methods=["POST"]) def api_settings(): try: payload = request.get_json(force=True) except Exception as e: return jsonify({"error": "Invalid JSON"}), 400 errors = [] errors += Brand.validate_state(payload.get("brands", [])) errors += Item.validate_state(payload.get("types", [])) errors += Area.validate_state(payload.get("sections", [])) errors += RoomFunction.validate_state(payload.get("functions", [])) errors += Room.validate_state(payload.get("rooms", [])) if errors: return jsonify({"errors": errors}), 400 try: with db.session.begin(): section_map = Area.sync_from_state(payload["sections"]) function_map = RoomFunction.sync_from_state(payload["functions"]) Brand.sync_from_state(payload["brands"]) Item.sync_from_state(payload["types"]) Room.sync_from_state(payload["rooms"], section_map, function_map) except Exception as e: db.session.rollback() return jsonify({"errors": [str(e)]}), 500 return jsonify({"message": "Settings updated successfully."}), 200