inventory/routes/settings.py

107 lines
4 KiB
Python

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