commit cb2d96ee664f502b0478ac8b550c9f11c6dbecd4 Author: “Naeel” Date: Thu Jun 18 12:17:04 2026 +0400 init: Application.cfc + db.cfc CRUD API + index.cfm diff --git a/Application.cfc b/Application.cfc new file mode 100644 index 0000000..a1799d0 --- /dev/null +++ b/Application.cfc @@ -0,0 +1,23 @@ +component { + this.name = "contractor"; + this.datasources["baza"] = { + class: "org.postgresql.Driver", + connectionString: "jdbc:postgresql://postgresqlk8s-master.418f9960-2eb7-4429-b2ec-ac64319d7268.svc.cluster.local:5432/baza", + username: "super", + password: "hoHdkA23yxlD9oMUlZ1bIbNyc6DE2mNJmyHMNkEpVD1F4suQs7O2lyN4t0qITyzt" + }; + this.defaultDatasource = "baza"; + + // REST + this.restEnabled = true; + this.restSettings = { + skipCFCWithError: true + }; + + public boolean function onRequestStart(string targetPage) { + if (structKeyExists(url, "reload")) { + applicationStop(); + } + return true; + } +} diff --git a/db.cfc b/db.cfc new file mode 100644 index 0000000..7194c0e --- /dev/null +++ b/db.cfc @@ -0,0 +1,147 @@ +component rest="true" restPath="db" { + + /** + * GET /db/test — проверить соединение + */ + remote any function test() httpMethod="GET" returnFormat="json" { + try { + queryExecute("SELECT 1"); + return {"ok": true, "message": "PostgreSQL connected"}; + } catch (any e) { + return {"ok": false, "error": e.message}; + } + } + + /** + * GET /db/tables — список таблиц + */ + remote any function tables() httpMethod="GET" returnFormat="json" { + try { + var q = queryExecute(" + SELECT table_name + FROM information_schema.tables + WHERE table_schema = 'public' + ORDER BY table_name + "); + var result = []; + for (var row in q) { + arrayAppend(result, row.table_name); + } + return {"ok": true, "tables": result}; + } catch (any e) { + return {"ok": false, "error": e.message}; + } + } + + /** + * GET /db/query?sql=SELECT... + */ + remote any function query(string sql) httpMethod="GET" returnFormat="json" { + if (!structKeyExists(arguments, "sql") || !len(trim(arguments.sql))) { + return {"ok": false, "error": "sql parameter required"}; + } + try { + var q = queryExecute(arguments.sql); + var cols = q.getColumnNames(); + var rows = []; + for (var r in q) { + var row = {}; + for (var c in cols) { + row[c] = r[c]; + } + arrayAppend(rows, row); + } + return {"ok": true, "columns": cols, "rows": rows, "count": q.recordCount}; + } catch (any e) { + return {"ok": false, "error": e.message}; + } + } + + /** + * POST /db/execute — выполнить INSERT/UPDATE/DELETE + * Body: {"sql": "INSERT INTO ...", "params": [...]} + */ + remote any function execute() httpMethod="POST" returnFormat="json" { + var body = deserializeJSON(getHttpRequestData().content); + if (!structKeyExists(body, "sql") || !len(trim(body.sql))) { + return {"ok": false, "error": "sql required"}; + } + try { + var params = structKeyExists(body, "params") ? body.params : []; + var q = queryExecute(body.sql, params); + return {"ok": true, "affected": q.recordCount}; + } catch (any e) { + return {"ok": false, "error": e.message}; + } + } + + /** + * GET /db/schema — создать схему contracts + */ + remote any function schema() httpMethod="GET" returnFormat="json" { + var ddl = [ + "CREATE TABLE IF NOT EXISTS documents ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + filename TEXT NOT NULL, + mime_type TEXT NOT NULL, + original_bytes BYTEA, + parsed_text TEXT, + elements_json JSONB, + status TEXT DEFAULT 'uploaded', + error_message TEXT, + created_at TIMESTAMPTZ DEFAULT now() + )", + "CREATE TABLE IF NOT EXISTS contracts ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + number TEXT NOT NULL, + client TEXT, + date_signed DATE, + status TEXT DEFAULT 'active', + created_at TIMESTAMPTZ DEFAULT now() + )", + "CREATE TABLE IF NOT EXISTS supplements ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + contract_id UUID REFERENCES contracts(id), + number TEXT, + date_signed DATE, + type TEXT DEFAULT 'initial', + document_id UUID REFERENCES documents(id), + created_at TIMESTAMPTZ DEFAULT now() + )", + "CREATE TABLE IF NOT EXISTS spec_rows ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + supplement_id UUID REFERENCES supplements(id), + row_num INTEGER, + name TEXT, + price NUMERIC, + qty NUMERIC, + sum NUMERIC, + date_start DATE, + date_end DATE, + created_at TIMESTAMPTZ DEFAULT now() + )", + "CREATE TABLE IF NOT EXISTS spec_history ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + contract_id UUID REFERENCES contracts(id), + supplement_id UUID REFERENCES supplements(id), + row_num INTEGER, + change_type TEXT NOT NULL, + old_values JSONB, + new_values JSONB, + created_at TIMESTAMPTZ DEFAULT now() + )" + ]; + + var results = []; + for (var sql in ddl) { + try { + queryExecute(sql); + arrayAppend(results, "OK"); + } catch (any e) { + arrayAppend(results, e.message); + } + } + return {"ok": true, "results": results}; + } + +} diff --git a/index.cfm b/index.cfm new file mode 100644 index 0000000..4595044 --- /dev/null +++ b/index.cfm @@ -0,0 +1,19 @@ + + + + + +Contractor — Lucee + +

Contractor API

+

API для сверки договоров — Lucee 6.0

+ + + +