Files
mont_vendor_maps/zkart_app/routes.py

168 lines
5.9 KiB
Python

from __future__ import annotations
from flask import Blueprint, jsonify, redirect, render_template, request, send_from_directory, session
from .config import ADMIN_LOGIN, ADMIN_PASSWORD, ADMIN_PATH, BASE_DIR
from .db import fetch_scope_data, get_db, scope_tables
bp = Blueprint("main", __name__)
def require_admin() -> bool:
return bool(session.get("is_admin"))
def parse_int(form_value: str | None) -> int | None:
if not form_value:
return None
try:
return int(form_value)
except ValueError:
return None
@bp.get("/")
def index():
return render_template("index.html")
@bp.get("/api/data")
def api_data():
scope = (request.args.get("scope") or "infra").strip().lower()
if scope in {"ib", "sec", "security"}:
scope = "ib"
else:
scope = "infra"
return jsonify(fetch_scope_data(scope))
@bp.route(ADMIN_PATH, methods=["GET", "POST"])
def admin_login_or_panel():
conn = get_db()
raw_scope = (request.args.get("scope") or request.form.get("scope") or "infra").strip().lower()
scope = "ib" if raw_scope in {"ib", "sec", "security"} else "infra"
tables = scope_tables(scope)
if request.method == "POST" and not require_admin() and request.form.get("action") == "login":
if request.form.get("username") == ADMIN_LOGIN and request.form.get("password") == ADMIN_PASSWORD:
session["is_admin"] = True
conn.close()
return redirect(ADMIN_PATH)
conn.close()
return render_template("login.html", error="Неверный логин или пароль")
if not require_admin():
conn.close()
return render_template("login.html", error=None)
if request.method == "POST":
action = request.form.get("action", "")
if action == "logout":
session.pop("is_admin", None)
conn.close()
return redirect(ADMIN_PATH)
if action == "add_vendor":
name = (request.form.get("name") or "").strip()
if name:
conn.execute(f"INSERT OR IGNORE INTO {tables['vendors']}(name) VALUES (?)", (name,))
elif action == "add_category":
name = (request.form.get("name") or "").strip()
if name:
conn.execute(f"INSERT OR IGNORE INTO {tables['categories']}(name) VALUES (?)", (name,))
elif action == "add_product":
vendor_id = parse_int(request.form.get("vendor_id"))
name = (request.form.get("name") or "").strip()
url = (request.form.get("url") or "").strip()
if vendor_id and name:
conn.execute(
f"INSERT OR IGNORE INTO {tables['products']}(vendor_id, name, url) VALUES (?, ?, ?)",
(vendor_id, name, url or None),
)
if url:
conn.execute(
f"UPDATE {tables['products']} SET url = ? WHERE vendor_id = ? AND name = ?",
(url, vendor_id, name),
)
elif action == "delete_vendor":
v_id = parse_int(request.form.get("vendor_id"))
if v_id:
conn.execute(f"DELETE FROM {tables['vendors']} WHERE id = ?", (v_id,))
elif action == "delete_category":
c_id = parse_int(request.form.get("category_id"))
if c_id:
conn.execute(f"DELETE FROM {tables['categories']} WHERE id = ?", (c_id,))
elif action == "delete_product":
p_id = parse_int(request.form.get("product_id"))
if p_id:
conn.execute(f"DELETE FROM {tables['products']} WHERE id = ?", (p_id,))
elif action == "save_matrix":
products = [r["id"] for r in conn.execute(f"SELECT id FROM {tables['products']}")]
categories = [r["id"] for r in conn.execute(f"SELECT id FROM {tables['categories']}")]
new_pairs: list[tuple[int, int]] = []
for p_id in products:
for c_id in categories:
if request.form.get(f"pc_{p_id}_{c_id}"):
new_pairs.append((p_id, c_id))
conn.execute(f"DELETE FROM {tables['product_categories']}")
conn.executemany(
f"INSERT OR IGNORE INTO {tables['product_categories']}(product_id, category_id) VALUES (?, ?)",
new_pairs,
)
conn.execute(f"DELETE FROM {tables['vendor_categories']}")
conn.execute(
f"""
INSERT OR IGNORE INTO {tables['vendor_categories']}(vendor_id, category_id)
SELECT DISTINCT p.vendor_id, pc.category_id
FROM {tables['products']} p
JOIN {tables['product_categories']} pc ON pc.product_id = p.id
"""
)
conn.commit()
conn.close()
return redirect(f"{ADMIN_PATH}?scope={scope}")
vendors = [dict(r) for r in conn.execute(f"SELECT id, name FROM {tables['vendors']} ORDER BY lower(name)")]
categories = [dict(r) for r in conn.execute(f"SELECT id, name FROM {tables['categories']} ORDER BY lower(name)")]
products = [
dict(r)
for r in conn.execute(
f"""
SELECT p.id, p.name, p.vendor_id, v.name AS vendor_name
, p.url
FROM {tables['products']} p
JOIN {tables['vendors']} v ON v.id = p.vendor_id
ORDER BY lower(v.name), lower(p.name)
"""
)
]
links = {
(r["product_id"], r["category_id"])
for r in conn.execute(f"SELECT product_id, category_id FROM {tables['product_categories']}")
}
conn.close()
return render_template(
"admin.html",
vendors=vendors,
categories=categories,
products=products,
links=links,
scope=scope,
)
@bp.get("/health")
def health():
return {"status": "ok"}
@bp.get("/assets/mont-logo")
def mont_logo():
return send_from_directory(BASE_DIR, "mont_logo.png")