p_import_ba_korrespondenz implementiert
This commit is contained in:
@@ -56,9 +56,11 @@ Alle zur Laufzeit via `pck_system.f_get_par_wert_by_programmid`:
|
||||
| `NETSTORE_REGION` | z.B. `eu-frankfurt-1` |
|
||||
| `NETSTORE_TENANT_ID` | Erlaubter Root-Prefix, z.B. `mandant_42/` |
|
||||
| `NETSTORE_CRED_ID` | Credential Static ID für apex_web_service calls, z.B. 'OCI_OBJ_STORE_CRED' |
|
||||
| `NETSTORE_MARKER_NAME` | Name der Marker-Datei im Object Store, der von Automaton abgelegt wird, um zu signalisieren, dass der entsprechende Unterordner komplett hochgeladen wurde. Verhindert die Verarbeitung von unvollständig hochgeladenen Ordnern. z.B.: `_READY_FOR_DB_PROCESSING_` |
|
||||
| `NETSTORE_MARKER_DB` | Name der Marker-Datei im Object Store, der von Automaton abgelegt wird, um zu signalisieren, dass der entsprechende Unterordner komplett hochgeladen wurde. Verhindert die Verarbeitung von unvollständig hochgeladenen Ordnern. z.B.: `_READY_FOR_DB_PROCESSING_` |
|
||||
| `NETSTORE_MARKER_SB` | Name der Marker-Datei im Object Store, der von DB beim Verarbeiten angelegt wird, wenn eine oder mehrere Dateien eines ZIPs nicht automatisiert importiert werden konnten. Das soll signalisieren, dass ein Sachbearbeiter die Dateien in diesem Unterordner manuell prüfen und importieren muss. z.B.: `_BITTE_PRÜFEN_` |
|
||||
| `NETSTORE_BA_PREFIX` | Pfad in Object Storage, wo BA-Daten liegen. Muss mit einem `/` enden, z.B. `BA/Eingang/` |
|
||||
| `NETSTORE_BA_IMPORT` | Name des Unterordners von NETSTORE_BA_PREFIX im Object Storage, wo entpackte Dateien, die noch importiert werden müssen, zwischengespeichert werden. |
|
||||
| `BA_IMPORT_SB_MIT_ID` | Mitarbeiter-ID für Import von BA Daten (z.B. Korrespondenzen). Diese Mitarbeiter-ID bekommt eine Wiedervorlage, für jede Datei, die nicht automatisch importiert werden konnte. |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,56 +2,111 @@ 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
|
||||
procedure p_import_ba_korrespondenz (
|
||||
i_object_key in varchar2
|
||||
,i_content in blob
|
||||
,i_target_folder in varchar2
|
||||
)
|
||||
/*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.
|
||||
-- Ruft inkasso.pck_import.f_import_ba_dokument auf.
|
||||
-- Bei Rückgabe 1 (Erfolg): Datei in den Zielordner verschieben.
|
||||
-- Bei Rückgabe != 1 (z.B. ungültiger Dateiname): Warnung loggen und Exception werfen
|
||||
-- — Datei bleibt liegen, Commit/Rollback liegt beim Aufrufer.
|
||||
-- Kein Commit hier — wird von p_process_incoming_ba_data übernommen.
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- Parameter: i_object_key Vollständiger OCI-Objektkey der zu verarbeitenden Datei
|
||||
-- i_content Dateiinhalt als BLOB
|
||||
-- Parameter: i_object_key Vollständiger OCI-Objektkey der zu verarbeitenden Datei
|
||||
-- i_content Dateiinhalt als BLOB
|
||||
-- i_target_folder Zielordner-Prefix für erfolgreich verarbeitete Dateien
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- MA Datum Änderung
|
||||
-- SCK 2026-04-08 Stub erstellt
|
||||
-- SCK 2026-04-09 Implementierung: Aufruf f_import_ba_dokument, Wiedervorlage bei Fehler
|
||||
-- SCK 2026-04-09 Move nach erfolgreichem Import in p_import_ba_korrespondenz verschoben
|
||||
------------------------------------------------------------------------------------------------Kopf*/
|
||||
is
|
||||
l_filename varchar2(512);
|
||||
l_file_size number;
|
||||
l_return number;
|
||||
l_log_action varchar2(512 char) := 'IMPORT_BA_PDF_FILE';
|
||||
begin
|
||||
-- TODO: Fachliche Verarbeitung implementieren
|
||||
-- Beispiel: CSV parsen und in Zieltabellen schreiben
|
||||
null;
|
||||
end p_import_file;
|
||||
-- Dateiname aus OCI-Objektkey ableiten (letztes Segment nach '/')
|
||||
l_filename := substr(i_object_key, instr(i_object_key, '/', -1) + 1);
|
||||
l_file_size := dbms_lob.getlength(i_content);
|
||||
|
||||
l_return := inkasso.pck_import.f_import_ba_dokument(
|
||||
i_datei => i_content
|
||||
,i_dateiname => l_filename
|
||||
,i_datei_groesse => l_file_size
|
||||
);
|
||||
|
||||
if l_return != 1
|
||||
then
|
||||
pck_log.p_warn(
|
||||
i_module => c_module
|
||||
,i_action => l_log_action
|
||||
,i_message => 'Import für Datei "' || l_filename || '" fehlgeschlagen (Rückgabe: ' || l_return || ') — Wiedervorlage erforderlich'
|
||||
,i_object_ref => i_object_key
|
||||
);
|
||||
|
||||
-- Wiedervorlage für Sachbearbeiter erstellen
|
||||
pck_wiedervorlage.p_wiedervorlage_anlegen (i_swv_stp_id_art => pck_stammdaten.f_get_stp_id_by_programmid('WV_IMPORT_DATEV') -- TODO: neue WV Art? z.B. WV_IMPORT_BA_DATEN
|
||||
,i_swv_wdatum => sysdate --TODO: welches Datum? sysdate?
|
||||
,i_swv_bemerkung => 'Bitte manuell Prüfen: Die Datei "' || l_filename || '" konnte nicht automatisch importiert werden (Siehe "' || i_object_key || '").'
|
||||
,i_swv_mit_id_wsachbearbeiter => pck_system.f_get_par_wert_by_programmid('BA_IMPORT_SB_MIT_ID')
|
||||
);
|
||||
|
||||
raise_application_error(-20000, 'Import fehlgeschlagen: "' || l_filename || '" (Rückgabe: ' || l_return || ')');
|
||||
end if;
|
||||
|
||||
-- Datei in Verarbeitet-Ordner verschieben
|
||||
pck_net_storage.p_move_object(
|
||||
i_object_key => i_object_key
|
||||
,i_target_prefix => i_target_folder
|
||||
);
|
||||
|
||||
pck_log.p_info(
|
||||
i_module => c_module
|
||||
,i_action => l_log_action
|
||||
,i_message => 'Datei "' || l_filename || '" erfolgreich verarbeitet und verschoben'
|
||||
,i_object_ref => i_object_key
|
||||
);
|
||||
end p_import_ba_korrespondenz;
|
||||
|
||||
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.
|
||||
-- Pro Datei: Import + Move → Commit; bei Exception: Rollback, Datei bleibt liegen,
|
||||
-- nächste Datei wird trotzdem verarbeitet.
|
||||
-- Nach dem Datei-Loop: DB-Marker immer löschen (verhindert erneuten Durchlauf).
|
||||
-- Wenn danach noch Dateien im Ordner liegen: SB-Marker anlegen damit Sachbearbeiter
|
||||
-- die übriggebliebenen Dateien manuell prüfen können.
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- MA Datum Änderung
|
||||
-- SCK 2026-04-08 Prozedur erstellt
|
||||
-- SCK 2026-04-09 Fehlerbehandlung: Datei bleibt liegen, Fehler-Marker, kein erneuter Durchlauf
|
||||
-- SCK 2026-04-09 SB-Marker statt l_had_errors-Flag; Move in p_import_ba_korrespondenz verschoben
|
||||
------------------------------------------------------------------------------------------------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;
|
||||
l_db_processing_marker_key varchar2(1024);
|
||||
l_sb_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_folders t_net_storage_tab;
|
||||
l_files t_net_storage_tab;
|
||||
l_has_remaining_files boolean;
|
||||
l_log_action varchar2(512 char) := 'IMPORT_BA_DATA';
|
||||
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)
|
||||
-- Unterordner in eingangs-ordner auflisten (es gibt einen Ordner für jeden entpackte ZIP-Datei) (Delimiter '/' liefert nur direkte Kinder)
|
||||
l_folders := pck_net_storage.f_list_objects(
|
||||
i_prefix => l_eingang_prefix
|
||||
,i_delimiter => '/'
|
||||
@@ -67,11 +122,11 @@ create or replace package body pck_auto_import as
|
||||
|
||||
-- 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');
|
||||
l_db_processing_marker_key := rec_folder.object_name || pck_system.f_get_par_wert_by_programmid('NETSTORE_MARKER_DB');
|
||||
|
||||
-- Marker prüfen: -20001 = nicht vorhanden → Upload noch nicht abgeschlossen
|
||||
begin
|
||||
l_meta := pck_net_storage.f_get_object_metadata(l_marker_key);
|
||||
l_meta := pck_net_storage.f_get_object_metadata(l_db_processing_marker_key);
|
||||
exception
|
||||
when others
|
||||
then
|
||||
@@ -99,7 +154,7 @@ create or replace package body pck_auto_import as
|
||||
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'
|
||||
if rec_file.object_name = l_db_processing_marker_key or rec_file.is_folder = 'Y'
|
||||
then
|
||||
continue;
|
||||
end if;
|
||||
@@ -108,24 +163,13 @@ create or replace package body pck_auto_import as
|
||||
-- 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
|
||||
);
|
||||
-- 2. Fachliche Verarbeitung + Move bei Erfolg (innerhalb p_import_ba_korrespondenz)
|
||||
p_import_ba_korrespondenz(rec_file.object_name, l_file_content, l_target_folder);
|
||||
|
||||
-- Commit pro Datei: OCI-Move ist nicht transaktional, daher DB-Änderungen sofort sichern
|
||||
-- sonst würde ein Fehler bei einer späteren Datei den DB-Import bereits verschobener Dateien zurückrollen
|
||||
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
|
||||
@@ -140,31 +184,46 @@ create or replace package body pck_auto_import as
|
||||
end;
|
||||
end loop;
|
||||
|
||||
-- Prüfen ob noch nicht verarbeitete Dateien im Unterordner verbleiben
|
||||
l_remaining := 0;
|
||||
-- DB-Marker immer entfernen — verhindert erneute Verarbeitung beim nächsten Lauf
|
||||
pck_net_storage.p_delete_object(l_db_processing_marker_key);
|
||||
|
||||
l_check := pck_net_storage.f_list_objects(
|
||||
-- Prüfen ob noch Dateien im Unterordner liegen (nicht erfolgreich importierte Dateien)
|
||||
l_files := 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))
|
||||
l_has_remaining_files := false;
|
||||
|
||||
for rec_remaining in (select object_name, is_folder from table(l_files))
|
||||
loop
|
||||
if rec_check.object_name != l_marker_key and rec_check.is_folder = 'N'
|
||||
if rec_remaining.is_folder != 'Y'
|
||||
then
|
||||
l_remaining := l_remaining + 1;
|
||||
l_has_remaining_files := true;
|
||||
exit;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
-- Marker löschen wenn Batch vollständig abgeschlossen
|
||||
if l_remaining = 0
|
||||
if l_has_remaining_files
|
||||
then
|
||||
pck_net_storage.p_delete_object(l_marker_key);
|
||||
|
||||
-- SB-Marker anlegen: signalisiert Sachbearbeitern, dass Dateien manuell geprüft werden müssen
|
||||
l_sb_marker_key := rec_folder.object_name || pck_system.f_get_par_wert_by_programmid('NETSTORE_MARKER_SB');
|
||||
pck_net_storage.p_upload_object(
|
||||
i_object_key => l_sb_marker_key
|
||||
,i_content => empty_blob()
|
||||
,i_content_type => 'application/octet-stream'
|
||||
);
|
||||
pck_log.p_warn(
|
||||
i_module => c_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_name
|
||||
);
|
||||
else
|
||||
pck_log.p_info(
|
||||
i_module => c_module
|
||||
,i_action => 'PROCESS_INCOMING'
|
||||
,i_message => 'Batch abgeschlossen, Marker gelöscht'
|
||||
,i_action => l_log_action
|
||||
,i_message => 'Batch abgeschlossen, alle Dateien erfolgreich importiert'
|
||||
,i_object_ref => rec_folder.object_name
|
||||
);
|
||||
end if;
|
||||
|
||||
Reference in New Issue
Block a user