create or replace package body pck_auto_import as c_module constant varchar2(20) := 'PCK_AUTO_IMPORT'; procedure p_import_file ( i_object_key in varchar2 ,i_content in blob ) /*Kopf------------------------------------------------------------------------------------------------ -- Beschreibung: Importiert eine einzelne Datei aus dem OCI Eingangsordner in die Datenbank. -- Stub — muss pro Dateityp fachlich implementiert werden. -- Kein Commit hier — wird von p_process_incoming_files übernommen. ------------------------------------------------------------------------------------------------------ -- Parameter: i_object_key Vollständiger OCI-Objektkey der zu verarbeitenden Datei -- i_content Dateiinhalt als BLOB ------------------------------------------------------------------------------------------------------ -- MA Datum Änderung -- SCK 2026-04-08 Stub erstellt ------------------------------------------------------------------------------------------------Kopf*/ is begin -- TODO: Fachliche Verarbeitung implementieren -- Beispiel: CSV parsen und in Zieltabellen schreiben null; end p_import_file; procedure p_process_incoming_ba_data /*Kopf------------------------------------------------------------------------------------------------ -- Beschreibung: Verarbeitet alle fertigen Eingangs-Batches aus dem OCI Eingangsordner. -- Wird von ORDS-Endpunkt und APEX Automation aufgerufen. -- Pro Datei: Import → Move → Commit (Rollback + Fehlereintrag bei Exception). -- Marker wird gelöscht wenn keine Dateien mehr im Unterordner verbleiben. ------------------------------------------------------------------------------------------------------ -- MA Datum Änderung -- SCK 2026-04-08 Prozedur erstellt ------------------------------------------------------------------------------------------------Kopf*/ is l_marker_key varchar2(1024); l_target_folder varchar2(4000 char); l_target_prefix varchar2(4000 char); l_eingang_prefix varchar2(4000 char); l_zip_name varchar2(512); l_file_content blob; l_meta pck_net_storage.t_object_meta; l_remaining number; l_folders t_net_storage_tab; l_files t_net_storage_tab; l_check t_net_storage_tab; begin -- Zielordner Name zusammenstellen l_target_prefix := pck_system.f_get_par_wert_by_programmid('NETSTORE_BA_PREFIX') || 'Verarbeitet ' || 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'); -- Unterordner in eingang/ auflisten (Delimiter '/' liefert nur direkte Kinder) l_folders := pck_net_storage.f_list_objects( i_prefix => l_eingang_prefix ,i_delimiter => '/' ); for rec_folder in (select object_name, is_folder from table(l_folders)) loop -- Nur Unterordner verarbeiten if rec_folder.is_folder != 'Y' then continue; end if; -- 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_marker_key := rec_folder.object_name || pck_system.f_get_par_wert_by_programmid('NETSTORE_MARKER_NAME'); -- Marker prüfen: -20001 = nicht vorhanden → Upload noch nicht abgeschlossen begin l_meta := pck_net_storage.f_get_object_metadata(l_marker_key); exception when others then if sqlcode = -20001 then continue; end if; raise; end; -- Zip-Namen aus Ordnerpfad ableiten: eingang// → l_zip_name := substr( rec_folder.object_name ,length(l_eingang_prefix) + 1 ,length(rec_folder.object_name) - length(l_eingang_prefix) - 1 ); l_target_folder := l_target_prefix || l_zip_name || '/'; -- Alle Dateien im Unterordner auflisten (kein Delimiter = flach, alle Tiefen) l_files := pck_net_storage.f_list_objects( i_prefix => rec_folder.object_name ,i_delimiter => '' ); for rec_file in (select object_name, is_folder from table(l_files)) loop -- Marker und Pseudo-Ordner überspringen if rec_file.object_name = l_marker_key or rec_file.is_folder = 'Y' then continue; end if; begin -- 1. Dateiinhalt laden l_file_content := pck_net_storage.f_download_object(rec_file.object_name); -- 2. Fachliche Verarbeitung (noch kein Commit) p_import_file(rec_file.object_name, l_file_content); -- 3. Datei in Zielordner verschieben (noch kein Commit) -- Rollback von p_move_object macht auch den Import rückgängig pck_net_storage.p_move_object( i_object_key => rec_file.object_name ,i_target_prefix => l_target_folder ); commit; pck_log.p_info( i_module => c_module ,i_action => 'IMPORT_FILE' ,i_message => 'Datei erfolgreich verarbeitet' ,i_object_ref => rec_file.object_name ); exception when others then rollback; pck_log.p_error( i_module => c_module ,i_action => 'IMPORT_FILE' ,i_message => 'Fehler bei Dateiverarbeitung: ' || sqlerrm ,i_detail => to_clob(dbms_utility.format_error_backtrace) ,i_object_ref => rec_file.object_name ); end; end loop; -- Prüfen ob noch nicht verarbeitete Dateien im Unterordner verbleiben l_remaining := 0; l_check := pck_net_storage.f_list_objects( i_prefix => rec_folder.object_name ,i_delimiter => '' ); for rec_check in (select object_name, is_folder from table(l_check)) loop if rec_check.object_name != l_marker_key and rec_check.is_folder = 'N' then l_remaining := l_remaining + 1; end if; end loop; -- Marker löschen wenn Batch vollständig abgeschlossen if l_remaining = 0 then pck_net_storage.p_delete_object(l_marker_key); pck_log.p_info( i_module => c_module ,i_action => 'PROCESS_INCOMING' ,i_message => 'Batch abgeschlossen, Marker gelöscht' ,i_object_ref => rec_folder.object_name ); end if; end loop; end p_process_incoming_ba_data; end pck_auto_import; /