// 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.DocumentTypeAttribute; import com.dvelop.d3.server.DocumentType; import com.dvelop.d3.server.RepositoryField; // Libraries to handle the diferent hook types import com.dvelop.d3.server.Entrypoint; // Foreign Libraries: import com.dvelop.d3.server.exceptions.D3Exception import com.google.gson.JsonArray import com.google.gson.JsonElement import com.google.gson.JsonObject import com.google.gson.JsonParser import groovy.json.StringEscapeUtils import org.apache.http.HttpEntity import org.apache.http.client.methods.CloseableHttpResponse import org.apache.http.client.methods.HttpGet import org.apache.http.client.methods.HttpPost import org.apache.http.entity.StringEntity import org.apache.http.impl.client.CloseableHttpClient import org.apache.http.impl.client.HttpClientBuilder import org.apache.http.util.EntityUtils import groovy.json.JsonSlurper import java.nio.charset.StandardCharsets; import constantValues; public class D3Hooks { @Entrypoint( entrypoint = "hook_insert_exit_20" ) public int insertExit_20( D3Interface d3, Document doc, String fileDestination, int importOk, User user, DocumentType docType ) { def empfaenger = []; def username = getUserIdpId( d3, "D3-User", constantValues.repo_id, constantValues.baseUri, constantValues.authUsr ); xlog( d3, 2, "username " + username ); empfaenger.push( username ); def e = createTask( d3, user, docType, doc, "Neues Dokument", "Es wurde ein neues Dokument importiert: " + doc.id, empfaenger, constantValues.baseUri, constantValues.authUsr, constantValues.repo_id ); return 0; } @Entrypoint( entrypoint = "hook_validate_import_entry_10" ) public int hook_validate_import_entry_10( D3Interface d3, User user, DocumentType docType, Document doc, String nextcall ) { d3.log.error( "START hook_validate_import_entry_10 " ); if ( doc.getStatus() != "DOC_STAT_RELEASE" ) { doc.setStatus( "Freigabe" ); } if ( isRepoIdInDocType( d3, docType.id, constantValues.GeschPNrId ) ) // Kundenstammdaten { if ( doc.field[ 6 ] ) { if ( doc.field[ 6 ].indexOf( "|" ) > 0 ) { def werte = doc.field[ 6 ].tokenize( "|" ); if ( werte[ 0 ].length() > 0 ) // Name { doc.field[ 5 ] = werte[ 0 ].trim(); } if ( werte[ 1 ].length() > 0 ) // Strasse { doc.field[ 7 ] = werte[ 1 ].trim(); } if ( werte[ 2 ].length() > 0 ) // PLZ { doc.field[ 8 ] = werte[ 2 ].trim(); } if ( werte[ 3 ].length() > 0 ) // Ort { doc.field[ 9 ] = werte[ 3 ].trim(); } if ( werte[ 4 ].length() > 0 ) // Land { doc.field[ 10 ] = werte[ 4 ].trim(); } if ( werte[ 5 ].length() > 0 ) // Nummer { doc.field[ 6 ] = werte[ 5 ].trim(); } } } if ( doc.field[ 5 ] ) { if ( doc.field[ 5 ].indexOf( "|" ) > 0 ) { def werte = doc.field[ 5 ].tokenize( "|" ); if ( werte[ 0 ].length() > 0 ) // Name { doc.field[ 5 ] = werte[ 0 ].trim(); } if ( werte[ 1 ].length() > 0 ) // Strasse { doc.field[ 7 ] = werte[ 1 ].trim(); } if ( werte[ 2 ].length() > 0 ) // PLZ { doc.field[ 8 ] = werte[ 2 ].trim(); } if ( werte[ 3 ].length() > 0 ) // Ort { doc.field[ 9 ] = werte[ 3 ].trim(); } if ( werte[ 4 ].length() > 0 ) // Land { doc.field[ 10 ] = werte[ 4 ].trim(); } if ( werte[ 5 ].length() > 0 ) // Nummer { doc.field[ 6 ] = werte[ 5 ].trim(); } } } } /////////////////////////// // eingefügt von CALB/d.velop AG / 2024.06.12 / Setzen des Mandanten bei SAP-Dokumenten (Mandant = 240) if ( ( isRepoIdInDocType( d3, docType.id, constantValues.MandantId ) ) && ( isRepoIdInDocType( d3, docType.id, constantValues.BuKrsId ) ) ) // Mandant / Buchungskreis ist in der Dokumentart enthalten { if ( doc.field[ 39 ] == "240" ) { if ( doc.field[ 1 ] ) { if ( doc.field[ 1 ].indexOf( "|" ) > 0 ) { // wird weiter unten behandelt } else { def sqlQuery = "SELECT mandant_name FROM [" + constantValues.DatabaseName + "].[dbo].[dv_mandant] where mandant_nr = '" + doc.field[ 1 ] + "'"; def sql = groovy.sql.Sql.newInstance( "jdbc:sqlserver://d3sql;databaseName=" + constantValues.DatabaseName, constantValues.DatabaseUser, constantValues.DatabasePassword, 'com.microsoft.sqlserver.jdbc.SQLServerDriver' ); def resultRows = sql.rows( sqlQuery ); doc.field[ 39 ] = resultRows[ 0 ].mandant_name; } } } } // Einfügung Ende / Setzen des Mandanten bei SAP-Dokumenten (Mandant = 240) /////////////////////////// if ( isRepoIdInDocType( d3, docType.id, constantValues.MatNrId ) ) // Materialstammdaten, ID 31 => Materialnummer { for ( int i = 1; i <= Integer.valueOf( d3.config.value( "CUR_60ER_FIELD_NR" ) ); i++ ) { if ( doc.field[ 61 ][ i ] ) { if ( doc.field[ 61 ][ i ].indexOf( "|" ) > 0 ) { def wert = doc.field[ 61 ][ i ].tokenize( "|" ); def ziel = ""; if ( wert[ 0 ].length() > 0 ) { doc.field[ 61 ][ i ] = wert[ 0 ].trim(); // Materialnummer } if ( wert[ 1 ] ) { if ( wert[ 1 ].length() > 0 ) { ziel = wert[ 1 ].trim(); // Materianbezeichnung } } doc.field[ 65 ][ i ] = ziel; ziel = ""; if ( wert[ 2 ] ) { if ( wert[ 2 ].length() > 0 ) { ziel = wert[ 2 ].trim(); // Produkthierarchie } } doc.field[ 66 ][ i ] = ziel; ziel = ""; if ( wert[ 3 ] ) { if ( wert[ 3 ].length() > 0 ) { ziel = wert[ 3 ].trim(); // Kundenartikelnummer } } doc.field[ 67 ][ i ] = ziel; } } } } if ( isRepoIdInDocType( d3, docType.id, 1 ) ) // Mandantenstammdaten (Buchungskreis, Firma) { // Wir schauen, was angegeben ist. Der Buchungskreis wird zuerst ausgewertet und schlägt den Mandantnamen (Feld Firma) (der nur ausgewertet wird, falls // kein Buchungskreis angegeben wurde). if ( doc.field[ 1 ] ) { if ( doc.field[ 1 ].indexOf( "|" ) > 0 ) { def werte = doc.field[ 1 ].tokenize( "|" ); if ( werte[ 0 ].length() > 0 ) // Nummer { doc.field[ 1 ] = werte[ 0 ].trim(); } if ( werte[ 1 ] ) { if ( werte[ 1 ].length() > 0 ) // Name { doc.field[ 39 ] = werte[ 1 ].trim(); } } } else { if ( ! doc.field[ 39 ] ) { // Buchungskreis gefüllt, Firma aber nicht, d.h. offenbar ein Beleg aus SAP (=> da wird nur der Buchungskreis angegeben) // Firma wird aus Stammdaten gefüllt def sql = groovy.sql.Sql.newInstance( "jdbc:sqlserver://d3sql;databaseName=" + constantValues.DatabaseName, constantValues.DatabaseUser, constantValues.DatabasePassword, 'com.microsoft.sqlserver.jdbc.SQLServerDriver' ); def row = sql.firstRow( "SELECT mandant_name FROM [" + constantValues.DatabaseName + "].[dbo].[dv_mandant] where mandant_nr = '" + doc.field[ 1 ] + "'" ); if ( row ) { doc.field[ 39 ] = row.mandant_name; } } } } else { if ( doc.field[ 39 ] ) { if ( doc.field[ 39 ].indexOf( "|" ) > 0 ) { def werte = doc.field[ 39 ].tokenize( "|" ); if ( werte[ 0 ].length() > 0 ) // Nummer { doc.field[ 1 ] = werte[ 0 ].trim(); } if ( werte[ 1 ] ) { if ( werte[ 1 ].length() > 0 ) // Name { doc.field[ 39 ] = werte[ 1 ].trim(); } } } } } } return 0; } @Entrypoint( entrypoint = "hook_validate_update_entry_10" ) public int hook_validate_update_entry_10( D3Interface d3, User user, DocumentType docType, Document doc, String nextcall ) { def ret = hook_validate_import_entry_10( d3, user, docType, doc, nextcall ); return ret; } @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") // temporäres Objekt holen, um zu prüfen, das sich Eigenschaften geändert haben def oldDocAttributes = d3.archive.getDocument(doc.id()); def ergebnis = hook_validate_update_entry_10( d3, user, docTypeNew, doc, "" ); d3.log.error("ENDE | hookUpdAttribEntry20") return 0; } @Entrypoint( entrypoint = "hook_insert_entry_10" ) public int hookInsertEntry10(D3Interface d3, User user, DocumentType docType, Document doc) { d3.log.info("START | hookInsertEntry10 "); /////////////////////////// // eingefügt von CALB/d.velop AG / 2024.06.11 / Versionierung von Fertigungsaufträgen if ( ( docType.id == "DFAUF" ) || ( docType.id == "DPEIN" ) || ( docType.id == "DMPRO" ) || ( docType.id == "DPZEU" ) ) { if ( doc.field[ 16 ] ) { def sqlQuery = "select doku_id from firmen_spezifisch where kue_dokuart = '" + docType.id + "' and dok_dat_feld_16 = '" + doc.field[ 16 ] + "'"; def treffer = d3.sql.executeAndGet( (String) sqlQuery ); if ( treffer.size() > 1 ) { d3.log.error( "Anzahl Treffer: " + treffer.size() + " => es gibt mehr als ein Dokument fuer Auftragsnummer " + doc.field[ 16 ] + " in der Dokumentart " + docType.id + " !" ); return -120; } if ( treffer.size() == 1 ) { sqlQuery = "select zeich_nr, var_nr from phys_datei where doku_id = '" + treffer[ 0 ].doku_id + "'"; treffer = d3.sql.executeAndGet( (String) sqlQuery ); if ( treffer.size() > 0 ) { d3.log.info( "Fertigungsauftrag gefunden, setze Dokumentnummer " + doc.number + " bei Auftragsnummer " + doc.field[ 16 ] ); doc.number = treffer[ 0 ].zeich_nr; } } } } // Einfügung Ende / Versionierung von Fertigungsaufträgen /////////////////////////// d3.log.info("ENDE | hookInsertEntry10 "); return 0; } public String getUserIdpId( D3Interface d3, String UserName, String repo_id, String baseUri, String authUserApiKey ) { CloseableHttpClient client = HttpClientBuilder.create( ).build( ); String userId; try { HttpGet get = new HttpGet( baseUri + "/identityprovider/scim/users?filter=userName%20eq%20rau%5C" + UserName ); //JSON Inhalt get.addHeader( "authorization", "Bearer " + authUserApiKey ); get.addHeader( "origin", baseUri ); get.addHeader( "Accept", "application/json" ); CloseableHttpResponse response = client.execute( get ); try { def statusCode = response.getStatusLine( ).getStatusCode( ); if( statusCode != 200 && statusCode != 201 ){ d3.log.error("getUserIdpId -> Error while trying to read user " + UserName + " status code: " + statusCode ); HttpEntity re = response.getEntity(); InputStream errStream = re.getContent(); String errContent = ""; if( errStream != null && errStream.available() > 0 ){ errContent = IOUtils.toString(errStream, StandardCharsets.UTF_8); } d3.log.error("getUserIdpId -> Error while trying to read user " + UserName + " response line: " + errContent); xlog( d3, 2, "User-ID nicht gefunden": errContent ); return ""; } HttpEntity entity = response.getEntity( ); String json = EntityUtils.toString( entity, StandardCharsets.UTF_8 ); def jsonSlurper = new JsonSlurper(); def returnwert = jsonSlurper.parseText( json ); userId = returnwert.resources.id[ 0 ]; } finally { response.close(); } } catch ( IOException e ) { e.printStackTrace(); } finally { try { client.close(); } catch (IOException e) { e.printStackTrace(); } } xlog( d3, 2, "gefundene User-ID: " + userId ); return userId; } public int xlog( D3Interface d3, int loglevel, String logtext ) { def logdatei = "d:\\d3\\logs\\d3hooklog.txt"; def g_loglevel = 5; def g_logdirect = "BEIDE"; // BEIDE oder D3LOG oder DATEI def date = new Date(); def zeitstempel = date.format( "yyyy.MM.dd HH:mm:ss", TimeZone.getTimeZone('CET') ); def loglevel_lang = "[INFO ]"; if ( loglevel <= g_loglevel ) { switch ( loglevel ) { case 1: loglevel_lang = "[FATAL]"; if ( ( g_logdirect == "D3LOG" ) || ( g_logdirect == "BEIDE" ) ) { d3.log.critical( logtext ); } break; case 2: loglevel_lang = "[ERROR]"; if ( ( g_logdirect == "D3LOG" ) || ( g_logdirect == "BEIDE" ) ) { d3.log.error( logtext ); } break; case 3: loglevel_lang = "[WARN ]"; if ( ( g_logdirect == "D3LOG" ) || ( g_logdirect == "BEIDE" ) ) { d3.log.warn( logtext ); } break; case 4: loglevel_lang = "[INFO ]"; if ( ( g_logdirect == "D3LOG" ) || ( g_logdirect == "BEIDE" ) ) { d3.log.info( logtext ); } break; case 5: loglevel_lang = "[DEBUG]"; // Da die d.3 Server i.d.R. nicht im Debug-Modus laufen, erscheinen DEBUG-Meldungen nicht im Log. if ( ( g_logdirect == "D3LOG" ) || ( g_logdirect == "BEIDE" ) ) { d3.log.debug( logtext ); } break; } } if ( ( g_logdirect == "DATEI" ) || ( g_logdirect == "BEIDE" ) ) { new File( logdatei ).append( zeitstempel + " " + loglevel_lang + " " + logtext + "\n", "UTF8" ); } return 0; } public static int createTask( D3Interface d3, User user, DocumentType docType, Document doc, String subject, String description, ArrayList assignees, String baseUri, String authUsr, String repo_id ) { d3.log.info( "createTask !" ); String assigneesString = ""; assignees.each { assigneesString = assigneesString + "\"${it}\","; } if ( assigneesString.length() > 0 ) { assigneesString = assigneesString.substring(0, assigneesString.length()-1); } CloseableHttpClient client = HttpClientBuilder.create( ).build( ); try { UUID uuid = UUID.randomUUID(); String randomUUIDString = uuid.toString(); //Post Task HttpPost post = new HttpPost( baseUri + "/task/tasks" ); def ddf11; if ( doc.field[ 11 ] == null ) { ddf11 = ""; } else { ddf11 = doc.field[ 11 ]; } def ddf12; if ( doc.field[ 12 ] == null ) { ddf12 = ""; } else { ddf12 = doc.field[ 12 ]; } //JSON Inhalt def lJsonString = """{ "subject" : "${subject}", "description" : "${description}", "assignees" : [${assigneesString}], "correlationKey" : "${randomUUIDString}", "context" : { "key" : "returnProcess", "type" : "process", "name" : "Import in Kundenbestellung" }, "metadata" : [ { "key" : "verkaeuferorg", "caption" : "Verkaeuferorganisation", "values" : ["${ddf11}"] }, { "key" : "verkaeufergruppe", "caption" : "Verkaeufergruppe", "values" : ["${ddf12}"] } ], "_links" : { "attachment" : { "href": "/dms/r/${repo_id}/o2/${doc.id()}"} } }"""; StringEntity params = new StringEntity( lJsonString, StandardCharsets.UTF_8 ); params.setContentType("application/json"); post.addHeader("authorization", "Bearer ${authUsr}"); post.addHeader("content-type", "application/json"); post.addHeader("origin", baseUri ); post.setEntity( params ); CloseableHttpResponse response = client.execute( post ); try { def statusCode = response.getStatusLine( ).getStatusCode( ); if( statusCode != 200 && statusCode != "200" && statusCode != 201 && statusCode != "201" ) { HttpEntity re = response.getEntity(); def lErrMsg = "createOfficeTaskFinished - Error while trying to create Task! Status Code: " + statusCode + " / Response: " + re.getContent().text; d3.log.info( "createOfficeTaskFinished" + "" + lErrMsg + " -> " + lJsonString); } } finally { response.close(); } } catch ( Exception e ) { d3.log.error( "createOfficeTaskFinished" + "" + e.getMessage() ); } finally { client.close(); } return 0; } private boolean isRepoIdInDocType( D3Interface d3, String docTypeShort, int repoId ) { boolean isRepoIdInDocType = false; try { Document docTemp = d3.archive.newDocument(); docTemp.setType( docTypeShort ); DocumentType docType = docTemp.getType(); if ( docTemp != null && docType != null ) { for ( int i = 1; i <= 89; i++ ) { try { DocumentTypeAttribute docTypeAttrib = docTemp.getType().getField().getAt( i ); if ( docTypeAttrib != null ) { RepositoryField repoField = docTypeAttrib.getRepositoryField(); if ( repoField != null ) { String currRepoId = repoField.getId(); if ( currRepoId != null ) { int currRepoIdInt = Integer.valueOf( currRepoId ); if ( currRepoIdInt == repoId ) { isRepoIdInDocType = true; break; } } } } } catch ( Exception eField ) { //nix } } } } catch ( Exception e ) { // wieder nix } //d3.log.error( "Nachricht: " + isRepoIdInDocType ); return isRepoIdInDocType; } }