diff --git a/database/packages/pck_auto_import.pkb b/database/packages/pck_auto_import.pkb index 729ff6d..bfdcd87 100644 --- a/database/packages/pck_auto_import.pkb +++ b/database/packages/pck_auto_import.pkb @@ -24,10 +24,33 @@ create or replace package body pck_auto_import as l_log_action constant varchar2(512 char) := 'BA_KORRESPONDENZEN_DATEIEINGANG_AUTOMATION'; l_automaton_endpoint constant varchar2(256 char) := 'api/process-incoming-ba-korrespondenz'; begin - -- Schritt 1: Offene Batches in OCI verarbeiten + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Automation gestartet' + ); + + -- Offene Batches in OCI verarbeiten + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Verarbeitung offener OCI-Batches gestartet' + ); + p_process_incoming_ba_data; - -- Schritt 2: Quarkus anstoßen — Fehler werden geloggt, nicht eskaliert + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Verarbeitung offener OCI-Batches abgeschlossen' + ); + + -- Quarkus anstoßen — Fehler werden geloggt, nicht eskaliert + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Quarkus Dateieingang Service wird angestoßen' + ); begin l_service_url := pck_system.f_get_par_wert_by_programmid('AUTOMATON_BASE_URL') || l_automaton_endpoint; l_api_key := pck_system.f_get_par_wert_by_programmid('AUTOMATON_API_KEY'); @@ -48,7 +71,7 @@ create or replace package body pck_auto_import as pck_log.p_info( i_module => c_log_module ,i_action => l_log_action - ,i_message => 'Dateieingang Service angestoßen (202 Accepted)' + ,i_message => 'BA Dateieingang Service angestoßen (202 Accepted)' ); when 409 then @@ -56,24 +79,25 @@ create or replace package body pck_auto_import as pck_log.p_info( i_module => c_log_module ,i_action => l_log_action - ,i_message => 'Dateieingang Service läuft bereits (409 Conflict) — kein neuer Lauf gestartet' + ,i_message => 'BA Dateieingang Service läuft bereits (409 Conflict) — kein neuer Lauf gestartet' ); else - pck_log.p_warn( + pck_log.p_error( i_module => c_log_module ,i_action => l_log_action - ,i_message => 'Dateieingang Service: unerwarteter HTTP-Status ' || l_http_status + ,i_message => 'Fehler in BA Dateieingang Service: unerwarteter HTTP-Status ' || l_http_status + ,i_detail => l_response ); end case; exception when others then -- Quarkus-Aufruf fehlgeschlagen: loggen, nicht eskalieren. - -- Nächster Stundenlauf führt Schritt 1 erneut aus. + -- Nächster Stundenlauf führt BA-Import-Schritt erneut aus. pck_log.p_error( i_module => c_log_module ,i_action => l_log_action - ,i_message => 'Aufruf des Dateieingang Service fehlgeschlagen: ' || sqlerrm + ,i_message => 'Aufruf des BA Dateieingang Service fehlgeschlagen: ' || sqlerrm ,i_detail => to_clob(dbms_utility.format_error_backtrace) ); end; @@ -111,6 +135,13 @@ create or replace package body pck_auto_import as l_filename := substr(i_object_key, instr(i_object_key, '/', -1) + 1); l_file_size := dbms_lob.getlength(i_content); + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Import gestartet: "' || l_filename || '" (' || l_file_size || ' Bytes)' + ,i_object_ref => i_object_key + ); + l_return := inkasso.pck_import.f_import_ba_dokument( i_datei => i_content ,i_dateiname => l_filename @@ -133,9 +164,23 @@ create or replace package body pck_auto_import as ,i_swv_mit_id_wsachbearbeiter => pck_system.f_get_par_wert_by_programmid('BA_IMPORT_SB_MIT_ID') ); + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Wiedervorlage angelegt.' + ,i_object_ref => i_object_key + ); + raise_application_error(-20000, 'Import fehlgeschlagen: "' || l_filename || '" (Rückgabe: ' || l_return || ')'); end if; + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Datei "' || l_filename || '" erfolgreich importiert.' + ,i_object_ref => i_object_key + ); + -- Datei in Verarbeitet-Ordner verschieben pck_net_storage.p_move_object( i_object_key => i_object_key @@ -179,9 +224,15 @@ create or replace package body pck_auto_import as l_has_remaining_files boolean; l_log_action varchar2(512 char) := 'IMPORT_BA_DATA'; begin + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Verarbeitung von eingehen BA Korrespondenzen gestartet' + ); + -- Zielordner Name zusammenstellen - l_target_prefix := pck_system.f_get_par_wert_by_programmid('NETSTORE_BA_PREFIX') || pck_system.f_get_par_wert_by_programmid('NETSTORE_BA_ARCHIV') || ' ' || to_char(sysdate, 'YYYY') || '/'; - l_eingang_prefix := pck_system.f_get_par_wert_by_programmid('NETSTORE_BA_PREFIX') || pck_system.f_get_par_wert_by_programmid('NETSTORE_BA_IMPORT'); + l_target_prefix := pck_system.f_get_par_wert_by_programmid('NETSTORE_TENANT_ID') || pck_system.f_get_par_wert_by_programmid('NETSTORE_BA_PREFIX') || pck_system.f_get_par_wert_by_programmid('NETSTORE_BA_ARCHIV') || ' ' || to_char(sysdate, 'YYYY') || '/'; + l_eingang_prefix := pck_system.f_get_par_wert_by_programmid('NETSTORE_TENANT_ID') || pck_system.f_get_par_wert_by_programmid('NETSTORE_BA_PREFIX') || pck_system.f_get_par_wert_by_programmid('NETSTORE_BA_IMPORT'); -- Unterordner in eingangs-ordner auflisten (es gibt einen Ordner für jeden entpackte ZIP-Datei) l_folders := pck_net_storage.f_list_objects( @@ -197,10 +248,24 @@ create or replace package body pck_auto_import as continue; end if; + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Datei-Ordner gefunden' + ,i_object_ref => rec_folder.object_key + ); + -- Der Marker ist eine Datei mit speziellem Namen, welche vom quarkus automaton in einen entpackten zip-ordner gelegt wird um zu signalisieren, dass alle Dateien des ZIPs erfolgreich in den ordner gelegt wurden. -- Das verhindert die verarbeitung von unvollständig entpackten zips l_db_processing_marker_key := rec_folder.object_key || pck_system.f_get_par_wert_by_programmid('NETSTORE_MARKER_DB'); + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Marker für Ordner wird geprüft. Marker: ' || l_db_processing_marker_key || ' in Ordner: ' || rec_folder.object_key + ,i_object_ref => rec_folder.object_key + ); + -- Marker prüfen: -20001 = nicht vorhanden → Upload noch nicht abgeschlossen begin l_meta := pck_net_storage.f_get_object_metadata(l_db_processing_marker_key); @@ -209,6 +274,12 @@ create or replace package body pck_auto_import as then if sqlcode = -20001 then + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Kein DB-Verarbeitungsmarker vorhanden — Batch wird übersprungen (Upload noch nicht abgeschlossen)' + ,i_object_ref => rec_folder.object_key + ); continue; end if; raise; @@ -222,6 +293,13 @@ create or replace package body pck_auto_import as ); l_target_folder := l_target_prefix || l_zip_name || '/'; + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Batch-Verarbeitung gestartet — Zielordner: "' || l_target_folder || '"' + ,i_object_ref => rec_folder.object_key + ); + -- Alle Dateien im Unterordner auflisten (inkl. Unterordner = alle Tiefen) l_files := pck_net_storage.f_list_objects( i_parent_folder => rec_folder.object_key @@ -237,6 +315,13 @@ create or replace package body pck_auto_import as end if; begin + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'BA-Datei wird verarbeitet' + ,i_object_ref => rec_file.object_key + ); + -- 1. Dateiinhalt laden l_file_content := pck_net_storage.f_download_object(rec_file.object_key); @@ -264,6 +349,13 @@ create or replace package body pck_auto_import as -- DB-Marker immer entfernen — verhindert erneute Verarbeitung beim nächsten Lauf pck_net_storage.p_delete_object(l_db_processing_marker_key); + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'DB-Verarbeitungsmarker gelöscht' + ,i_object_ref => l_db_processing_marker_key + ); + -- Prüfen ob noch Dateien im Unterordner liegen (nicht erfolgreich importierte Dateien) l_files := pck_net_storage.f_list_objects( i_parent_folder => rec_folder.object_key @@ -283,6 +375,13 @@ create or replace package body pck_auto_import as if l_has_remaining_files then + pck_log.p_warn( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Batch mit Fehlern abgeschlossen — mind. eine Datei konnte nicht importiert werden, SB-Marker wird hochgeladen...' + ,i_object_ref => rec_folder.object_key + ); + -- Sachbearbeiter (SB)-Marker anlegen: signalisiert Sachbearbeitern, dass Dateien manuell geprüft werden müssen l_sb_marker_key := rec_folder.object_key || pck_system.f_get_par_wert_by_programmid('NETSTORE_MARKER_SB'); pck_net_storage.p_upload_object( @@ -290,12 +389,7 @@ create or replace package body pck_auto_import as ,i_content => empty_blob() ,i_content_type => 'application/octet-stream' ); - pck_log.p_warn( - i_module => c_log_module - ,i_action => l_log_action - ,i_message => 'Batch mit Fehlern abgeschlossen — mind. eine Datei konnte nicht importiert werden, SB-Marker gesetzt' - ,i_object_ref => rec_folder.object_key - ); + else pck_log.p_info( i_module => c_log_module diff --git a/database/packages/pck_net_storage.pkb b/database/packages/pck_net_storage.pkb index 686f7a7..d4c0112 100644 --- a/database/packages/pck_net_storage.pkb +++ b/database/packages/pck_net_storage.pkb @@ -69,6 +69,7 @@ create or replace package body pck_net_storage as ------------------------------------------------------------------------------------------------Kopf*/ is l_tenant_prefix varchar2(256); + l_log_action varchar2(256) := 'ASSERT_ALLOWED'; begin if i_object_key is null then @@ -82,6 +83,15 @@ create or replace package body pck_net_storage as l_tenant_prefix := pck_system.f_get_par_wert_by_programmid('NETSTORE_TENANT_ID'); + /* + -- Log for debugging Prefix check + pck_log.p_info( + i_module => c_log_module + ,i_action => l_log_action + ,i_message => 'Checking Prefix: Netstore tenant-Prefix: ' || l_tenant_prefix || '; Accessed Prefix: ' || substr(i_object_key, 1, length(l_tenant_prefix)) || '; Accessed Object: ' || i_object_key + ); + */ + if l_tenant_prefix is not null and length(l_tenant_prefix) > 0 then if substr(i_object_key, 1, length(l_tenant_prefix)) != l_tenant_prefix