""" test_routes.py — Тестовый слой (/test Blueprint). Мост к БД извне для отладки и диагностики. Не зависит от бизнес-слоёв, только от db.py. Эндпоинты: GET /test — статус БД + список доступных действий POST /test status — только статус БД POST /test createdb — создать базу данных (если не существует) POST /test tables — список таблиц в public схеме POST /test sql {...} — выполнить произвольный SQL """ import os from psycopg2 import sql as psysql from flask import Blueprint, jsonify, request import db import llm_client test_bp = Blueprint("test", __name__) @test_bp.route("/test", methods=["GET", "POST"]) def test(): """ Тестовый слой: проверка БД и выполнение запросов. GET — статус подключения POST — выполнить действие (status/tables/sql/createdb) """ # ── GET — показать статус и список команд ──────────────────── if request.method == "GET": conn, err = db.connect() return jsonify({ "db": "ok" if conn else f"fail: {err}", "actions": [ "GET /test — статус БД", "POST /test status — статус БД (JSON)", "POST /test createdb — создать БД (если нет)", "POST /test tables — список таблиц", "POST /test exec {...} — INSERT/UPDATE/DDL (без fetch)", "POST /test llm {...} — тест LLM (промпт → ответ)", "POST /test sql {...} — SELECT (с fetch)", ], }) # ── POST — выполнить действие ──────────────────────────────── data = request.get_json(silent=True) or {} action = data.get("action", "status") if action == "status": conn, err = db.connect() return jsonify({"db": "ok" if conn else f"fail: {err}"}) if action == "tables": result, err = db.query( "SELECT table_name FROM information_schema.tables " "WHERE table_schema = 'public' ORDER BY table_name" ) if err: return jsonify({"error": err}), 500 return jsonify({"tables": [r[0] for r in result["rows"]]}) if action == "createdb": # Подключаемся к дефолтной БД 'postgres' и создаём целевую try: conn = db._pg_connect("postgres") conn.autocommit = True cur = conn.cursor() db_name = data.get("name") or os.environ.get("DB_NAME", "contracts") cur.execute("SELECT 1 FROM pg_database WHERE datname = %s", (db_name,)) if cur.fetchone(): msg = f"DB '{db_name}' already exists" else: cur.execute(psysql.SQL("CREATE DATABASE {}").format(psysql.Identifier(db_name))) msg = f"DB '{db_name}' created" cur.close() conn.close() return jsonify({"result": msg}) except Exception as e: return jsonify({"error": str(e)}), 500 if action == "exec": # Выполнить INSERT/UPDATE/DELETE/DDL через db.execute() # (не делает fetch, поэтому подходит для CREATE TABLE и т.д.) sql_text = data.get("sql", "") if not sql_text: return jsonify({"error": "no sql"}), 400 rowcount, err = db.execute(sql_text) if err: return jsonify({"error": err}), 500 return jsonify({"rowcount": rowcount}) if action == "sql": sql_text = data.get("sql", "") if not sql_text: return jsonify({"error": "no sql"}), 400 result, err = db.query(sql_text) if err: return jsonify({"error": err}), 500 return jsonify(result) if action == "llm": # Тест LLM: отправить промпт → получить ответ prompt = data.get("prompt", "Скажи 'Привет, мир!'") model = data.get("model") # None = default max_tokens = data.get("max_tokens", 500) result = llm_client.ask(prompt, model=model, max_tokens=max_tokens) if "error" in result: return jsonify(result), 500 return jsonify(result) if action == "debug": # Показать переменные окружения (с маскировкой ключей) import os as _os vars_info = {} for k, v in sorted(_os.environ.items()): if any(x in k.upper() for x in ("KEY", "PASS", "SECRET", "TOKEN")): vars_info[k] = f"{v[:6]}... (len={len(v)})" if v else "(empty)" elif any(x in k.upper() for x in ("DB_", "LLM_", "FLASK", "PORT")): vars_info[k] = v return jsonify({"env": vars_info, "python": _os.sys.version}) return jsonify({"error": f"unknown action: {action}"}), 400