mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 19:03:17 +00:00
- Replace remaining budget.ts prepare() with fn_budget_replace and fn_project_update - Migrate excel.ts findExisting, document store, assign, and catalogs to RPC - Add 015-rpc-documents.sql for project/company/worker document metadata - Document RPC envelope conventions in db/README.md - Add http_errors_test and front api-response composables Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
164 lines
7.4 KiB
PL/PgSQL
164 lines
7.4 KiB
PL/PgSQL
--liquibase formatted sql
|
|
-- PANELS · core · RPC documentos (metadata post-S3)
|
|
|
|
--changeset panel:core-015a-fn-project-document-store endDelimiter:; splitStatements:true
|
|
CREATE OR REPLACE FUNCTION core.fn_project_document_store(payload jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
SECURITY INVOKER
|
|
SET search_path = core
|
|
AS $$
|
|
DECLARE
|
|
v_project_id bigint := (payload->>'project_id')::bigint;
|
|
v_type text := btrim(payload->>'type_code');
|
|
v_doc_id bigint;
|
|
BEGIN
|
|
IF v_project_id IS NULL OR v_type IS NULL OR v_type = '' THEN
|
|
RETURN core.rpc_err('VALIDATION', 'fn_project_document_store: project_id y type_code son obligatorios',
|
|
jsonb_build_object('fn', 'fn_project_document_store'));
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM project_document_types WHERE code = v_type) THEN
|
|
RETURN core.rpc_err('VALIDATION',
|
|
format('fn_project_document_store: tipo de documento %s no válido para proyectos', v_type),
|
|
jsonb_build_object('fn', 'fn_project_document_store', 'type_code', v_type));
|
|
END IF;
|
|
UPDATE project_documents SET is_current = false WHERE project_id = v_project_id AND type_code = v_type;
|
|
INSERT INTO project_documents (
|
|
project_id, type_code, original_name, mime, size_bytes, sha256, iv, storage_name,
|
|
is_current, parse_status, uploaded_by_id, uploaded_by_name
|
|
) VALUES (
|
|
v_project_id, v_type, payload->>'original_name', payload->>'mime',
|
|
(payload->>'size_bytes')::integer, payload->>'sha256', payload->>'iv', payload->>'storage_name',
|
|
true, 'manual', NULLIF(payload->>'uploaded_by_id', '')::integer, coalesce(payload->>'uploaded_by_name', '')
|
|
) RETURNING id INTO v_doc_id;
|
|
RETURN core.rpc_ok(jsonb_build_object('id', v_doc_id),
|
|
format('Documento %s guardado para proyecto id=%s (doc id=%s)', v_type, v_project_id, v_doc_id),
|
|
jsonb_build_object('fn', 'fn_project_document_store', 'project_id', v_project_id, 'id', v_doc_id));
|
|
EXCEPTION WHEN OTHERS THEN
|
|
RETURN core.rpc_from_exception('fn_project_document_store', SQLSTATE, SQLERRM);
|
|
END;
|
|
$$;
|
|
|
|
--changeset panel:core-015b-fn-company-document-store endDelimiter:; splitStatements:true
|
|
CREATE OR REPLACE FUNCTION core.fn_company_document_store(payload jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
SECURITY INVOKER
|
|
SET search_path = core
|
|
AS $$
|
|
DECLARE
|
|
v_company_id bigint := (payload->>'company_id')::bigint;
|
|
v_type text := btrim(payload->>'type_code');
|
|
v_doc_id bigint;
|
|
BEGIN
|
|
IF v_company_id IS NULL OR v_type IS NULL OR v_type = '' THEN
|
|
RETURN core.rpc_err('VALIDATION', 'fn_company_document_store: company_id y type_code son obligatorios',
|
|
jsonb_build_object('fn', 'fn_company_document_store'));
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM company_document_types WHERE code = v_type) THEN
|
|
RETURN core.rpc_err('VALIDATION',
|
|
format('fn_company_document_store: tipo de documento %s no válido para empresas', v_type),
|
|
jsonb_build_object('fn', 'fn_company_document_store', 'type_code', v_type));
|
|
END IF;
|
|
UPDATE company_documents SET is_current = false WHERE company_id = v_company_id AND type_code = v_type;
|
|
INSERT INTO company_documents (
|
|
company_id, type_code, original_name, mime, size_bytes, sha256, iv, storage_name,
|
|
is_current, parse_status, uploaded_by_id, uploaded_by_name
|
|
) VALUES (
|
|
v_company_id, v_type, payload->>'original_name', payload->>'mime',
|
|
(payload->>'size_bytes')::integer, payload->>'sha256', payload->>'iv', payload->>'storage_name',
|
|
true, 'manual', NULLIF(payload->>'uploaded_by_id', '')::integer, coalesce(payload->>'uploaded_by_name', '')
|
|
) RETURNING id INTO v_doc_id;
|
|
RETURN core.rpc_ok(jsonb_build_object('id', v_doc_id),
|
|
format('Documento %s guardado para empresa id=%s (doc id=%s)', v_type, v_company_id, v_doc_id),
|
|
jsonb_build_object('fn', 'fn_company_document_store', 'company_id', v_company_id, 'id', v_doc_id));
|
|
EXCEPTION WHEN OTHERS THEN
|
|
RETURN core.rpc_from_exception('fn_company_document_store', SQLSTATE, SQLERRM);
|
|
END;
|
|
$$;
|
|
|
|
--changeset panel:core-015c-fn-document-get endDelimiter:; splitStatements:true
|
|
CREATE OR REPLACE FUNCTION core.fn_project_document_get(payload jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
SECURITY INVOKER
|
|
SET search_path = core
|
|
AS $$
|
|
DECLARE
|
|
v_project_id bigint := (payload->>'project_id')::bigint;
|
|
v_doc_id bigint := (payload->>'doc_id')::bigint;
|
|
v_doc jsonb;
|
|
BEGIN
|
|
SELECT to_jsonb(d) INTO v_doc FROM project_documents d
|
|
WHERE d.id = v_doc_id AND d.project_id = v_project_id;
|
|
IF v_doc IS NULL THEN
|
|
RETURN core.rpc_err('NOT_FOUND',
|
|
format('fn_project_document_get: documento id=%s no encontrado en proyecto %s', v_doc_id, v_project_id),
|
|
jsonb_build_object('fn', 'fn_project_document_get', 'doc_id', v_doc_id, 'project_id', v_project_id));
|
|
END IF;
|
|
RETURN core.rpc_ok(jsonb_build_object('document', v_doc),
|
|
format('Documento id=%s del proyecto %s obtenido', v_doc_id, v_project_id),
|
|
jsonb_build_object('fn', 'fn_project_document_get', 'doc_id', v_doc_id));
|
|
EXCEPTION WHEN OTHERS THEN
|
|
RETURN core.rpc_from_exception('fn_project_document_get', SQLSTATE, SQLERRM);
|
|
END;
|
|
$$;
|
|
|
|
CREATE OR REPLACE FUNCTION core.fn_company_document_get(payload jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
SECURITY INVOKER
|
|
SET search_path = core
|
|
AS $$
|
|
DECLARE
|
|
v_company_id bigint := (payload->>'company_id')::bigint;
|
|
v_doc_id bigint := (payload->>'doc_id')::bigint;
|
|
v_doc jsonb;
|
|
BEGIN
|
|
SELECT to_jsonb(d) INTO v_doc FROM company_documents d
|
|
WHERE d.id = v_doc_id AND d.company_id = v_company_id;
|
|
IF v_doc IS NULL THEN
|
|
RETURN core.rpc_err('NOT_FOUND',
|
|
format('fn_company_document_get: documento id=%s no encontrado en empresa %s', v_doc_id, v_company_id),
|
|
jsonb_build_object('fn', 'fn_company_document_get', 'doc_id', v_doc_id, 'company_id', v_company_id));
|
|
END IF;
|
|
RETURN core.rpc_ok(jsonb_build_object('document', v_doc),
|
|
format('Documento id=%s de la empresa %s obtenido', v_doc_id, v_company_id),
|
|
jsonb_build_object('fn', 'fn_company_document_get', 'doc_id', v_doc_id));
|
|
EXCEPTION WHEN OTHERS THEN
|
|
RETURN core.rpc_from_exception('fn_company_document_get', SQLSTATE, SQLERRM);
|
|
END;
|
|
$$;
|
|
|
|
CREATE OR REPLACE FUNCTION core.fn_worker_document_get(payload jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
SECURITY INVOKER
|
|
SET search_path = core
|
|
AS $$
|
|
DECLARE
|
|
v_worker_id bigint := (payload->>'worker_id')::bigint;
|
|
v_doc_id bigint := (payload->>'doc_id')::bigint;
|
|
v_doc jsonb;
|
|
BEGIN
|
|
SELECT to_jsonb(d) INTO v_doc FROM documents d
|
|
WHERE d.id = v_doc_id AND d.worker_id = v_worker_id;
|
|
IF v_doc IS NULL THEN
|
|
RETURN core.rpc_err('NOT_FOUND',
|
|
format('fn_worker_document_get: documento id=%s no encontrado para trabajador %s', v_doc_id, v_worker_id),
|
|
jsonb_build_object('fn', 'fn_worker_document_get', 'doc_id', v_doc_id, 'worker_id', v_worker_id));
|
|
END IF;
|
|
RETURN core.rpc_ok(jsonb_build_object('document', v_doc),
|
|
format('Documento id=%s del trabajador %s obtenido', v_doc_id, v_worker_id),
|
|
jsonb_build_object('fn', 'fn_worker_document_get', 'doc_id', v_doc_id));
|
|
EXCEPTION WHEN OTHERS THEN
|
|
RETURN core.rpc_from_exception('fn_worker_document_get', SQLSTATE, SQLERRM);
|
|
END;
|
|
$$;
|
|
|
|
--changeset panel:core-015d-fn-documents-grants endDelimiter:; splitStatements:true
|
|
GRANT EXECUTE ON FUNCTION core.fn_project_document_store(jsonb) TO panels_core_app;
|
|
GRANT EXECUTE ON FUNCTION core.fn_company_document_store(jsonb) TO panels_core_app;
|
|
GRANT EXECUTE ON FUNCTION core.fn_project_document_get(jsonb) TO panels_core_app;
|
|
GRANT EXECUTE ON FUNCTION core.fn_company_document_get(jsonb) TO panels_core_app;
|
|
GRANT EXECUTE ON FUNCTION core.fn_worker_document_get(jsonb) TO panels_core_app;
|