import groovy.sql.GroovyRowResult import java.io.File; import java.lang.reflect.Field import java.net.URI; import java.util.Calendar; import java.util.Date import javax.swing.text.html.FrameSetView; import com.dvelop.casemanagement.clients.ConditionExecutionClient; import com.dvelop.casemanagement.clients.HTTPClientException; import com.dvelop.casemanagement.config.io.HookHandler; import com.dvelop.casemanagement.constants.IniConstants; import com.dvelop.d3.server.ArchiveObject; import com.dvelop.d3.server.Condition import com.dvelop.d3.server.Document; import com.dvelop.d3.server.DocumentType; import com.dvelop.d3.server.Entrypoint; import com.dvelop.d3.server.User; import com.dvelop.d3.server.core.D3Interface; //TODO: Refactor statics into a util class public class dbsCaseContractHooks { private static HookHandler handler; private static Map> langMap; private static final int leadingZeroCount = 5; static { langMap = new HashMap>(); langMap.put("001", new HashMap()); langMap.put("049", new HashMap()); } private String getTranslation(String language, String key) { Map l; if(langMap.containsKey( language)) { l = langMap.get( language); } else { l = langMap.get( "001"); } if(l.containsKey(key)) { return l.get(key); } return key; } private static HookHandler getHandler(D3Interface d3) { if(dbsCaseContractHooks.handler == null) { List paths = new ArrayList(); for(int i = 0; i < 100; i++) { String path = d3.conf.value("HOOK_GROOVY_DIRS_CUSTOMER", i); if(path != null && path.length() > 0) { paths.add(path); } else { break; } } dbsCaseContractHooks.handler = new HookHandler(paths); } return dbsCaseContractHooks.handler; } @Entrypoint( entrypoint = "hook_upd_attrib_entry_20" ) public int hook_upd_attrib_entry_20_dbsContract ( D3Interface d3, Document doc , User user, DocumentType docType, DocumentType docTypeNew) { String docTypeShort = docType.id; if(getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_VERTRAG).equals( docTypeShort) || getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_RAHMEN).equals( docTypeShort)) { String completeAction = "${user.getLongName()} aktualisierte Eigenschaften.".toString(); Integer updateField = Integer.parseInt( getHandler(d3).getOption( IniConstants.DBS_CASEORCONTRACT_LASTCHANGEACTION)); String currentActionValue = doc.field[updateField]; if(currentActionValue == null || "".equals(currentActionValue)) { doc.field[updateField] = completeAction; } else { Document file = d3.archive.getDocument(doc.id, user.id); if(file != null) { String oldValue = file.field[updateField]; if(currentActionValue.equals( oldValue )) { doc.field[updateField] = completeAction; } } } } return 0; } @Entrypoint( entrypoint = "hook_insert_exit_20" ) public int hook_insert_exit_20_dbsContract (D3Interface d3 , Document doc, String fileDestination, def importOk, User user, DocumentType docType) { // check importOk for int and string -> type change after update of d.3 server if(importOk == "1" || importOk == 1 ) { String docTypeShort = docType.id; String restPath = getHandler(d3).getOption( IniConstants.DBS_PRESENTATION_SERVER_BASE_URL); ConditionExecutionClient client = new ConditionExecutionClient(restPath); switch(docTypeShort) { case getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_VERTRAG): case getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_RAHMEN): try { d3.log.info("Informing dbs | case manager contract about import of document with doc id " + doc.id + "."); if(!client.importOfDocument( doc.id, user.id)) { d3.log.error("Could not inform dbs | case manager contract about import of document!"); return -1; } } catch (HTTPClientException e) { d3.log.error("Could not inform dbs | case manager contract about import of document with doc id " + doc.id + ": " + e.getLogMsg() + " entity was: " + e.getEntityMsg() ); return -1; } catch (Exception e) { d3.log.error("Could not inform dbs | case manager contract about import of document with doc id " + doc.id + ": " + e.getMessage() ); return -1; } break; case getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_VERTR_VUNT): try { d3.log.info("Informing dbs | case manager contract about import of contract paper with doc id " + doc.id + "."); if(!client.importOfMail( doc.id)) { d3.log.error("Could not inform dbs | case manager contract about import of contract paper with doc id " + doc.id + "."); return -1; } } catch (HTTPClientException e) { d3.log.error("Could not inform dbs | case manager contract about import of contract paper with doc id " + doc.id + ": " + e.getLogMsg() + " entity was: " + e.getEntityMsg() ); return -1; } catch (Exception e) { d3.log.error("Could not inform dbs | case manager contract about import of contract paper with doc id " + doc.id + ": " + e.getMessage() ); return -1; } //Break is missing intentionally! case getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_VERTR_DOK): updateLastActionOfContract(d3, user, doc, " importierte ein neues Dokument."); break; } } return 0; } @Entrypoint( entrypoint = "hook_upd_attrib_exit_20" ) public int hook_upd_attrib_exit_20_dbsContract ( D3Interface d3, Document doc , Integer errorCode, User user, DocumentType docType, DocumentType docTypeNew) { if(errorCode == 0) { String docTypeShort = docType.id; String restPath = getHandler(d3).getOption( IniConstants.DBS_PRESENTATION_SERVER_BASE_URL); ConditionExecutionClient client = new ConditionExecutionClient(restPath); switch(docTypeShort) { case getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_VERTRAG): case getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_RAHMEN): try { d3.log.info("Informing dbs | case manager contract about update of document with doc id " + doc.id + "."); if(!client.updateOfDocument( doc.id, user.id)) { d3.log.error("Could not inform dbs | case manager contract about update of document with doc id " + doc.id + "."); return -1; } } catch (HTTPClientException e) { d3.log.error("Could not inform dbs | case manager contract about update of document with doc id " + doc.id + ": " + e.getLogMsg() + " entity was: " + e.getEntityMsg() ); return -1; } catch (Exception e) { d3.log.error("Could not inform dbs | case manager contract about update of document with doc id " + doc.id + ": " + e.getMessage() ); return -1; } break; case getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_VERTR_DOK): case getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_VERTR_VUNT): updateLastActionOfContract(d3, user, doc, " aktualisierte ein bestehendes Dokument."); break; } } return 0; } private void updateLastActionOfContract(D3Interface d3, User user, Document doc, String action) { Integer internalNumberField = Integer.parseInt( getHandler(d3).getOption(IniConstants.DBS_VERTRAGSNUMMER)); Integer updateField = Integer.parseInt( getHandler(d3).getOption( IniConstants.DBS_CASEORCONTRACT_LASTCHANGEACTION)); String frameStart = getHandler(d3).getOption( IniConstants.DBS_PREFIX_RAHMEN); String docTypeFather = getHandler(d3).getOption( IniConstants.DBS_KUE_DOKUART_VERTRAG); String internalNumberFather = doc.field[internalNumberField]; if(internalNumberFather != null && internalNumberFather.startsWith( frameStart)) { docTypeFather = getHandler(d3).getOption( IniConstants.DBS_KUE_DOKUART_RAHMEN); } if(internalNumberField != null && updateField != null && internalNumberFather != null && docTypeFather != null ) { def query = "SELECT doku_id FROM firmen_spezifisch WHERE dok_dat_feld_${internalNumberField} = ? AND kue_dokuart = ?"; def params = [internalNumberFather, docTypeFather]; GroovyRowResult resultRow = d3.sql.firstRow(query, params); if(resultRow != null && resultRow.containsKey("doku_id" ) && resultRow.getProperty("doku_id") != null) { String docIdFile = resultRow.getProperty("doku_id"); String completeAction = "${user.getLongName()} ${action}".toString(); Document file = d3.archive.getDocument(docIdFile, user.id); if(file != null) { file.field[updateField] = completeAction; file.updateAttributes(user.id, true); } } else { throw new RuntimeException("Could not find any contract files with the internal contract number ${internalNumberFather}" ); } } else { throw new RuntimeException("dbs | case manager contract hook configuration not found or the configuration was not completed! Please check your configuration."); } } // To provide the hook for entrypoint 'hook_validate_import_entry_10' uncomment the following annotation. // Mind that for this method the d.3 server version 8.1 is required. @Entrypoint( entrypoint = "hook_validate_import_entry_10" ) public int hook_validate_import_entry_10_dbsContract ( D3Interface d3, User user, DocumentType docType, Document doc, String nextcall ) { String docTypeContractRV = getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_RAHMEN); String docTypeContractEV = getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_VERTRAG); String docTypeContractEVDOK = getHandler(d3).getOption( IniConstants.DBS_KUE_DOKUART_VERTR_DOK); String docTypeContractEVUNT = getHandler( d3).getOption( IniConstants.DBS_KUE_DOKUART_VERTR_VUNT); String docTypeShort = docType.id; Integer internalNumberField = Integer.parseInt( getHandler(d3).getOption(IniConstants.DBS_VERTRAGSNUMMER)); if(docTypeContractRV == null || docTypeContractEV == null || docTypeContractEVDOK == null || docTypeContractEVUNT == null) { throw new RuntimeException("dbs | case manager hook configuration not found or the configuration was not completed! Please check your configuration."); } try { if( docTypeContractRV.equals(docTypeShort) || docTypeContractEV.equals(docTypeShort)) { String importAction = "${user.getLongName()} importierte Akte.".toString(); Integer updateField = Integer.parseInt( getHandler(d3).getOption( IniConstants.DBS_CASEORCONTRACT_LASTCHANGEACTION)); doc.field[updateField] = importAction; } // date validation if activated in administration if ( Integer.parseInt( getHandler(d3).getOption( IniConstants.DBS_VALIDATEDATE)) == 1) { if ( docTypeContractEV.equals( docTypeShort)) { d3.log.info("checking internal contract number for blanket contract agreement"); Integer internalFrameContractNumberField = Integer.parseInt( getHandler( d3).getOption( IniConstants.DBS_VERTRAG_DOKDAT_RAHMEN)); String internalFrameContractNumber = doc.field[internalFrameContractNumberField]; if ( internalFrameContractNumber != null && internalFrameContractNumber != "" ) { Integer startDateField = Integer.parseInt(getHandler( d3).getOption( IniConstants.DBS_CONTRACT_STARTDATE_CONTRACT)); Date startDateEV = doc.field[startDateField]; Integer endDateField = Integer.parseInt(getHandler( d3).getOption( IniConstants.DBS_CONTRACT_ENDDATE_CONTRACT)); Date endDateEV = doc.field[endDateField]; String docIdFrameContract = getDocId(d3, internalFrameContractNumber, docTypeContractRV, internalNumberField); if ( docIdFrameContract != "" ) { d3.log.info("comparing contract start / end dates with corresponding dates of blanket contract agreement") Date startDateRV = getDate(d3, docIdFrameContract, docTypeContractRV, startDateField); if (startDateRV != null ) { if (startDateEV != null && startDateEV.before( startDateRV)) { d3.log.error("An error occurred validating the contract dates! The specified start date lies before the start date of the blanket agreement."); return -8140505; } if ( endDateEV != null && endDateEV.before( startDateRV)) { d3.log.error("An error occurred validating the contract dates! The specified end date lies before the start date of the blanket agreement."); return -8140506; } } Date endDateRV = getDate(d3, docIdFrameContract, docTypeContractRV, endDateField); if (endDateRV != null ){ if (startDateEV != null && startDateEV.after( endDateRV)) { d3.log.error("An error occurred validating the contract dates! The specified start date lies after the end date of the blanket agreement."); return -8140507; } if ( endDateEV != null && endDateEV.after( endDateRV)) { d3.log.error("An error occurred validating the contract dates! The specified end date lies after the end date of the blanket agreement."); return -8140508; } } } else { d3.log.error("Please check the specified internal contract number for the blanket agreement."); return -8140502; } } } } if ( docTypeContractEV.equals( docTypeShort) || docTypeContractRV.equals( docTypeShort) || docTypeContractEVDOK.equals( docTypeShort)) { if ( doc.field[internalNumberField] != null && doc.field[internalNumberField] != "") { d3.log.info("docfield[${internalNumberField}] for the internal contract number was not empty"); int numberOfFoundInternalContractNumber = countExistingInternalContractNumber(d3, docTypeShort, doc.field[internalNumberField], internalNumberField ); if (numberOfFoundInternalContractNumber >= 1) { d3.log.info("next api function: ${nextcall}"); if ( !"ImportNewVersionDocument".equals( nextcall) || numberOfFoundInternalContractNumber > 1 ) { d3.log.error("Please check the internal contract number. The internal contract number '${doc.field[internalNumberField]}' is already assigned to other contract files and it is forbidden to use duplicates."); return -8140503; } } doc.number = doc.field[internalNumberField]; return 0; } else { if ( doc.number != null && doc.number != "") { d3.log.info("doc number was not empty"); doc.field[internalNumberField] = doc.number; int numberOfFoundInternalContractNumber = countExistingInternalContractNumber(d3, docTypeShort, doc.field[internalNumberField], internalNumberField ); if (numberOfFoundInternalContractNumber >= 1) { d3.log.error("Please check the internal contract number. The internal contract number '${doc.field[internalNumberField]}' is already assigned to other contract files and it is forbidden to use duplicates."); return -8140503; } return 0; } } d3.log.info("Need to generate a new number: "); setNextContractNumber(d3, docType, doc); } else if ( docTypeContractEVUNT.equals( docTypeShort)) { int numberOfFoundInternalContractNumberEV = countExistingInternalContractNumber(d3, docTypeContractEV, doc.field[internalNumberField], internalNumberField ); if ( numberOfFoundInternalContractNumberEV == 0 ) { int numberOfFoundInternalContractNumberRV = countExistingInternalContractNumber(d3, docTypeContractRV, doc.field[internalNumberField], internalNumberField ); if ( numberOfFoundInternalContractNumberRV == 0) { d3.log.error("Please check the internal contract number."); return -8140509; } } } } catch( Exception e) { d3.log.error("An Exception occured: ${e.getCause()} StackTrace: ${e}"); return -1; } return 0; } private void setNextContractNumber(D3Interface d3, DocumentType docType, Document doc) { String docTypeContractRV = getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_RAHMEN); String docTypeContractEV = getHandler(d3).getOption(IniConstants.DBS_KUE_DOKUART_VERTRAG); if(docTypeContractRV == null || docTypeContractEV == null) { throw new RuntimeException("dbs | case manager hook configuration not found or the configuration was not completed! Please check your configuration."); } String prefixType = null; String docTypeShortForPrefix = docTypeContractEV; if ( docType.id == docTypeContractRV){ docTypeShortForPrefix = docTypeContractRV; } switch(docTypeShortForPrefix) { case docTypeContractRV: prefixType = IniConstants.DBS_PREFIX_RAHMEN; break; case docTypeContractEV: prefixType = IniConstants.DBS_PREFIX_ID; break; default: throw new RuntimeException("The hook function \"setNextContractNumber\" was called with an unknown doc type! Expected ${docTypeContractEV} or ${docTypeContractRV} but was ${docTypeShortForPrefix}"); } String configuredPrefix = getHandler(d3).getOption(prefixType); Integer internalNumberField = Integer.parseInt( getHandler(d3).getOption(IniConstants.DBS_VERTRAGSNUMMER)); if(configuredPrefix == null || internalNumberField == null) { throw new RuntimeException("dbs | case manager hook configuration not found or the configuration was not completed! Please check your configuration."); } GroovyObject prefixGenerator = preparePrefixGenerator(d3); String prefix = prefixGenerator.generateContractNumberPrefix(configuredPrefix); d3.log.info("Generated prefix for internal contract number: ${prefix}"); String query = "select max( dok_dat_feld_${internalNumberField} ) as docNumberCount from firmen_spezifisch where kue_dokuart = ? and (dok_dat_feld_${internalNumberField} like ?)"; GroovyRowResult resultRow = d3.sql.firstRow(query, [docTypeShortForPrefix, (prefix + "%")]); int number = 0; if(resultRow != null && resultRow.containsKey("docNumberCount" ) && resultRow.getProperty("docNumberCount") != null) { Integer result = Integer.parseInt(resultRow.getProperty("docNumberCount").substring( prefix.length())); number = result != null ? result : 0; } number++; String numberString = String.valueOf( number); if(numberString.length() > leadingZeroCount) { throw new RuntimeException("Could not generate a valid contract number. There are no more contract numbers left! Please use a higher leading zero count."); } while(numberString.length() < leadingZeroCount) { numberString = "0" + numberString; } String contractNumberResult = prefix + numberString; d3.log.info("Generated contractNumber: ${contractNumberResult} setting docfield[${internalNumberField}]"); doc.field[internalNumberField] = contractNumberResult; doc.number = contractNumberResult; } private int countExistingInternalContractNumber(D3Interface d3, String docTypeShort, String internalNumberValue, Integer internalNumberField ) { int countedInternalNumbers = 0; if ( internalNumberValue == null || internalNumberValue.trim().equals( "")){ return countedInternalNumbers; } String query = "select count( doku_id) as countedIdenticalInternalNumbers from firmen_spezifisch where kue_dokuart = ? and (dok_dat_feld_${internalNumberField} = ?)"; List params = [docTypeShort, internalNumberValue]; GroovyRowResult resultRow = d3.sql.firstRow(query, params); if(resultRow != null && resultRow.containsKey("countedIdenticalInternalNumbers" ) && resultRow.getProperty("countedIdenticalInternalNumbers") != null) { countedInternalNumbers = resultRow.getProperty("countedIdenticalInternalNumbers"); } return countedInternalNumbers; } private String getDocId( D3Interface d3, String internalContractNumber, String docTypeShort, Integer internalNumberField) { String docId = ""; String query = "SELECT doku_id FROM firmen_spezifisch WHERE dok_dat_feld_${internalNumberField} = ? AND kue_dokuart = ?"; List params = [internalContractNumber, docTypeShort]; List resultRowList = d3.sql.executeAndGet( query, params, 2); if(resultRowList != null ) { if (resultRowList.size() == 2) { d3.log.error("More than one blanket agreement with the internal contract number ${internalContractNumber} was found."); } else if ( resultRowList.size() == 1) { docId = resultRowList[0].getProperty("doku_id"); } } return docId; } private Date getDate(D3Interface d3, String docId, String docTypeShort, Integer dateField) { Date requestedDate = null; String query = "select dok_dat_feld_${dateField} as returnedDate from firmen_spezifisch where kue_dokuart = ? and doku_id = ?"; List params = [ docTypeShort, docId]; GroovyRowResult resultRow = d3.sql.firstRow(query, params); if(resultRow != null && resultRow.containsKey("returnedDate" ) && resultRow.getProperty("returnedDate") != null) { requestedDate = resultRow.getProperty("returnedDate"); } return requestedDate; } private GroovyObject preparePrefixGenerator(D3Interface d3) { String currentPath = getClass().protectionDomain.codeSource.location.path; d3.log.info("Looking for file to generate prefix here (encoded): ${currentPath}"); URI uri = new URI(currentPath); d3.log.info("Looking for file to generate prefix here (decoded): ${uri.getPath()}"); File sourceFilePrefixGeneration = new File(new File( uri.getPath()).getParentFile(), "dbsCaseContractHooks_prefixGen.groovy"); d3.log.info("Found file to generate prefix: ${sourceFilePrefixGeneration.getPath()}"); Class prefixGenerationClass = new GroovyClassLoader(getClass().getClassLoader()).parseClass(sourceFilePrefixGeneration); GroovyObject prefixGenerationObject = (GroovyObject) prefixGenerationClass.newInstance(); return prefixGenerationObject; } }