init: Application.cfc + db.cfc CRUD API + index.cfm
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<cfsetting showdebugoutput="no" enablecfoutputonly="yes">
|
||||
|
||||
<cfoutput>
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head><meta charset="UTF-8"><title>Contractor — Lucee</title></head>
|
||||
<body>
|
||||
<h1>Contractor API</h1>
|
||||
<p>API для сверки договоров — Lucee 6.0</p>
|
||||
<ul>
|
||||
<li><a href="/rest/db/test">GET /rest/db/test</a> — проверка БД</li>
|
||||
<li><a href="/rest/db/tables">GET /rest/db/tables</a> — список таблиц</li>
|
||||
<li><a href="/rest/db/schema">GET /rest/db/schema</a> — создать схему</li>
|
||||
<li>GET /rest/db/query?sql=SELECT...</li>
|
||||
<li>POST /rest/db/execute — {"sql":"...", "params":[...]}</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
</cfoutput>
|
||||
Reference in New Issue
Block a user