001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.module.endow.batch.service.impl; 017 018 import java.util.ArrayList; 019 import java.util.List; 020 021 import org.kuali.kfs.module.endow.EndowConstants; 022 import org.kuali.kfs.module.endow.EndowParameterKeyConstants; 023 import org.kuali.kfs.module.endow.batch.PooledFundControlTransactionsStep; 024 import org.kuali.kfs.module.endow.batch.service.PooledFundControlTransactionsService; 025 import org.kuali.kfs.module.endow.businessobject.EndowmentSourceTransactionLine; 026 import org.kuali.kfs.module.endow.businessobject.EndowmentTargetTransactionLine; 027 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLineBase; 028 import org.kuali.kfs.module.endow.businessobject.PooledFundControl; 029 import org.kuali.kfs.module.endow.businessobject.TransactionArchive; 030 import org.kuali.kfs.module.endow.businessobject.TransactionArchiveSecurity; 031 import org.kuali.kfs.module.endow.businessobject.TransactionDocumentExceptionReportLine; 032 import org.kuali.kfs.module.endow.businessobject.TransactionDocumentTotalReportLine; 033 import org.kuali.kfs.module.endow.dataaccess.PooledFundControlTransactionsDao; 034 import org.kuali.kfs.module.endow.document.CashDecreaseDocument; 035 import org.kuali.kfs.module.endow.document.CashIncreaseDocument; 036 import org.kuali.kfs.module.endow.document.EndowmentSecurityDetailsDocumentBase; 037 import org.kuali.kfs.module.endow.document.service.KEMService; 038 import org.kuali.kfs.module.endow.document.validation.event.AddTransactionLineEvent; 039 import org.kuali.kfs.module.endow.util.GloabalVariablesExtractHelper; 040 import org.kuali.kfs.sys.context.SpringContext; 041 import org.kuali.kfs.sys.service.ReportWriterService; 042 import org.kuali.rice.kew.exception.WorkflowException; 043 import org.kuali.rice.kns.rule.event.RouteDocumentEvent; 044 import org.kuali.rice.kns.service.BusinessObjectService; 045 import org.kuali.rice.kns.service.DocumentService; 046 import org.kuali.rice.kns.service.KualiRuleService; 047 import org.kuali.rice.kns.service.ParameterService; 048 import org.kuali.rice.kns.service.TransactionalDocumentDictionaryService; 049 import org.kuali.rice.kns.util.GlobalVariables; 050 import org.kuali.rice.kns.util.KualiDecimal; 051 import org.kuali.rice.kns.util.ObjectUtils; 052 import org.springframework.transaction.annotation.Transactional; 053 054 /* 055 * This class is the implementation of the Bach Generate Pooled fund Control Transactions 056 */ 057 @Transactional 058 public class PooledFundControlTransactionsServiceImpl implements PooledFundControlTransactionsService { 059 060 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PooledFundControlTransactionsServiceImpl.class); 061 062 protected BusinessObjectService businessObjectService; 063 protected DocumentService documentService; 064 protected ParameterService parameterService; 065 protected KualiRuleService kualiRuleService; 066 067 protected KEMService kemService; 068 069 protected PooledFundControlTransactionsDao pooledFundControlTransactionsDao; 070 071 protected ReportWriterService pooledFundControlTransactionsExceptionReportWriterService; 072 protected ReportWriterService pooledFundControlTransactionsTotalReportWriterService; 073 074 private TransactionDocumentTotalReportLine totalReportLine = null; 075 private TransactionDocumentExceptionReportLine exceptionReportLine = null; 076 077 /* 078 * @see org.kuali.kfs.module.endow.batch.service.PooledFundControlTransactionsService#generatePooledFundControlTransactions() 079 */ 080 public boolean generatePooledFundControlTransactions() { 081 082 LOG.info("Begin the batch Generate Pooled Fund Control Transactions ..."); 083 084 // prepare for reports 085 initializeReports(); 086 087 // All the jobs below should be attempted regardless of the status of another. 088 // In fact, all jobs in the process could be run concurrently. 089 // The job, itself, does not fail but completes with exceptions. 090 createCashDocumentForPurchase(); 091 createCashDocumentForSale(); 092 createCashDocumentForSaleGainLoss(); 093 createCashDocumentForIncomeDistribution(); 094 095 LOG.info("The batch Generate Pooled Fund Control Transactions was finished"); 096 097 return true; 098 } 099 100 /** 101 * Creates an ECI or an ECDD eDoc according to the total amount of holding cost for EAI 102 */ 103 protected boolean createCashDocumentForPurchase() { 104 return createCashDocumentBasedOnHoldingCost(EndowConstants.DocumentTypeNames.ENDOWMENT_ASSET_INCREASE, EndowParameterKeyConstants.PURCHASE_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_TARGET, EndowParameterKeyConstants.PURCHASE_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.PRINCIPAL); 105 } 106 107 /** 108 * Creates an ECI or an ECDD eDoc according to the total amount of holding cost for EAD 109 */ 110 protected boolean createCashDocumentForSale() { 111 return createCashDocumentBasedOnHoldingCost(EndowConstants.DocumentTypeNames.ENDOWMENT_ASSET_DECREASE, EndowParameterKeyConstants.SALE_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_SOURCE, EndowParameterKeyConstants.SALE_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.PRINCIPAL); 112 } 113 114 /** 115 * Creates an ECI or an ECDD eDoc according to the total amount of holding cost 116 * @param documentName 117 * @param DocDescription 118 * @param noRouteInd 119 * @param ipInd 120 */ 121 protected boolean createCashDocumentBasedOnHoldingCost(String documentName, String DocDescription, String securityLineType, String noRouteInd, String ipInd) { 122 123 List<String> documentTypeNames = new ArrayList<String>(); 124 documentTypeNames.add(documentName); 125 List<PooledFundControl> pooledFundControlRecords = (List<PooledFundControl>) pooledFundControlTransactionsDao.getAllPooledFundControlTransaction(); 126 //if (pooledFundControlRecords == null) return; 127 128 // generate a cash document per each PooledFundControl 129 // If one should fail, that would be an exception to report and the remainder that does not fail should continue. 130 for (PooledFundControl pooledFundControl : pooledFundControlRecords) { 131 KualiDecimal totalAmount = KualiDecimal.ZERO; 132 // get the list of TransactionArchiveSecurity that has the same security id and document name 133 List<TransactionArchiveSecurity> transactionArchiveSecurityRecords = pooledFundControlTransactionsDao.getTransactionArchiveSecurityWithSecurityId(pooledFundControl, documentTypeNames, kemService.getCurrentDate()); 134 if (transactionArchiveSecurityRecords != null) { 135 // get the total of security cost 136 for (TransactionArchiveSecurity transactionArchiveSecurity : transactionArchiveSecurityRecords) { 137 totalAmount = totalAmount.add(new KualiDecimal(transactionArchiveSecurity.getHoldingCost())); 138 } 139 } 140 141 // create a cash document per security id of pooled fund control 142 if (totalAmount.isPositive()) { 143 createECI(pooledFundControl, totalAmount, DocDescription, securityLineType, noRouteInd, ipInd); 144 } else if (totalAmount.isNegative()) { 145 totalAmount = totalAmount.negated(); 146 createECDD(pooledFundControl, totalAmount, DocDescription, securityLineType, noRouteInd, ipInd); 147 } 148 } 149 150 return true; 151 } 152 153 /** 154 * Creates an ECI or an ECDD eDoc according to the total amount of gain/loss for transaction type EAD 155 */ 156 protected boolean createCashDocumentForSaleGainLoss() { 157 158 List<String> documentTypeNames = new ArrayList<String>(); 159 documentTypeNames.add(EndowConstants.DocumentTypeNames.ENDOWMENT_ASSET_DECREASE); 160 List<PooledFundControl> pooledFundControlRecords = (List<PooledFundControl>) pooledFundControlTransactionsDao.getAllPooledFundControlTransaction(); 161 //if (pooledFundControlRecords == null) return; 162 163 // generate a cash document per each PooledFundControl 164 // If one should fail, that would be an exception to report and the remainder that does not fail should continue. 165 for (PooledFundControl pooledFundControl : pooledFundControlRecords) { 166 KualiDecimal totalAmount = KualiDecimal.ZERO; 167 // get the list of TransactionArchiveSecurity that has the same security id and document name 168 List<TransactionArchiveSecurity> transactionArchiveSecurityRecords = pooledFundControlTransactionsDao.getTransactionArchiveSecurityWithSecurityId(pooledFundControl, documentTypeNames, kemService.getCurrentDate()); 169 // get the total of security long term and short term gain and loss 170 if (transactionArchiveSecurityRecords != null) { 171 for (TransactionArchiveSecurity transactionArchiveSecurity : transactionArchiveSecurityRecords) { 172 totalAmount = totalAmount.add(new KualiDecimal(transactionArchiveSecurity.getLongTermGainLoss()).add(new KualiDecimal(transactionArchiveSecurity.getShortTermGainLoss()))); 173 } 174 } 175 // create a cash document per security id of pooled fund control 176 // If the pool is paying out gains, the net value of the pool must be reduced (ECDD). 177 // If it is 'recovering' (paying out) Losses, we must increase the value of the pool (ECI). 178 if (totalAmount.isPositive()) { 179 createECDD(pooledFundControl, totalAmount, EndowParameterKeyConstants.GAIN_LOSS_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_SOURCE, EndowParameterKeyConstants.GAIN_LOSS_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.PRINCIPAL); 180 } else if (totalAmount.isNegative()) { 181 totalAmount = totalAmount.negated(); 182 createECI(pooledFundControl, totalAmount, EndowParameterKeyConstants.GAIN_LOSS_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_SOURCE, EndowParameterKeyConstants.GAIN_LOSS_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.PRINCIPAL); 183 } 184 } 185 186 return true; 187 } 188 189 /** 190 * Creates an ECI or an ECDD eDoc according to the total amount of income/principle cash for transaction type ECI and ECDD 191 */ 192 protected boolean createCashDocumentForIncomeDistribution() { 193 194 List<String> documentTypeNames = new ArrayList<String>(); 195 documentTypeNames.add(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE); 196 documentTypeNames.add(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE); 197 List<PooledFundControl> pooledFundControlRecords = (List<PooledFundControl>) pooledFundControlTransactionsDao.getAllPooledFundControlTransaction(); 198 //if (pooledFundControlRecords == null) return; 199 200 // If one should fail, that would be an exception to report and the remainder that does not fail should continue. 201 for (PooledFundControl pooledFundControl : pooledFundControlRecords) { 202 KualiDecimal totalAmount = KualiDecimal.ZERO; 203 List<TransactionArchive> transactionArchiveRecords = pooledFundControlTransactionsDao.getTransactionArchiveWithSecurityAndDocNames(pooledFundControl, documentTypeNames, kemService.getCurrentDate()); 204 if (transactionArchiveRecords != null) { 205 for (TransactionArchive transactionArchive : transactionArchiveRecords) { 206 totalAmount = totalAmount.add(new KualiDecimal(transactionArchive.getIncomeCashAmount())).add(new KualiDecimal(transactionArchive.getPrincipalCashAmount())); 207 } 208 } 209 210 // create a cash document per security id of pooled fund control 211 if (totalAmount.isPositive()) { 212 createECDD(pooledFundControl, totalAmount, EndowParameterKeyConstants.INCOME_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_SOURCE, EndowParameterKeyConstants.INCOME_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.INCOME); 213 } else if (totalAmount.isNegative()) { 214 totalAmount = totalAmount.negated(); 215 createECI(pooledFundControl, totalAmount, EndowParameterKeyConstants.INCOME_DESCRIPTION, EndowConstants.TRANSACTION_SECURITY_TYPE_SOURCE, EndowParameterKeyConstants.INCOME_NO_ROUTE_IND, EndowConstants.IncomePrincipalIndicator.INCOME); 216 } 217 } 218 219 return true; 220 } 221 222 /** 223 * Creates ECI 224 * @param pooledFundControl 225 * @param totalAmount 226 * @param paramDescriptionName 227 * @param securityLineType 228 * @param paramNoRouteInd 229 * @param incomePrincipalIndicator 230 * @return 231 */ 232 protected boolean createECI(PooledFundControl pooledFundControl, KualiDecimal totalAmount, String paramDescriptionName, String securityLineTypeCode, String paramNoRouteInd, String incomePrincipalIndicator) { 233 234 LOG.info("Creating ECI ..."); 235 236 boolean success = true; 237 CashIncreaseDocument cashIncreaseDocument = null; 238 239 // initialize CashIncreaseDocument 240 cashIncreaseDocument = initializeCashDocument(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE, EndowConstants.MAXMUM_NUMBER_OF_EDOC_INITIALIZATION_TRY); 241 if (ObjectUtils.isNull(cashIncreaseDocument)) { 242 return false; 243 } 244 cashIncreaseDocument.getDocumentHeader().setDocumentDescription(parameterService.getParameterValue(PooledFundControlTransactionsStep.class, paramDescriptionName)); 245 cashIncreaseDocument.setTransactionSourceTypeCode(EndowConstants.TransactionSourceTypeCode.AUTOMATED); 246 247 // set security and add a transaction line 248 String etranTypeCode = getEtranTypeCode(pooledFundControl, paramDescriptionName); 249 populateECI(cashIncreaseDocument, pooledFundControl, totalAmount, securityLineTypeCode, incomePrincipalIndicator, etranTypeCode); 250 251 // if there are transaction lines, proceed. 252 if (cashIncreaseDocument.getNextTargetLineNumber() > 1) { 253 // validate and submit it. Since we have only one transaction line for each ECI, we do not need to validate the transaction line separately 254 GlobalVariables.clear(); 255 if (validateECI(cashIncreaseDocument)) { 256 success = submitCashDocument(cashIncreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE, paramNoRouteInd); 257 if (success) { 258 writeTotalReport(cashIncreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE, incomePrincipalIndicator); 259 LOG.info("Submitted an ECI successfully: document# " + cashIncreaseDocument.getDocumentNumber()); 260 } 261 } else { 262 success = false; 263 writeDocumentValdiationErrorReport(cashIncreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE); 264 LOG.error("createECI() Validation Error: Document# " + cashIncreaseDocument.getDocumentHeader().getDocumentNumber()); 265 try { 266 documentService.saveDocument(cashIncreaseDocument); 267 } catch (WorkflowException wfe) { 268 LOG.error("createECI() Saving Error: Document# " + cashIncreaseDocument.getDocumentHeader().getDocumentNumber() + " : " + wfe.getMessage()); 269 } 270 } 271 } else { 272 LOG.error("ECI was not sumitted because no transaction lines are found in document# " + cashIncreaseDocument.getDocumentNumber()); 273 } 274 275 return success; 276 } 277 278 /** 279 * Creates ECDD 280 * @param pooledFundControl 281 * @param totalAmount 282 * @param paramDescriptionName 283 * @param securityLineType 284 * @param paramNoRouteInd 285 * @param incomePrincipalIndicator 286 * @return 287 */ 288 protected boolean createECDD(PooledFundControl pooledFundControl, KualiDecimal totalAmount, String paramDescriptionName, String securityLineType, String paramNoRouteInd, String incomePrincipalIndicator) { 289 290 LOG.info("Creating ECDD ..."); 291 292 boolean success = true; 293 CashDecreaseDocument cashDecreaseDocument = null; 294 295 // initialize CashDecreaseDocument 296 cashDecreaseDocument = initializeCashDocument(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE, EndowConstants.MAXMUM_NUMBER_OF_EDOC_INITIALIZATION_TRY); 297 if (ObjectUtils.isNull(cashDecreaseDocument)) { 298 return false; 299 } 300 cashDecreaseDocument.getDocumentHeader().setDocumentDescription(parameterService.getParameterValue(PooledFundControlTransactionsStep.class, paramDescriptionName)); 301 cashDecreaseDocument.setTransactionSourceTypeCode(EndowConstants.TransactionSourceTypeCode.AUTOMATED); 302 303 // set security and a transaction line 304 String etranTypeCode = getEtranTypeCode(pooledFundControl, paramDescriptionName); 305 populateECDD(cashDecreaseDocument, pooledFundControl, totalAmount, securityLineType, incomePrincipalIndicator, etranTypeCode); 306 307 // if there are transaction lines, proceed. 308 if (cashDecreaseDocument.getNextSourceLineNumber() > 1) { 309 // validate and submit it. Since we have only one transaction line for each ECDD, we do not need to validate the transaction line separately 310 GlobalVariables.clear(); 311 if (validateECDD(cashDecreaseDocument)) { 312 success = submitCashDocument(cashDecreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE, paramNoRouteInd); 313 if (success) { 314 writeTotalReport(cashDecreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE, incomePrincipalIndicator); 315 LOG.info("Submitted an ECDD successfully: document# " + cashDecreaseDocument.getDocumentNumber()); 316 } 317 } else { 318 success = false; 319 writeDocumentValdiationErrorReport(cashDecreaseDocument, EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE); 320 LOG.error("createECDD() Validation Error: Document# " + cashDecreaseDocument.getDocumentHeader().getDocumentNumber()); 321 try { 322 documentService.saveDocument(cashDecreaseDocument); 323 } catch (WorkflowException wfe) { 324 LOG.error("createECDD() Saving Error: Document# " + cashDecreaseDocument.getDocumentHeader().getDocumentNumber() + " : " + wfe.getMessage()); 325 } 326 } 327 } else { 328 LOG.error("ECDD was not sumitted because no transaction lines are found in document# " + cashDecreaseDocument.getDocumentNumber()); 329 } 330 331 return success; 332 } 333 334 /** 335 * Populates security and transaction lines 336 * @param cashIncreaseDocument 337 * @param pooledFundControl 338 * @param totalAmount 339 * @param securityLineTypeCode 340 * @param transactionIPIndicatorCode 341 */ 342 protected void populateECI(CashIncreaseDocument cashIncreaseDocument, PooledFundControl pooledFundControl, KualiDecimal totalAmount, String securityLineTypeCode, String transactionIPIndicatorCode, String etranTypeCode) { 343 344 // create a transaction line - needs only one for this batch job 345 EndowmentTargetTransactionLine endowmentTargetTransactionLine = new EndowmentTargetTransactionLine(); 346 endowmentTargetTransactionLine.setTransactionLineNumber(new Integer(1)); 347 endowmentTargetTransactionLine.setKemid(pooledFundControl.getFundKEMID()); 348 endowmentTargetTransactionLine.setEtranCode(etranTypeCode); 349 endowmentTargetTransactionLine.setTransactionIPIndicatorCode(transactionIPIndicatorCode); 350 endowmentTargetTransactionLine.setTransactionAmount(totalAmount); 351 352 GlobalVariables.clear(); 353 if (validateTransactionLine(cashIncreaseDocument, endowmentTargetTransactionLine, EndowConstants.NEW_TARGET_TRAN_LINE_PROPERTY_NAME)) { 354 // add a transaction line - only one for this batch 355 cashIncreaseDocument.addTargetTransactionLine(endowmentTargetTransactionLine); 356 // set security 357 cashIncreaseDocument.getTargetTransactionSecurity().setSecurityLineTypeCode(securityLineTypeCode); 358 cashIncreaseDocument.getTargetTransactionSecurity().setSecurityID(pooledFundControl.getPooledSecurityID()); 359 cashIncreaseDocument.getTargetTransactionSecurity().setRegistrationCode(pooledFundControl.getFundRegistrationCode()); // 360 361 } else { 362 writeTransactionLineValidationErrorReport(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_INCREASE, cashIncreaseDocument.getDocumentNumber(), cashIncreaseDocument.getTargetTransactionSecurity().getSecurityID(), pooledFundControl.getFundKEMID(), totalAmount); 363 } 364 } 365 366 /** 367 * Populates security and transaction lines 368 * @param cashDecreaseDocument 369 * @param pooledFundControl 370 * @param totalAmount 371 * @param securityLineTypeCode 372 * @param transactionIPIndicatorCode 373 */ 374 protected void populateECDD(CashDecreaseDocument cashDecreaseDocument, PooledFundControl pooledFundControl, KualiDecimal totalAmount, String securityLineTypeCode, String transactionIPIndicatorCode, String etranTypeCode) { 375 376 // create a transaction line - needs only one for this batch job 377 EndowmentSourceTransactionLine endowmentSourceTransactionLine = new EndowmentSourceTransactionLine(); 378 endowmentSourceTransactionLine.setTransactionLineNumber(new Integer(1)); 379 endowmentSourceTransactionLine.setKemid(pooledFundControl.getFundKEMID()); 380 endowmentSourceTransactionLine.setEtranCode(etranTypeCode); 381 endowmentSourceTransactionLine.setTransactionIPIndicatorCode(transactionIPIndicatorCode); 382 //endowmentSourceTransactionLine.setTransactionLineTypeCode(securityLineTypeCode); 383 endowmentSourceTransactionLine.setTransactionAmount(totalAmount); 384 385 GlobalVariables.clear(); 386 if (validateTransactionLine(cashDecreaseDocument, endowmentSourceTransactionLine, EndowConstants.NEW_SOURCE_TRAN_LINE_PROPERTY_NAME)) { 387 // add transaction line 388 cashDecreaseDocument.addSourceTransactionLine(endowmentSourceTransactionLine); 389 // set security 390 cashDecreaseDocument.getSourceTransactionSecurity().setSecurityLineTypeCode(securityLineTypeCode); 391 cashDecreaseDocument.getSourceTransactionSecurity().setSecurityID(pooledFundControl.getPooledSecurityID()); 392 cashDecreaseDocument.getSourceTransactionSecurity().setRegistrationCode(pooledFundControl.getFundRegistrationCode()); 393 } else { 394 writeTransactionLineValidationErrorReport(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE, cashDecreaseDocument.getDocumentNumber(), cashDecreaseDocument.getSourceTransactionSecurity().getSecurityID(), pooledFundControl.getFundKEMID(), totalAmount); 395 } 396 } 397 398 /** 399 * Initialize a cash document. If fails, try as many times as EndowConstants.MAXMUM_NUMBER_OF_EDOC_INITILIZATION_TRY. 400 * @param <C> 401 * @param documentType 402 * @param counter 403 * @return 404 */ 405 protected <C extends EndowmentSecurityDetailsDocumentBase> C initializeCashDocument(String documentType, int counter) { 406 407 C cashDocument = null; 408 409 if (counter > 0) { 410 try { 411 cashDocument = (C) getDocumentService().getNewDocument(SpringContext.getBean(TransactionalDocumentDictionaryService.class).getDocumentClassByName(documentType)); 412 } catch (WorkflowException e) { 413 LOG.error( (EndowConstants.MAXMUM_NUMBER_OF_EDOC_INITIALIZATION_TRY - counter + 1) + ": The creation of " + documentType + " failed. Tyring it again ..."); 414 cashDocument = (C) initializeCashDocument(documentType, --counter); 415 } 416 } 417 418 return cashDocument; 419 } 420 421 /** 422 * Submits the document 423 * @param <T> 424 * @param cashDocument 425 * @param documentType 426 * @param paramNoRouteInd 427 * @return 428 */ 429 protected <T extends EndowmentSecurityDetailsDocumentBase> boolean submitCashDocument(T cashDocument, String documentType, String paramNoRouteInd) { 430 431 boolean success = false; 432 433 try { 434 cashDocument.setNoRouteIndicator(isNoRoute(paramNoRouteInd)); 435 documentService.routeDocument(cashDocument, "Submitted by the batch job", null); 436 success = true; 437 } catch (WorkflowException wfe) { 438 writeSubmissionErrorReport(cashDocument, documentType, wfe.getMessage()); 439 LOG.error("submitCashDocument() Routing Error: Document# " + cashDocument.getDocumentHeader().getDocumentNumber() + " : " + wfe.getMessage()); 440 try { 441 documentService.saveDocument(cashDocument); 442 } catch (WorkflowException wfe2) { 443 LOG.error("submitCashDocument() Saving Error: Document# " + cashDocument.getDocumentHeader().getDocumentNumber() + " : " + wfe2.getMessage()); 444 } 445 } catch (Exception e) { // in case 446 writeSubmissionErrorReport(cashDocument, documentType, e.getMessage()); 447 LOG.error("submitCashDocument() Runtime Error: Document# " + cashDocument.getDocumentHeader().getDocumentNumber() + " : " + e.getMessage()); 448 try { 449 documentService.saveDocument(cashDocument); 450 } catch (WorkflowException wfe3) { 451 LOG.error("submitCashDocument() Saving Error: Document# " + cashDocument.getDocumentHeader().getDocumentNumber() + " : " + wfe3.getMessage()); 452 } 453 } 454 455 return success; 456 } 457 458 /** 459 * Validate Cash Transaction line 460 * @param <C> 461 * @param <T> 462 * @param cashDocument 463 * @param endowmentTransactionLine 464 * @param trnsactionPropertyName 465 * @return 466 */ 467 protected <C extends EndowmentSecurityDetailsDocumentBase, T extends EndowmentTransactionLineBase> boolean validateTransactionLine(C cashDocument, T endowmentTransactionLine, String trnsactionPropertyName) { 468 return kualiRuleService.applyRules(new AddTransactionLineEvent(trnsactionPropertyName, cashDocument, endowmentTransactionLine)); 469 } 470 471 /** 472 * validate the ECI business rules 473 * @param cashIncreaseDocument 474 * @return boolean 475 */ 476 protected boolean validateECI(CashIncreaseDocument cashIncreaseDocument) { 477 return kualiRuleService.applyRules(new RouteDocumentEvent(cashIncreaseDocument)); 478 } 479 480 /** 481 * validate the ECDD business rules 482 * @param cashDecreaseDocument 483 * @return boolean 484 */ 485 protected boolean validateECDD(CashDecreaseDocument cashDecreaseDocument) { 486 return kualiRuleService.applyRules(new RouteDocumentEvent(cashDecreaseDocument)); 487 } 488 489 /** 490 * Gets the transaction type code based on the document component type 491 * @param pooledFundControl 492 * @param docComponentType 493 * @return 494 */ 495 protected String getEtranTypeCode(PooledFundControl pooledFundControl, String docComponentType) { 496 String etranTypeCode = ""; 497 if (docComponentType.equalsIgnoreCase(EndowParameterKeyConstants.PURCHASE_DESCRIPTION)) { 498 etranTypeCode = pooledFundControl.getFundAssetPurchaseOffsetTranCode(); 499 } else if (docComponentType.equalsIgnoreCase(EndowParameterKeyConstants.SALE_DESCRIPTION)) { 500 etranTypeCode = pooledFundControl.getFundAssetSaleOffsetTranCode(); 501 } else if (docComponentType.equalsIgnoreCase(EndowParameterKeyConstants.GAIN_LOSS_DESCRIPTION)) { 502 etranTypeCode = pooledFundControl.getFundSaleGainLossOffsetTranCode(); 503 } else if (docComponentType.equalsIgnoreCase(EndowParameterKeyConstants.INCOME_DESCRIPTION)) { 504 etranTypeCode = pooledFundControl.getFundCashDepositOffsetTranCode(); 505 } 506 507 return etranTypeCode; 508 } 509 510 /** 511 * check if it is no route 512 * @return boolean 513 */ 514 public boolean isNoRoute(String paramNoRouteInd) { 515 return parameterService.getIndicatorParameter(PooledFundControlTransactionsStep.class, paramNoRouteInd); 516 } 517 518 /** 519 * Writes the total report 520 * @param <C> 521 * @param cashDocument 522 * @param documentType 523 */ 524 protected <C extends EndowmentSecurityDetailsDocumentBase> void writeTotalReport(C cashDocument, String documentType, String incomePrincipalIndicator) { 525 totalReportLine.setDocumentType(documentType); 526 totalReportLine.setDocumentId(cashDocument.getDocumentNumber()); 527 totalReportLine.setSecurityId(cashDocument.getTargetTransactionSecurity().getSecurityID()); 528 if (incomePrincipalIndicator.equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.PRINCIPAL)) { 529 totalReportLine.setPrincipalAmount(cashDocument.getTargetPrincipalTotal().add(cashDocument.getSourcePrincipalTotal())); 530 totalReportLine.setPrincipalUnits(cashDocument.getTargetPrincipalTotalUnits().add(cashDocument.getSourcePrincipalTotalUnits())); 531 } else if (incomePrincipalIndicator.equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.INCOME)) { 532 totalReportLine.setIncomeAmount(cashDocument.getTargetIncomeTotal().add(cashDocument.getSourceIncomeTotal())); 533 totalReportLine.setIncomeUnits(cashDocument.getTargetIncomeTotalUnits().add(cashDocument.getSourceIncomeTotalUnits())); 534 } 535 if (cashDocument.getNextTargetLineNumber() > 1) { 536 totalReportLine.setTotalNumberOfTransactionLines(cashDocument.getNextTargetLineNumber() - 1); 537 } else { 538 totalReportLine.setTotalNumberOfTransactionLines(cashDocument.getNextSourceLineNumber() - 1); 539 } 540 pooledFundControlTransactionsTotalReportWriterService.writeTableRow(totalReportLine); 541 542 // reset for the next total report 543 totalReportLine.setTotalNumberOfTransactionLines(0); 544 totalReportLine.setPrincipalAmount(KualiDecimal.ZERO); 545 totalReportLine.setPrincipalUnits(KualiDecimal.ZERO); 546 totalReportLine.setIncomeAmount(KualiDecimal.ZERO); 547 totalReportLine.setIncomeUnits(KualiDecimal.ZERO); 548 } 549 550 /** 551 * Writes transaction line validation errors per each 552 * @param documentType 553 * @param kemid 554 * @param transactionAmount 555 */ 556 protected void writeTransactionLineValidationErrorReport(String documentType, String documentId, String securityId, String kemid, KualiDecimal transactionAmount) { 557 exceptionReportLine.setDocumentType(documentType); 558 exceptionReportLine.setDocumentId(documentId); 559 exceptionReportLine.setSecurityId(securityId); 560 exceptionReportLine.setKemid(kemid); 561 exceptionReportLine.setIncomeAmount(transactionAmount); 562 pooledFundControlTransactionsExceptionReportWriterService.writeTableRow(exceptionReportLine); 563 564 List<String> errorMessages = GloabalVariablesExtractHelper.extractGlobalVariableErrors(); 565 for (String errorMessage : errorMessages) { 566 pooledFundControlTransactionsExceptionReportWriterService.writeFormattedMessageLine("Reason: %s", errorMessage); 567 } 568 pooledFundControlTransactionsExceptionReportWriterService.writeNewLines(1); 569 } 570 571 /** 572 * Writes document validation errors 573 * @param <T> 574 * @param cashDocument 575 * @param documentType 576 */ 577 protected <T extends EndowmentSecurityDetailsDocumentBase> void writeDocumentValdiationErrorReport(T cashDocument, String documentType) { 578 exceptionReportLine.setDocumentType(documentType); 579 exceptionReportLine.setDocumentId(cashDocument.getDocumentNumber()); 580 exceptionReportLine.setSecurityId(cashDocument.getTargetTransactionSecurity().getSecurityID()); 581 exceptionReportLine.setIncomeAmount(cashDocument.getTargetIncomeTotal()); 582 pooledFundControlTransactionsExceptionReportWriterService.writeTableRow(exceptionReportLine); 583 584 List<String> errorMessages = GloabalVariablesExtractHelper.extractGlobalVariableErrors(); 585 for (String errorMessage : errorMessages) { 586 pooledFundControlTransactionsExceptionReportWriterService.writeFormattedMessageLine("Reason: %s", errorMessage); 587 } 588 pooledFundControlTransactionsExceptionReportWriterService.writeNewLines(1); 589 } 590 591 /** 592 * Writes the submission errors 593 * @param <T> 594 * @param cashDocument 595 * @param documentType 596 */ 597 protected <T extends EndowmentSecurityDetailsDocumentBase> void writeSubmissionErrorReport(T cashDocument, String documentType, String errorMessage) { 598 exceptionReportLine.setDocumentType(documentType); 599 exceptionReportLine.setDocumentId(cashDocument.getDocumentNumber()); 600 exceptionReportLine.setSecurityId(cashDocument.getTargetTransactionSecurity().getSecurityID()); 601 exceptionReportLine.setIncomeAmount(cashDocument.getTargetIncomeTotal()); 602 pooledFundControlTransactionsExceptionReportWriterService.writeTableRow(exceptionReportLine); 603 pooledFundControlTransactionsExceptionReportWriterService.writeFormattedMessageLine("Reason: %s", errorMessage); 604 pooledFundControlTransactionsExceptionReportWriterService.writeNewLines(1); 605 } 606 607 /** 608 * Initializes reports 609 */ 610 protected void initializeReports() { 611 612 // initialize totalReportLine 613 this.totalReportLine = new TransactionDocumentTotalReportLine(); 614 pooledFundControlTransactionsTotalReportWriterService.writeSubTitle("<pooledFundControlTransactionsJob> Totals Processed"); 615 pooledFundControlTransactionsTotalReportWriterService.writeNewLines(1); 616 pooledFundControlTransactionsTotalReportWriterService.writeTableHeader(totalReportLine); 617 618 // initialize exceptionReportLine 619 this.exceptionReportLine = new TransactionDocumentExceptionReportLine(); 620 pooledFundControlTransactionsExceptionReportWriterService.writeSubTitle("<pooledFundControlTransactionsJob> Exception Report"); 621 pooledFundControlTransactionsExceptionReportWriterService.writeNewLines(1); 622 pooledFundControlTransactionsExceptionReportWriterService.writeTableHeader(exceptionReportLine); 623 } 624 625 /** 626 * Sets the businessObjectService attribute value. 627 * @param businessObjectService The businessObjectService to set. 628 */ 629 public void setBusinessObjectService(BusinessObjectService businessObjectService) { 630 this.businessObjectService = businessObjectService; 631 } 632 633 /** 634 * Sets the pooledFundControlTransactionsDaoOjb attribute value. 635 * @param pooledFundControlTransactionsDaoOjb The pooledFundControlTransactionsDaoOjb to set. 636 */ 637 public void setPooledFundControlTransactionsDao(PooledFundControlTransactionsDao pooledFundControlTransactionsDao) { 638 this.pooledFundControlTransactionsDao = pooledFundControlTransactionsDao; 639 } 640 641 /** 642 * Gets the documentService attribute. 643 * @return Returns the documentService. 644 */ 645 public DocumentService getDocumentService() { 646 return documentService; 647 } 648 649 /** 650 * Sets the documentService attribute value. 651 * @param documentService The documentService to set. 652 */ 653 public void setDocumentService(DocumentService documentService) { 654 this.documentService = documentService; 655 } 656 657 /** 658 * Sets the kualiRuleService attribute value. 659 * @param kualiRuleService The kualiRuleService to set. 660 */ 661 public void setKualiRuleService(KualiRuleService kualiRuleService) { 662 this.kualiRuleService = kualiRuleService; 663 } 664 665 /** 666 * Sets the parameterService attribute value. 667 * @param parameterService The parameterService to set. 668 */ 669 public void setParameterService(ParameterService parameterService) { 670 this.parameterService = parameterService; 671 } 672 673 /** 674 * Sets the pooledFundControlTransactionsExceptionReportWriterService attribute value. 675 * @param pooledFundControlTransactionsExceptionReportWriterService The pooledFundControlTransactionsExceptionReportWriterService to set. 676 */ 677 public void setPooledFundControlTransactionsExceptionReportWriterService(ReportWriterService pooledFundControlTransactionsExceptionReportWriterService) { 678 this.pooledFundControlTransactionsExceptionReportWriterService = pooledFundControlTransactionsExceptionReportWriterService; 679 } 680 681 /** 682 * Sets the pooledFundControlTransactionsTotalReportWriterService attribute value. 683 * @param pooledFundControlTransactionsTotalReportWriterService The pooledFundControlTransactionsTotalReportWriterService to set. 684 */ 685 public void setPooledFundControlTransactionsTotalReportWriterService(ReportWriterService pooledFundControlTransactionsTotalReportWriterService) { 686 this.pooledFundControlTransactionsTotalReportWriterService = pooledFundControlTransactionsTotalReportWriterService; 687 } 688 689 /** 690 * Sets the kemService attribute value. 691 * @param kemService The kemService to set. 692 */ 693 public void setKemService(KEMService kemService) { 694 this.kemService = kemService; 695 } 696 697 }