diff --git a/Stadt Essen/proz01_prozessakte.groovy b/Stadt Essen/proz01_prozessakte.groovy new file mode 100644 index 0000000..dd1cdcb --- /dev/null +++ b/Stadt Essen/proz01_prozessakte.groovy @@ -0,0 +1,602 @@ + +// (1) Global d.3 libraries +import com.dvelop.d3.server.core.D3Interface +import com.dvelop.d3.server.Document +import com.dvelop.d3.server.User +import com.dvelop.d3.server.Condition +import com.dvelop.d3.server.DocumentType +import groovy.sql.GroovyRowResult + +import com.dvelop.d3.server.ValueSet +import com.dvelop.d3.server.RepositoryField + +import java.sql.Timestamp +import java.util.Calendar +import java.text.SimpleDateFormat + +// Libraries to handle the different hook types +import com.dvelop.d3.server.Entrypoint + +public class proz01_prozessakte { + boolean logging = true; + + private static int POS_AZ = 1; + private static int POS_Jahr = 2; + private static int POS_StatZ = 3; + private static int POS_GerichtAZ = 4; + private static int POS_Klaeger = 9; + private static int POS_Zda = 13; + private static int POS_Beklaeger = 15; + private static int POS_AusArt = 23; + private static int POS_DokGrp = 30; + private static int POS_DokTyp = 31; + private static int POS_AusDat = 51; + private static int POS_ZLM = 35; + private static int POS_LOESCHGRD = 36; + private static int POS_GADRESSE = 33; + private static int POS_Gericht = 20; + private static int POS_DOKIDORG = 10; + private static int POS_DOKDAT = 55; + // Feldpostitionen Adressverwaltung + private static int POS_FFOE = 2; + private static int POS_Name = 9; + private static int POS_Strasse = 21; + private static int POS_Hnr = 29; + private static int POS_Plz = 24; + private static int POS_Ort = 25; + + private static String WM_TRENNZEICHEN = ";"; + + // Variablen - Aufbewahrungsfristen (in Jahren) + private static int FRIST_AUSSONDERUNG = 10; // 10 Jahre + private static int STATUS_ZDA = 0; + private static int NEUES_AZ = 0; + private static int CHANGE_GERICHT = 0; + + // Datenbanktabelle + private static String TB_DokGrpTyp = "DV_PROZ_Doktyp"; + + private static String G01_DS_PROZESSA = "APROZ"; + private static String G01_DS_PROZESSD = "DPROZ"; + private static String G01_DS_ORGANI = "DPROZ"; + + + // Offenbar eigentlich zentral abzulegen + + private static String G01_STR_JA = "Ja"; + private static String G01_STR_NEIN = "Nein"; + + + @Entrypoint( entrypoint = "hook_insert_entry_10" ) + public int hook_insert_entry_10(D3Interface d3, User user, DocumentType docType, Document doc) + { + + !logging ?: d3.log.info(" hook_insert_entry_10: Anfang") + proz01_split_AZ( 1, doc, d3 ); + proz01_split_Gericht( doc, d3 ); + !logging ?: d3.log.info(" hook_insert_entry_10: Ende") + + return 0; + } + + + @Entrypoint( entrypoint = "hook_insert_exit_10" ) + public int hookInsertExit10 (D3Interface d3, Document doc, String fileDestination, Integer importOk, User user, DocumentType docType) + { + !logging ?: d3.log.info("START | hookInsertExit10 "); + + if ( docType == G01_DS_PROZESSA ) + { + proz01_fill_AZ_Nummer( 0, doc, d3 ); + } + + + !logging ?: d3.log.info("ENDE | hookInsertExit10 "); + return 0; + } + + + @Entrypoint( entrypoint = "hook_upd_attrib_entry_20" ) + public int hookUpdAttribEntry20(D3Interface d3, Document doc, User user, DocumentType docType, DocumentType docTypeNew) + { + d3.log.info("START | hookUpdAttribEntry20") + + // temporäres Objekt holen, um zu prüfen, das sich Eigenschaften geändert haben + def oldDocAttributes = d3.archive.getDocument(doc.id()); + //d3.log.error( "1 Dokumentart: " + docType.id() ); + //d3.log.error( "1 Gericht (" + POS_Gericht + "): " + doc.field[ POS_Gericht ] + " ll " + oldDocAttributes.field[ POS_Gericht ] ); + //d3.log.error( "1 Adresse (" + POS_GADRESSE + "): " + doc.field[ POS_GADRESSE ] + " ll " + oldDocAttributes.field[ POS_GADRESSE ] ); + + if ( docType.id() == G01_DS_ORGANI ) + { + if ( doc.field[ POS_Name ] != oldDocAttributes.field[ POS_Name ] ) + { + CHANGE_GERICHT = 1; + } + + if ( doc.field[ POS_Strasse ] != oldDocAttributes.field[ POS_Strasse ] ) + { + CHANGE_GERICHT = 1; + } + + if ( doc.field[ POS_Hnr ] != oldDocAttributes.field[ POS_Hnr ] ) + { + CHANGE_GERICHT = 1; + } + + if ( doc.field[ POS_Plz ] != oldDocAttributes.field[ POS_Plz ] ) + { + CHANGE_GERICHT = 1; + } + + if ( doc.field[ POS_Ort ] != oldDocAttributes.field[ POS_Ort ] ) + { + CHANGE_GERICHT = 1; + } + + d3.log.error( "hookUpdAttribEntry20 " + CHANGE_GERICHT ); + + } + else + { + proz01_split_AZ( 1, doc, d3 ); + proz01_split_Gericht( doc, d3 ); + + if ( doc.field[ POS_Zda ] != oldDocAttributes.field[ POS_Zda ] ) + { + STATUS_ZDA = 1; + } + + // Wenn das Feld zum Löschen markiert auf Ja gesetzt wurde, überprüfe ob beim Löschgrund etwas eingetragen wurde. Falls nicht, gebe eine Fehlermeldung aus. + // Wenn das Feld zum Löschen markiert auf Nein gesetzt wurde, dann leere das Feld Löschgrund + + if ( doc.field[ POS_ZLM ] != oldDocAttributes.field[ POS_ZLM ] ) + { + if ( doc.field[ POS_ZLM ] == G01_STR_JA ) + { + if ( doc.field[ POS_LOESCHGRD ] == "" ) + { + return -403; + } + } + else if ( doc.field[ POS_ZLM ] == G01_STR_NEIN ) + { + doc.field[ POS_LOESCHGRD ] = ""; + } + } + } + + if ( ( docType.id() == G01_DS_PROZESSA ) && ( doc.field[ POS_Jahr ] != oldDocAttributes.field[ POS_Jahr ] ) ) + { + NEUES_AZ = 1; + } + + d3.log.error( "2 Dokumentart: " + docType.id() ); + d3.log.error( "2 Gericht (" + POS_Gericht + "): " + doc.field[ POS_Gericht ] + " ll " + oldDocAttributes.field[ POS_Gericht ] ); + d3.log.error( "2 Adresse (" + POS_GADRESSE + "): " + doc.field[ POS_GADRESSE ] + " ll " + oldDocAttributes.field[ POS_GADRESSE ] ); + + if ( ( docType.id() == G01_DS_PROZESSA ) && ( ( doc.field[ POS_Gericht ] != oldDocAttributes.field[ POS_Gericht ] ) || ( doc.field[ POS_GADRESSE ] != oldDocAttributes.field[ POS_GADRESSE ] ) ) ) + { + def sqlQuery = "SELECT dok_dat_feld_" + POS_Name + " POS_Name, dok_dat_feld_" + POS_Strasse + " POS_Strasse, dok_dat_feld_" + POS_Hnr + " POS_Hnr, dok_dat_feld_" + POS_Plz + " POS_Plz, dok_dat_feld_" + POS_Ort + " POS_Ort FROM firmen_spezifisch WHERE kue_dokuart = 'AAORG' AND dok_dat_feld_" + POS_Name + " = '" + doc.field[POS_Gericht] + "'"; + + def ergebnis = d3.sql.executeAndGet( sqlQuery ); + //d3.log.error( "Name: " + ergebnis[ 0 ].POS_Name ); + //d3.log.error( "POS_Strasse: " + ergebnis[ 0 ].POS_Strasse ); + //d3.log.error( "POS_Hnr: " + ergebnis[ 0 ].POS_Hnr ); + //d3.log.error( "POS_Plz: " + ergebnis[ 0 ].POS_Plz ); + //d3.log.error( "POS_Ort: " + ergebnis[ 0 ].POS_Ort ); + + + + + if ( ( ergebnis[ 0 ].POS_Name == "" ) || ( ergebnis[ 0 ].POS_Strasse == "" ) || ( ergebnis[ 0 ].POS_Hnr == "" ) || ( ergebnis[ 0 ].POS_Plz == "" ) || ( ergebnis[ 0 ].POS_Ort == "" ) ) + { + //Gerichtsdaten nicht gepflegt! Bitte in der Organisation pflegen. + return -569; + } + + def Gerichtsadresse = ergebnis[ 0 ].POS_Strasse + " " + ergebnis[ 0 ].POS_Hnr + ", " + ergebnis[ 0 ].POS_Plz + " " + ergebnis[ 0 ].POS_Ort; + + if ( Gerichtsadresse != doc.field[ POS_GADRESSE ] ) + { + //Gerichtsadresse entspricht nicht dem aktuell ausgewählten Gericht! + return -570; + } + + } + + + + + + + d3.log.info("ENDE | hookUpdAttribEntry20") + return 0; + } + + + @Entrypoint( entrypoint = "hook_upd_attrib_exit_20" ) + public int hookUpdAttribExit20(D3Interface d3, Document doc, Integer errorCode, User user, DocumentType docType, DocumentType docTypeOld) + { + d3.log.info("START | hookUpdAttribExit20 ") + + def strZDA, strDatum; + + if ( ( NEUES_AZ == 1 ) && ( docType != G01_DS_ORGANI ) ) + { + NEUES_AZ = 0; + proz01_fill_AZ_Nummer( doc, d3, 1 ); + } + + + + if ( ( STATUS_ZDA == 1 ) && ( docType != G01_DS_ORGANI ) ) + { + STATUS_ZDA = 0; + + if ( doc.field[ POS_Zda ] == G01_STR_JA ) + { + strZDA = G01_STR_JA; + strDatum = proz01_getAussonderungsdatum( FRIST_AUSSONDERUNG ); + } + else + { + if ( doc.field[ POS_Zda ] == G01_STR_NEIN ) + { + strZDA = G01_STR_NEIN; + strDatum = ""; + } + + } + + // hier wird das docSearchCreate übernommen; dafür gibt es aber aktuell keine Entsprechung in Groovy. + // das wird in Groovy direkt umgesetzt; d.h. man macht das manuell, was der JPL-Massenänderungs-Code en gros macht: + + def massen_sql = "select doku_id from firmen_spezifisch where ( kue_dokuart = '" + G01_DS_PROZESSA + "' or kue_dokuart = '" + G01_DS_PROZESSD + "' ) and dok_dat_feld_" + POS_AZ + " = '" + doc.field(POS_AZ) + "'"; + + def massen_ergebnis = d3.sql.executeAndGet( massen_sql ); + + if ( massen_ergebnis.size() > 0 ) + { + int i; + for ( i = 0 ; i < massen_ergebnis.size(); i++ ) + { + def updateDoc = d3.archive.getDocument( massen_ergebnis[ i ].doku_id ); + + updateDoc.field[ POS_Zda ] = strZDA; + updateDoc.field[ POS_AusDat ] = strDatum; + updateDoc.field[ POS_AusArt ] = doc.field[ POS_AusArt ]; + updateDoc.updateAttributes( "Master" ); + } + } + + if ( CHANGE_GERICHT == 1 && docType == G01_DS_ORGANI ) + { + CHANGE_GERICHT = 0; + + def m_sql2 = "SELECT dok_dat_feld_" + POS_Name + " name, dok_dat_feld_" + POS_Strasse + " strasse, dok_dat_feld_" + POS_Hnr + " hnr, dok_dat_feld_" + POS_Plz + " plz, dok_dat_feld_" + POS_Ort + " ort FROM firmen_spezifisch WHERE kue_dokuart = 'AAORG' AND doku_id = '" + doc.id + "'"; + + def me2 = d3.sql.executeAndGet( m_sql2 ); + + if ( me2.size() == 1 ) + { + def strGAdresse = me2[ 0 ].strasse + " " + me2[ 0 ].hnr + " " + me2[ 0 ].plz + " " + me2[ 0 ].ort; + + m_sql3 = "select doku_id from firmen_spezifisch where kue_dokuart = '" + G01_DS_PROZESSA + "' and dok_dat_feld_" + POS_DOKIDORG + " = '" + doc.id + "'"; + + def me3 = d3.sql.executeAndGet( m_sql1 ); + + if ( me3.size() > 0 ) + { + def ud2 = d3.archive.getDocument( me3[ i ].doku_id ); + + ud2.field[ POS_GADRESSE ] = strGAdresse; + ud2.field[ POS_Gericht ] = me2[ 0 ].name; + + ud2.updateAttributes( "Master" ); + + } + + } + + } + + + + + } + + d3.log.info("ENDE | hookUpdAttribExit20 ") + return 0; + } + + + @Entrypoint( entrypoint = "hook_validate_update_entry_10" ) + public int hookValidateUpdateEntry10(D3Interface d3, User user, DocumentType docType, Document doc, String nextcall) { + d3.log.error("START | hookValidateUpdateEntry10 "); + + proz01_split_AZ( 1, doc, d3 ); + proz01_split_Gericht( doc, d3 ); + + d3.log.error("ENDE | hookValidateUpdateEntry10 "); + return 0; + } + + + @Entrypoint( entrypoint = "hook_search_entry_10" ) + public int hookSearchEntry10(D3Interface d3, User user, DocumentType docType, Document searchContext) { + d3.log.error("START | hookSearchEntry10 "); + + proz01_split_AZ( 0, searchContext, d3 ); + proz01_split_Gericht( searchContext, d3 ); + + d3.log.error("ENDE | hookSearchEntry10 "); + return 0; + } + + + + + + + + + /////////////////////////////////////// + // Wertemengenhooks + /////////////////////////////////////// + + + @ValueSet( entrypoint = "proz01_fill_Klaeger" ) + def proz01_fill_Klaeger( D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc ) + { + def where = ""; + + if ( doc.field[ POS_Klaeger ] != null ) + { + if ( doc.field[ POS_Klaeger ].length() >= 3 ) + { + where = " AND (dok_dat_feld_" + POS_AZ + " LIKE '%" + doc.field[ POS_Klaeger ] + "%' OR dok_dat_feld_" + POS_Klaeger + " LIKE '%" + doc.field[ POS_Klaeger ] + "%')"; + } + } + + def sqlStatement = "SELECT DISTINCT top 1000 dok_dat_feld_" + POS_AZ + " feld_1, dok_dat_feld_" + POS_Klaeger + " feld_2, dok_dat_feld_" + POS_GerichtAZ + " feld_3 FROM firmen_spezifisch WHERE kue_dokuart = '" + G01_DS_PROZESSA + "' " + where; + + def resultRows = d3.sql.executeAndGet( (String) sqlStatement ); + + if ( resultRows.size() > 0 ) + { + reposField.provideValuesForValueSet( resultRows.collect{ it.feld_1 + ";" + it.feld_2 + ";" + it.feld_3 } ); + } + } + + + @ValueSet( entrypoint = "proz01_fill_Beklagter" ) + def proz01_fill_Beklagter( D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc ) + { + def where = ""; + + if ( doc.field[ POS_Beklaeger ] != null ) + { + if ( doc.field[ POS_Beklaeger ].length() >= 3 ) + { + where = " AND (dok_dat_feld_" + POS_Beklaeger + " LIKE '%" + doc.field[ POS_Beklaeger ] + "%' )"; + } + } + + def sqlStatement = "SELECT DISTINCT top 1000 dok_dat_feld_" + POS_Beklaeger + " feld_1 FROM firmen_spezifisch WHERE kue_dokuart = '" + G01_DS_PROZESSA + "'" + where; + + def resultRows = d3.sql.executeAndGet( (String) sqlStatement ); + + if ( resultRows.size() > 0 ) + { + reposField.provideValuesForValueSet( resultRows.collect{ it.feld_1 } ); + } + + } + + + @ValueSet( entrypoint = "proz01_WM_DOKGRP" ) + def proz01_WM_DOKGRP( D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc ) + { + def where = ""; + + if ( ( doc.field[ POS_DokTyp ] != "" ) && ( doc.field[ POS_DokTyp ] != null ) && ( doc.field[ POS_DokTyp ] != "null" ) ) + { + where = " where Dokumenttyp = '" + doc.field[ POS_DokTyp ] + "'"; + } + + def sqlStatement = "select distinct Dokumentgruppe from " + TB_DokGrpTyp; + + def resultRows = d3.sql.executeAndGet( (String) sqlStatement ); + + if ( resultRows.size() > 0 ) + { + reposField.provideValuesForValueSet( resultRows.collect{ it.Dokumentgruppe } ); + } + } + + + @ValueSet( entrypoint = "proz01_WM_DOKTYP" ) + def proz01_WM_DOKTYP( D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc ) + { + def where = ""; + + if ( ( doc.field[ POS_DokGrp ] != "" ) && ( doc.field[ POS_DokGrp ] != null ) && ( doc.field[ POS_DokGrp ] != "null" ) ) + { + where = " where Dokumentgruppe = '" + doc.field[ POS_DokGrp ] + "'"; + } + + def sqlStatement = "select distinct Dokumenttyp from " + TB_DokGrpTyp + where; + + def resultRows = d3.sql.executeAndGet( (String) sqlStatement ); + + d3.log.error( sqlStatement ); + + if ( resultRows.size() > 0 ) + { + reposField.provideValuesForValueSet( resultRows.collect{ it.Dokumenttyp } ); + } + } + + + @ValueSet( entrypoint = "proz01_getGericht" ) + def proz01_getGericht( D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc ) + { + def where = ""; + + if ( doc.field[ POS_Gericht ] != null ) + { + if ( doc.field[ POS_Gericht ].length() >= 3 ) + { + where = " AND dok_dat_feld_" + POS_Name + " LIKE '%:" + doc.field[ POS_Gericht ] + "%' "; + } + } + + def sqlQuery = "SELECT fs.dok_dat_feld_" + POS_Name + " feld_1, fs.dok_dat_feld_" + POS_Strasse + " feld_2, fs.dok_dat_feld_" + POS_Hnr + " feld_3, fs.dok_dat_feld_" + POS_Plz + " feld_4, fs.dok_dat_feld_" + POS_Ort + " feld_5, fs.doku_id \ + FROM firmen_spezifisch fs \ + LEFT JOIN benutzergruppen gruppe \ + ON gruppe.benutzergruppe = fs.dok_dat_feld_" + POS_FFOE + " \ + Left JOIN benutzer_in_gruppe bInGrp \ + ON gruppe.gruppen_id = bInGrp.benutzergruppe \ + WHERE fs.kue_dokuart = 'AAORG' AND (bInGrp.benutzername = '" + user + "' OR fs.dok_dat_feld_" + POS_FFOE + " IS NULL) " + where; + + + def resultRows = d3.sql.executeAndGet( (String) sqlQuery ); + + if ( resultRows.size() > 0 ) + { + reposField.provideValuesForValueSet( resultRows.collect{ it.feld_1 + "|" + it.feld_2 + "|" + it.feld_3 + "|" + it.feld_4 + "|" + it.feld_5 + "|" + it.doku_id } ); + } + } + + + + + + /////////////////////////////////////// + // Arbeitsfunktionen + /////////////////////////////////////// + + + //////////////////// proz01_split_AZ ///////////////////////////////////////////////// + // Funktion zum Aufteilen des Feldes Aktenzeichen nach AZ;Klaeger;Gerichtszeichen + // und fuellen in die jeweiligen Felder + ////////////////////////////////////////////////////////////////////////////////// + + public void proz01_split_AZ( int NotSearch, Document doc, D3Interface d3 ) + { + def strKlaeger = doc.field[ POS_Klaeger ].toString(); + + if ( strKlaeger != null ) + { + def erg = strKlaeger.tokenize( WM_TRENNZEICHEN ); + + if ( erg.size() > 2 ) + { + doc.field[ POS_Klaeger ] = ""; + doc.field[ POS_AZ ] = erg[ 0 ]; + + if ( NotSearch == 1 ) + { + doc.field[ POS_Klaeger ] = erg[ 1 ]; + doc.field[ POS_GerichtAZ ] = erg[ 2 ]; + } + } + } + } + + + + /////////////////////////// proz01_fill_AZ_Nummer ////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////////////// + + public void proz01_fill_AZ_Nummer( Document doc, D3Interface d3, int update ) + { + + def treffer; + def strNummer; + + if ( update == 0 ) + { + def sqlQuery = "SELECT TOP (1) right(dok_dat_feld_" + POS_AZ + ", 4) + 1 nummero_uno from firmen_spezifisch WHERE kue_dokuart = '" + G01_DS_PROZESSA + "' ORDER BY right(dok_dat_feld_" + POS_AZ +" ,4) DESC "; + + treffer = d3.sql.executeAndGet( (String) sqlQuery ); + + strNummer = doc.field[ POS_Jahr ] + "-" + (String) treffer[ 0 ].nummero_uno.padLeft( 4, '0' ); + + } + else + { + if ( update == 1 ) + { + if ( doc.field[ POS_AZ ] != null ) + { + def docfield_pos_az = doc.field[ POS_AZ ].toString(); + + def tok = docfield_pos_az.tokenize( "-" ); + if ( tok.size() > 1 ) + { + strNummer = doc.field[ POS_Jahr ] + "-" + tok.get(2); + } + } + } + } + + def currentDoc = d3.archive.getDocument( doc.id ); + currentDoc.field[ POS_AZ ] = strNummer; + currentDoc.updateAttributes( "Master" ); + + // Update-Call returniert nichts definitiv Verwertbares, daher wird keine Logmeldung ausgegeben (anders als im JPL-Code). + + } + + + + //////////////////// l01_split_Gericht ///////////////////////////////////////////////// + // Funktion zum Aufteilen des Felds Aktenzeichen nach AZ;Klaeger;Gerichtszeichen + // und fuellen in die jeweiligen Felder + ////////////////////////////////////////////////////////////////////////////////// + + public void proz01_split_Gericht( Document doc, D3Interface d3 ) + { + def strGericht = doc.field[ POS_Gericht ].toString(); + + if ( strGericht != null ) + { + def erg = strGericht.tokenize( "|" ); + + if ( erg.size() > 1 ) + { + doc.field[ POS_Gericht ] = erg[ 0 ]; + doc.field[ POS_GADRESSE ] = erg[ 1 ] + " " + erg[ 2 ] + ", " + erg[ 3 ] + " " + erg[ 4 ]; + doc.field[ POS_DOKIDORG ] = erg[ 5 ]; + } + } + } + + + + //////////////////// proz01_getAussonderungsdatum ///////////////////////////////////////////////// + // Liefert das Aussonderungsdatum anhand einer Frist + // Parameter: iFrist - Aufbewahrungsfrist + ////////////////////////////////////////////////////////////////////////////////// + + public String proz01_getAussonderungsdatum( String iFrist ) + { + def ergebnis = ""; + + Date date = new Date(); + + int dateYear = date.format( "yyyy" ); + + ergebnis = dateYear + iFrist; + + return "31.12." + ergebnis; + + } + + + + +} diff --git a/Stadt Essen/proz01_prozessakte.jpl b/Stadt Essen/proz01_prozessakte.jpl new file mode 100644 index 0000000..518d7ba --- /dev/null +++ b/Stadt Essen/proz01_prozessakte.jpl @@ -0,0 +1,578 @@ +// ##################### Stadt Essen - Prozessakte ###################### + +// Dokumentarten - in g01 deklariert +//global G01_DS_PROZESSA = "APROZ" +//global G01_DS_PROZESSD = "DPROZ" + +// Feldpositionen +vars POS_AZ = 1 +vars POS_Jahr = 2 +vars POS_StatZ = 3 +vars POS_GerichtAZ = 4 +vars POS_Klaeger = 9 +vars POS_Zda = 13 +vars POS_Beklaeger = 15 +vars POS_AusArt = 23 +vars POS_DokGrp = 30 +vars POS_DokTyp = 31 +vars POS_AusDat = 51 +vars POS_ZLM = 35 +vars POS_LOESCHGRD = 36 +vars POS_GADRESSE = 33 +vars POS_Gericht = 20 +vars POS_DOKIDORG = 10 + +// Feldpostitionen Adressverwaltung +vars POS_FFOE = 2 +vars POS_Name = 9 +vars POS_Strasse = 21 +vars POS_Hnr = 29 +vars POS_Plz = 24 +vars POS_Ort = 25 + +// Variablen - Aufbewahrungsfristen (in Jahren) +vars FRIST_AUSSONDERUNG = 10 // 10 Jahre +vars WM_TRENNZEICHEN = ";" +vars STATUS_ZDA = 0 +vars NEUES_AZ = 0 +vars CHANGE_GERICHT = 0 + +// Datenbanktabelle +vars TB_DokGrpTyp = "DV_PROZ_Doktyp" + +/////////////////////////// proz01_insert_entry_10 ///////////////////////////////////// +// Vor Archivierung +// Uebernehmen der Werte aus der Akte +// Vorbelegen der laufenden Nummer +////////////////////////////////////////////////////////////////////////////////////// +proc proz01_insert_entry_10(user_ref, doc_type_short) +{ + call proz01_split_AZ(1) + call proz01_split_Gericht() +} + +/////////////////////////// proz01_insert_exit_10 /////////////////////////////////////// +// nach dem Import, Rollback noch moeglich +//////////////////////////////////////////////////////////////////////////////////////// +proc proz01_insert_exit_10 (doc_id, file_destination, import_ok, user_ref, doc_type_short) +{ + if(doc_type_short == G01_DS_PROZESSA) + { + // Erstellung des Aktenzeichens + vars update = 0 + call proz01_fill_AZ_Nummer(doc_id, update) + } +} + +//////////////////////////////// proz01_upd_attrib_entry_20 //////////////////////////// +// vor Änderung von Attributwerten +////////////////////////////////////////////////////////////////////////////////////// +proc proz01_upd_attrib_entry_20(doc_id, user_ref, doc_type_short, doc_type_short_new) +{ + if(doc_type_short == G01_DS_ORGANI) + { + if(g02_strAttrHasChanged(doc_id, dok_dat_feld[POS_Name], POS_Name) == 1) + { + CHANGE_GERICHT = 1 + } + else if(g02_strAttrHasChanged(doc_id, dok_dat_feld[POS_Strasse], POS_Strasse) == 1) + { + CHANGE_GERICHT = 1 + } + else if(g02_strAttrHasChanged(doc_id, dok_dat_feld[POS_Hnr], POS_Hnr) == 1) + { + CHANGE_GERICHT = 1 + } + else if(g02_strAttrHasChanged(doc_id, dok_dat_feld[POS_Plz], POS_Plz) == 1) + { + CHANGE_GERICHT = 1 + } + else if(g02_strAttrHasChanged(doc_id, dok_dat_feld[POS_Ort], POS_Ort) == 1) + { + CHANGE_GERICHT = 1 + } + call api_log_error("proz01_upd_attrib_entry_20 Adresse verändert? :CHANGE_GERICHT ") + + } + else + { + call proz01_split_AZ(1) + call proz01_split_Gericht() + + if(g02_strAttrHasChanged(doc_id, dok_dat_feld[POS_Zda], POS_Zda) == 1) + { + STATUS_ZDA = 1 + } + + // Wenn das Feld zum Löschen markiert auf Ja gesetzt wurde, überprüfe ob beim Löschgrund etwas eingetragen wurde. Falls nicht, gebe eine Fehlermeldung aus. + // Wenn das Feld zum Löschen markiert auf Nein gesetzt wurde, dann leere das Feld Löschgrund + if(dok_dat_feld[POS_ZLM] != get_doc_property(doc_id, "doc_field[:POS_ZLM]")) + { + if(dok_dat_feld[POS_ZLM] == G01_STR_JA) + { + if(dok_dat_feld[POS_LOESCHGRD] == "") + { + return -403 //Bitte geben Sie einen Löschgrund an! + } + } + else if(dok_dat_feld[POS_ZLM] == G01_STR_NEIN) + { + dok_dat_feld[POS_LOESCHGRD] = "" + } + } + + + if(doc_type_short == G01_DS_PROZESSA && g02_strAttrHasChanged(doc_id, dok_dat_feld[POS_Jahr], POS_Jahr) == 1) + { + NEUES_AZ = 1 + } + + // hinzugefügt am 13.02.23 - Bei manueller Änderung des Feld Aktenzeichen wird eine Fehlermeldung ausgegeben + //if((user_ref != "d3_async" || user_ref != "Master" ) && g02_strAttrHasChanged(doc_id, dok_dat_feld[POS_AZ], POS_AZ) == 1) + //{ + // call api_log_error("proz01_upd_attrib_entry_20 - Das aktenezichen wurde von :user_ref verändert!") + // return -403 + //} + + + if(doc_type_short == G01_DS_PROZESSA && (g02_strAttrHasChanged(doc_id, dok_dat_feld[POS_Gericht], POS_Gericht) == 1 || g02_strAttrHasChanged(doc_id, dok_dat_feld[POS_GADRESSE], POS_GADRESSE) == 1)) + { + vars DocID, Name, Strasse, PLZ, Ort, Hnr, iCnt + + DBMS ALIAS Name, Strasse, Hnr, PLZ, Ort + DBMS SQL SELECT dok_dat_feld_:POS_Name, dok_dat_feld_:POS_Strasse, dok_dat_feld_:POS_Hnr, dok_dat_feld_:POS_Plz, dok_dat_feld_:POS_Ort \ + FROM firmen_spezifisch \ + WHERE kue_dokuart = 'AAORG' AND dok_dat_feld_:POS_Name = :+dok_dat_feld[POS_Gericht] //AND doku_id = :+doc_id + iCnt = @dmrowcount + DBMS ALIAS + + + + if(Name == "" || Strasse == "" || Hnr == "" || PLZ == "" || Ort == "") + { + //Gerichtsdaten nicht gepflegt! Bitte in der Organisation pflegen. + return -569 + } + + vars Gerichtsadresse = Strasse ## " " ## Hnr ## ", " ## PLZ ## " " ## Ort + call api_log_error("Änderung Ticket vor IF Gerichtsadresse - :Strasse :Hnr :PLZ :Ort") + if(Gerichtsadresse != dok_dat_feld[POS_GADRESSE]) + { + //Gerichtsadresse entspricht nicht dem aktuell ausgewählten Gericht! + return -570 + } + + } + + + } + +} + +//////////////////////////////// ld01_upd_attrib_exit_20 ///////////////////////////// +// UpdateAttribute: NACH Aenderung +// +////////////////////////////////////////////////////////////////////////////////////// +proc proz01_upd_attrib_exit_20(doc_id, error_number, user_ref, doc_type_short, doc_type_short_old) +{ + // Update des Aktenzeichens bei Änderung des Jahres + if(NEUES_AZ == 1 && doc_type_short != G01_DS_ORGANI) + { + NEUES_AZ = 0 + vars update = 1 + call proz01_fill_AZ_Nummer(doc_id, update) + } + + + if(STATUS_ZDA == 1 && doc_type_short != G01_DS_ORGANI) + { + STATUS_ZDA = 0 + + vars strZDA, strDatum + + if(dok_dat_feld[POS_Zda] == G01_STR_JA) + { + strZDA = G01_STR_JA + strDatum = proz01_getAussonderungsdatum(FRIST_AUSSONDERUNG) + } + else if(dok_dat_feld[POS_Zda] == G01_STR_NEIN) + { + strZDA = G01_STR_NEIN + strDatum = "" + } + + call docSearchCreate() + call docSearchAddSearchParam("doc_type_short", "==", G01_DS_PROZESSA) + call docSearchAddSearchParam("doc_type_short", "==", G01_DS_PROZESSD) + call docSearchAddSearchParam("doc_field[:POS_AZ]", "==", dok_dat_feld[POS_AZ]) + call docSearchAddReplacementParam("doc_field[:POS_Zda]", "*", strZDA) + call docSearchAddReplacementParam("doc_field[:POS_AusDat]", "*", strDatum) + call docSearchAddReplacementParam("doc_field[:POS_AusArt]", "*", dok_dat_feld[POS_AusArt]) + call docSearchExecute() + call docSearchDestroy() + } + + if(CHANGE_GERICHT == 1 && doc_type_short == G01_DS_ORGANI) + { + CHANGE_GERICHT = 0 + + vars strDocID, strNameNeu, strStrasseNeu, strPLZNeu, strOrtNeu, strHnrNeu, iCnt + + DBMS ALIAS strNameNeu, strStrasseNeu, strHnrNeu, strPLZNeu, strOrtNeu + DBMS SQL SELECT dok_dat_feld_:POS_Name, dok_dat_feld_:POS_Strasse, dok_dat_feld_:POS_Hnr, dok_dat_feld_:POS_Plz, dok_dat_feld_:POS_Ort \ + FROM firmen_spezifisch \ + WHERE kue_dokuart = 'AAORG' AND doku_id = :+doc_id + iCnt = @dmrowcount + DBMS ALIAS + + call api_log_error("proz01_upd_attrib_exit_20 Datenbankabfrage durchgelaufen iCnt => :iCnt") + + if(iCnt == 1) + { + vars strGAdresse = strStrasseNeu ## " " ## strHnrNeu ## ", " ## strPLZNeu ## " " ## strOrtNeu + call api_log_error("proz01_upd_attrib_exit_20 neue Adresse => :strGAdresse neuer Name => :strNameNeu") + + call docSearchCreate() + call docSearchAddSearchParam("doc_type_short", "==", G01_DS_PROZESSA) + call docSearchAddSearchParam("doc_field[:POS_DOKIDORG]", "==", doc_id) + call docSearchAddReplacementParam("doc_field[:POS_GADRESSE]", "*", strGAdresse) + call docSearchAddReplacementParam("doc_field[:POS_Gericht]", "*", strNameNeu) + call docSearchExecute() + call docSearchDestroy() + } + } +} + +//////////////////////////////// proz01_validate_update_entry_10 /////////////////////// +// Vor Pruefen der Daten vor dem Ändern +////////////////////////////////////////////////////////////////////////////////////// +proc proz01_validate_update_entry_10(user_ref, doc_type_short) +{ + call api_log_error("proz01_validate_update_entry_10 gestartet") + call proz01_split_AZ(1) + call proz01_split_Gericht() +} + +/////////////////////////// proz01_search_entry_10 ///////////////////////////////////// +// vor der Recherche +////////////////////////////////////////////////////////////////////////////////////// +proc proz01_search_entry_10(user_ref, doc_type_short) +{ + call proz01_split_AZ(0) + call proz01_split_Gericht() + +} + + +////////////////// Wertemengenhooks //////////////////////////////////////////////// + +//////////////////// proz01_fill_Klaeger ///////////////////////////////////////////////// +// Wertemengenhook zum fuellen des Felds Kläger mit AZ;Klaeger;Gerichtszeichen +// aus der Datenbank +////////////////////////////////////////////////////////////////////////////////// +proc proz01_fill_Klaeger(repos_id) +{ + vars iRet, iCnt, i + vars strAZ[1000], strKlaeger[1000], strGerichtsZ[1000] + + vars strEingabe = dok_dat_feld[POS_Klaeger] + vars igetippt = @length(strEingabe) + vars igetippt_min = 3 + + if(igetippt >= igetippt_min) + { + DBMS ALIAS strAZ, strKlaeger, strGerichtsZ + DBMS SQL SELECT DISTINCT dok_dat_feld_:POS_AZ, dok_dat_feld_:POS_Klaeger, dok_dat_feld_:POS_GerichtAZ \ + FROM firmen_spezifisch WHERE kue_dokuart = :+G01_DS_PROZESSA AND (dok_dat_feld_:POS_AZ LIKE '%:strEingabe%' OR dok_dat_feld_:POS_Klaeger LIKE '%:strEingabe%') + iRet = @dmretcode + iCnt = @dmrowcount + DBMS ALIAS + + for i = 1 while (i <= iCnt) step 1 + { + d3server_value_char_allowed[i] = strAZ[i] ## ";" ## strKlaeger[i] ## ";" ## strGerichtsZ[i] + d3server_repos_id_allowed[i] = repos_id + } + } + +} + +//////////////////// proz01_fill_Beklagter ///////////////////////////////////////////////// +// Wertemengenhook zum fuellen des Felds Beklagter mit AZ;Beklagter;Gerichtszeichen +// aus der Datenbank +////////////////////////////////////////////////////////////////////////////////// +proc proz01_fill_Beklagter(repos_id) +{ + vars iRet, iCnt, i + vars strAZ[1000], strBeklagter[1000], strGerichtsZ[1000] + + vars strEingabe = dok_dat_feld[POS_Beklaeger] + vars igetippt = @length(strEingabe) + vars igetippt_min = 3 + + /* + if(igetippt >= igetippt_min) + { + DBMS ALIAS strAZ, strBeklagter, strGerichtsZ + DBMS SQL SELECT DISTINCT dok_dat_feld_:POS_AZ, dok_dat_feld_:POS_Beklaeger, dok_dat_feld_:POS_GerichtAZ \ + FROM firmen_spezifisch WHERE kue_dokuart = :+G01_DS_PROZESSA AND (dok_dat_feld_:POS_AZ LIKE '%:strEingabe%' OR dok_dat_feld_:POS_Beklaeger LIKE '%:strEingabe%') + iRet = @dmretcode + iCnt = @dmrowcount + DBMS ALIAS + + for i = 1 while (i <= iCnt) step 1 + { + d3server_value_char_allowed[i] = strAZ[i] ## ";" ## strBeklagter[i] ## ";" ## strGerichtsZ[i] + d3server_repos_id_allowed[i] = repos_id + } + } + + */ + + //Neu erstellt von N.Tietjen 25.10.2022 + if(igetippt >= igetippt_min) + { + DBMS ALIAS d3server_value_char_allowed, d3server_repos_id_allowed + DBMS SQL SELECT DISTINCT dok_dat_feld_:POS_Beklaeger, :+repos_id \ + FROM firmen_spezifisch WHERE kue_dokuart = :+G01_DS_PROZESSA AND dok_dat_feld_:POS_Beklaeger LIKE '%:strEingabe%' + iRet = @dmretcode + iCnt = @dmrowcount + DBMS ALIAS + } + +} + +//////////////////proz01_WM_DOKGRP //////////////////////////////////////////////// +proc proz01_WM_DOKGRP(repos_id) +{ + vars strDokTyp = dok_dat_feld[POS_DokTyp] + + if(strDokTyp != "") + { + DBMS ALIAS d3server_value_char_allowed, d3server_repos_id_allowed + DBMS SQL SELECT DISTINCT Dokumentgruppe, ':repos_id' FROM :TB_DokGrpTyp WHERE Dokumenttyp = :+strDokTyp + DBMS ALIAS + } + else + { + DBMS ALIAS d3server_value_char_allowed, d3server_repos_id_allowed + DBMS SQL SELECT DISTINCT Dokumentgruppe, ':repos_id' FROM :TB_DokGrpTyp + DBMS ALIAS + } +} + +//////////////////proz01_WM_DOKTYP //////////////////////////////////////////////// +proc proz01_WM_DOKTYP(repos_id) +{ + vars strDokGrp = dok_dat_feld[POS_DokGrp] + + if(strDokGrp != "") + { + DBMS ALIAS d3server_value_char_allowed, d3server_repos_id_allowed + DBMS SQL SELECT DISTINCT Dokumenttyp, ':repos_id' FROM :TB_DokGrpTyp WHERE Dokumentgruppe = :+strDokGrp + DBMS ALIAS + } + else + { + DBMS ALIAS d3server_value_char_allowed, d3server_repos_id_allowed + DBMS SQL SELECT DISTINCT Dokumenttyp, ':repos_id' FROM :TB_DokGrpTyp + DBMS ALIAS + } +} + + +/////////////////// UNTERFUNKTIONEN //////////////////////////////////////////////// + +//////////////////// l01_split_AZ ///////////////////////////////////////////////// +// Funktion zum des Felds Aktenzeichen nach AZ;Klaeger;Gerichtszeichen +// und fuellen in die jeweiligen Felder +////////////////////////////////////////////////////////////////////////////////// +proc proz01_split_AZ(NotSearch) +{ + vars strKlaeger = dok_dat_feld[POS_Klaeger] + //call api_log_error("proz01_split_AZ gestartet - strKlaeger => :strKlaeger") + + vars iSplit = api_function("string_split", strKlaeger, WM_TRENNZEICHEN) + + //call api_log_error("proz01_split_AZ - NotSearch => :NotSearch iSplit => :iSplit") + + if(iSplit > 2) + { + // Neu hinzugefügt - Leeren des Feldes Kläger bei der Suche - LH 06.12.22 + dok_dat_feld[POS_Klaeger] = "" + dok_dat_feld[POS_AZ] = api_splitted_string[1] + + if(NotSearch == 1) + { + //call api_log_error("proz01_split_AZ - in NotSearch") + dok_dat_feld[POS_Klaeger] = api_splitted_string[2] + dok_dat_feld[POS_GerichtAZ] = api_splitted_string[3] + } + } +} + +/////////////////////////// proz01_WM_AZ_Nummer ////////////////////////////////////// +// Wertemenge für laufende Nummer +// Zusammengesetzt aus: Fortlaufende Nummer, Herrsteller, Anwendungsbezeichnung +////////////////////////////////////////////////////////////////////////////////////// +proc proz01_fill_AZ_Nummer(doc_id, update) +{ + vars iRet, iCnt + vars strNummer, sqlCount + vars strJahr = dok_dat_feld[POS_Jahr] + vars strLNR = dok_dat_feld[POS_AZ] + + if (update == 0) + { + /*DBMS ALIAS sqlCount + DBMS SQL SELECT COUNT(*) FROM firmen_spezifisch WHERE kue_dokuart = :+G01_DS_PROZESSA + iRet = @dmretcode + if(iRet != 0 && iRet != DM_NO_MORE_ROWS) + { + call api_log_error ("proz01_fill_AZ_Nummer => Fehler beim Ermitteln von Prozessakten. FEHLER: :iRet") + } + DBMS ALIAS + */ + DBMS ALIAS sqlCount + DBMS SQL SELECT TOP (1) right(dok_dat_feld_:POS_AZ, 4) + 1 from firmen_spezifisch WHERE kue_dokuart = :+G01_DS_PROZESSA ORDER BY right(dok_dat_feld_:POS_AZ,4) DESC + iRet = @dmretcode + if(iRet != 0 && iRet != DM_NO_MORE_ROWS) + { + call api_log_error ("proz01_fill_AZ_Nummer => Fehler beim Ermitteln von Prozessakten. FEHLER: :iRet") + } + DBMS ALIAS + + + vars string strCount = sqlCount + iRet = api_function ("string_fill_leading_char", strCount, 0, 4) + strNummer = strJahr ## "-" ## api_converted_string + } + else if(update == 1) + { + vars strTrennzeichen = "-" + vars iSplit = api_function("string_split", strLNR, strTrennzeichen) + if (iSplit > 1) + { + strNummer = strJahr ## "-" ## api_splitted_string[2] + } + } + + iRet = api_function ("attribute_update_single", POS_AZ , strNummer, "", doc_id, "") + + if(iRet != 0 ) + { + call api_log_error ("proz01_fill_AZ_Nummer => Fehler beim Setzen des Aktenzeichens für :doc_id . FEHLER: :iRet") + } + + // Vererbung des neuen Gerichtsaktenzeichens auf die darunterliegenden Dokumente - soll nicht umgesetzt werden + /*if(iRet == 0 && update == 1) + { + call docSearchCreate() + call docSearchAddSearchParam("doc_type_short", "==", G01_DS_PROZESSD) + call docSearchAddSearchParam("doc_field[:POS_AZ]", "==", strLNR) + call docSearchAddReplacementParam("doc_field[:POS_AZ]", "*", strNummer) + call docSearchExecute() + call docSearchDestroy() + } */ + + // Kategorie-Kürzel ermitteln + //strNummer = api_str_sub( strNummer, 4, 4) //Position Trennzeichen für Kategorie-Kürzel + //call api_log_error("proz01_fill_AZ_Nummer nach splitten der Funktion strNummer => :strNummer ") + + /*if(iCnt == 1 && strNummer != -1) + { + vars strLNr = strNummer + 0001 + iRet = api_function ("string_fill_leading_char", strLNr, 0, 4) + call api_log_error("proz01_fill_AZ_Nummer nach splitten der Funktion strLNr => :strLNr iRet => :iRet") + if(iRet >= 0) + { + d3server_value_char_allowed = strJahr ## "-" ## strLNr + d3server_repos_id_allowed = repos_id + } + } */ +} + +////////////////////////////////////////////////////////////////////// +// Auslesen des Gerichts und dessen Adresse aus der Adressverwaltung +// Einfügen in die Felder Gericht und Gerichtadresse +///////////////////////////////////////////////////////////////////// +proc proz01_getGericht(repos_id, user, doc_type_short) +{ + vars strGericht = dok_dat_feld[POS_Gericht] + vars strGAdresse = dok_dat_feld[POS_GADRESSE] + vars strEingabe = dok_dat_feld[POS_Strasse] + + vars strGName[1000], strGStrasse[1000], strGHNR[1000], strGPLZ[1000], strGOrt[1000], strDokId[1000] + vars iCnt, iRet, i + vars igetippt = @length(strGericht) + vars igetippt_min = 2 + + if(igetippt >= igetippt_min) + { + /*DBMS ALIAS strGName, strGStrasse, strGHNR, strGPLZ, strGOrt + DBMS SQL SELECT dok_dat_feld_:POS_Name, dok_dat_feld_:POS_Strasse, dok_dat_feld_:POS_Hnr, dok_dat_feld_:POS_Plz, dok_dat_feld_:POS_Ort \ + FROM firmen_spezifisch \ + WHERE kue_dokuart = 'AAORG' AND dok_dat_feld_:POS_Name like '%:strGericht%' + iCnt = @dmrowcount + iRet = @dmretcode + DBMS ALIAS + */ + + // Sucht die Adressen raus, bei denen der Benutzer in der federfuehrenden OE Gruppe ist oder bei der keine federfuehrende OE eingetragen ist + DBMS ALIAS strGName, strGStrasse, strGHNR, strGPLZ, strGOrt, strDokId + DBMS SQL SELECT fs.dok_dat_feld_:POS_Name, fs.dok_dat_feld_:POS_Strasse, fs.dok_dat_feld_:POS_Hnr, fs.dok_dat_feld_:POS_Plz, fs.dok_dat_feld_:POS_Ort, fs.doku_id \ + FROM firmen_spezifisch fs \ + LEFT JOIN benutzergruppen gruppe \ + ON gruppe.benutzergruppe = fs.dok_dat_feld_:POS_FFOE \ + Left JOIN benutzer_in_gruppe bInGrp \ + ON gruppe.gruppen_id = bInGrp.benutzergruppe \ + WHERE fs.kue_dokuart = 'AAORG' AND (bInGrp.benutzername = :+user OR fs.dok_dat_feld_:POS_FFOE IS NULL) AND dok_dat_feld_:POS_Name LIKE '%:strGericht%' + iCnt = @dmrowcount + iRet = @dmretcode + DBMS ALIAS + + + for i = 1 while (i <= iCnt) step 1 + { + d3server_value_char_allowed[i] = strGName[i] ## "|" ## strGStrasse[i] ## " " ## strGHNR[i] ## ", " ## strGPLZ[i] ## " " ## strGOrt[i] ## "|" ## strDokId[i] + d3server_repos_id_allowed [i] = repos_id + } + } + +} + +//////////////////// l01_split_Gericht ///////////////////////////////////////////////// +// Funktion zum des Felds Aktenzeichen nach AZ;Klaeger;Gerichtszeichen +// und fuellen in die jeweiligen Felder +////////////////////////////////////////////////////////////////////////////////// +proc proz01_split_Gericht() +{ + vars strGericht = dok_dat_feld[POS_Gericht] + vars strTrennzeichen = "|" + + vars iSplit = api_function("string_split", strGericht, strTrennzeichen) + + if(iSplit > 1) + { + dok_dat_feld[POS_Gericht] = api_splitted_string[1] + dok_dat_feld[POS_GADRESSE] = api_splitted_string[2] + dok_dat_feld[POS_DOKIDORG] = api_splitted_string[3] + } +} + +/** +# Funktion: Liefert das Aussonderungsdatum anhand einer Frist +# Parameter: iFrist - Aufbewahrungsfrist +# Rückgabewert: - +**/ +String proc proz01_getAussonderungsdatum(iFrist) +{ + vars dAussondatum = "" + + vars heutigesDatum = aktuelles_datum_deu + + dAussondatum = heutigesDatum(7,4) + iFrist + dAussondatum = "31.12." ## dAussondatum + + return dAussondatum +} diff --git a/Stadt Essen/sg02_Sozialakte.groovy b/Stadt Essen/sg02_Sozialakte.groovy new file mode 100644 index 0000000..55a9236 --- /dev/null +++ b/Stadt Essen/sg02_Sozialakte.groovy @@ -0,0 +1,621 @@ + + +// (1) Global d.3 libraries +import com.dvelop.d3.server.core.D3Interface +import com.dvelop.d3.server.Document +import com.dvelop.d3.server.User +import com.dvelop.d3.server.Condition +import com.dvelop.d3.server.DocumentType +import groovy.sql.GroovyRowResult + +import com.dvelop.d3.server.ValueSet +import com.dvelop.d3.server.RepositoryField + +import java.sql.Timestamp +import java.util.Calendar +import java.text.SimpleDateFormat + +// Libraries to handle the different hook types +import com.dvelop.d3.server.Entrypoint + +public class sg02_sozialakte { + + // Dokumentarten + private static String SG02_DS_SOZ_AKTE = "ASOZ"; + private static String SG02_DS_SOZ_DOKU = "DSOZ"; + private static String G01_DS_POSTEINGANG = ""; + + // DB-Positionen + private static int POS_SACHGEBIET = 1 // Sachgebiet + private static int POS_AZ = 2 // Aktenzeichen + private static int POS_NACHNAME = 3 // Nachname (HV) + private static int POS_VORNAME = 4 // Vorname (HV) + private static int POS_STRASSE = 9 // Straße + private static int POS_PLZ = 10 // PLZ + private static int POS_ZDA = 13 // zdA-verfügt + private static int POS_DOKTYP = 14 // Dokumenttyp + private static int POS_DOKGRP = 15 // Dokumentgruppe + private static int POS_HNR = 16 // Hausnummer + private static int POS_ORT = 17 // Ort + private static int POS_AUSART = 23 // Aussonderungsart + private static int POS_STORNO = 27 // in LISSA storbniert + private static int POS_WIDERSPRUCH = 30 // Interne 50-1-4 Widerspruchsnummer + private static int POS_AZ_RECHT = 31 // Aktenzeichen Rechtsanwälte + private static int POS_LOESCH_FLAG = 33 // zum Löschen markiert + private static int POS_GEBURTSDATUM = 50 // Geburtsdatum (HV) + private static int POS_AUSSONDDAT = 51 // Aussonderungsdatum + private static int POS_LOESCHGRD = 35 // Löschgrund + private static int POS_ZLM = 33 // Zum Löschen Markiert + + // DB Tabellen + private static String TB_LISSA_DOKTYP = "CS_LISSA_DOKTYP" + + // kundenspezifische Werte + private static int FRIST_AUSSONDERUNG = 84 + + // statische Werte (nicht ändern) + private static int STATUS_SACHGEBIET = 0 + private static int STATUS_ZDA = 0 + private static int SG01_SCHALTER_POST = 0 //Diesen schalter auf 1 setzen, wenn die Posteingangsbearbeitung in Verbindung mit Sozialdokumenten genutzt wird. + private static String STR_JA = "Ja" + private static String STR_NEIN = "Nein" + private static int laengeAZ = 8 // Länge des Aktenzeichens + + private static String G01_STR_NEIN = "Nein" + private static String G01_STR_JA = "Ja" + + + @Entrypoint( entrypoint = "hook_insert_entry_10" ) + public int hook_insert_entry_10(D3Interface d3, User user, DocumentType docType, Document doc) + { + d3.log.error("START | hook_insert_entry_10 " + doc.id() ); + + sg02_split_AZ( d3, doc, 0 ); + def iRet = sg02_fuelleFelder( d3, doc, docType.id ); + d3.log.error("ENDE | hook_insert_entry_10 " + doc.id() ); + return iRet; + } + + + @Entrypoint( entrypoint = "hook_new_version_entry_10" ) + public int hookNewVersionEntry10(D3Interface d3, Document doc, String fileSource, String fileDestination, User user, DocumentType docType) + { + d3.log.error("START | hookNewVersionEntry10 " + doc.id() ); + + sg02_split_AZ( d3, doc, 0 ); + def iRet = sg02_fuelleFelder( d3, doc, docType.id ); + d3.log.error("ENDE | hookNewVersionEntry10 " + doc.id() ); + return iRet; + } + + + + @Entrypoint( entrypoint = "hook_upd_attrib_entry_20" ) + public int hookUpdAttribEntry20(D3Interface d3, Document doc, User user, DocumentType docType, DocumentType docTypeNew) + { + d3.log.error("START | hookUpdAttribEntry20" + doc.id() ); + def rc = 0; + + // temporäres Objekt holen, um zu prüfen, das sich Eigenschaften geändert haben + oldDocAttributes = d3.archive.getDocument(doc.id()); + + sg02_split_AZ( d3, doc, 0); + + if ( docType.id == SG02_DS_SOZ_AKTE ) + { + STATUS_SACHGEBIET = 1; + } + + if ( oldDocAttributes.field[ POS_ZDA ] == doc.field[ POS_ZDA ] ) + { + def massen_sql = "select f.doku_id from firmen_spezifisch f, phys_datei p where f.kue_dokuart = 'SG02_DS_SOZ_DOKU' and f.dok_dat_feld_" + POS_AZ + " = '" + doc.field[ POS_AZ ] + "' and p.logi_verzeichnis = 'Be' and f.doku_id = p.doku_id"; + def massen_ergebnis = d3.sql.executeAndGet( massen_sql ); + + if ( massen_ergebnis.size() > 0 ) + { + d3.log.error( "[sg02_upd_attrib_entry_20] Sozialakte (" + doc.field[POS_AZ] + ") kann nicht zdA-verfügt werden da noch Dokumente in Bearbeitung sind." ); + rc = -350; + } + + if ( rc == 0 ) + { + STATUS_ZDA = 1; + } + } + + if ( docType.id == SG02_DS_SOZ_DOKU ) + { + if ( doc.field[ POS_ZLM ] == STR_JA ) + { + if ( doc.field[ POS_LOESCHGRD ] == "" ) + { + return -403; + } + } + else if ( doc.field[ POS_ZLM ] == STR_NEIN ) + { + doc.field[ POS_LOESCHGRD ] = ""; + } + + if ( oldDocAttributes.field[ POS_STORNO ] == doc.field[ POS_STORNO ] ) + { + if ( doc.field[ POS_STORNO ] == G01_STR_JA ) + { + doc.field[ POS_LOESCH_FLAG ] = G01_STR_JA; + doc.field[ POS_LOESCHGRD ] = "In LISSA storniert."; + } + } + + } + + if ( rc == 0 && docType.id == G01_DS_POSTEINGANG ) + { + sg02_clear_vorname( d3, doc, docType.id ); + } + + d3.log.error("ENDE | hookUpdAttribEntry20" + doc.id() ); + return rc; + } + + + + @Entrypoint( entrypoint = "hook_upd_attrib_exit_20" ) + public int hookUpdAttribExit20(D3Interface d3, Document doc, Integer errorCode, User user, DocumentType docType, DocumentType docTypeOld) + { + d3.log.error("START | hookUpdAttribExit20 " + doc.id() ); + + if ( errorCode == 0 ) + { + if ( STATUS_SACHGEBIET == 1 ) + { + STATUS_SACHGEBIET = 0; + + // hier wird das docSearchCreate übernommen; dafür gibt es aber aktuell keine Entsprechung in Groovy. + // das wird in Groovy direkt umgesetzt; d.h. man macht das manuell, was der JPL-Massenänderungs-Code en gros macht: + + def massen_sql = "select doku_id from firmen_spezifisch where kue_dokuart = '" + SG02_DS_SOZ_DOKU + "' and dok_dat_feld_" + POS_AZ + " = '" + doc.field(POS_AZ) + "'"; + + def massen_ergebnis = d3.sql.executeAndGet( massen_sql ); + + if ( massen_ergebnis.size() > 0 ) + { + int i; + for ( i = 0 ; i < massen_ergebnis.size(); i++ ) + { + def updateDoc = d3.archive.getDocument( massen_ergebnis[ i ].doku_id ); + + updateDoc.field[ POS_SACHGEBIET ] = doc.field[ POS_SACHGEBIET ]; + updateDoc.updateAttributes( "Master" ); + } + } + } + + if ( STATUS_ZDA == 1 ) + { + STATUS_ZDA = 0; + + def strZDA, strDatum, strArt; + + if ( doc.field[ POS_ZDA ] == G01_STR_JA ) + { + strZDA = G01_STR_JA; + strDatum = sg02_getDate( FRIST_AUSSONDERUNG, 1 ); + } + else if ( doc.field[POS_ZDA] == G01_STR_NEIN ) + { + strZDA = G01_STR_NEIN; + strDatum = ""; + } + + strArt = doc.field[ POS_AUSART ] + if ( strArt == "" ) + { + strArt = "B"; + } + + // hier wird das docSearchCreate übernommen; dafür gibt es aber aktuell keine Entsprechung in Groovy. + // das wird in Groovy direkt umgesetzt; d.h. man macht das manuell, was der JPL-Massenänderungs-Code en gros macht: + + def massen_sql = "select doku_id from firmen_spezifisch where ( kue_dokuart = '" + SG02_DS_SOZ_AKTE + "' or kue_dokuart = '" + SG02_DS_SOZ_DOKU + "' )and dok_dat_feld_" + POS_AZ + " = '" + doc.field(POS_AZ) + "'"; + + def massen_ergebnis = d3.sql.executeAndGet( massen_sql ); + + if ( massen_ergebnis.size() > 0 ) + { + int i; + for ( i = 0 ; i < massen_ergebnis.size(); i++ ) + { + def updateDoc = d3.archive.getDocument( massen_ergebnis[ i ].doku_id ); + + updateDoc.field[ POS_ZDA ] = strZDA; + updateDoc.field[ POS_AUSSONDDAT ] = strDatum; + updateDoc.field[ POS_AZ ] = strArt; + // man könnte updateAttributes auch mit dem zweiten Parameter "true" aufrufen, das sollte dann das Ausführen von Hooks + // für das Update unterbinden. Beim JPL-Masterdata-update läuft das vermutlich nämlich genau so. Machen wir hier aber erstmal nicht. + updateDoc.updateAttributes( "Master" ); + } + } + + + } + + } + + d3.log.error("ENDE | hookUpdAttribExit20 " + doc.id() ); + return 0; + } + + + + @Entrypoint( entrypoint = "hook_search_entry_10" ) + public int hookSearchEntry10(D3Interface d3, User user, DocumentType docType, Document searchContext) + { + d3.log.error("START | hookSearchEntry10 " ); + + sg02_split_AZ( d3, doc, 1 ); + + if ( isNumeric( doc.field[ POS_AZ ] ) ) + { + if ( doc.field[ POS_AZ ].length() > 0 && doc.field[ POS_AZ ].length() < laengeAZ ) + { + doc.field[ POS_AZ ] = sg02_FillLeadingChar( doc.field[ POS_AZ ] ); + } + } + + d3.log.error("ENDE | hookSearchEntry10 " ); + return 0; + } + + + + @Entrypoint( entrypoint = "hook_validate_update_entry_10" ) + public int hookValidateUpdateEntry10(D3Interface d3, User user, DocumentType docType, Document doc, String nextcall) + { + d3.log.error("START | hookValidateUpdateEntry10 " + doc.id() ); + + sg02_split_AZ( d3, doc, 0 ); + + if ( doc.field[ POS_AZ ].length() < laengeAZ ) + { + doc.field[ POS_AZ ] = sg02_FillLeadingChar( doc.field[ POS_AZ ] ); + } + + def rc = sg02_fuelleFelder( d3, doc, docType.id ); + + d3.log.error("ENDE | hookValidateUpdateEntry10 " + doc.id() ); + return rc; + } + + + +// ---------------------------------- Wertemengen ---------------------------------- + + //////////////////////////////// sg02_SOZ_WM_Aktenzeichen //////////////////////////// + // -> Funktion füllt das Feld Aktenzeichen mit Wertemenge + // aus der d.3 Datenbank + ////////////////////////////////////////////////////////////////////////////////////// + @ValueSet( entrypoint = "sg02_SOZ_WM_Aktenzeichen" ) + def sg02_SOZ_WM_Aktenzeichen(D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc ) + { + if ( doc.field[ POS_AZ ] != null ) + { + if ( doc.field[ POS_AZ ].length() > 2 ) + { + def sqlQuery = "select dok_dat_feld_" + POS_AZ + " POS_AZ, dok_dat_feld_" + POS_NACHNAME + " POS_NACHNAME, dok_dat_feld_" + POS_VORNAME + " POS_VORNAME, dok_dat_feld_" + POS_SACHGEBIET + " POS_SACHGEBIET, CONVERT(varchar, dok_dat_feld_" + POS_GEBURTSDATUM + ", 104) POS_GEBURTSDATUM from firmen_spezifisch where kue_dokuart = '" + SG02_DS_SOZ_AKTE + "' and ( dok_dat_feld_" + POS_AZ + " like '%" + doc.field[ POS_AZ ] + "%' or dok_dat_feld_" + POS_NACHNAME + " like '%" + doc.field[ POS_AZ ] + "%' or dok_dat_feld_" + POS_VORNAME + " like '%" + doc.field[ POS_AZ ] + "%' or dok_dat_feld_" + POS_SACHGEBIET + " like '%" + doc.field[ POS_AZ ] + "%' or CONVERT(varchar, dok_dat_feld_" + POS_GEBURTSDATUM + ", 104) like '%" + doc.field[ POS_AZ ] + "%' ) "; + + def resultRows = d3.sql.executeAndGet( sqlQuery ); + + if ( resultRows.size() > 0 ) + { + reposField.provideValuesForValueSet( resultRows.collect{ it.POS_AZ + "~" + it.POS_NACHNAME + "~" + it.POS_VORNAME + "~" + it.POS_GEBURTSDATUM + "~" + it.POS_SACHGEBIET } ); + } + } + } + } + + + + //////////////////////////////// sg02_SOZ_WM_Dokumentgruppe ////////////////////////// + // + // füllt das Feld Dokumenttruppe anhand des Feldes Kategorie + ////////////////////////////////////////////////////////////////////////////////////// + @ValueSet( entrypoint = "sg02_SOZ_WM_Dokumentgruppe" ) + def sg02_SOZ_WM_Dokumentgruppe(D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc ) + { + def resultRows = d3.sql.executeAndGet( "select distinct Dokumentgruppe from " + TB_LISSA_DOKTYP ); + + if ( resultRows.size() > 0 ) + { + reposField.provideValuesForValueSet( resultRows.collect{ it.Dokumentgruppe } ); + } + } + + + + //////////////////////////////// sg02_SOZ_WM_Dokumenttyp ///////////////////////////// + // + // füllt das Feld Dokumenttyp anhand des Feldes Dokumentgruppe + ////////////////////////////////////////////////////////////////////////////////////// + @ValueSet( entrypoint = "sg02_SOZ_WM_Dokumenttyp" ) + def sg02_SOZ_WM_Dokumenttyp(D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc ) + { + def sqlQuery = ""; + + if ( doc.field[ POS_AZ ] != null && ! doc.field[ POS_AZ ].isEmpty() ) + { + sqlQuery = "select distinct Dokumenttyp from " + TB_LISSA_DOKTYP + " where Dokumentgruppe = '" + doc.field[ POS_DOKGRP ] + "' "; + } + else + { + sqlQuery = "select distinct Dokumenttyp from " + TB_LISSA_DOKTYP; + } + + + def resultRows = d3.sql.executeAndGet( sqlQuery ); + + if ( resultRows.size() > 0 ) + { + reposField.provideValuesForValueSet( resultRows.collect{ it.Dokumenttyp } ); + } + + } + + + + //////////////////////////////// sg02_SOZ_WM_WiderspruchNr ///////////////////////////// + // + // füllt das Feld Widerspruchsnummern anhand des Feldes Aktenzeichen + ////////////////////////////////////////////////////////////////////////////////////// + @ValueSet( entrypoint = "sg02_SOZ_WM_WiderspruchNr" ) + def sg02_SOZ_WM_WiderspruchNr(D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc ) + { + sg02_split_AZ( d3, doc, 1 ); + + def sqlQuery = ""; + + if ( doc.field[ POS_AZ ] != "" ) + { + sqlQuery = "select distinct dok_dat_feld_" + POS_WIDERSPRUCH + " POS_WIDERSPRUCH from firmen_spezifisch where dok_dat_feld_" + POS_AZ + " = '" + doc.field[ POS_AZ ] + "' "; + } + else + { + sqlQuery = "select distinct dok_dat_feld_" + POS_WIDERSPRUCH + " POS_WIDERSPRUCH from firmen_spezifisch"; + } + + + def resultRows = d3.sql.executeAndGet( sqlQuery ); + + if ( resultRows.size() > 0 ) + { + reposField.provideValuesForValueSet( resultRows.collect{ it.POS_WIDERSPRUCH } ); + } + + } + + + + //////////////////////////////// sg02_SOZ_WM_AZ_Rechtsanwalt ///////////////////////////// + // + // füllt das Feld Aktenzeichen Rechtsanwälte anhand des Feldes Aktenzeichen + ////////////////////////////////////////////////////////////////////////////////////// + @ValueSet( entrypoint = "sg02_SOZ_WM_AZ_Rechtsanwalt" ) + def sg02_SOZ_WM_AZ_Rechtsanwalt(D3Interface d3, RepositoryField reposField, User user, DocumentType docType, int rowNo, int validate, Document doc ) + { + sg02_split_AZ( d3, doc, 1 ); + + def sqlQuery = ""; + + if ( doc.field[ POS_AZ ] != "" ) + { + sqlQuery = "select distinct dok_dat_feld_" + POS_AZ_RECHT + " POS_AZ_RECHT from firmen_spezifisch where dok_dat_feld_" + POS_AZ + " = '" + doc.field[ POS_AZ ] + "' "; + } + else + { + sqlQuery = "select distinct dok_dat_feld_" + POS_AZ_RECHT + " POS_AZ_RECHT from firmen_spezifisch"; + } + + + def resultRows = d3.sql.executeAndGet( sqlQuery ); + + if ( resultRows.size() > 0 ) + { + reposField.provideValuesForValueSet( resultRows.collect{ it.POS_AZ_RECHT } ); + } + + } + + + +// ---------------------------------- Funktionen ---------------------------------- + + + + /////////////////////////// sg02_isSozial ////////////////////////////////////////// + // Püft ob das übergebene Dokumentartkürzel zur Lösung gehört + ////////////////////////////////////////////////////////////////////////////////////// + public int sg02_isSozial(doc_type_short) + { + if ( doc_type_short == SG02_DS_SOZ_AKTE || doc_type_short == SG02_DS_SOZ_DOKU ) + { + return true; + } + return false; + } + + + + //////////////////////////////// sg02_split_AZ /////////////////////////////////////// + // -> Ermittelt den Wert Aktenzeichen aus der Wertemenge + ////////////////////////////////////////////////////////////////////////////////////// + + public void sg02_split_AZ( D3Interface d3, Document doc, int IsSearch ) + { + if ( doc.field[ POS_AZ ] != null ) + { + if ( ! doc.field[ POS_AZ ].isEmpty() ) + { + if ( doc.field[ POS_AZ ].indexOf( "~" ) >= 0 ) + { + def tok = doc.field[ POS_AZ ].tokenize( "~" ); + + if ( tok.size() > 1 ) + { + doc.field[ POS_AZ ] = tok[ 0 ]; + + if ( IsSearch == 0 ) + { + doc.field[ POS_NACHNAME ] = tok[ 1 ]; + doc.field[ POS_VORNAME ] = tok[ 2 ]; + SimpleDateFormat dateFormat = new SimpleDateFormat( "dd.MM.yyyy" ); + Date parsedDate = dateFormat.parse( tok[ 3 ] ); + doc.field[ POS_GEBURTSDATUM ] = new Timestamp( parsedDate.getTime() ); + doc.field[ POS_SACHGEBIET ] = tok[ 4 ]; + } + } + } + } + } + } + + + + /////////////////////////// sg02_getDate ///////////////////////////////////////////// + // Gibt das Tagesdatum + Frist zurück + // + // strFrist Die Frist in Monaten um die das Tagesdatum erhoeht wird + // iEndOfYear Unterscheidung ob der genaue Wert oder der letzte Tag des Jahres berechnet wird + // 0 = genauer Wert / 1 = Ende des Jahres + ////////////////////////////////////////////////////////////////////////////////////// + + public String sg02_getDate( int iFrist, int iEndOfYear ) + { + String strDatum = ""; + String strEndOfYear = ""; + + def STATEMENT = "SELECT DATEADD(month, " + iFrist + ", GETDATE()) zeitstempel, '31.12.' + CONVERT(varchar,YEAR(DATEADD(month, " + iFrist + ", GETDATE()))) datum"; + + def resultRows = d3.sql.executeAndGet( STATEMENT ); + + if ( resultRows.size() > 0 ) + { + if ( iEndOfYear == 1 ) + { + return resultRows[ 0 ].datum; + } + else + { + return resultRows[ 0 ].zeitstempel; + } + } + } + + + + ////////////////////////// sg02_fuelleFelder ///////////////////////////////////////////// + + + public int sg02_fuelleFelder( D3Interface d3, Document doc, String doc_type_short ) + { + int retVal = 0; + + if ( doc_type_short == SG02_DS_SOZ_DOKU ) + { + def STATEMENT = "select doku_id from firmen_spezifisch where kue_dokuart = '" + SG02_DS_SOZ_AKTE + "' and dok_dat_feld_" + POS_AZ + " = '" + doc.field[ POS_AZ ] + "' "; + + def treffer = d3.sql.executeAndGet( (String) STATEMENT ); + + if ( treffer.size() > 0 ) + { + int i; + for ( i = 0 ; i < treffer.size(); i++ ) + { + def updateDoc = d3.archive.getDocument( treffer[ i ].doku_id ); + + if ( updateDoc.field[ POS_ZDA ] == G01_STR_JA ) + { + d3.log.error( "[sg02_fuelleFelder] Sozialakte (:dok_dat_feld[POS_AZ]) ist zdA-verfügt und darf nicht bearbeitet werden." ); + retVal = -316; //Änderung oder Archivierung nicht erlaubt - Akte oder Vorgang ist schon abgeschlossen + } + else + { + + + if ( doc.field[ POS_SACHGEBIET ] == "" ) + { + doc.field[ POS_SACHGEBIET ] = updateDoc.field[ POS_SACHGEBIET ]; + } + + if ( doc.field[ POS_NACHNAME ] == "" ) + { + doc.field[ POS_NACHNAME ] = updateDoc.field[ POS_NACHNAME ]; + } + + if ( doc.field[ POS_VORNAME ] == "" ) + { + doc.field[ POS_VORNAME ] = updateDoc.field[ POS_VORNAMEPOS_VORNAME ]; + } + + if ( doc.field[ POS_STRASSE ] == "" ) + { + doc.field[ POS_STRASSE ] = updateDoc.field[ POS_STRASSE ]; + } + + if ( doc.field[ POS_PLZ ] == "" ) + { + doc.field[ POS_PLZ ] = updateDoc.field[ POS_PLZ ]; + } + + if ( doc.field[ POS_HNR ] == "" ) + { + doc.field[ POS_HNR ] = updateDoc.field[ POS_HNR ]; + } + + if ( doc.field[ POS_ORT ] == "" ) + { + doc.field[ POS_ORT ] = updateDoc.field[ POS_ORT ]; + } + + if ( doc.field[ POS_GEBURTSDATUM ] == "" ) + { + doc.field[ POS_GEBURTSDATUM ] = updateDoc.field[ POS_GEBURTSDATUM ]; + } + + + } + } + } + } + + return retVal; + } + + + + + // Funktion: Wenn ein Posteingangsdokument in ein Sozialdokument umgewandelt wird, muss das Dokdatfeld Vorname geleert werden, + // da es ansonsten in der Aktenbildung nach oben vererbt wird. In der Posteingangsbearbeitung ist das Dokdatfeld 4 Original behalten. + // Rückgabewert: + // 0 = wurde geleert. + public int sg02_clear_vorname( D3Interface d3, Document doc, String doc_type_short ) + { + if ( doc.field[ POS_VORNAME ] == "Nein" || doc.field[ POS_VORNAME ] == "Ja" ) + { + doc.field[ POS_VORNAME ] = ""; + } + + return 0; + } + + + + // Kommentar in JPL-Datei passt nicht zur Funktion. + public String sg02_FillLeadingChar( String strAZ ) + { + def paddedString = String.format( "%08d", strAZ ); + + return paddedString; + } + +} + + diff --git a/Stadt Essen/sg02_Sozialakte.jpl b/Stadt Essen/sg02_Sozialakte.jpl new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/Stadt Essen/sg02_Sozialakte.jpl @@ -0,0 +1 @@ + \ No newline at end of file