initial commit
This commit is contained in:
297
Scripts/DC_BACKEND_PKG.sql
Normal file
297
Scripts/DC_BACKEND_PKG.sql
Normal file
@@ -0,0 +1,297 @@
|
||||
-- =============================================================================
|
||||
-- DC_BACKEND_PKG
|
||||
-- PL/SQL-Schnittstelle zum Quarkus dc-backend (Kubernetes Service dc-backend:8090)
|
||||
--
|
||||
-- Voraussetzungen:
|
||||
-- - APEX_WEB_SERVICE-Berechtigung für das Schema:
|
||||
-- GRANT EXECUTE ON APEX_240100.APEX_WEB_SERVICE TO <schema>; -- APEX-Version anpassen
|
||||
-- - ACL für ausgehende HTTP-Verbindung im selben Namespace:
|
||||
-- DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
|
||||
-- host => 'dc-backend', lower_port => 8090, upper_port => 8090,
|
||||
-- ace => xs$ace_type(privilege_list => xs$name_list('connect','resolve'),
|
||||
-- principal_name => '<schema>', principal_type => xs_acl.ptype_db));
|
||||
--
|
||||
-- Deployment:
|
||||
-- sqlplus user/pass@db @"Scripts/DC_BACKEND_PKG.sql"
|
||||
-- =============================================================================
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- Package Spec
|
||||
-- =============================================================================
|
||||
CREATE OR REPLACE PACKAGE DC_BACKEND_PKG AS
|
||||
|
||||
-- Basis-URL des dc-backend Kubernetes Service
|
||||
c_base_url CONSTANT VARCHAR2(200) := 'http://dc-backend:8090';
|
||||
|
||||
-- API-Key (X-API-KEY Header).
|
||||
-- Leer = kein Auth (Dev-Modus).
|
||||
-- Zur Laufzeit setzen: DC_BACKEND_PKG.g_api_key := 'mein-key';
|
||||
g_api_key VARCHAR2(500) := '';
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Startet die KI-gestützte Dokumentenprüfung für ein Projekt (asynchron).
|
||||
-- Das Projekt muss im Status PENDING sein.
|
||||
-- POST /check/{p_project_id} → 202 Accepted
|
||||
--
|
||||
-- p_project_id ID des dc_projects-Eintrags
|
||||
-- p_status_code HTTP-Statuscode der Antwort (202 = OK, 409 = nicht PENDING)
|
||||
-- p_response JSON-Antwort des Backend
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE start_check(
|
||||
p_project_id IN NUMBER,
|
||||
p_status_code OUT NUMBER,
|
||||
p_response OUT VARCHAR2
|
||||
);
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Health-Check: prüft ob der dc-backend Service erreichbar ist.
|
||||
-- GET /check/health → 200 UP
|
||||
--
|
||||
-- Rückgabe: TRUE = Service läuft, FALSE = nicht erreichbar
|
||||
-- -------------------------------------------------------------------------
|
||||
FUNCTION health_check RETURN BOOLEAN;
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Startet die Prüfung und wirft eine Exception wenn nicht 202 zurückkommt.
|
||||
-- Convenience-Wrapper für direkte APEX-Button-Aufrufe.
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE start_check_or_raise(
|
||||
p_project_id IN NUMBER
|
||||
);
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Fortschritts-Record
|
||||
-- -------------------------------------------------------------------------
|
||||
TYPE t_project_status IS RECORD (
|
||||
status dc_projects.status%TYPE,
|
||||
processing_progress dc_projects.progress%TYPE,
|
||||
is_completed BOOLEAN,
|
||||
is_running BOOLEAN,
|
||||
is_pending BOOLEAN
|
||||
);
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Liest Status und Fortschritt eines Projekts direkt aus der DB.
|
||||
-- Kein REST-Aufruf – sofort und transaktionssicher.
|
||||
--
|
||||
-- Beispiel:
|
||||
-- l_s := DC_BACKEND_PKG.get_status(1);
|
||||
-- DBMS_OUTPUT.PUT_LINE(l_s.status || ' ' || l_s.processing_progress || '%');
|
||||
-- -------------------------------------------------------------------------
|
||||
FUNCTION get_status(
|
||||
p_project_id IN NUMBER
|
||||
) RETURN t_project_status;
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Wartet (polling) bis das Projekt COMPLETED oder ein Timeout erreicht ist.
|
||||
-- Wirft eine Exception bei Timeout oder wenn das Projekt nicht gefunden wird.
|
||||
--
|
||||
-- p_timeout_sec Max. Wartezeit in Sekunden (Default: 1800 = 30 Min.)
|
||||
-- p_interval_sec Polling-Intervall in Sekunden (Default: 5)
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE wait_for_completion(
|
||||
p_project_id IN NUMBER,
|
||||
p_timeout_sec IN NUMBER DEFAULT 1800,
|
||||
p_interval_sec IN NUMBER DEFAULT 5
|
||||
);
|
||||
|
||||
END DC_BACKEND_PKG;
|
||||
/
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- Package Body
|
||||
-- =============================================================================
|
||||
CREATE OR REPLACE PACKAGE BODY DC_BACKEND_PKG AS
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Setzt gemeinsame Request-Header (Content-Type + optional API-Key)
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE set_headers IS
|
||||
l_idx PLS_INTEGER := 1;
|
||||
BEGIN
|
||||
APEX_WEB_SERVICE.G_REQUEST_HEADERS.DELETE;
|
||||
|
||||
APEX_WEB_SERVICE.G_REQUEST_HEADERS(l_idx).NAME := 'Content-Type';
|
||||
APEX_WEB_SERVICE.G_REQUEST_HEADERS(l_idx).VALUE := 'application/json';
|
||||
l_idx := l_idx + 1;
|
||||
|
||||
IF g_api_key IS NOT NULL AND LENGTH(TRIM(g_api_key)) > 0 THEN
|
||||
APEX_WEB_SERVICE.G_REQUEST_HEADERS(l_idx).NAME := 'X-API-KEY';
|
||||
APEX_WEB_SERVICE.G_REQUEST_HEADERS(l_idx).VALUE := g_api_key;
|
||||
END IF;
|
||||
END set_headers;
|
||||
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE start_check(
|
||||
p_project_id IN NUMBER,
|
||||
p_status_code OUT NUMBER,
|
||||
p_response OUT VARCHAR2
|
||||
) IS
|
||||
l_url VARCHAR2(500);
|
||||
l_response CLOB;
|
||||
BEGIN
|
||||
l_url := c_base_url || '/check/' || TO_CHAR(p_project_id);
|
||||
|
||||
set_headers();
|
||||
|
||||
l_response := APEX_WEB_SERVICE.MAKE_REST_REQUEST(
|
||||
p_url => l_url,
|
||||
p_http_method => 'POST',
|
||||
p_body => '{}' -- leerer Body, projectId ist im Pfad
|
||||
);
|
||||
|
||||
p_status_code := APEX_WEB_SERVICE.G_STATUS_CODE;
|
||||
p_response := SUBSTR(l_response, 1, 4000);
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
p_status_code := -1;
|
||||
p_response := 'Verbindungsfehler: ' || SQLERRM;
|
||||
END start_check;
|
||||
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
FUNCTION health_check RETURN BOOLEAN IS
|
||||
l_url VARCHAR2(500);
|
||||
l_response CLOB;
|
||||
l_status NUMBER;
|
||||
BEGIN
|
||||
l_url := c_base_url || '/check/health';
|
||||
|
||||
set_headers();
|
||||
|
||||
l_response := APEX_WEB_SERVICE.MAKE_REST_REQUEST(
|
||||
p_url => l_url,
|
||||
p_http_method => 'GET'
|
||||
);
|
||||
|
||||
l_status := APEX_WEB_SERVICE.G_STATUS_CODE;
|
||||
RETURN l_status = 200;
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RETURN FALSE;
|
||||
END health_check;
|
||||
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE start_check_or_raise(
|
||||
p_project_id IN NUMBER
|
||||
) IS
|
||||
l_status NUMBER;
|
||||
l_response VARCHAR2(4000);
|
||||
BEGIN
|
||||
start_check(
|
||||
p_project_id => p_project_id,
|
||||
p_status_code => l_status,
|
||||
p_response => l_response
|
||||
);
|
||||
|
||||
IF l_status = 202 THEN
|
||||
-- OK: Verarbeitung wurde gestartet
|
||||
NULL;
|
||||
ELSIF l_status = 409 THEN
|
||||
RAISE_APPLICATION_ERROR(-20100,
|
||||
'Projekt ' || p_project_id || ' ist nicht im Status PENDING.');
|
||||
ELSIF l_status = 401 THEN
|
||||
RAISE_APPLICATION_ERROR(-20101,
|
||||
'Ungültiger API-Key für dc-backend.');
|
||||
ELSIF l_status = -1 THEN
|
||||
RAISE_APPLICATION_ERROR(-20102,
|
||||
'dc-backend nicht erreichbar: ' || l_response);
|
||||
ELSE
|
||||
RAISE_APPLICATION_ERROR(-20103,
|
||||
'Unerwarteter HTTP-Status ' || l_status || ': ' || l_response);
|
||||
END IF;
|
||||
END start_check_or_raise;
|
||||
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
FUNCTION get_status(
|
||||
p_project_id IN NUMBER
|
||||
) RETURN t_project_status IS
|
||||
l_rec t_project_status;
|
||||
BEGIN
|
||||
SELECT status, progress
|
||||
INTO l_rec.status, l_rec.processing_progress
|
||||
FROM dc_projects
|
||||
WHERE id = p_project_id;
|
||||
|
||||
l_rec.is_completed := l_rec.status = 'COMPLETED';
|
||||
l_rec.is_running := l_rec.status = 'IN_PROGRESS';
|
||||
l_rec.is_pending := l_rec.status = 'PENDING';
|
||||
RETURN l_rec;
|
||||
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
RAISE_APPLICATION_ERROR(-20110,
|
||||
'Projekt ' || p_project_id || ' nicht gefunden.');
|
||||
END get_status;
|
||||
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE wait_for_completion(
|
||||
p_project_id IN NUMBER,
|
||||
p_timeout_sec IN NUMBER DEFAULT 1800,
|
||||
p_interval_sec IN NUMBER DEFAULT 5
|
||||
) IS
|
||||
l_start TIMESTAMP := SYSTIMESTAMP;
|
||||
l_status t_project_status;
|
||||
BEGIN
|
||||
LOOP
|
||||
l_status := get_status(p_project_id);
|
||||
|
||||
EXIT WHEN l_status.is_completed;
|
||||
|
||||
IF EXTRACT(SECOND FROM (SYSTIMESTAMP - l_start))
|
||||
+ EXTRACT(MINUTE FROM (SYSTIMESTAMP - l_start)) * 60
|
||||
+ EXTRACT(HOUR FROM (SYSTIMESTAMP - l_start)) * 3600
|
||||
> p_timeout_sec
|
||||
THEN
|
||||
RAISE_APPLICATION_ERROR(-20111,
|
||||
'Timeout nach ' || p_timeout_sec || 's – Projekt ' ||
|
||||
p_project_id || ' noch im Status ' || l_status.status ||
|
||||
' (' || l_status.processing_progress || '%).');
|
||||
END IF;
|
||||
|
||||
DBMS_SESSION.SLEEP(p_interval_sec);
|
||||
END LOOP;
|
||||
END wait_for_completion;
|
||||
|
||||
|
||||
END DC_BACKEND_PKG;
|
||||
/
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- Schnelltest (optional, auskommentiert)
|
||||
-- =============================================================================
|
||||
/*
|
||||
-- Health-Check
|
||||
BEGIN
|
||||
IF DC_BACKEND_PKG.health_check() THEN
|
||||
DBMS_OUTPUT.PUT_LINE('dc-backend: UP');
|
||||
ELSE
|
||||
DBMS_OUTPUT.PUT_LINE('dc-backend: NICHT ERREICHBAR');
|
||||
END IF;
|
||||
END;
|
||||
/
|
||||
|
||||
-- Prüfung starten (Projekt-ID anpassen)
|
||||
DECLARE
|
||||
l_status NUMBER;
|
||||
l_response VARCHAR2(4000);
|
||||
BEGIN
|
||||
DC_BACKEND_PKG.start_check(
|
||||
p_project_id => 1,
|
||||
p_status_code => l_status,
|
||||
p_response => l_response
|
||||
);
|
||||
DBMS_OUTPUT.PUT_LINE('Status: ' || l_status);
|
||||
DBMS_OUTPUT.PUT_LINE('Response: ' || l_response);
|
||||
END;
|
||||
/
|
||||
*/
|
||||
535
Scripts/Datenmodell DocumentCheck.sql
Normal file
535
Scripts/Datenmodell DocumentCheck.sql
Normal file
@@ -0,0 +1,535 @@
|
||||
drop table dc_users cascade constraints;
|
||||
drop table dc_document_types cascade constraints;
|
||||
drop table dc_user_roles cascade constraints;
|
||||
drop table dc_question_catalogs cascade constraints;
|
||||
drop table dc_question_categories cascade constraints;
|
||||
drop table dc_questions cascade constraints;
|
||||
drop table dc_reference_documents cascade constraints;
|
||||
drop table dc_projects cascade constraints;
|
||||
drop table dc_project_documents cascade constraints;
|
||||
drop table dc_results cascade constraints;
|
||||
-- create tables
|
||||
|
||||
create table dc_users (
|
||||
id number generated by default on null as identity
|
||||
constraint dc_users_id_pk primary key,
|
||||
username varchar2(50 char)
|
||||
constraint users_username_unq unique not null,
|
||||
email varchar2(100 char)
|
||||
constraint users_email_unq unique not null,
|
||||
password_hash varchar2(255 char),
|
||||
role varchar2(20 char),
|
||||
is_active number default on null 1,
|
||||
created_at date default on null sysdate,
|
||||
updated_at date default on null sysdate,
|
||||
row_version integer not null,
|
||||
created date not null,
|
||||
created_by varchar2(255 char) not null,
|
||||
updated date not null,
|
||||
updated_by varchar2(255 char) not null
|
||||
);
|
||||
|
||||
create table dc_document_types (
|
||||
id number generated by default on null as identity
|
||||
constraint dc_document_types_id_pk primary key,
|
||||
name varchar2(100 char) not null,
|
||||
description clob,
|
||||
row_version integer not null,
|
||||
created date not null,
|
||||
created_by varchar2(255 char) not null,
|
||||
updated date not null,
|
||||
updated_by varchar2(255 char) not null
|
||||
);
|
||||
|
||||
create table dc_reference_documents (
|
||||
id number generated by default on null as identity
|
||||
constraint dc_reference_documents_id_pk primary key,
|
||||
uploaded_by number constraint dc_reference_documents_uploaded_by_fk
|
||||
references dc_users,
|
||||
document_type_id number constraint dc_reference_documents_doc_type_fk
|
||||
references dc_document_types,
|
||||
name varchar2(100 char) not null,
|
||||
description clob,
|
||||
file_path varchar2(500 char),
|
||||
upload_date date default on null sysdate,
|
||||
mime_type varchar2(100 char),
|
||||
row_version integer not null,
|
||||
created date not null,
|
||||
created_by varchar2(255 char) not null,
|
||||
updated date not null,
|
||||
updated_by varchar2(255 char) not null
|
||||
);
|
||||
|
||||
-- table index
|
||||
create index dc_reference_documents_i1 on dc_reference_documents (uploaded_by);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
create table dc_user_roles (
|
||||
id number generated by default on null as identity
|
||||
constraint dc_user_roles_id_pk primary key,
|
||||
role_name varchar2(20 char)
|
||||
constraint user_roles_role_name_unq unique not null,
|
||||
description clob,
|
||||
row_version integer not null,
|
||||
created date not null,
|
||||
created_by varchar2(255 char) not null,
|
||||
updated date not null,
|
||||
updated_by varchar2(255 char) not null
|
||||
);
|
||||
|
||||
|
||||
|
||||
create table dc_question_catalogs (
|
||||
id number generated by default on null as identity
|
||||
constraint dc_question_catalogs_id_pk primary key,
|
||||
created_by_user number constraint dc_question_catalogs_created_by_fk
|
||||
references dc_users,
|
||||
based_on_reference number constraint dc_question_catalogs_reference_document_fk
|
||||
references dc_reference_documents,
|
||||
document_type_id number constraint dc_question_catalogs_doc_type_fk
|
||||
references dc_document_types,
|
||||
name varchar2(100 char) not null,
|
||||
description varchar2(4000 char),
|
||||
row_version integer not null,
|
||||
created date not null,
|
||||
created_by varchar2(255 char) not null,
|
||||
updated date not null,
|
||||
updated_by varchar2(255 char) not null
|
||||
);
|
||||
|
||||
-- table index
|
||||
create index dc_question_catalogs_i1 on dc_question_catalogs (created_by);
|
||||
|
||||
|
||||
|
||||
create table dc_question_categories (
|
||||
id number generated by default on null as identity
|
||||
constraint dc_question_categories_id_pk primary key,
|
||||
catalog_id number constraint dc_question_categories_catalog_id_fk
|
||||
references dc_question_catalogs,
|
||||
name varchar2(100 char) not null,
|
||||
description varchar2(4000 char),
|
||||
row_version integer not null,
|
||||
created date not null,
|
||||
created_by varchar2(255 char) not null,
|
||||
updated date not null,
|
||||
updated_by varchar2(255 char) not null
|
||||
);
|
||||
|
||||
-- table index
|
||||
create index dc_question_categories_i1 on dc_question_categories (catalog_id);
|
||||
|
||||
|
||||
|
||||
create table dc_questions (
|
||||
id number generated by default on null as identity
|
||||
constraint dc_questions_id_pk primary key,
|
||||
category_id number constraint dc_questions_category_id_fk
|
||||
references dc_question_categories,
|
||||
question_text clob not null,
|
||||
evaluation_type varchar2(20 char),
|
||||
threshold number,
|
||||
result_handling varchar2(20 char),
|
||||
example_0_percent clob,
|
||||
example_100_percent clob,
|
||||
row_version integer not null,
|
||||
created date not null,
|
||||
created_by varchar2(255 char) not null,
|
||||
updated date not null,
|
||||
updated_by varchar2(255 char) not null
|
||||
);
|
||||
|
||||
-- table index
|
||||
create index dc_questions_i1 on dc_questions (category_id);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
create table dc_projects (
|
||||
id number generated by default on null as identity
|
||||
constraint dc_projects_id_pk primary key,
|
||||
catalog_id number constraint dc_projects_catalog_id_fk
|
||||
references dc_question_catalogs,
|
||||
created_by_user number constraint dc_projects_created_by_fk
|
||||
references dc_users,
|
||||
name varchar2(100 char) not null,
|
||||
description clob,
|
||||
status varchar2(20 char) constraint dc_projects_status_ck
|
||||
check (status in ('PENDING','IN_PROGRESS','COMPLETED')),
|
||||
progress number default on null 0,
|
||||
completed_at date,
|
||||
notification_email varchar2(100 char),
|
||||
row_version integer not null,
|
||||
created date not null,
|
||||
created_by varchar2(255 char) not null,
|
||||
updated date not null,
|
||||
updated_by varchar2(255 char) not null
|
||||
);
|
||||
|
||||
-- table index
|
||||
create index dc_projects_i1 on dc_projects (catalog_id);
|
||||
|
||||
create index dc_projects_i2 on dc_projects (created_by);
|
||||
|
||||
|
||||
|
||||
create table dc_project_documents (
|
||||
id number generated by default on null as identity
|
||||
constraint dc_project_documents_id_pk primary key,
|
||||
project_id number constraint dc_project_documents_project_id_fk
|
||||
references dc_projects,
|
||||
document_type_id number constraint dc_project_documents_doc_type_fk
|
||||
references dc_document_types,
|
||||
catalog_id number constraint dc_project_documents_catalog_id_fk
|
||||
references dc_question_catalogs,
|
||||
original_file blob,
|
||||
original_text clob,
|
||||
translated_text clob,
|
||||
filename varchar2(255 char) not null,
|
||||
mime_type varchar2(100 char),
|
||||
uploaded_at date default on null sysdate,
|
||||
row_version integer not null,
|
||||
created date not null,
|
||||
created_by varchar2(255 char) not null,
|
||||
updated date not null,
|
||||
updated_by varchar2(255 char) not null
|
||||
);
|
||||
|
||||
-- table index
|
||||
create index dc_project_documents_i1 on dc_project_documents (project_id);
|
||||
|
||||
|
||||
|
||||
create table dc_results (
|
||||
id number generated by default on null as identity
|
||||
constraint dc_results_id_pk primary key,
|
||||
project_id number constraint dc_results_project_id_fk
|
||||
references dc_projects,
|
||||
question_id number constraint dc_results_question_id_fk
|
||||
references dc_questions,
|
||||
doc_id number constraint dc_results_doc_id_fk
|
||||
references dc_project_documents,
|
||||
answer clob,
|
||||
score number,
|
||||
result_type varchar2(20 char) constraint dc_results_result_type_ck
|
||||
check (result_type in ('OK','UNKLAR','NOK')),
|
||||
deviation number default on null 0,
|
||||
warning number default on null 0,
|
||||
the_comment clob,
|
||||
evaluated_at date default on null sysdate,
|
||||
row_version integer not null,
|
||||
created date not null,
|
||||
created_by varchar2(255 char) not null,
|
||||
updated date not null,
|
||||
updated_by varchar2(255 char) not null
|
||||
);
|
||||
|
||||
-- table index
|
||||
create index dc_results_i1 on dc_results (project_id);
|
||||
|
||||
create index dc_results_i2 on dc_results (question_id);
|
||||
|
||||
create index dc_results_i3 on dc_results (doc_id);
|
||||
|
||||
|
||||
|
||||
-- triggers
|
||||
create or replace trigger dc_users_biu
|
||||
before insert or update
|
||||
on dc_users
|
||||
for each row
|
||||
begin
|
||||
if inserting then
|
||||
:new.row_version := 1;
|
||||
elsif updating then
|
||||
:new.row_version := NVL(:old.row_version, 0) + 1;
|
||||
end if;
|
||||
if inserting then
|
||||
:new.created := sysdate;
|
||||
:new.created_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end if;
|
||||
:new.updated := sysdate;
|
||||
:new.updated_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end dc_users_biu;
|
||||
/
|
||||
|
||||
|
||||
create or replace trigger dc_user_roles_biu
|
||||
before insert or update
|
||||
on dc_user_roles
|
||||
for each row
|
||||
begin
|
||||
if inserting then
|
||||
:new.row_version := 1;
|
||||
elsif updating then
|
||||
:new.row_version := NVL(:old.row_version, 0) + 1;
|
||||
end if;
|
||||
if inserting then
|
||||
:new.created := sysdate;
|
||||
:new.created_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end if;
|
||||
:new.updated := sysdate;
|
||||
:new.updated_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end dc_user_roles_biu;
|
||||
/
|
||||
|
||||
create or replace trigger dc_document_types_biu
|
||||
before insert or update
|
||||
on dc_document_types
|
||||
for each row
|
||||
begin
|
||||
if inserting then
|
||||
:new.row_version := 1;
|
||||
elsif updating then
|
||||
:new.row_version := NVL(:old.row_version, 0) + 1;
|
||||
end if;
|
||||
if inserting then
|
||||
:new.created := sysdate;
|
||||
:new.created_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end if;
|
||||
:new.updated := sysdate;
|
||||
:new.updated_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end dc_document_types_biu;
|
||||
/
|
||||
|
||||
create or replace trigger dc_question_catalogs_biu
|
||||
before insert or update
|
||||
on dc_question_catalogs
|
||||
for each row
|
||||
begin
|
||||
if inserting then
|
||||
:new.row_version := 1;
|
||||
elsif updating then
|
||||
:new.row_version := NVL(:old.row_version, 0) + 1;
|
||||
end if;
|
||||
if inserting then
|
||||
:new.created := sysdate;
|
||||
:new.created_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end if;
|
||||
:new.updated := sysdate;
|
||||
:new.updated_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end dc_question_catalogs_biu;
|
||||
/
|
||||
|
||||
|
||||
create or replace trigger dc_question_categories_biu
|
||||
before insert or update
|
||||
on dc_question_categories
|
||||
for each row
|
||||
begin
|
||||
if inserting then
|
||||
:new.row_version := 1;
|
||||
elsif updating then
|
||||
:new.row_version := NVL(:old.row_version, 0) + 1;
|
||||
end if;
|
||||
if inserting then
|
||||
:new.created := sysdate;
|
||||
:new.created_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end if;
|
||||
:new.updated := sysdate;
|
||||
:new.updated_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end dc_question_categories_biu;
|
||||
/
|
||||
|
||||
|
||||
create or replace trigger dc_questions_biu
|
||||
before insert or update
|
||||
on dc_questions
|
||||
for each row
|
||||
begin
|
||||
if inserting then
|
||||
:new.row_version := 1;
|
||||
elsif updating then
|
||||
:new.row_version := NVL(:old.row_version, 0) + 1;
|
||||
end if;
|
||||
if inserting then
|
||||
:new.created := sysdate;
|
||||
:new.created_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end if;
|
||||
:new.updated := sysdate;
|
||||
:new.updated_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end dc_questions_biu;
|
||||
/
|
||||
|
||||
|
||||
create or replace trigger dc_reference_documents_biu
|
||||
before insert or update
|
||||
on dc_reference_documents
|
||||
for each row
|
||||
begin
|
||||
if inserting then
|
||||
:new.row_version := 1;
|
||||
elsif updating then
|
||||
:new.row_version := NVL(:old.row_version, 0) + 1;
|
||||
end if;
|
||||
if inserting then
|
||||
:new.created := sysdate;
|
||||
:new.created_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end if;
|
||||
:new.updated := sysdate;
|
||||
:new.updated_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end dc_reference_documents_biu;
|
||||
/
|
||||
|
||||
|
||||
create or replace trigger dc_projects_biu
|
||||
before insert or update
|
||||
on dc_projects
|
||||
for each row
|
||||
begin
|
||||
if inserting then
|
||||
:new.row_version := 1;
|
||||
elsif updating then
|
||||
:new.row_version := NVL(:old.row_version, 0) + 1;
|
||||
end if;
|
||||
if inserting then
|
||||
:new.created := sysdate;
|
||||
:new.created_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end if;
|
||||
:new.updated := sysdate;
|
||||
:new.updated_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end dc_projects_biu;
|
||||
/
|
||||
|
||||
|
||||
create or replace trigger dc_project_documents_biu
|
||||
before insert or update
|
||||
on dc_project_documents
|
||||
for each row
|
||||
begin
|
||||
if inserting then
|
||||
:new.row_version := 1;
|
||||
elsif updating then
|
||||
:new.row_version := NVL(:old.row_version, 0) + 1;
|
||||
end if;
|
||||
if inserting then
|
||||
:new.created := sysdate;
|
||||
:new.created_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end if;
|
||||
:new.updated := sysdate;
|
||||
:new.updated_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end dc_project_documents_biu;
|
||||
/
|
||||
|
||||
|
||||
create or replace trigger dc_results_biu
|
||||
before insert or update
|
||||
on dc_results
|
||||
for each row
|
||||
begin
|
||||
if inserting then
|
||||
:new.row_version := 1;
|
||||
elsif updating then
|
||||
:new.row_version := NVL(:old.row_version, 0) + 1;
|
||||
end if;
|
||||
if inserting then
|
||||
:new.created := sysdate;
|
||||
:new.created_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end if;
|
||||
:new.updated := sysdate;
|
||||
:new.updated_by := coalesce(sys_context('APEX$SESSION','APP_USER'),user);
|
||||
end dc_results_biu;
|
||||
/
|
||||
|
||||
|
||||
-- Generated by Quick SQL 1.2.9 13.4.2026, 17:07:42
|
||||
|
||||
/*
|
||||
users
|
||||
id number generated by default on null as identity constraint users_id_pk primary key
|
||||
username vc50 /nn /unique
|
||||
email vc100 /nn /unique
|
||||
password_hash vc255
|
||||
role vc20
|
||||
is_active num /default 1
|
||||
created_at date /default sysdate
|
||||
updated_at date /default sysdate
|
||||
|
||||
user_roles
|
||||
id number generated by default on null as identity constraint user_roles_id_pk primary key
|
||||
role_name vc20 /nn /unique
|
||||
description clob
|
||||
|
||||
question_catalogs
|
||||
id number generated by default on null as identity constraint question_catalogs_id_pk primary key
|
||||
name vc100 /nn
|
||||
description clob
|
||||
created_by num /references users
|
||||
created_at date /default sysdate
|
||||
updated_at date /default sysdate
|
||||
|
||||
question_categories
|
||||
id number generated by default on null as identity constraint question_categories_id_pk primary key
|
||||
catalog_id num /references question_catalogs
|
||||
name vc100 /nn
|
||||
description clob
|
||||
|
||||
questions
|
||||
id number generated by default on null as identity constraint questions_id_pk primary key
|
||||
category_id num /references question_categories
|
||||
question_text clob /nn
|
||||
evaluation_type vc20
|
||||
threshold num
|
||||
result_handling vc20
|
||||
example_0_percent clob
|
||||
example_100_percent clob
|
||||
|
||||
reference_documents
|
||||
id number generated by default on null as identity constraint reference_documents_id_pk primary key
|
||||
name vc100 /nn
|
||||
description clob
|
||||
file_path vc500
|
||||
uploaded_by num /references users
|
||||
upload_date date /default sysdate
|
||||
mime_type vc100
|
||||
|
||||
projects
|
||||
id number generated by default on null as identity constraint projects_id_pk primary key
|
||||
name vc100 /nn
|
||||
description clob
|
||||
catalog_id num /references question_catalogs
|
||||
created_by num /references users
|
||||
created_at date /default sysdate
|
||||
status vc20 /check PENDING, IN_PROGRESS, COMPLETED
|
||||
progress num /default 0
|
||||
completed_at date
|
||||
notification_email vc100
|
||||
|
||||
project_documents
|
||||
id number generated by default on null as identity constraint project_documents_id_pk primary key
|
||||
project_id num /references projects
|
||||
original_file blob
|
||||
translated_file blob
|
||||
filename vc255 /nn
|
||||
mime_type vc100
|
||||
uploaded_at date /default sysdate
|
||||
|
||||
results
|
||||
id number generated by default on null as identity constraint results_id_pk primary key
|
||||
project_id num /references projects
|
||||
question_id num /references questions
|
||||
doc_id num /references project_documents
|
||||
answer clob
|
||||
score num
|
||||
result_type vc20 /check OK, UNKLAR, NOK
|
||||
deviation num /default 0
|
||||
warning num /default 0
|
||||
comment clob
|
||||
evaluated_at date /default sysdate
|
||||
|
||||
|
||||
|
||||
Non-default options:
|
||||
# settings = {"apex":"Y","auditcols":"Y","db":"23","drop":"Y","prefix":"Dc","pk":"IDENTITY","rowversion":"Y"}
|
||||
|
||||
*/
|
||||
498
Scripts/Fragenkatalog-AGB anlegen.sql
Normal file
498
Scripts/Fragenkatalog-AGB anlegen.sql
Normal file
@@ -0,0 +1,498 @@
|
||||
DECLARE
|
||||
-- IDs
|
||||
v_doc_type_id dc_document_types.id%TYPE;
|
||||
v_catalog_id dc_question_catalogs.id%TYPE;
|
||||
v_cat1_id dc_question_categories.id%TYPE;
|
||||
v_cat2_id dc_question_categories.id%TYPE;
|
||||
v_cat3_id dc_question_categories.id%TYPE;
|
||||
v_cat4_id dc_question_categories.id%TYPE;
|
||||
v_cat5_id dc_question_categories.id%TYPE;
|
||||
v_cat6_id dc_question_categories.id%TYPE;
|
||||
|
||||
BEGIN
|
||||
|
||||
-- ============================================================
|
||||
-- 1. DOKUMENTENTYP
|
||||
-- ============================================================
|
||||
INSERT INTO dc_document_types (
|
||||
name, description,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
'AGB',
|
||||
'Allgemeine Geschäftsbedingungen – vorformulierte Vertragsbedingungen gemäß §305 BGB',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
)
|
||||
RETURNING id INTO v_doc_type_id;
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 2. FRAGENKATALOG
|
||||
-- ============================================================
|
||||
INSERT INTO dc_question_catalogs (
|
||||
created_by_user, based_on_reference, document_type_id,
|
||||
name, description,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
NULL, NULL, v_doc_type_id,
|
||||
'AGB-Prüfkatalog (BGB §305–310)',
|
||||
'Prüfung von Allgemeinen Geschäftsbedingungen auf Konformität mit dem deutschen AGB-Recht. '
|
||||
|| 'Grundlage: §§305–310 BGB sowie aktuelle BGH-Rechtsprechung.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
)
|
||||
RETURNING id INTO v_catalog_id;
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 3. KATEGORIEN
|
||||
-- ============================================================
|
||||
INSERT INTO dc_question_categories (
|
||||
catalog_id, name, description,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_catalog_id,
|
||||
'Einbeziehung & Transparenz',
|
||||
'Prüfung ob die AGB wirksam einbezogen wurden und dem Transparenzgebot (§307 Abs. 1 S. 2 BGB) entsprechen.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
)
|
||||
RETURNING id INTO v_cat1_id;
|
||||
|
||||
INSERT INTO dc_question_categories (
|
||||
catalog_id, name, description,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_catalog_id,
|
||||
'Haftung & Gewährleistung',
|
||||
'Prüfung von Haftungsbeschränkungen und Gewährleistungsregelungen auf Zulässigkeit nach §309 Nr. 7/8 BGB.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
)
|
||||
RETURNING id INTO v_cat2_id;
|
||||
|
||||
INSERT INTO dc_question_categories (
|
||||
catalog_id, name, description,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_catalog_id,
|
||||
'Zahlungs- & Lieferbedingungen',
|
||||
'Prüfung von Zahlungsfristen, Verzugszinsen, Lieferfristen und Eigentumsvorbehalt.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
)
|
||||
RETURNING id INTO v_cat3_id;
|
||||
|
||||
INSERT INTO dc_question_categories (
|
||||
catalog_id, name, description,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_catalog_id,
|
||||
'Laufzeit & Kündigung',
|
||||
'Prüfung von Vertragslaufzeiten, Kündigungsfristen und automatischer Verlängerung gemäß §309 Nr. 9 BGB.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
)
|
||||
RETURNING id INTO v_cat4_id;
|
||||
|
||||
INSERT INTO dc_question_categories (
|
||||
catalog_id, name, description,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_catalog_id,
|
||||
'Datenschutz & Compliance',
|
||||
'Prüfung der Datenschutzklauseln auf Konformität mit DSGVO und BDSG.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
)
|
||||
RETURNING id INTO v_cat5_id;
|
||||
|
||||
INSERT INTO dc_question_categories (
|
||||
catalog_id, name, description,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_catalog_id,
|
||||
'Verbotene Klauseln §307–309 BGB',
|
||||
'Prüfung auf explizit verbotene oder unangemessen benachteiligende Klauseln.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
)
|
||||
RETURNING id INTO v_cat6_id;
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 4. FRAGEN
|
||||
-- ============================================================
|
||||
|
||||
------------------------------------------------------------
|
||||
-- KATEGORIE 1: Einbeziehung & Transparenz
|
||||
------------------------------------------------------------
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat1_id,
|
||||
'Wird dem Vertragspartner vor oder bei Vertragsschluss ausdrücklich auf die Geltung der AGB hingewiesen (§305 Abs. 2 Nr. 1 BGB)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'Kein Hinweis auf AGB vorhanden; AGB nur im Footer der Website verlinkt ohne ausdrücklichen Hinweis beim Vertragsschluss.',
|
||||
'AGB sind ausdrücklich im Vertragsangebot genannt, z. B.: „Es gelten unsere AGB in der jeweils gültigen Fassung, abrufbar unter [URL]."',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat1_id,
|
||||
'Wird dem Vertragspartner die zumutbare Möglichkeit verschafft, vom Inhalt der AGB Kenntnis zu nehmen (§305 Abs. 2 Nr. 2 BGB)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'AGB nur auf Anfrage erhältlich; kein direkter Link, kein Aushang, keine Übergabe.',
|
||||
'Vollständiger Text der AGB ist abrufbar unter einem direkt verlinkten URL oder wird als Anhang mitgesendet.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat1_id,
|
||||
'Sind alle Klauseln klar, verständlich und ohne Fachsprache formuliert (Transparenzgebot §307 Abs. 1 S. 2 BGB)?',
|
||||
'SCORE', 60, 'ABWEICHUNG',
|
||||
'Klauseln enthalten unverständliche Fachbegriffe ohne Erläuterung; Satzgefüge sind verschachtelt und mehrdeutig.',
|
||||
'Klauseln sind in einfacher Sprache formuliert, kurze Sätze, wichtige Begriffe werden erklärt.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat1_id,
|
||||
'Enthält das Dokument eine Versionsnummer oder ein Datum, das die aktuell gültige Fassung eindeutig kennzeichnet?',
|
||||
'SCORE', 70, 'HINWEIS',
|
||||
'Kein Datum, keine Versionsnummer vorhanden.',
|
||||
'Fußzeile enthält: „Stand: Januar 2025, Version 3.1"',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat1_id,
|
||||
'Wird geregelt, wie Änderungen der AGB dem Vertragspartner mitgeteilt werden und wann diese wirksam werden?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'Keine Regelung zu AGB-Änderungen; stillschweigende Zustimmung durch Weiterbenutzung des Dienstes wird unterstellt.',
|
||||
'Änderungen werden per E-Mail angekündigt mit einer Einspruchsfrist von mindestens 6 Wochen; Widerspruchsrecht ist ausdrücklich genannt.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
-- KATEGORIE 2: Haftung & Gewährleistung
|
||||
------------------------------------------------------------
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat2_id,
|
||||
'Wird die Haftung für Vorsatz und grobe Fahrlässigkeit vollständig ausgeschlossen (§309 Nr. 7a BGB – unzulässig)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Jegliche Haftung, einschließlich Vorsatz und grober Fahrlässigkeit, wird hiermit ausgeschlossen."',
|
||||
'Haftungsausschluss gilt nur für leichte Fahrlässigkeit; Vorsatz und grobe Fahrlässigkeit bleiben ausdrücklich unberührt.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat2_id,
|
||||
'Wird die Haftung für Körper- und Gesundheitsschäden ausgeschlossen (§309 Nr. 7b BGB – unzulässig)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Eine Haftung für Personen- und Sachschäden jeglicher Art ist ausgeschlossen."',
|
||||
'Haftung für Personenschäden ist explizit ausgenommen: „Die Haftungsbeschränkung gilt nicht für Schäden an Leben, Körper oder Gesundheit."',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat2_id,
|
||||
'Werden gesetzliche Gewährleistungsrechte des Käufers vollständig ausgeschlossen (§309 Nr. 8b BGB – unzulässig bei Neuwaren)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Gewährleistungsansprüche sind vollständig ausgeschlossen."',
|
||||
'Gewährleistungsfrist wird auf das gesetzliche Minimum (2 Jahre bei Neuwaren) gesetzt; vollständiger Ausschluss ist nicht vorhanden.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat2_id,
|
||||
'Wird die Haftung für die Verletzung wesentlicher Vertragspflichten (Kardinalpflichten) unangemessen eingeschränkt?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Jegliche Haftung des Anbieters ist auf 50 € begrenzt, unabhängig von der Art der Pflichtverletzung."',
|
||||
'Haftungsbegrenzung gilt nicht für die Verletzung wesentlicher Vertragspflichten; bei deren Verletzung haftet der Anbieter auf den typischerweise vorhersehbaren Schaden.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
-- KATEGORIE 3: Zahlungs- & Lieferbedingungen
|
||||
------------------------------------------------------------
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat3_id,
|
||||
'Sind die vereinbarten Zahlungsfristen klar und eindeutig definiert?',
|
||||
'SCORE', 60, 'HINWEIS',
|
||||
'Keine Angabe zur Zahlungsfrist; Fälligkeit unklar.',
|
||||
'Zahlung ist innerhalb von 14 Tagen nach Rechnungsstellung ohne Abzug fällig.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat3_id,
|
||||
'Werden unangemessen hohe Verzugszinsen oder Vertragsstrafen bei Zahlungsverzug festgelegt (§309 Nr. 6 BGB)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Bei Zahlungsverzug werden Zinsen in Höhe von 15 % p. a. sowie eine Bearbeitungsgebühr von 50 € pro Mahnung berechnet."',
|
||||
'Verzugszinsen entsprechen dem gesetzlichen Zinssatz (§288 BGB); keine unverhältnismäßigen Mahngebühren.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat3_id,
|
||||
'Sind Lieferfristen verbindlich oder werden nur unverbindliche Richtwerte ohne Konsequenzen bei Überschreitung angegeben?',
|
||||
'SCORE', 50, 'HINWEIS',
|
||||
'„Lieferzeiten sind unverbindlich; eine Überschreitung berechtigt nicht zur Stornierung."',
|
||||
'Lieferfristen sind verbindlich; bei Überschreitung um mehr als 14 Tage hat der Käufer ein Rücktrittsrecht.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat3_id,
|
||||
'Wird ein erweiterter Eigentumsvorbehalt vereinbart, der über die gelieferte Ware hinausgeht (z. B. Kontokorrentvorbehalt)?',
|
||||
'SCORE', 50, 'HINWEIS',
|
||||
'„Das Eigentum verbleibt beim Verkäufer bis zur vollständigen Bezahlung aller gegenwärtigen und zukünftigen Forderungen aus der Geschäftsbeziehung."',
|
||||
'Einfacher Eigentumsvorbehalt: Eigentum geht nach vollständiger Bezahlung des jeweiligen Kaufpreises über.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
-- KATEGORIE 4: Laufzeit & Kündigung
|
||||
------------------------------------------------------------
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat4_id,
|
||||
'Beträgt die Erstlaufzeit bei Dauerschuldverhältnissen mehr als zwei Jahre (§309 Nr. 9a BGB – unzulässig)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Der Vertrag hat eine Mindestlaufzeit von 36 Monaten."',
|
||||
'Mindestlaufzeit beträgt maximal 24 Monate.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat4_id,
|
||||
'Verlängert sich der Vertrag bei Nichtkündigung um mehr als ein Jahr automatisch (§309 Nr. 9b BGB – unzulässig)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Wird der Vertrag nicht 3 Monate vor Ablauf gekündigt, verlängert er sich automatisch um 24 Monate."',
|
||||
'Automatische Verlängerung beträgt maximal 12 Monate; Kündigungsfrist höchstens 3 Monate.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat4_id,
|
||||
'Beträgt die Kündigungsfrist für den Vertragspartner mehr als drei Monate (§309 Nr. 9c BGB – unzulässig)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Der Vertrag kann mit einer Frist von 6 Monaten zum Vertragsende gekündigt werden."',
|
||||
'Kündigungsfrist beträgt maximal 3 Monate zum Ende der Vertragslaufzeit.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat4_id,
|
||||
'Ist das Recht zur außerordentlichen Kündigung aus wichtigem Grund explizit oder durch Generalausschluss eingeschränkt?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Eine Kündigung ist ausschließlich zum regulären Vertragsende möglich."',
|
||||
'Das Recht zur fristlosen Kündigung aus wichtigem Grund gemäß §314 BGB bleibt ausdrücklich unberührt.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
-- KATEGORIE 5: Datenschutz & Compliance
|
||||
------------------------------------------------------------
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat5_id,
|
||||
'Wird eine Rechtsgrundlage für die Verarbeitung personenbezogener Daten gemäß Art. 6 DSGVO genannt?',
|
||||
'SCORE', 70, 'ABWEICHUNG',
|
||||
'Keine Angabe zur Rechtsgrundlage der Datenverarbeitung in den AGB.',
|
||||
'Datenverarbeitung erfolgt auf Grundlage von Art. 6 Abs. 1 lit. b DSGVO (Vertragserfüllung); weitere Grundlagen sind aufgeführt.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat5_id,
|
||||
'Wird der Verantwortliche gemäß Art. 4 Nr. 7 DSGVO mit vollständigen Kontaktdaten genannt?',
|
||||
'SCORE', 70, 'ABWEICHUNG',
|
||||
'Kein Verantwortlicher genannt; nur allgemeiner Firmenname ohne Adresse.',
|
||||
'Name, Anschrift, E-Mail und ggf. Datenschutzbeauftragter sind vollständig angegeben.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat5_id,
|
||||
'Werden die Betroffenenrechte (Auskunft, Löschung, Berichtigung, Widerspruch) gemäß Art. 15–21 DSGVO kommuniziert?',
|
||||
'SCORE', 60, 'ABWEICHUNG',
|
||||
'Kein Hinweis auf Betroffenenrechte.',
|
||||
'Alle Betroffenenrechte sind aufgeführt mit Hinweis auf den Kontaktweg zur Ausübung.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat5_id,
|
||||
'Wird eine Weitergabe von Daten an Dritte oder eine Übermittlung in Drittländer außerhalb der EU geregelt?',
|
||||
'SCORE', 60, 'HINWEIS',
|
||||
'Keine Regelung zur Datenweitergabe; Drittlandübermittlung unerwähnt.',
|
||||
'Datenweitergabe an Dritte ist aufgelistet; Drittlandübermittlung erfolgt nur auf Basis von Standardvertragsklauseln gemäß Art. 46 DSGVO.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
-- KATEGORIE 6: Verbotene Klauseln §307–309 BGB
|
||||
------------------------------------------------------------
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat6_id,
|
||||
'Enthält die AGB eine Klausel, die dem Verwender einseitig das Recht einräumt, vereinbarte Leistungen zu ändern (§308 Nr. 4 BGB)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Wir behalten uns vor, unsere Leistungen jederzeit und ohne Ankündigung zu ändern oder einzustellen."',
|
||||
'Leistungsänderungen sind nur aus sachlich gerechtfertigtem Grund zulässig; dem Kunden steht ein Sonderkündigungsrecht zu.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat6_id,
|
||||
'Wird dem Vertragspartner das Recht zur Aufrechnung mit unbestrittenen oder rechtskräftig festgestellten Forderungen entzogen (§309 Nr. 3 BGB)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Eine Aufrechnung gegen Forderungen des Anbieters ist ausgeschlossen."',
|
||||
'Aufrechnung ist zulässig mit unbestrittenen oder rechtskräftig festgestellten Gegenforderungen.',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat6_id,
|
||||
'Wird der Gerichtsstand ausschließlich auf den Sitz des Verwenders festgelegt, obwohl der Vertragspartner Verbraucher ist (§29c ZPO)?',
|
||||
'SCORE', 50, 'ABWEICHUNG',
|
||||
'„Ausschließlicher Gerichtsstand für alle Streitigkeiten ist München."',
|
||||
'Gerichtsstandvereinbarung gilt nur für Kaufleute; bei Verbrauchern gilt der gesetzliche Gerichtsstand (Wohnort des Verbrauchers).',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat6_id,
|
||||
'Wird die Anwendung deutschen Rechts ausdrücklich geregelt, und werden verbraucherschützende Vorschriften des Herkunftslandes des Kunden ausgehebelt?',
|
||||
'SCORE', 50, 'HINWEIS',
|
||||
'„Es gilt ausschließlich deutsches Recht unter vollständigem Ausschluss des UN-Kaufrechts sowie aller ausländischen Schutzvorschriften."',
|
||||
'Rechtswahl gilt für Kaufleute; Verbraucher genießen den Schutz der zwingenden Vorschriften ihres Heimatlandes (Art. 6 Rom-I-VO).',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
INSERT INTO dc_questions (
|
||||
category_id, question_text, evaluation_type, threshold, result_handling,
|
||||
example_0_percent, example_100_percent,
|
||||
row_version, created, created_by, updated, updated_by
|
||||
) VALUES (
|
||||
v_cat6_id,
|
||||
'Enthält die AGB eine salvatorische Klausel für den Fall der Unwirksamkeit einzelner Bestimmungen?',
|
||||
'SCORE', 70, 'HINWEIS',
|
||||
'Keine salvatorische Klausel vorhanden; Unwirksamkeit einzelner Klauseln könnte gesamte AGB gefährden.',
|
||||
'„Sollten einzelne Bestimmungen dieser AGB unwirksam sein, bleibt die Wirksamkeit der übrigen Bestimmungen unberührt."',
|
||||
1, SYSDATE, 'SYSTEM', SYSDATE, 'SYSTEM'
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
DBMS_OUTPUT.PUT_LINE('Erfolgreich angelegt:');
|
||||
DBMS_OUTPUT.PUT_LINE(' Dokumententyp-ID : ' || v_doc_type_id);
|
||||
DBMS_OUTPUT.PUT_LINE(' Katalog-ID : ' || v_catalog_id);
|
||||
DBMS_OUTPUT.PUT_LINE(' Kategorie 1 ID : ' || v_cat1_id || ' (Einbeziehung & Transparenz)');
|
||||
DBMS_OUTPUT.PUT_LINE(' Kategorie 2 ID : ' || v_cat2_id || ' (Haftung & Gewährleistung)');
|
||||
DBMS_OUTPUT.PUT_LINE(' Kategorie 3 ID : ' || v_cat3_id || ' (Zahlungs- & Lieferbedingungen)');
|
||||
DBMS_OUTPUT.PUT_LINE(' Kategorie 4 ID : ' || v_cat4_id || ' (Laufzeit & Kündigung)');
|
||||
DBMS_OUTPUT.PUT_LINE(' Kategorie 5 ID : ' || v_cat5_id || ' (Datenschutz & Compliance)');
|
||||
DBMS_OUTPUT.PUT_LINE(' Kategorie 6 ID : ' || v_cat6_id || ' (Verbotene Klauseln §307–309 BGB)');
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
ROLLBACK;
|
||||
DBMS_OUTPUT.PUT_LINE('FEHLER: ' || SQLERRM);
|
||||
RAISE;
|
||||
END;
|
||||
/
|
||||
737
Scripts/ORDS REST Services.sql
Normal file
737
Scripts/ORDS REST Services.sql
Normal file
@@ -0,0 +1,737 @@
|
||||
-- =============================================================================
|
||||
-- ORDS REST Services: Dokumenten-Check
|
||||
-- Modul: frigosped.dc
|
||||
-- Base-Path: /api/dc/
|
||||
-- =============================================================================
|
||||
-- Voraussetzungen:
|
||||
-- - Oracle Database 23c mit installiertem ORDS (>= 23.x)
|
||||
-- - Script wird als Schema-Owner ausgeführt (hat ORDS_METADATA-Rolle)
|
||||
-- - Datenbankschema bereits angelegt via "Datenmodell DocumentCheck.sql"
|
||||
--
|
||||
-- Deployment:
|
||||
-- sqlplus user/pass@db @"Scripts/ORDS REST Services.sql"
|
||||
--
|
||||
-- Das Skript ist idempotent: bestehende Modul-Definition wird gelöscht und
|
||||
-- neu erstellt. Bestehende Daten bleiben unberührt.
|
||||
--
|
||||
-- Endpunkt-Übersicht:
|
||||
-- 1. GET /api/dc/catalogs/ Alle Fragenkataloge
|
||||
-- 2. GET /api/dc/catalogs/:id/questions/ Fragen eines Katalogs (flach)
|
||||
-- 3. GET /api/dc/projects/:id Projektdetail
|
||||
-- 4. POST /api/dc/projects/:id/start → IN_PROGRESS
|
||||
-- 5. PUT /api/dc/projects/:id/progress Fortschritt aktualisieren
|
||||
-- 6. POST /api/dc/projects/:id/complete → COMPLETED
|
||||
-- 7. GET /api/dc/projects/:id/documents/ Dokument-Liste (kein BLOB)
|
||||
-- 8. GET /api/dc/documents/:id/file BLOB-Download
|
||||
-- 9. PUT /api/dc/documents/:id/texts OCR-Text + Übersetzung schreiben
|
||||
-- 10. POST /api/dc/projects/:id/results Prüfergebnis einfügen
|
||||
-- 11. DELETE /api/dc/projects/:id/results Alle Ergebnisse löschen
|
||||
-- =============================================================================
|
||||
|
||||
-- =============================================================================
|
||||
-- BLOCK 1: Modul, Templates und Handler
|
||||
-- =============================================================================
|
||||
BEGIN
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Idempotenz: Modul löschen falls vorhanden
|
||||
-- -------------------------------------------------------------------------
|
||||
BEGIN
|
||||
ORDS.DELETE_MODULE(p_module_name => 'frigosped.dc');
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN NULL;
|
||||
END;
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Modul definieren
|
||||
-- -------------------------------------------------------------------------
|
||||
ORDS.DEFINE_MODULE(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_base_path => '/api/dc/',
|
||||
p_items_per_page => 0, -- Pagination deaktiviert (Quarkus steuert selbst)
|
||||
p_status => 'PUBLISHED',
|
||||
p_comments => 'Dokumenten-Check Backend-API fuer den Quarkus-Verarbeitungsserver'
|
||||
);
|
||||
|
||||
|
||||
-- ===========================================================================
|
||||
-- TEMPLATE 1: catalogs/
|
||||
-- ===========================================================================
|
||||
ORDS.DEFINE_TEMPLATE(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'catalogs/',
|
||||
p_priority => 0,
|
||||
p_etag_type => 'HASH',
|
||||
p_comments => 'Alle Fragenkataloge mit Dokumenttyp-Name'
|
||||
);
|
||||
|
||||
-- 1. GET /api/dc/catalogs/
|
||||
ORDS.DEFINE_HANDLER(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'catalogs/',
|
||||
p_method => 'GET',
|
||||
p_source_type => ORDS.SOURCE_TYPE_COLLECTION_FEED,
|
||||
p_items_per_page => 0,
|
||||
p_comments => 'Gibt alle Kataloge mit Dokumenttyp-Name zurueck',
|
||||
p_source => q'[
|
||||
SELECT
|
||||
c.id,
|
||||
c.name,
|
||||
c.description,
|
||||
c.document_type_id,
|
||||
dt.name AS document_type_name,
|
||||
c.row_version,
|
||||
c.created,
|
||||
c.updated
|
||||
FROM dc_question_catalogs c
|
||||
JOIN dc_document_types dt ON dt.id = c.document_type_id
|
||||
ORDER BY c.name
|
||||
]'
|
||||
);
|
||||
|
||||
|
||||
-- ===========================================================================
|
||||
-- TEMPLATE 2: catalogs/:catalog_id/questions/
|
||||
-- ===========================================================================
|
||||
ORDS.DEFINE_TEMPLATE(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'catalogs/:catalog_id/questions/',
|
||||
p_priority => 0,
|
||||
p_etag_type => 'HASH',
|
||||
p_comments => 'Alle Fragen eines Katalogs (flach mit Kategorie-Info)'
|
||||
);
|
||||
|
||||
-- 2. GET /api/dc/catalogs/:catalog_id/questions/
|
||||
ORDS.DEFINE_HANDLER(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'catalogs/:catalog_id/questions/',
|
||||
p_method => 'GET',
|
||||
p_source_type => ORDS.SOURCE_TYPE_COLLECTION_FEED,
|
||||
p_items_per_page => 0,
|
||||
p_comments => 'Flacher Join: Kategorie + Frage-Spalten, nach Kategorie/ID sortiert',
|
||||
p_source => q'[
|
||||
SELECT
|
||||
q.id AS question_id,
|
||||
cat.id AS category_id,
|
||||
cat.name AS category_name,
|
||||
cat.description AS category_description,
|
||||
q.question_text,
|
||||
q.evaluation_type,
|
||||
q.threshold,
|
||||
q.result_handling,
|
||||
q.example_0_percent,
|
||||
q.example_100_percent,
|
||||
q.row_version
|
||||
FROM dc_questions q
|
||||
JOIN dc_question_categories cat ON cat.id = q.category_id
|
||||
WHERE cat.catalog_id = :catalog_id
|
||||
ORDER BY cat.name, q.id
|
||||
]'
|
||||
);
|
||||
|
||||
|
||||
-- ===========================================================================
|
||||
-- TEMPLATE 3: projects/:project_id (kein Trailing-Slash = Einzel-Ressource)
|
||||
-- ===========================================================================
|
||||
ORDS.DEFINE_TEMPLATE(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id',
|
||||
p_priority => 0,
|
||||
p_etag_type => 'HASH',
|
||||
p_comments => 'Einzelnes Projekt'
|
||||
);
|
||||
|
||||
-- 3. GET /api/dc/projects/:project_id
|
||||
ORDS.DEFINE_HANDLER(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id',
|
||||
p_method => 'GET',
|
||||
p_source_type => ORDS.SOURCE_TYPE_COLLECTION_ITEM,
|
||||
p_items_per_page => 1,
|
||||
p_comments => 'Projektdetail als einzelnes JSON-Objekt; 404 wenn nicht gefunden',
|
||||
p_source => q'[
|
||||
SELECT
|
||||
p.id,
|
||||
p.name,
|
||||
p.description,
|
||||
p.catalog_id,
|
||||
p.created_by_user,
|
||||
p.status,
|
||||
p.progress,
|
||||
p.completed_at,
|
||||
p.notification_email,
|
||||
p.row_version,
|
||||
p.created,
|
||||
p.updated
|
||||
FROM dc_projects p
|
||||
WHERE p.id = :project_id
|
||||
]'
|
||||
);
|
||||
|
||||
|
||||
-- ===========================================================================
|
||||
-- TEMPLATE 4: projects/:project_id/start
|
||||
-- ===========================================================================
|
||||
ORDS.DEFINE_TEMPLATE(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id/start',
|
||||
p_priority => 0,
|
||||
p_comments => 'Projekt-Status auf IN_PROGRESS setzen'
|
||||
);
|
||||
|
||||
-- 4. POST /api/dc/projects/:project_id/start
|
||||
ORDS.DEFINE_HANDLER(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id/start',
|
||||
p_method => 'POST',
|
||||
p_source_type => ORDS.SOURCE_TYPE_PLSQL,
|
||||
p_comments => '200 OK; 409 wenn Status nicht PENDING; 404 wenn Projekt fehlt',
|
||||
p_source => q'[
|
||||
DECLARE
|
||||
v_status dc_projects.status%TYPE;
|
||||
BEGIN
|
||||
SELECT status
|
||||
INTO v_status
|
||||
FROM dc_projects
|
||||
WHERE id = :project_id
|
||||
FOR UPDATE NOWAIT;
|
||||
|
||||
IF v_status != 'PENDING' THEN
|
||||
:status_code := 409;
|
||||
HTP.P('{"error":"Projekt ist nicht im Status PENDING",'
|
||||
|| '"current_status":"' || v_status || '"}');
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
UPDATE dc_projects
|
||||
SET status = 'IN_PROGRESS',
|
||||
progress = 0
|
||||
WHERE id = :project_id;
|
||||
|
||||
:status_code := 200;
|
||||
HTP.P('{"project_id":' || :project_id
|
||||
|| ',"status":"IN_PROGRESS"}');
|
||||
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
:status_code := 404;
|
||||
HTP.P('{"error":"Projekt nicht gefunden","project_id":' || :project_id || '}');
|
||||
WHEN OTHERS THEN
|
||||
ROLLBACK;
|
||||
:status_code := 500;
|
||||
HTP.P('{"error":"' || REPLACE(SQLERRM, '"', '''') || '"}');
|
||||
END;
|
||||
]'
|
||||
);
|
||||
|
||||
|
||||
-- ===========================================================================
|
||||
-- TEMPLATE 5: projects/:project_id/progress
|
||||
-- ===========================================================================
|
||||
ORDS.DEFINE_TEMPLATE(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id/progress',
|
||||
p_priority => 0,
|
||||
p_comments => 'Verarbeitungsfortschritt aktualisieren'
|
||||
);
|
||||
|
||||
-- 5. PUT /api/dc/projects/:project_id/progress
|
||||
-- Body: {"progress": 45}
|
||||
ORDS.DEFINE_HANDLER(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id/progress',
|
||||
p_method => 'PUT',
|
||||
p_source_type => ORDS.SOURCE_TYPE_PLSQL,
|
||||
p_comments => 'Setzt progress (0-100); 400 bei ungueltigem Wert',
|
||||
p_source => q'[
|
||||
DECLARE
|
||||
v_progress NUMBER;
|
||||
v_body CLOB;
|
||||
BEGIN
|
||||
v_body := :body_text;
|
||||
v_progress := TO_NUMBER(JSON_VALUE(v_body, '$.progress'));
|
||||
|
||||
IF v_progress IS NULL OR v_progress < 0 OR v_progress > 100 THEN
|
||||
:status_code := 400;
|
||||
HTP.P('{"error":"progress muss eine Zahl zwischen 0 und 100 sein"}');
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
UPDATE dc_projects
|
||||
SET progress = v_progress
|
||||
WHERE id = :project_id;
|
||||
|
||||
IF SQL%ROWCOUNT = 0 THEN
|
||||
:status_code := 404;
|
||||
HTP.P('{"error":"Projekt nicht gefunden","project_id":' || :project_id || '}');
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
:status_code := 200;
|
||||
HTP.P('{"project_id":' || :project_id
|
||||
|| ',"progress":' || v_progress || '}');
|
||||
|
||||
EXCEPTION
|
||||
WHEN VALUE_ERROR THEN
|
||||
:status_code := 400;
|
||||
HTP.P('{"error":"progress muss eine gueltige Zahl sein"}');
|
||||
WHEN OTHERS THEN
|
||||
ROLLBACK;
|
||||
:status_code := 500;
|
||||
HTP.P('{"error":"' || REPLACE(SQLERRM, '"', '''') || '"}');
|
||||
END;
|
||||
]'
|
||||
);
|
||||
|
||||
|
||||
-- ===========================================================================
|
||||
-- TEMPLATE 6: projects/:project_id/complete
|
||||
-- ===========================================================================
|
||||
ORDS.DEFINE_TEMPLATE(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id/complete',
|
||||
p_priority => 0,
|
||||
p_comments => 'Projekt auf COMPLETED setzen'
|
||||
);
|
||||
|
||||
-- 6. POST /api/dc/projects/:project_id/complete
|
||||
ORDS.DEFINE_HANDLER(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id/complete',
|
||||
p_method => 'POST',
|
||||
p_source_type => ORDS.SOURCE_TYPE_PLSQL,
|
||||
p_comments => 'Setzt status=COMPLETED, completed_at=SYSDATE, progress=100',
|
||||
p_source => q'[
|
||||
DECLARE
|
||||
v_status dc_projects.status%TYPE;
|
||||
v_now DATE := SYSDATE;
|
||||
BEGIN
|
||||
SELECT status
|
||||
INTO v_status
|
||||
FROM dc_projects
|
||||
WHERE id = :project_id
|
||||
FOR UPDATE NOWAIT;
|
||||
|
||||
IF v_status = 'COMPLETED' THEN
|
||||
:status_code := 409;
|
||||
HTP.P('{"error":"Projekt ist bereits COMPLETED","project_id":' || :project_id || '}');
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
UPDATE dc_projects
|
||||
SET status = 'COMPLETED',
|
||||
completed_at = v_now,
|
||||
progress = 100
|
||||
WHERE id = :project_id;
|
||||
|
||||
:status_code := 200;
|
||||
HTP.P('{"project_id":' || :project_id
|
||||
|| ',"status":"COMPLETED"'
|
||||
|| ',"completed_at":"' || TO_CHAR(v_now, 'YYYY-MM-DD"T"HH24:MI:SS') || '"'
|
||||
|| '}');
|
||||
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
:status_code := 404;
|
||||
HTP.P('{"error":"Projekt nicht gefunden","project_id":' || :project_id || '}');
|
||||
WHEN OTHERS THEN
|
||||
ROLLBACK;
|
||||
:status_code := 500;
|
||||
HTP.P('{"error":"' || REPLACE(SQLERRM, '"', '''') || '"}');
|
||||
END;
|
||||
]'
|
||||
);
|
||||
|
||||
|
||||
-- ===========================================================================
|
||||
-- TEMPLATE 7: projects/:project_id/documents/
|
||||
-- ===========================================================================
|
||||
ORDS.DEFINE_TEMPLATE(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id/documents/',
|
||||
p_priority => 0,
|
||||
p_etag_type => 'HASH',
|
||||
p_comments => 'Dokument-Liste eines Projekts (ohne BLOB-Payload)'
|
||||
);
|
||||
|
||||
-- 7. GET /api/dc/projects/:project_id/documents/
|
||||
ORDS.DEFINE_HANDLER(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id/documents/',
|
||||
p_method => 'GET',
|
||||
p_source_type => ORDS.SOURCE_TYPE_COLLECTION_FEED,
|
||||
p_items_per_page => 0,
|
||||
p_comments => 'Metadaten aller Dokumente; has_original_text/has_translated_text als 0/1',
|
||||
p_source => q'[
|
||||
SELECT
|
||||
d.id,
|
||||
d.filename,
|
||||
d.mime_type,
|
||||
d.document_type_id,
|
||||
d.catalog_id,
|
||||
d.uploaded_at,
|
||||
CASE WHEN d.original_text IS NOT NULL THEN 1 ELSE 0 END AS has_original_text,
|
||||
CASE WHEN d.translated_text IS NOT NULL THEN 1 ELSE 0 END AS has_translated_text,
|
||||
d.row_version,
|
||||
d.created,
|
||||
d.updated
|
||||
FROM dc_project_documents d
|
||||
WHERE d.project_id = :project_id
|
||||
ORDER BY d.uploaded_at
|
||||
]'
|
||||
);
|
||||
|
||||
|
||||
-- ===========================================================================
|
||||
-- TEMPLATE 8: documents/:doc_id/file
|
||||
-- ===========================================================================
|
||||
ORDS.DEFINE_TEMPLATE(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'documents/:doc_id/file',
|
||||
p_priority => 0,
|
||||
p_comments => 'BLOB-Download: original_file mit korrektem Content-Type'
|
||||
);
|
||||
|
||||
-- 8. GET /api/dc/documents/:doc_id/file
|
||||
-- SOURCE_TYPE_MEDIA: Pflicht-Aliase: content, content_type, filename
|
||||
ORDS.DEFINE_HANDLER(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'documents/:doc_id/file',
|
||||
p_method => 'GET',
|
||||
p_source_type => ORDS.SOURCE_TYPE_MEDIA,
|
||||
p_comments => 'Streamt original_file BLOB; ORDS setzt Content-Type aus mime_type-Spalte',
|
||||
p_source => q'[
|
||||
SELECT
|
||||
d.original_file AS content,
|
||||
d.mime_type AS content_type,
|
||||
d.filename AS filename,
|
||||
d.updated AS last_modified
|
||||
FROM dc_project_documents d
|
||||
WHERE d.id = :doc_id
|
||||
]'
|
||||
);
|
||||
|
||||
|
||||
-- ===========================================================================
|
||||
-- TEMPLATE 9: documents/:doc_id/texts
|
||||
-- ===========================================================================
|
||||
ORDS.DEFINE_TEMPLATE(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'documents/:doc_id/texts',
|
||||
p_priority => 0,
|
||||
p_comments => 'OCR-Ergebnis und Uebersetzung zurueckschreiben'
|
||||
);
|
||||
|
||||
-- 9. PUT /api/dc/documents/:doc_id/texts
|
||||
-- Body: {"original_text": "## ...", "translated_text": "## ..."}
|
||||
-- Beide Felder sind optional: NULL-Wert ueberschreibt nicht (nur wenn im Body vorhanden)
|
||||
ORDS.DEFINE_HANDLER(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'documents/:doc_id/texts',
|
||||
p_method => 'PUT',
|
||||
p_source_type => ORDS.SOURCE_TYPE_PLSQL,
|
||||
p_comments => 'Schreibt original_text und/oder translated_text als CLOB',
|
||||
p_source => q'[
|
||||
DECLARE
|
||||
v_body CLOB;
|
||||
v_original_text CLOB;
|
||||
v_translated CLOB;
|
||||
v_rows INTEGER;
|
||||
BEGIN
|
||||
v_body := :body_text;
|
||||
-- RETURNING CLOB erlaubt Werte groesser als 32767 Bytes (wichtig fuer OCR-Output)
|
||||
v_original_text := JSON_VALUE(v_body, '$.original_text' RETURNING CLOB);
|
||||
v_translated := JSON_VALUE(v_body, '$.translated_text' RETURNING CLOB);
|
||||
|
||||
UPDATE dc_project_documents
|
||||
SET original_text = CASE
|
||||
WHEN JSON_EXISTS(v_body, '$.original_text')
|
||||
THEN v_original_text
|
||||
ELSE original_text
|
||||
END,
|
||||
translated_text = CASE
|
||||
WHEN JSON_EXISTS(v_body, '$.translated_text')
|
||||
THEN v_translated
|
||||
ELSE translated_text
|
||||
END
|
||||
WHERE id = :doc_id;
|
||||
|
||||
v_rows := SQL%ROWCOUNT;
|
||||
IF v_rows = 0 THEN
|
||||
:status_code := 404;
|
||||
HTP.P('{"error":"Dokument nicht gefunden","doc_id":' || :doc_id || '}');
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
:status_code := 200;
|
||||
HTP.P('{"doc_id":' || :doc_id || ',"updated":true}');
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
ROLLBACK;
|
||||
:status_code := 500;
|
||||
HTP.P('{"error":"' || REPLACE(SQLERRM, '"', '''') || '"}');
|
||||
END;
|
||||
]'
|
||||
);
|
||||
|
||||
|
||||
-- ===========================================================================
|
||||
-- TEMPLATE 10+11: projects/:project_id/results
|
||||
-- (POST = Einfuegen, DELETE = Alle loeschen)
|
||||
-- ===========================================================================
|
||||
ORDS.DEFINE_TEMPLATE(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id/results',
|
||||
p_priority => 0,
|
||||
p_comments => 'Prüfergebnisse: POST einfuegen, DELETE alle loeschen'
|
||||
);
|
||||
|
||||
-- 10. POST /api/dc/projects/:project_id/results
|
||||
-- Body: {
|
||||
-- "question_id": 5,
|
||||
-- "doc_id": 101,
|
||||
-- "answer": "Ja, §305 BGB ist erfuellt.",
|
||||
-- "score": 85,
|
||||
-- "result_type": "OK",
|
||||
-- "deviation": 0,
|
||||
-- "warning": 0,
|
||||
-- "the_comment": "Klare Einbeziehungsklausel vorhanden"
|
||||
-- }
|
||||
ORDS.DEFINE_HANDLER(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id/results',
|
||||
p_method => 'POST',
|
||||
p_source_type => ORDS.SOURCE_TYPE_PLSQL,
|
||||
p_comments => '201 Created mit Location-Header; 400 bei fehlendem question_id/doc_id/result_type',
|
||||
p_source => q'[
|
||||
DECLARE
|
||||
v_body CLOB;
|
||||
v_question_id NUMBER;
|
||||
v_doc_id NUMBER;
|
||||
v_answer CLOB;
|
||||
v_score NUMBER;
|
||||
v_result_type VARCHAR2(20);
|
||||
v_deviation NUMBER;
|
||||
v_warning NUMBER;
|
||||
v_comment CLOB;
|
||||
v_new_id NUMBER;
|
||||
BEGIN
|
||||
v_body := :body_text;
|
||||
v_question_id := TO_NUMBER(JSON_VALUE(v_body, '$.question_id'));
|
||||
v_doc_id := TO_NUMBER(JSON_VALUE(v_body, '$.doc_id'));
|
||||
v_answer := JSON_VALUE(v_body, '$.answer' RETURNING CLOB);
|
||||
v_score := TO_NUMBER(JSON_VALUE(v_body, '$.score'));
|
||||
v_result_type := JSON_VALUE(v_body, '$.result_type');
|
||||
v_deviation := NVL(TO_NUMBER(JSON_VALUE(v_body, '$.deviation')), 0);
|
||||
v_warning := NVL(TO_NUMBER(JSON_VALUE(v_body, '$.warning')), 0);
|
||||
v_comment := JSON_VALUE(v_body, '$.the_comment' RETURNING CLOB);
|
||||
|
||||
-- Pflichtfelder prüfen
|
||||
IF v_question_id IS NULL OR v_doc_id IS NULL THEN
|
||||
:status_code := 400;
|
||||
HTP.P('{"error":"question_id und doc_id sind Pflichtfelder"}');
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
IF v_result_type NOT IN ('OK', 'UNKLAR', 'NOK') THEN
|
||||
:status_code := 400;
|
||||
HTP.P('{"error":"result_type muss OK, UNKLAR oder NOK sein",'
|
||||
|| '"received":"' || NVL(v_result_type, 'NULL') || '"}');
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
INSERT INTO dc_results (
|
||||
project_id,
|
||||
question_id,
|
||||
doc_id,
|
||||
answer,
|
||||
score,
|
||||
result_type,
|
||||
deviation,
|
||||
warning,
|
||||
the_comment,
|
||||
evaluated_at
|
||||
) VALUES (
|
||||
:project_id,
|
||||
v_question_id,
|
||||
v_doc_id,
|
||||
v_answer,
|
||||
v_score,
|
||||
v_result_type,
|
||||
v_deviation,
|
||||
v_warning,
|
||||
v_comment,
|
||||
SYSDATE
|
||||
)
|
||||
RETURNING id INTO v_new_id;
|
||||
|
||||
-- Location-Header gemaess REST-Konvention
|
||||
ORDS.SET_RESPONSE_HEADER(
|
||||
'Location',
|
||||
'/api/dc/projects/' || :project_id || '/results/' || v_new_id
|
||||
);
|
||||
|
||||
:status_code := 201;
|
||||
HTP.P('{"id":' || v_new_id
|
||||
|| ',"project_id":' || :project_id
|
||||
|| ',"question_id":' || v_question_id
|
||||
|| ',"doc_id":' || v_doc_id
|
||||
|| ',"result_type":"' || v_result_type || '"'
|
||||
|| ',"score":' || NVL(TO_CHAR(v_score), 'null')
|
||||
|| '}');
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
ROLLBACK;
|
||||
:status_code := 500;
|
||||
HTP.P('{"error":"' || REPLACE(SQLERRM, '"', '''') || '"}');
|
||||
END;
|
||||
]'
|
||||
);
|
||||
|
||||
-- 11. DELETE /api/dc/projects/:project_id/results
|
||||
ORDS.DEFINE_HANDLER(
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_pattern => 'projects/:project_id/results',
|
||||
p_method => 'DELETE',
|
||||
p_source_type => ORDS.SOURCE_TYPE_PLSQL,
|
||||
p_comments => 'Loescht alle Ergebnisse eines Projekts (fuer Re-Processing)',
|
||||
p_source => q'[
|
||||
DECLARE
|
||||
v_deleted INTEGER;
|
||||
BEGIN
|
||||
DELETE FROM dc_results
|
||||
WHERE project_id = :project_id;
|
||||
|
||||
v_deleted := SQL%ROWCOUNT;
|
||||
|
||||
:status_code := 200;
|
||||
HTP.P('{"project_id":' || :project_id
|
||||
|| ',"deleted_count":' || v_deleted || '}');
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
ROLLBACK;
|
||||
:status_code := 500;
|
||||
HTP.P('{"error":"' || REPLACE(SQLERRM, '"', '''') || '"}');
|
||||
END;
|
||||
]'
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
END;
|
||||
/
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- BLOCK 2: Auth / Privilege (fuer Produktion)
|
||||
-- =============================================================================
|
||||
-- In der Entwicklung kann dieser Block auskommentiert bleiben – das Modul
|
||||
-- ist dann ohne Auth-Pruefung erreichbar (STATUS = PUBLISHED genuegt).
|
||||
--
|
||||
-- Fuer Produktion einkommentieren und danach den OAuth2-Client anlegen:
|
||||
--
|
||||
-- SELECT client_id, client_secret
|
||||
-- FROM user_ords_clients
|
||||
-- WHERE name = 'quarkus_dc_backend';
|
||||
--
|
||||
-- Den client_id/client_secret in die Quarkus application.properties eintragen.
|
||||
-- =============================================================================
|
||||
/*
|
||||
BEGIN
|
||||
-- Rolle anlegen (falls noch nicht vorhanden)
|
||||
BEGIN
|
||||
ORDS.CREATE_ROLE(p_role_name => 'dc_api_user');
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN NULL;
|
||||
END;
|
||||
|
||||
-- Privilege loeschen falls vorhanden
|
||||
BEGIN
|
||||
ORDS.DROP_PRIVILEGE(p_name => 'dc.api.privilege');
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN NULL;
|
||||
END;
|
||||
|
||||
-- Privilege definieren: mappt Rolle auf alle /api/dc/-Endpunkte
|
||||
ORDS.DEFINE_PRIVILEGE(
|
||||
p_privilege_name => 'dc.api.privilege',
|
||||
p_roles => ORDS_TYPES.T_ORDS_VARCHARS('dc_api_user'),
|
||||
p_patterns => ORDS_TYPES.T_ORDS_VARCHARS('/api/dc/*'),
|
||||
p_module_name => 'frigosped.dc',
|
||||
p_label => 'Dokumenten-Check API',
|
||||
p_description => 'Zugriff auf alle /api/dc/-Endpunkte',
|
||||
p_comments => 'Wird dem OAuth2-Client quarkus_dc_backend zugewiesen'
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
END;
|
||||
/
|
||||
|
||||
-- OAuth2-Client fuer den Quarkus-Server (einmalig ausfuehren)
|
||||
BEGIN
|
||||
OAUTH.CREATE_CLIENT(
|
||||
p_name => 'quarkus_dc_backend',
|
||||
p_grant_type => 'CLIENT_CREDENTIALS',
|
||||
p_owner => 'Frigosped',
|
||||
p_description => 'Quarkus-Verarbeitungsserver Service-Account',
|
||||
p_redirect_uri => NULL,
|
||||
p_support_email => 'admin@frigosped.de',
|
||||
p_privilege_names => 'dc.api.privilege'
|
||||
);
|
||||
COMMIT;
|
||||
END;
|
||||
/
|
||||
*/
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- Test-Aufrufe (curl)
|
||||
-- =============================================================================
|
||||
-- Ersetze <BASE> und <SCHEMA> mit deinen ORDS-Werten, z.B.:
|
||||
-- BASE="https://apex.example.com/ords/FRIGOSPED_APP"
|
||||
--
|
||||
-- Ohne Auth (Entwicklung):
|
||||
--
|
||||
-- # 1. Alle Kataloge
|
||||
-- curl -sS "$BASE/api/dc/catalogs/" | jq .
|
||||
--
|
||||
-- # 2. Fragen fuer Katalog 1
|
||||
-- curl -sS "$BASE/api/dc/catalogs/1/questions/" | jq .
|
||||
--
|
||||
-- # 3. Projektdetail
|
||||
-- curl -sS "$BASE/api/dc/projects/42" | jq .
|
||||
--
|
||||
-- # 4. Projekt starten
|
||||
-- curl -sS -X POST "$BASE/api/dc/projects/42/start" | jq .
|
||||
--
|
||||
-- # 5. Fortschritt setzen
|
||||
-- curl -sS -X PUT -H "Content-Type: application/json" \
|
||||
-- -d '{"progress":35}' "$BASE/api/dc/projects/42/progress" | jq .
|
||||
--
|
||||
-- # 6. Projekt abschliessen
|
||||
-- curl -sS -X POST "$BASE/api/dc/projects/42/complete" | jq .
|
||||
--
|
||||
-- # 7. Dokumente auflisten
|
||||
-- curl -sS "$BASE/api/dc/projects/42/documents/" | jq .
|
||||
--
|
||||
-- # 8. Datei herunterladen
|
||||
-- curl -sS -o original.pdf "$BASE/api/dc/documents/101/file"
|
||||
--
|
||||
-- # 9. OCR-Text + Uebersetzung zurueckschreiben
|
||||
-- curl -sS -X PUT -H "Content-Type: application/json" \
|
||||
-- -d '{"original_text":"## Vertrag\n\nAbsatz 1...",
|
||||
-- "translated_text":"## Vertrag (DE)\n\nAbsatz 1..."}' \
|
||||
-- "$BASE/api/dc/documents/101/texts" | jq .
|
||||
--
|
||||
-- # 10. Ergebnis einfuegen
|
||||
-- curl -sS -X POST -H "Content-Type: application/json" \
|
||||
-- -d '{"question_id":5,"doc_id":101,"answer":"Ja, §305 erfuellt.",
|
||||
-- "score":85,"result_type":"OK","deviation":0,"warning":0,
|
||||
-- "the_comment":"Klare Einbeziehungsklausel vorhanden"}' \
|
||||
-- "$BASE/api/dc/projects/42/results" | jq .
|
||||
--
|
||||
-- # 11. Alle Ergebnisse loeschen (Re-Processing)
|
||||
-- curl -sS -X DELETE "$BASE/api/dc/projects/42/results" | jq .
|
||||
-- =============================================================================
|
||||
Reference in New Issue
Block a user