feat: Externe Dokument-Referenzen erkennen, herunterladen & mitbewerten

Nach der Transkription eines Dokuments werden referenzierte externe
Dokumente (AGB, Verhaltenskodex) erkannt, sicher heruntergeladen und ihr
Text dem Hauptdokument fuer die "Summen"-Bewertung angehaengt (Option D).
Die Referenzen werden zusaetzlich als eigene, herunterladbare Zeilen
gespeichert.

- DB: dc_project_documents um parent_document_id, is_reference, source_url
  erweitert (DC_REFERENCES_ALTER.sql)
- ORDS: Dokumentenliste um die Felder erweitert; neue Endpunkte
  POST /documents/:id/references und DELETE /projects/:id/references;
  q-Quote-Parserfehler im ai-costs-Handler ('[]') behoben
- Backend: ReferenceDownloadService (SSRF-sicher via DNS-/Public-IP-
  Validierung, Redirect-Pruefung, Groessen-/Timeout-Limits, jsoup fuer HTML),
  EvaluationService.extractReferenceUrls (LLM-basierte URL-Erkennung),
  Orchestrierung (Discovery in Phase A, Referenz-Skip + combinedText in Phase B)
- Config: dc.references.* in application.properties

Verifiziert an Projekt 144: AGB-PDF/-HTML heruntergeladen, verknuepft,
"Summen"-Bewertung zitiert AGB-Klauseln aus dem Referenzdokument.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 12:45:55 +02:00
parent d00525c15f
commit c75f460ec5
91 changed files with 3949 additions and 255 deletions

View File

@@ -52,12 +52,28 @@ CREATE OR REPLACE PACKAGE DC_BACKEND_PKG AS
-- -------------------------------------------------------------------------
FUNCTION health_check RETURN BOOLEAN;
-- -------------------------------------------------------------------------
-- Setzt Projekt auf PENDING zurück eigene Transaktion (AUTONOMOUS COMMIT).
-- dc_projects.status → PENDING, report_markdown → NULL
-- dc_project_documents.original_text/translated_text → NULL, progress → 0
-- dc_results löschen
-- -------------------------------------------------------------------------
PROCEDURE reset_project(
p_project_id IN NUMBER
);
-- -------------------------------------------------------------------------
-- Startet die Prüfung und wirft eine Exception wenn nicht 202 zurückkommt.
-- Convenience-Wrapper für direkte APEX-Button-Aufrufe.
--
-- p_reset TRUE = Projekt vor dem Start zurücksetzen (eigener COMMIT):
-- dc_projects.status → PENDING, report_markdown → NULL
-- dc_project_documents.original_text/translated_text → NULL, progress → 0
-- dc_results löschen
-- -------------------------------------------------------------------------
PROCEDURE start_check_or_raise(
p_project_id IN NUMBER
p_project_id IN NUMBER,
p_reset IN BOOLEAN DEFAULT FALSE
);
-- -------------------------------------------------------------------------
@@ -200,6 +216,31 @@ END DC_BACKEND_PKG;
-- =============================================================================
CREATE OR REPLACE PACKAGE BODY DC_BACKEND_PKG AS
-- -------------------------------------------------------------------------
-- Setzt Projekt auf PENDING zurück eigene Transaktion (AUTONOMOUS).
-- -------------------------------------------------------------------------
PROCEDURE reset_project(p_project_id IN NUMBER) IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE dc_projects
SET status = 'PENDING',
report_markdown = NULL
WHERE id = p_project_id;
UPDATE dc_project_documents
SET original_text = NULL,
translated_text = NULL,
progress = 0,
status = 'PENDING'
WHERE project_id = p_project_id;
DELETE FROM dc_results
WHERE project_id = p_project_id;
COMMIT;
END reset_project;
-- -------------------------------------------------------------------------
-- Setzt gemeinsame Request-Header (Content-Type + optional API-Key)
-- -------------------------------------------------------------------------
@@ -274,11 +315,16 @@ CREATE OR REPLACE PACKAGE BODY DC_BACKEND_PKG AS
-- -------------------------------------------------------------------------
PROCEDURE start_check_or_raise(
p_project_id IN NUMBER
p_project_id IN NUMBER,
p_reset IN BOOLEAN DEFAULT FALSE
) IS
l_status NUMBER;
l_response VARCHAR2(4000);
BEGIN
IF p_reset THEN
reset_project(p_project_id);
END IF;
start_check(
p_project_id => p_project_id,
p_status_code => l_status,