2026-04-08 16:23:02 +02:00
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;
2026-04-09 09:00:17 +02:00
procedure p_process_incoming_ba_data
2026-04-08 16:23:02 +02:00
/*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
2026-04-09 09:42:29 +02:00
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;
2026-04-08 16:23:02 +02:00
begin
2026-04-09 09:29:05 +02:00
-- Zielordner Name zusammenstellen
2026-04-09 09:42:29 +02:00
l_target_prefix := pck_system.f_get_par_wert_by_programmid('NETSTORE_BA_PREFIX') || 'Verarbeitet ' || to_char(sysdate, 'YYYY') || '/';
2026-04-09 09:29:05 +02:00
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');
2026-04-08 16:23:02 +02:00
-- Unterordner in eingang/ auflisten (Delimiter '/' liefert nur direkte Kinder)
2026-04-09 09:42:29 +02:00
l_folders := pck_net_storage.f_list_objects(
2026-04-09 09:29:05 +02:00
i_prefix => l_eingang_prefix
2026-04-08 16:23:02 +02:00
,i_delimiter => '/'
);
2026-04-09 09:42:29 +02:00
for rec_folder in (select object_name, is_folder from table(l_folders))
2026-04-08 16:23:02 +02:00
loop
-- Nur Unterordner verarbeiten
2026-04-09 09:42:29 +02:00
if rec_folder.is_folder != 'Y'
2026-04-08 16:23:02 +02:00
then
continue;
end if;
2026-04-09 09:42:29 +02:00
-- 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.
2026-04-09 09:00:17 +02:00
-- Das verhindert die verarbeitung von unvollständig entpackten zips
2026-04-09 09:42:29 +02:00
l_marker_key := rec_folder.object_name || pck_system.f_get_par_wert_by_programmid('NETSTORE_MARKER_NAME');
2026-04-08 16:23:02 +02:00
-- 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/<zip-name>/ → <zip-name>
l_zip_name := substr(
2026-04-09 09:42:29 +02:00
rec_folder.object_name
2026-04-09 09:29:05 +02:00
,length(l_eingang_prefix) + 1
2026-04-09 09:42:29 +02:00
,length(rec_folder.object_name) - length(l_eingang_prefix) - 1
2026-04-08 16:23:02 +02:00
);
2026-04-09 09:29:05 +02:00
l_target_folder := l_target_prefix || l_zip_name || '/';
2026-04-08 16:23:02 +02:00
-- Alle Dateien im Unterordner auflisten (kein Delimiter = flach, alle Tiefen)
2026-04-09 09:42:29 +02:00
l_files := pck_net_storage.f_list_objects(
i_prefix => rec_folder.object_name
2026-04-08 16:23:02 +02:00
,i_delimiter => ''
);
2026-04-09 09:42:29 +02:00
for rec_file in (select object_name, is_folder from table(l_files))
2026-04-08 16:23:02 +02:00
loop
-- Marker und Pseudo-Ordner überspringen
2026-04-09 09:42:29 +02:00
if rec_file.object_name = l_marker_key or rec_file.is_folder = 'Y'
2026-04-08 16:23:02 +02:00
then
continue;
end if;
begin
-- 1. Dateiinhalt laden
2026-04-09 09:42:29 +02:00
l_file_content := pck_net_storage.f_download_object(rec_file.object_name);
2026-04-08 16:23:02 +02:00
-- 2. Fachliche Verarbeitung (noch kein Commit)
2026-04-09 09:42:29 +02:00
p_import_file(rec_file.object_name, l_file_content);
2026-04-08 16:23:02 +02:00
-- 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(
2026-04-09 09:42:29 +02:00
i_object_key => rec_file.object_name
2026-04-08 16:23:02 +02:00
,i_target_prefix => l_target_folder
);
commit;
pck_log.p_info(
i_module => c_module
,i_action => 'IMPORT_FILE'
,i_message => 'Datei erfolgreich verarbeitet'
2026-04-09 09:42:29 +02:00
,i_object_ref => rec_file.object_name
2026-04-08 16:23:02 +02:00
);
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)
2026-04-09 09:42:29 +02:00
,i_object_ref => rec_file.object_name
2026-04-08 16:23:02 +02:00
);
end;
end loop;
-- Prüfen ob noch nicht verarbeitete Dateien im Unterordner verbleiben
l_remaining := 0;
2026-04-09 09:42:29 +02:00
l_check := pck_net_storage.f_list_objects(
i_prefix => rec_folder.object_name
2026-04-08 16:23:02 +02:00
,i_delimiter => ''
);
2026-04-09 09:42:29 +02:00
for rec_check in (select object_name, is_folder from table(l_check))
2026-04-08 16:23:02 +02:00
loop
2026-04-09 09:42:29 +02:00
if rec_check.object_name != l_marker_key and rec_check.is_folder = 'N'
2026-04-08 16:23:02 +02:00
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'
2026-04-09 09:42:29 +02:00
,i_object_ref => rec_folder.object_name
2026-04-08 16:23:02 +02:00
);
end if;
end loop;
2026-04-09 09:00:17 +02:00
end p_process_incoming_ba_data;
2026-04-08 16:23:02 +02:00
end pck_auto_import;
/