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.math.BigDecimal; 019 import java.sql.Date; 020 import java.util.ArrayList; 021 import java.util.Collection; 022 import java.util.HashMap; 023 import java.util.List; 024 025 import org.kuali.kfs.module.endow.EndowConstants; 026 import org.kuali.kfs.module.endow.EndowPropertyConstants; 027 import org.kuali.kfs.module.endow.batch.service.KemidFeeService; 028 import org.kuali.kfs.module.endow.batch.service.ProcessFeeTransactionsService; 029 import org.kuali.kfs.module.endow.businessobject.EndowmentExceptionReportHeader; 030 import org.kuali.kfs.module.endow.businessobject.EndowmentSourceTransactionLine; 031 import org.kuali.kfs.module.endow.businessobject.FeeMethod; 032 import org.kuali.kfs.module.endow.businessobject.FeeProcessingTotalsProcessedDetailTotalLine; 033 import org.kuali.kfs.module.endow.businessobject.FeeProcessingTotalsProcessedGrandTotalLine; 034 import org.kuali.kfs.module.endow.businessobject.FeeProcessingTotalsProcessedReportHeader; 035 import org.kuali.kfs.module.endow.businessobject.FeeProcessingTotalsProcessedSubTotalLine; 036 import org.kuali.kfs.module.endow.businessobject.FeeProcessingWaivedAndAccruedDetailTotalLine; 037 import org.kuali.kfs.module.endow.businessobject.FeeProcessingWaivedAndAccruedGrandTotalLine; 038 import org.kuali.kfs.module.endow.businessobject.FeeProcessingWaivedAndAccruedReportHeader; 039 import org.kuali.kfs.module.endow.businessobject.FeeProcessingWaivedAndAccruedSubTotalLine; 040 import org.kuali.kfs.module.endow.businessobject.KemidFee; 041 import org.kuali.kfs.module.endow.dataaccess.CurrentTaxLotBalanceDao; 042 import org.kuali.kfs.module.endow.dataaccess.HoldingHistoryDao; 043 import org.kuali.kfs.module.endow.dataaccess.KemidFeeDao; 044 import org.kuali.kfs.module.endow.dataaccess.TransactionArchiveDao; 045 import org.kuali.kfs.module.endow.document.CashDecreaseDocument; 046 import org.kuali.kfs.module.endow.document.service.FeeMethodService; 047 import org.kuali.kfs.module.endow.document.service.KEMService; 048 import org.kuali.kfs.module.endow.document.service.TransactionArchiveService; 049 import org.kuali.kfs.module.endow.document.validation.event.AddTransactionLineEvent; 050 import org.kuali.kfs.module.endow.util.GloabalVariablesExtractHelper; 051 import org.kuali.kfs.module.endow.util.KEMCalculationRoundingHelper; 052 import org.kuali.kfs.sys.KFSConstants; 053 import org.kuali.kfs.sys.context.SpringContext; 054 import org.kuali.kfs.sys.service.ReportWriterService; 055 import org.kuali.rice.kew.exception.WorkflowException; 056 import org.kuali.rice.kim.bo.Person; 057 import org.kuali.rice.kim.service.PersonService; 058 import org.kuali.rice.kns.bo.Note; 059 import org.kuali.rice.kns.rule.event.RouteDocumentEvent; 060 import org.kuali.rice.kns.service.DocumentService; 061 import org.kuali.rice.kns.service.KNSServiceLocator; 062 import org.kuali.rice.kns.service.KualiConfigurationService; 063 import org.kuali.rice.kns.service.KualiRuleService; 064 import org.kuali.rice.kns.service.NoteService; 065 import org.kuali.rice.kns.service.TransactionalDocumentDictionaryService; 066 import org.kuali.rice.kns.util.KualiDecimal; 067 import org.kuali.rice.kns.util.ObjectUtils; 068 import org.springframework.transaction.annotation.Transactional; 069 070 /** 071 * This class implements the ProcessFeeTransactionsService. 072 */ 073 @Transactional 074 public class ProcessFeeTransactionsServiceImpl implements ProcessFeeTransactionsService { 075 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ProcessFeeTransactionsServiceImpl.class); 076 077 protected KemidFeeService kemidFeeService; 078 protected FeeMethodService feeMethodService; 079 protected KEMService kemService; 080 protected TransactionArchiveDao transactionArchiveDao; 081 protected HoldingHistoryDao holdingHistoryDao; 082 protected CurrentTaxLotBalanceDao currentTaxLotBalanceDao; 083 protected KemidFeeDao kemidFeeDao; 084 protected DocumentService documentService; 085 protected KualiRuleService kualiRuleService; 086 protected NoteService noteService; 087 protected PersonService personService; 088 protected KualiConfigurationService configService; 089 090 protected ReportWriterService processFeeTransactionsExceptionReportsWriterService; 091 protected ReportWriterService processFeeTransactionsTotalProcessedReportsWriterService; 092 protected ReportWriterService processFeeTransactionsWaivedAndAccruedFeesReportsWriterService; 093 094 protected EndowmentExceptionReportHeader processFeeTransactionsExceptionReportHeader; 095 protected FeeProcessingTotalsProcessedReportHeader processFeeTransactionsTotalProcessedReportHeader; 096 protected FeeProcessingWaivedAndAccruedReportHeader processFeeTransactionsWaivedAndAccruedFeesReportHeader; 097 098 protected EndowmentExceptionReportHeader processFeeTransactionsRowValues; 099 protected EndowmentExceptionReportHeader processFeeTransactionsExceptionRowReason; 100 101 protected FeeProcessingWaivedAndAccruedDetailTotalLine feeProcessingWaivedAndAccruedDetailTotalLine; 102 protected FeeProcessingWaivedAndAccruedSubTotalLine feeProcessingWaivedAndAccruedSubTotalLine; 103 protected FeeProcessingWaivedAndAccruedGrandTotalLine feeProcessingWaivedAndAccruedGrandTotalLine; 104 105 protected FeeProcessingTotalsProcessedDetailTotalLine feeProcessingTotalsProcessedDetailTotalLine; 106 protected FeeProcessingTotalsProcessedSubTotalLine feeProcessingTotalsProcessedSubTotalLine; 107 protected FeeProcessingTotalsProcessedGrandTotalLine feeProcessingTotalsProcessedGrandTotalLine; 108 109 //the properties to hold count, total amounts and fee etc. 110 protected long totalNumberOfRecords = 0; 111 protected BigDecimal totalAmountCalculated = BigDecimal.ZERO; 112 protected BigDecimal feeToBeCharged = BigDecimal.ZERO; 113 protected BigDecimal transactionIncomeAmount = BigDecimal.ZERO; 114 protected BigDecimal transacationPrincipalAmount = BigDecimal.ZERO; 115 protected BigDecimal totalHoldingUnits = BigDecimal.ZERO; 116 117 //properties to help in writing subtotals and grand totals lines. 118 //lines generated 119 protected int totalProcessedLinesGeneratedSubTotal = 0; 120 protected int totalProcessedLinesGeneratedGrandTotal = 0; 121 122 //income, principal subtotals at the eDoc level 123 protected BigDecimal totalProcessedIncomeAmountSubTotalEDoc = BigDecimal.ZERO; 124 protected BigDecimal totalProcessedPrincipalAmountSubTotalEDoc = BigDecimal.ZERO; 125 126 //income, principal subtotals at the fee method level 127 protected BigDecimal totalProcessedIncomeAmountSubTotal = BigDecimal.ZERO; 128 protected BigDecimal totalProcessedPrincipalAmountSubTotal = BigDecimal.ZERO; 129 130 //income, principal subtotals at the grand total level 131 protected BigDecimal totalProcessedIncomeAmountGrandTotal = BigDecimal.ZERO; 132 protected BigDecimal totalProcessedPrincipalAmountGrandTotal = BigDecimal.ZERO; 133 134 /** 135 * Constructs a HoldingHistoryMarketValuesUpdateServiceImpl instance 136 */ 137 public ProcessFeeTransactionsServiceImpl() { 138 //report writer headers 139 processFeeTransactionsExceptionReportHeader = new EndowmentExceptionReportHeader(); 140 processFeeTransactionsTotalProcessedReportHeader = new FeeProcessingTotalsProcessedReportHeader(); 141 processFeeTransactionsWaivedAndAccruedFeesReportHeader = new FeeProcessingWaivedAndAccruedReportHeader(); 142 143 processFeeTransactionsRowValues = new EndowmentExceptionReportHeader(); 144 processFeeTransactionsExceptionRowReason = new EndowmentExceptionReportHeader(); 145 146 //waiver and accrual report.... 147 feeProcessingWaivedAndAccruedDetailTotalLine = new FeeProcessingWaivedAndAccruedDetailTotalLine(); 148 feeProcessingWaivedAndAccruedSubTotalLine = new FeeProcessingWaivedAndAccruedSubTotalLine(); 149 feeProcessingWaivedAndAccruedGrandTotalLine = new FeeProcessingWaivedAndAccruedGrandTotalLine(); 150 151 //Totals processed report.... 152 feeProcessingTotalsProcessedDetailTotalLine = new FeeProcessingTotalsProcessedDetailTotalLine(); 153 feeProcessingTotalsProcessedSubTotalLine = new FeeProcessingTotalsProcessedSubTotalLine(); 154 feeProcessingTotalsProcessedGrandTotalLine = new FeeProcessingTotalsProcessedGrandTotalLine(); 155 } 156 157 /** 158 * The fee process is intended to provide as much flexibility to the institution as possible when 159 * designing the charges to be assessed against a KEMID. The fees can be based on either balances 160 * or activity and can be charged, accrued or waived at the KEMID level. 161 * @see oorg.kuali.kfs.module.endow.batch.service.ProcessFeeTransactionsService#processFeeTransactions()\ 162 * return boolean true if successful else false 163 */ 164 public boolean processFeeTransactions() { 165 LOG.info("processFeeTransactions() started"); 166 167 boolean success = true; 168 169 writeReportHeaders(); 170 171 if (!updateKemidFeeWaivedYearToDateAmount()) { 172 writeTableRowAndTableReason("Reason: unable to update update Waiver Fee Year To Date column to Zero."); 173 return false; 174 } 175 176 //Update the fee transactions. 177 success &= processUpdateFeeTransactions(); 178 179 //generate the waived and accrued report... 180 success &= generateWaivedAndAccruedReport(); 181 182 return success; 183 } 184 185 /** 186 * Updates waived fee year to date column to zero in WAIVED_FEE_YTD 187 * @return true if updated successfully else return false 188 */ 189 protected boolean updateKemidFeeWaivedYearToDateAmount() { 190 LOG.info("updateKemidFeeWaivedFeeYearToDateToZero() started"); 191 192 // 6.2.1 Basic Process - Step 1: 193 boolean updated = true; 194 195 if (!kemidFeeDao.updateKemidFeeWaivedFeeYearToDateToZero()) { 196 writeTableRowAndTableReason("Batch Process Fee Transactions job is aborted. Unable to update KEMID Year-To-Date Waiver Fee amounts"); 197 return false; 198 } 199 200 LOG.info("updateKemidFeeWaivedFeeYearToDateToZero() ended."); 201 return updated; 202 } 203 204 /** 205 * Writes the reports headers for totals processed, waived and accrued fee, and exceptions reports. 206 */ 207 protected void writeReportHeaders() { 208 //writes the exception report header 209 processFeeTransactionsExceptionReportsWriterService.writeNewLines(1); 210 processFeeTransactionsExceptionReportsWriterService.writeTableHeader(processFeeTransactionsExceptionReportHeader); 211 212 //writes the Waived and Accrued Fees report header.... 213 processFeeTransactionsWaivedAndAccruedFeesReportsWriterService.writeNewLines(1); 214 processFeeTransactionsWaivedAndAccruedFeesReportsWriterService.writeTableHeader(processFeeTransactionsWaivedAndAccruedFeesReportHeader); 215 216 //writes the Totals Processed report header.... 217 processFeeTransactionsTotalProcessedReportsWriterService.writeNewLines(1); 218 processFeeTransactionsTotalProcessedReportsWriterService.writeTableHeader(processFeeTransactionsTotalProcessedReportHeader); 219 } 220 221 /** 222 * Processes update Fee Transactions 223 */ 224 protected boolean processUpdateFeeTransactions() { 225 LOG.info("processUpdateFeeTransactions() started"); 226 227 boolean success = true; 228 229 java.util.Date currentDate = kemService.getCurrentDate(); 230 int maxNumberOfTransactionLinesPerDocument = kemService.getMaxNumberOfTransactionLinesPerDocument(); 231 232 Collection<FeeMethod> feeMethods = feeMethodService.getFeeMethodsByNextProcessingDate(currentDate); 233 for (FeeMethod feeMethod : feeMethods) { 234 String feeTypeCode = feeMethod.getFeeTypeCode(); 235 236 //1. IF the END_FEE_MTHD_T: FEE_TYP_CD is equal to T (Transactions) 237 if (feeTypeCode.equals(EndowConstants.FeeMethod.FEE_TYPE_CODE_VALUE_FOR_TRANSACTIONS)) { 238 processTransactionArchivesCountForTransactionsFeeType(feeMethod); 239 } 240 241 //2. IF the END_FEE_MTHD_T: FEE_TYP_CD is equal to B (Balance) 242 if (feeTypeCode.equals(EndowConstants.FeeMethod.FEE_TYPE_CODE_VALUE_FOR_BALANCES)) { 243 processBalanceFeeType(feeMethod); 244 } 245 246 if (feeTypeCode.equals(EndowConstants.FeeMethod.FEE_TYPE_CODE_VALUE_FOR_TRANSACTIONS) || 247 feeTypeCode.equals(EndowConstants.FeeMethod.FEE_TYPE_CODE_VALUE_FOR_BALANCES)) { 248 performCalculationsForKemId(feeMethod); 249 success &= generateCashDecreaseDocument(feeMethod, maxNumberOfTransactionLinesPerDocument); 250 } 251 } 252 253 if (feeMethods.size() > 0) { //REMOVE 254 // write out the grand totals line for Totals processed report... 255 writeTotalsProcessedGrandTotalsLine(); 256 } 257 258 LOG.info("processUpdateFeeTransactions() ended."); 259 260 return success; 261 } 262 263 /** 264 * Generates the fee waived and fee accrued report 265 */ 266 protected boolean generateWaivedAndAccruedReport() { 267 LOG.info("generateWaivedAndAccruedReport() started"); 268 269 boolean success = true; 270 KualiDecimal accruedFeeGrandTotal = KualiDecimal.ZERO; 271 KualiDecimal waivedFeeGrandTotal = KualiDecimal.ZERO; 272 273 Date currentDate = kemService.getCurrentDate(); 274 275 Collection<FeeMethod> feeMethods = feeMethodService.getFeeMethodsByNextProcessingDate(currentDate); 276 277 for (FeeMethod feeMethod : feeMethods) { 278 KualiDecimal accruedFeeSubTotal = KualiDecimal.ZERO; 279 KualiDecimal waivedFeeSubTotal = KualiDecimal.ZERO; 280 281 Collection<KemidFee> kemidFeeRecords = kemidFeeService.getAllKemidForFeeMethodCode(feeMethod.getCode()); 282 283 for (KemidFee kemidFee : kemidFeeRecords) { 284 feeProcessingWaivedAndAccruedDetailTotalLine.setTotal(feeMethod.getCode()); 285 feeProcessingWaivedAndAccruedDetailTotalLine.setKemid(kemidFee.getKemid()); 286 feeProcessingWaivedAndAccruedDetailTotalLine.setTotalAccruedFees(kemidFee.getTotalAccruedFees()); 287 feeProcessingWaivedAndAccruedDetailTotalLine.setTotalWaivedFees(kemidFee.getTotalWaivedFees()); 288 289 processFeeTransactionsWaivedAndAccruedFeesReportsWriterService.writeTableRow(feeProcessingWaivedAndAccruedDetailTotalLine); 290 291 accruedFeeSubTotal = accruedFeeSubTotal.add(kemidFee.getTotalAccruedFees()); 292 waivedFeeSubTotal = waivedFeeSubTotal.add(kemidFee.getTotalWaivedFees()); 293 } 294 295 feeProcessingWaivedAndAccruedSubTotalLine.setTotalAccruedFees(accruedFeeSubTotal); 296 feeProcessingWaivedAndAccruedSubTotalLine.setTotalWaivedFees(waivedFeeSubTotal); 297 298 if (kemidFeeRecords.size() > 0) { 299 processFeeTransactionsWaivedAndAccruedFeesReportsWriterService.writeTableRow(feeProcessingWaivedAndAccruedSubTotalLine); 300 processFeeTransactionsWaivedAndAccruedFeesReportsWriterService.writeNewLines(1); 301 } 302 accruedFeeGrandTotal = accruedFeeGrandTotal.add(accruedFeeSubTotal); 303 waivedFeeGrandTotal = waivedFeeGrandTotal.add(waivedFeeSubTotal); 304 } 305 306 feeProcessingWaivedAndAccruedGrandTotalLine.setTotalAccruedFees(accruedFeeGrandTotal); 307 feeProcessingWaivedAndAccruedGrandTotalLine.setTotalWaivedFees(waivedFeeGrandTotal); 308 processFeeTransactionsWaivedAndAccruedFeesReportsWriterService.writeTableRow(feeProcessingWaivedAndAccruedGrandTotalLine); 309 310 LOG.info("generateWaivedAndAccruedReport() ended."); 311 312 return success; 313 } 314 315 /** 316 * IF the END_FEE_MTHD_T: FEE_TYP_CD is equal to T (Transactions), then the fee 317 * will use the transaction records from END_TRAN_ARCHV_T to calculate the fee. 318 * IF the END_FEE_MTHD_T: FEE_RT_DEF_CD is equal to C (Count), then the process will total 319 * the number of the records that fit the selection criteria (6.2.2.1) where the 320 * END_TRAN_ARCHV_T:TRAN_PSTD_DT is greater than the END_KEMID_FEE_TFEE_MTHD_T: FEE_LST_PROC_DT. 321 * IF the END_FEE_MTHD_T: FEE_RT_DEF_CD is equal to V (Value), then the process will total 322 * the TRAN_INC_CSH_AMT, and/or TRAN_PRIN_CSH_AMT of the records that fit the selection 323 * criteria (6.2.2.1) where the END_TRAN_ARCHV_T: TRAN_PSTD_DT is greater than the 324 * END_KEMID_FEE_TFEE_MTHD_T: FEE_LST_PROC_DT. 325 */ 326 protected void processTransactionArchivesCountForTransactionsFeeType(FeeMethod feeMethod) { 327 // case: FEE_RT_DEF_CD = C for count 328 if (feeMethod.getFeeRateDefinitionCode().equalsIgnoreCase(EndowConstants.FeeMethod.FEE_RATE_DEFINITION_CODE_FOR_COUNT)) { 329 totalNumberOfRecords = transactionArchiveDao.getTransactionArchivesCountForTransactions(feeMethod); 330 totalAmountCalculated = KEMCalculationRoundingHelper.multiply(feeMethod.getFirstFeeRate(), BigDecimal.valueOf(totalNumberOfRecords), EndowConstants.Scale.SECURITY_INCOME_RATE); 331 } 332 333 // case: FEE_RT_DEF_CD = V for value... 334 if (feeMethod.getFeeRateDefinitionCode().equalsIgnoreCase(EndowConstants.FeeMethod.FEE_RATE_DEFINITION_CODE_FOR_VALUE)) { 335 HashMap<String, BigDecimal> incomeAndPrincipalValues = transactionArchiveDao.getTransactionArchivesIncomeAndPrincipalCashAmountForTransactions(feeMethod); 336 transactionIncomeAmount = incomeAndPrincipalValues.get(EndowPropertyConstants.TRANSACTION_ARCHIVE_INCOME_CASH_AMOUNT); 337 transacationPrincipalAmount = incomeAndPrincipalValues.get(EndowPropertyConstants.TRANSACTION_ARCHIVE_PRINCIPAL_CASH_AMOUNT); 338 } 339 } 340 341 /** 342 * IF fee rate code is equal to C (Count), then process will examine the number of units held and 343 * If fee balance type code is equal to AU (Average Units) the process will total the holding units 344 * where month end date is greater than last process date divided by number of records selected. 345 * If fee balance type code is equal to MU (Month End Units) the process will total holding units 346 * for all records where the END_ME_DT_T: ME_DT is the most recent date. 347 * If the fee balance type code is equal to CU (Current Units) the process will total the holding units 348 * 349 * IF rate def code is equal to V (Value), then the process will examine the Market Value of the records. 350 * If fee balance type code is equal to AMV (Average Market Value) the process will total holding market value 351 * where month end date is greater last process date and divide the result by the number of records selected. 352 * If fee balance type code is equal to MMV (Month End market Value) the process will 353 * total holding market value for all records where month end date is the most recent date. 354 * If fee balance type code is equal to CMV (Current Market Value) the process will 355 * total holding market value for all selected records. 356 */ 357 protected void processBalanceFeeType(FeeMethod feeMethod) { 358 if (feeMethod.getFeeRateDefinitionCode().equalsIgnoreCase(EndowConstants.FeeMethod.FEE_RATE_DEFINITION_CODE_FOR_COUNT)) { 359 //when FEE_BAL_TYP_CD = AU OR CU then total END_HLDG_HIST_T:HLDG_UNITS column 360 performFeeRateDefintionForCountCalculations(feeMethod); 361 } 362 363 //if FEE_RATE_DEFINITION_CODE = "V" 364 if (feeMethod.getFeeRateDefinitionCode().equalsIgnoreCase(EndowConstants.FeeMethod.FEE_RATE_DEFINITION_CODE_FOR_VALUE)) { 365 performFeeRateDefintionForValueCalculations(feeMethod); 366 } 367 } 368 369 /** 370 * performs calculations when Fee Rate Definition Code is C 371 */ 372 protected void performFeeRateDefintionForCountCalculations(FeeMethod feeMethod) { 373 String feeBalanceTypeCode = feeMethod.getFeeBalanceTypeCode(); 374 375 //when FEE_BAL_TYP_CD = AU OR MU then total END_HLDG_HIST_T:HLDG_UNITS column 376 if (feeBalanceTypeCode.equals(EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_AVERAGE_UNITS) || 377 feeBalanceTypeCode.equals(EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_MONTH_END_UNITS)) { 378 totalHoldingUnits = holdingHistoryDao.getHoldingHistoryTotalHoldingUnits(feeMethod); 379 } 380 381 if (feeBalanceTypeCode.equals(EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_CURRENT_UNITS)) { 382 totalHoldingUnits = currentTaxLotBalanceDao.getCurrentTaxLotBalanceTotalHoldingUnits(feeMethod); 383 } 384 385 totalAmountCalculated = KEMCalculationRoundingHelper.multiply(feeMethod.getFirstFeeRate(), totalHoldingUnits, EndowConstants.Scale.SECURITY_MARKET_VALUE); 386 } 387 388 /** 389 * performs calculations when Fee Rate Definition Code is V 390 */ 391 protected void performFeeRateDefintionForValueCalculations(FeeMethod feeMethod) { 392 String feeBalanceTypeCode = feeMethod.getFeeBalanceTypeCode(); 393 394 //when FEE_BAL_TYP_CD = AMV OR MMV then total END_HLDG_HIST_T:HLDG_UNITS column 395 if (feeBalanceTypeCode.equals(EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_AVERAGE_MARKET_VALUE) || 396 feeBalanceTypeCode.equals(EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_MONTH_END_MARKET_VALUE)) { 397 totalHoldingUnits = holdingHistoryDao.getHoldingHistoryTotalHoldingMarketValue(feeMethod); 398 } 399 400 if (feeBalanceTypeCode.equals(EndowConstants.FeeBalanceTypes.FEE_BALANCE_TYPE_VALUE_FOR_CURRENT_MARKET_VALUE)) { 401 totalHoldingUnits = currentTaxLotBalanceDao.getCurrentTaxLotBalanceTotalHoldingMarketValue(feeMethod); 402 } 403 404 totalAmountCalculated = KEMCalculationRoundingHelper.multiply(feeMethod.getFirstFeeRate(), totalHoldingUnits, EndowConstants.Scale.SECURITY_MARKET_VALUE); 405 } 406 407 /** 408 * Performs the calculations to get the fee amount to be charged against the selected kemids 409 * @param feeMethod 410 */ 411 protected void performCalculationsForKemId(FeeMethod feeMethod) { 412 LOG.info("performCalculationsForKemId() started"); 413 414 Collection<KemidFee> kemidFeeRecords = new ArrayList(); 415 416 kemidFeeRecords = kemidFeeService.getAllKemidForFeeMethodCode(feeMethod.getCode()); 417 418 for (KemidFee kemidFee : kemidFeeRecords) { 419 if (kemidFeeService.chargeFeeToKemid(feeMethod, kemidFee)) { 420 performCalculationsAgainstTotalAmountCalculated(feeMethod); 421 calculateMinumumFeeAmount(feeMethod); 422 if (checkForMinimumThresholdAmount(feeMethod, kemidFee)) { 423 if (kemidFee.isAccrueFees()) { 424 processFeeAccrual(feeMethod, kemidFee); 425 } 426 if (kemidFee.isWaiveFees()) { 427 processFeeWaiver(feeMethod, kemidFee); 428 } 429 } 430 } 431 } 432 433 LOG.info("performCalculationsForKemId() ended."); 434 } 435 436 /** 437 * Perform the calculations against the total amount calculated for each KEMID following the process outlined in step three above and calculate the fee amount by adding together the results of the following calculations: 438 * 1. Multiply the value of the total amount calculated that is less than or equal to the 439 * END_KEMID_FEE_TFEE_MTHD_T: FEE_BRK_1 by END_KEMID_FEE_TFEE_MTHD_T: FEE_RT_1 440 * 2. Multiply the value of the total amount calculated that is greater than the 441 * END_KEMID_FEE_TFEE_MTHD_T: FEE_BRK_1 and less than or equal to the END_KEMID_FEE_TFEE_MTHD_T: FEE_BRK_2 by END_KEMID_FEE_TFEE_MTHD_T: FEE_RT_2 442 * 3. Multiply the value of the total amount calculated that is greater than the 443 * END_KEMID_FEE_TFEE_MTHD_T: FEE_BRK_2 by END_KEMID_FEE_TFEE_MTHD_T: FEE_RT_3. 444 * @param feeMethod 445 */ 446 protected void performCalculationsAgainstTotalAmountCalculated(FeeMethod feeMethod) { 447 BigDecimal firstFeeBreakpoint = feeMethod.getFirstFeeBreakpoint().bigDecimalValue(); 448 BigDecimal secondFeeBreakpoint = feeMethod.getSecondFeeBreakpoint().bigDecimalValue(); 449 450 if (totalAmountCalculated.compareTo(firstFeeBreakpoint) <= 0) { 451 feeToBeCharged = feeToBeCharged.add(KEMCalculationRoundingHelper.multiply(totalAmountCalculated, feeMethod.getFirstFeeRate(), EndowConstants.Scale.SECURITY_MARKET_VALUE)); 452 } 453 454 if (totalAmountCalculated.compareTo(firstFeeBreakpoint) > 0 && 455 totalAmountCalculated.compareTo(secondFeeBreakpoint) <= 0){ 456 feeToBeCharged = feeToBeCharged.add(KEMCalculationRoundingHelper.multiply(totalAmountCalculated, feeMethod.getSecondFeeRate(), EndowConstants.Scale.SECURITY_MARKET_VALUE)); 457 } 458 459 if (totalAmountCalculated.compareTo(secondFeeBreakpoint) > 0){ 460 feeToBeCharged = feeToBeCharged.add(KEMCalculationRoundingHelper.multiply(totalAmountCalculated, feeMethod.getThirdFeeRate(), EndowConstants.Scale.SECURITY_MARKET_VALUE)); 461 } 462 } 463 464 /** 465 * IF the calculated fee is less than the amount in END_FEE_MTHD_T: FEE_MIN_AMT, then 466 * the feee to be charged is the minimum fee amount.. 467 * @param feeMethod 468 */ 469 protected void calculateMinumumFeeAmount(FeeMethod feeMethod) { 470 if (totalAmountCalculated.compareTo(feeMethod.getMinimumFeeToCharge().bigDecimalValue()) < 0) { 471 feeToBeCharged = feeMethod.getMinimumFeeToCharge().bigDecimalValue(); 472 } 473 } 474 475 /** 476 * IF the calculated fee amount is LESS than the value in END_FEE_MTHD_T: FEE_MIN_THRSHLD, 477 * then do not charge the fee (no transaction generated. The information should be reported as an 478 * exception on the exception report. 479 * @param feeMethod 480 * @param kemidFee 481 * @return true calculated fee amount is greater than 0 482 */ 483 protected boolean checkForMinimumThresholdAmount(FeeMethod feeMethod, KemidFee kemidFee) { 484 boolean shouldNotCharge = true; 485 486 if (feeToBeCharged.compareTo(feeMethod.getMinimumFeeThreshold().bigDecimalValue()) < 0) { 487 writeExceptionReportLine(feeMethod.getCode(), kemidFee.getKemid(), "Reason: Fee is not charged as the fee is less than the minimum threshold"); 488 return false; 489 } 490 491 return shouldNotCharge; 492 } 493 494 /** 495 * IF the field ACR_FEE is equal to Y (Yes), then add the calculated fee amount to the value in 496 * END_KEMID_FEE_MTHD_T: ACRD_FEE_TO_DT. 497 * @param feeMethod, kemidFee 498 * @return feeAcrrued true if fee amount is added to total accrued fees else return false 499 */ 500 protected boolean processFeeAccrual(FeeMethod feeMethod, KemidFee kemidFee) { 501 boolean feeAcrrued = true; 502 503 KualiDecimal accruelFee = new KualiDecimal(feeToBeCharged.toString()); 504 kemidFee.setTotalAccruedFees(kemidFee.getTotalAccruedFees().add(accruelFee)); 505 506 //unable to save. write to exception... 507 if (!kemidFeeService.saveKemidFee(kemidFee)) { 508 writeExceptionReportLine(feeMethod.getCode(), kemidFee.getKemid(), "Reason: Unable to add Calculated Fee to Total Accrued Fees in END_KEMID_FEE_T table."); 509 return false; 510 } 511 512 return feeAcrrued; 513 } 514 515 /** 516 * IF the field WAIVE_FEE is equal to Y (Yes), then add the calculated fee amount to the value 517 * in END_KEMID_FEE_MTHD_T: WAIVED_FEE_TO_DT and add the calculated fee amount to the value in 518 * END_KEMID_FEE_MTHD_T: WAIVED_FEE_YDT 519 * @param feeMethod, kemidFee 520 * @return feeWaived - true if fee amount is added to total waived fees else return false 521 */ 522 protected boolean processFeeWaiver(FeeMethod feeMethod, KemidFee kemidFee) { 523 boolean feeWaived = true; 524 525 KualiDecimal accruelFee = new KualiDecimal(feeToBeCharged.toString()); 526 kemidFee.setTotalWaivedFeesThisFiscalYear(kemidFee.getTotalWaivedFeesThisFiscalYear().add(accruelFee)); 527 kemidFee.setTotalWaivedFees(kemidFee.getTotalWaivedFees().add(accruelFee)); 528 529 //save kemidFee record. 530 if (!kemidFeeService.saveKemidFee(kemidFee)) { 531 writeExceptionReportLine(feeMethod.getCode(), kemidFee.getKemid(), "Reason: Unable to add Calculated Fee to Total Waived Fees in END_KEMID_FEE_T table."); 532 return false; 533 } 534 535 return feeWaived; 536 } 537 538 /** 539 * Generate a CashDecreaseDocument (ECDD) and processes the document by submitting/routing it. 540 * @param feeMethod, kemidFee 541 */ 542 protected boolean generateCashDecreaseDocument(FeeMethod feeMethod, int maxNumberOfTransacationLines) { 543 LOG.info("generateCashDecreaseDocument() entered."); 544 545 String feeMethodCode = feeMethod.getCode(); 546 int lineNumber = 0; 547 548 Collection<KemidFee> kemidFeeRecords = kemidFeeService.getAllKemidForFeeMethodCode(feeMethodCode); 549 550 if (kemidFeeRecords.size() <= 0) { 551 return true; 552 } 553 554 // initialize CashDecreaseDocument... 555 CashDecreaseDocument cashDecreaseDocument = (CashDecreaseDocument) createNewCashDecreaseDocument(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE); 556 if (ObjectUtils.isNull(cashDecreaseDocument)) { 557 writeExceptionReportLine(feeMethodCode, null, "Reason: Unable to create a new CashDecreaseDocument."); 558 return false; 559 } 560 561 //sets document description and source type code and subtype code 562 setDocumentOverviewAndDetails(cashDecreaseDocument, feeMethod.getName()); 563 564 for (KemidFee kemidFee : kemidFeeRecords) { 565 if (lineNumber <= maxNumberOfTransacationLines) { 566 if (!createTransactionLines(cashDecreaseDocument, feeMethod, kemidFee, ++lineNumber, maxNumberOfTransacationLines)) { 567 //did not add the line so reduce the number of lines generated.... 568 --lineNumber; 569 } 570 } 571 else { 572 // reached max transactions. submit and then create a new document.... 573 if (kualiRuleService.applyRules(new RouteDocumentEvent(cashDecreaseDocument))) { 574 if (submitDocumentForApprovalProcess(cashDecreaseDocument, feeMethod)) { 575 // write the detail line for eDoc level... 576 writeTotalsProcessedDetailTotalsLine(cashDecreaseDocument.getDocumentNumber(), feeMethodCode, lineNumber); 577 578 // initialize CashDecreaseDocument... 579 cashDecreaseDocument = (CashDecreaseDocument) createNewCashDecreaseDocument(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE); 580 if (ObjectUtils.isNull(cashDecreaseDocument)) { 581 writeExceptionReportLine(feeMethodCode, kemidFee.getKemid(), "Reason: Unable to create a new CashDecreaseDocument."); 582 return false; 583 } 584 585 setDocumentOverviewAndDetails(cashDecreaseDocument, feeMethod.getName()); 586 lineNumber = 0; 587 } 588 else { 589 //write out exception since can not submit the document.... 590 writeExceptionReportLine(feeMethodCode, kemidFee.getKemid(), "Reason: Unable to submit or route the document."); 591 writeExceptionReportLine(feeMethodCode, kemidFee.getKemid(), "Reason: The document did not pass the rule validations during routing."); 592 } 593 } 594 else { 595 // document rules did not pass the validations. so write exception report.... 596 writeExceptionReportLine(feeMethodCode, kemidFee.getKemid(), "Reason: The document did not pass the rule validations during routing."); 597 wrtieExceptionMessagaeFromGlobalVariables(feeMethodCode, kemidFee.getKemid()); 598 } 599 } 600 } 601 602 //submit the document as all the transactional lines have been added.. 603 if (kualiRuleService.applyRules(new RouteDocumentEvent(cashDecreaseDocument))) { 604 if (submitDocumentForApprovalProcess(cashDecreaseDocument, feeMethod)) { 605 // write the detail line for eDoc level... 606 writeTotalsProcessedDetailTotalsLine(cashDecreaseDocument.getDocumentNumber(), feeMethodCode, lineNumber); 607 } 608 else { 609 //write out exception since can not submit the document.... 610 writeExceptionReportLine(feeMethodCode, null, "Reason: Unable to submit or route the document."); 611 wrtieExceptionMessagaeFromGlobalVariables(feeMethodCode, null); 612 } 613 614 } 615 else { 616 // document rules did not pass the validations. so write exception report.... 617 writeExceptionReportLine(feeMethodCode, null, "Reason: The document did not pass the rule validations during routing."); 618 wrtieExceptionMessagaeFromGlobalVariables(feeMethodCode, null); 619 } 620 621 writeTotalsProcessedSubTotalsLine(feeMethodCode); 622 LOG.info("generateCashDecreaseDocument() ended."); 623 624 return true; 625 } 626 627 protected void writeTotalsProcessedDetailTotalsLine(String documentNumber, String feeMethodCode, int totalLinesGenerated) { 628 feeProcessingTotalsProcessedDetailTotalLine.setFeeMethodCode(feeMethodCode); 629 feeProcessingTotalsProcessedDetailTotalLine.setEDocNumber(documentNumber); 630 feeProcessingTotalsProcessedDetailTotalLine.setLinesGenerated(totalLinesGenerated); 631 feeProcessingTotalsProcessedDetailTotalLine.setTotalIncomeAmount(new KualiDecimal(totalProcessedIncomeAmountSubTotalEDoc.toString())); 632 feeProcessingTotalsProcessedDetailTotalLine.setTotalPrincipalAmount(new KualiDecimal(totalProcessedPrincipalAmountSubTotalEDoc.toString())); 633 634 processFeeTransactionsTotalProcessedReportsWriterService.writeTableRow(feeProcessingTotalsProcessedDetailTotalLine); 635 // processFeeTransactionsTotalProcessedReportsWriterService.writeNewLines(1); 636 637 // add the edoc subtotals to fee method subtotal... 638 totalProcessedLinesGeneratedSubTotal += totalLinesGenerated; 639 totalProcessedIncomeAmountSubTotal = totalProcessedIncomeAmountSubTotal.add(totalProcessedIncomeAmountSubTotalEDoc); 640 totalProcessedPrincipalAmountSubTotal = totalProcessedPrincipalAmountSubTotal.add(totalProcessedPrincipalAmountSubTotalEDoc); 641 } 642 643 protected void writeTotalsProcessedSubTotalsLine(String feeMethodCode) { 644 feeProcessingTotalsProcessedSubTotalLine.setEDocNumber(""); 645 feeProcessingTotalsProcessedSubTotalLine.setLinesGenerated(totalProcessedLinesGeneratedSubTotal); 646 feeProcessingTotalsProcessedSubTotalLine.setTotalIncomeAmount(new KualiDecimal(totalProcessedIncomeAmountSubTotal.toString())); 647 feeProcessingTotalsProcessedSubTotalLine.setTotalPrincipalAmount(new KualiDecimal(totalProcessedPrincipalAmountSubTotal.toString())); 648 649 processFeeTransactionsTotalProcessedReportsWriterService.writeTableRow(feeProcessingTotalsProcessedSubTotalLine); 650 processFeeTransactionsTotalProcessedReportsWriterService.writeNewLines(1); 651 652 totalProcessedIncomeAmountGrandTotal = totalProcessedIncomeAmountGrandTotal.add(totalProcessedIncomeAmountSubTotal); 653 totalProcessedPrincipalAmountGrandTotal = totalProcessedPrincipalAmountGrandTotal.add(totalProcessedPrincipalAmountSubTotal); 654 totalProcessedLinesGeneratedGrandTotal += totalProcessedLinesGeneratedSubTotal; 655 } 656 657 protected void writeTotalsProcessedGrandTotalsLine() { 658 feeProcessingTotalsProcessedGrandTotalLine.setEDocNumber(""); 659 feeProcessingTotalsProcessedGrandTotalLine.setLinesGenerated(totalProcessedLinesGeneratedGrandTotal); 660 feeProcessingTotalsProcessedGrandTotalLine.setTotalIncomeAmount(new KualiDecimal(totalProcessedIncomeAmountGrandTotal.toString())); 661 feeProcessingTotalsProcessedGrandTotalLine.setTotalPrincipalAmount(new KualiDecimal(totalProcessedPrincipalAmountGrandTotal.toString())); 662 663 processFeeTransactionsTotalProcessedReportsWriterService.writeTableRow(feeProcessingTotalsProcessedGrandTotalLine); 664 } 665 666 /** 667 * Sets document description, source type code to A (automated), and subtype code to C (cash) 668 * @param cashDecreaseDocument newly generated document. 669 * @param documentDescription fee method description to be used as document description 670 */ 671 protected void setDocumentOverviewAndDetails(CashDecreaseDocument cashDecreaseDocument, String documentDescription) { 672 cashDecreaseDocument.getDocumentHeader().setDocumentDescription(documentDescription); 673 cashDecreaseDocument.setTransactionSourceTypeCode(EndowConstants.TransactionSourceTypeCode.AUTOMATED); 674 cashDecreaseDocument.setTransactionSubTypeCode(EndowConstants.TransactionSubTypeCode.CASH); 675 } 676 677 /** 678 * After the last transaction line allowed in the eDoc (based on the institutional parameter) or 679 * the last KEMID fee calculated for the fee method, IF the END_FEE_MTHD_T: FEE_POST_PEND_IND is 680 * equal to Y submit the document as a blanket approved 'No Route' document. 681 * Otherwise, submit the document for routing and approval. 682 * @param cashDecreaseDocument 683 * @param feeMethod 684 * @return true if successful in submitting or routing the document. 685 */ 686 protected boolean submitDocumentForApprovalProcess(CashDecreaseDocument cashDecreaseDocument, FeeMethod feeMethod) { 687 LOG.info("submitDocumentForApprovalProcess() entered."); 688 689 boolean success = true; 690 691 if (feeMethod.getFeePostPendingIndicator()) { 692 cashDecreaseDocument.setNoRouteIndicator(false); 693 success = submitCashDecreaseDocument(cashDecreaseDocument, feeMethod.getCode()); 694 } 695 else { 696 cashDecreaseDocument.setNoRouteIndicator(true); 697 success = routeCashDecreaseDocument(cashDecreaseDocument, feeMethod.getCode()); 698 } 699 700 LOG.info("submitDocumentForApprovalProcess() ended."); 701 702 return success; 703 } 704 705 /** 706 * Gets a new document of the document type from the workflow using document service. 707 * @param documentType 708 * @return newCashDecreaseDocument if successfully created a new document else return null 709 */ 710 protected CashDecreaseDocument createNewCashDecreaseDocument(String documentType) { 711 CashDecreaseDocument newCashDecreaseDocument = null; 712 713 try { 714 newCashDecreaseDocument = (CashDecreaseDocument) documentService.getNewDocument(SpringContext.getBean(TransactionalDocumentDictionaryService.class).getDocumentClassByName(documentType)); 715 } catch (WorkflowException wfe) { 716 LOG.info("Failed to initialize CashDecreaseDocument"); 717 return null; 718 } 719 720 return newCashDecreaseDocument; 721 } 722 723 /** 724 * 725 * IF the END_KEMID_FEE_T: PCT_CHRG_FEE_TO_INC is equal to 100%, then generate the 726 * transaction line(s) for the eDoc 727 * @param cashDecreaseDocument 728 * @param feeMethod 729 * @param kemidFee 730 * @param lineNumber current transaction line number 731 * @param maxNumberOfTransacationLines The system parameter specifying the max number of lines 732 * @return true if transaction lines created. 733 */ 734 protected boolean createTransactionLines(CashDecreaseDocument cashDecreaseDocument, FeeMethod feeMethod, KemidFee kemidFee, int lineNumber, int maxNumberOfTransacationLines) { 735 // logic as in 9.3.b 736 if (kemidFee.getPercentOfFeeChargedToIncome().equals(new KualiDecimal("1"))) { 737 EndowmentSourceTransactionLine endowmentSourceTransactionLine = createEndowmentSourceTransactionLine(lineNumber, feeMethod, kemidFee, EndowConstants.IncomePrincipalIndicator.INCOME, feeToBeCharged); 738 if (addTransactionLineToDocument(cashDecreaseDocument, endowmentSourceTransactionLine, lineNumber, feeMethod.getCode())) { 739 totalProcessedIncomeAmountSubTotalEDoc = totalProcessedIncomeAmountSubTotalEDoc.add(feeToBeCharged); 740 return true; 741 } 742 else { 743 return false; 744 } 745 } 746 747 // logic to charge according to logic in 9.3.c 748 BigDecimal feeAmountForIncome = KEMCalculationRoundingHelper.multiply(feeToBeCharged, new BigDecimal(kemidFee.getPercentOfFeeChargedToIncome().toString()), EndowConstants.Scale.SECURITY_MARKET_VALUE); 749 EndowmentSourceTransactionLine endowmentSourceTransactionLine = createEndowmentSourceTransactionLine(lineNumber, feeMethod, kemidFee, EndowConstants.IncomePrincipalIndicator.INCOME, feeAmountForIncome); 750 751 if (addTransactionLineToDocument(cashDecreaseDocument, endowmentSourceTransactionLine, ++lineNumber, feeMethod.getCode())) { 752 totalProcessedIncomeAmountSubTotalEDoc = totalProcessedIncomeAmountSubTotalEDoc.add(feeAmountForIncome); 753 } 754 else { 755 return false; 756 } 757 758 BigDecimal feeAmountForPrincipal = KEMCalculationRoundingHelper.multiply(feeToBeCharged, new BigDecimal(kemidFee.getPercentOfFeeChargedToPrincipal().toString()), EndowConstants.Scale.SECURITY_MARKET_VALUE); 759 760 if (lineNumber <= maxNumberOfTransacationLines) { 761 endowmentSourceTransactionLine = createEndowmentSourceTransactionLine(lineNumber, feeMethod, kemidFee, EndowConstants.IncomePrincipalIndicator.PRINCIPAL, feeAmountForPrincipal); 762 if (addTransactionLineToDocument(cashDecreaseDocument, endowmentSourceTransactionLine, ++lineNumber, feeMethod.getCode())) { 763 totalProcessedPrincipalAmountSubTotalEDoc = totalProcessedPrincipalAmountSubTotalEDoc.add(feeAmountForPrincipal); 764 return true; 765 } 766 else { 767 return false; 768 } 769 } 770 else { 771 boolean submitted = submitDocumentForApprovalProcess(cashDecreaseDocument, feeMethod); 772 //write sub totals at eDoc leve.... 773 writeTotalsProcessedDetailTotalsLine(cashDecreaseDocument.getDocumentNumber(), feeMethod.getCode(), lineNumber); 774 775 // initialize CashDecreaseDocument... 776 cashDecreaseDocument = (CashDecreaseDocument) createNewCashDecreaseDocument(EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_DECREASE); 777 if (ObjectUtils.isNull(cashDecreaseDocument)) { 778 writeExceptionReportLine(feeMethod.getCode(), null, "Reason: Unable to create a new CashDecreaseDocument."); 779 return false; 780 } 781 782 setDocumentOverviewAndDetails(cashDecreaseDocument, feeMethod.getName()); 783 784 lineNumber = 0; 785 endowmentSourceTransactionLine = createEndowmentSourceTransactionLine(lineNumber, feeMethod, kemidFee, EndowConstants.IncomePrincipalIndicator.PRINCIPAL, feeAmountForPrincipal); 786 return addTransactionLineToDocument(cashDecreaseDocument, endowmentSourceTransactionLine, ++lineNumber, feeMethod.getCode()); 787 } 788 } 789 790 /** 791 * 792 * Add the new transaction line after applying the validation rules to the line. 793 * @param cashDecreaseDocument 794 * @param endowmentSourceTransactionLine 795 * @param lineNumber 796 * @return true if the line passed the business rules and added successfully else false. 797 */ 798 protected boolean addTransactionLineToDocument(CashDecreaseDocument cashDecreaseDocument, EndowmentSourceTransactionLine endowmentSourceTransactionLine, int lineNumber, String feeMethodCode) { 799 boolean added = true; 800 801 if (kualiRuleService.applyRules(new AddTransactionLineEvent(EndowConstants.NEW_SOURCE_TRAN_LINE_PROPERTY_NAME, cashDecreaseDocument, endowmentSourceTransactionLine))) { 802 cashDecreaseDocument.getSourceTransactionLines().add(endowmentSourceTransactionLine); 803 cashDecreaseDocument.setNextSourceLineNumber(lineNumber); 804 } 805 else { 806 LOG.info("CashDecreaseDocument Rules Failed. The transaction line is not added for Kemid: " + endowmentSourceTransactionLine.getKemid()); 807 wrtieExceptionMessagaeFromGlobalVariables(feeMethodCode, endowmentSourceTransactionLine.getKemid()); 808 --lineNumber; 809 810 return false; 811 } 812 813 return added; 814 } 815 816 /** 817 * extracts the error messages in the global variables for this session id and writes as exception report 818 */ 819 protected void wrtieExceptionMessagaeFromGlobalVariables(String feeMethodCode, String kemid) { 820 processFeeTransactionsRowValues.setColumnHeading1(feeMethodCode); 821 processFeeTransactionsRowValues.setColumnHeading2(kemid); 822 processFeeTransactionsRowValues.setColumnHeading3(feeToBeCharged.toString()); 823 processFeeTransactionsExceptionReportsWriterService.writeTableRow(processFeeTransactionsRowValues); 824 825 // List<String> errorMessages = extractGlobalVariableErrors(); 826 List<String> errorMessages = GloabalVariablesExtractHelper.extractGlobalVariableErrors(); 827 828 for (String errorMessage : errorMessages) { 829 processFeeTransactionsExceptionReportsWriterService.writeFormattedMessageLine("Reason: %s", errorMessage); 830 } 831 832 processFeeTransactionsExceptionReportsWriterService.writeNewLines(1); 833 } 834 835 /** 836 * Creates a source transaction line 837 * @param lineNumber the current transaction line number 838 * @param feeMethod 839 * @param kemidFee 840 * @param iPIndicator Income or principal indicator for this line 841 * @param feeAmount the calculate fee amount for the transaction amount field 842 * @return endowmentSourceTransactionLine the new source transaction line 843 */ 844 protected EndowmentSourceTransactionLine createEndowmentSourceTransactionLine(int lineNumber, FeeMethod feeMethod, KemidFee kemidFee, String iPIndicator, BigDecimal feeAmount) { 845 EndowmentSourceTransactionLine endowmentSourceTransactionLine = new EndowmentSourceTransactionLine(); 846 endowmentSourceTransactionLine.setTransactionLineNumber(lineNumber); 847 endowmentSourceTransactionLine.setKemid(kemidFee.getChargeFeeToKemid()); 848 endowmentSourceTransactionLine.setEtranCode(feeMethod.getFeeExpenseETranCode()); 849 endowmentSourceTransactionLine.setTransactionIPIndicatorCode(iPIndicator); 850 endowmentSourceTransactionLine.setTransactionAmount(new KualiDecimal(feeToBeCharged.toString())); 851 852 return endowmentSourceTransactionLine; 853 } 854 855 /** 856 * 857 * submits the document. It sets the no route indicator to true and creates a note and sets its text and 858 * adds the note to the document. The document is saved and put into workflow 859 * @param cashDecreaseDocument 860 * @return true if document submitted else false 861 */ 862 protected boolean submitCashDecreaseDocument(CashDecreaseDocument cashDecreaseDocument, String feeMethodCode) { 863 boolean saved = true; 864 865 try { 866 documentService.saveDocument(cashDecreaseDocument); 867 } 868 catch (WorkflowException wfe) { 869 LOG.info("CashDecreaseDocument Rules Failed. The transaction line is not added for Document: " + cashDecreaseDocument.getDocumentNumber()); 870 wrtieExceptionMessagaeFromGlobalVariables(feeMethodCode, null); 871 return false; 872 } 873 catch (Exception ex) { 874 return false; 875 } 876 877 return saved; 878 } 879 880 /** 881 * Routes the document 882 * @param cashDecreaseDocument 883 * @return true if successful else return false 884 */ 885 protected boolean routeCashDecreaseDocument(CashDecreaseDocument cashDecreaseDocument, String feeMethodCode) { 886 boolean routed = true; 887 888 try { 889 documentService.routeDocument(cashDecreaseDocument, "Created by Fee Transactions Batch Job and routed.", null); 890 } 891 catch (WorkflowException wfe) { 892 try { 893 // write errors messages and clear them befor saving..... 894 LOG.info("CashDecreaseDocument Rules Failed. The transaction line is not added for Document: " + cashDecreaseDocument.getDocumentNumber()); 895 wrtieExceptionMessagaeFromGlobalVariables(feeMethodCode, null); 896 897 documentService.saveDocument(cashDecreaseDocument); 898 } 899 catch (WorkflowException wfesave) { 900 return false; 901 } 902 catch (Exception ex) { 903 return false; 904 } 905 906 return false; 907 } 908 909 return routed; 910 } 911 912 /** 913 * Writes the exception report line after setting fee method code and kemid and the reason 914 * @param feeMethodCode 915 * @param kemid 916 * @param reason the reason written on the reason line. 917 */ 918 protected void writeExceptionReportLine(String feeMethodCode, String kemid, String reason) { 919 processFeeTransactionsRowValues.setColumnHeading1(feeMethodCode); 920 processFeeTransactionsRowValues.setColumnHeading2(kemid); 921 processFeeTransactionsRowValues.setColumnHeading3(feeToBeCharged.toString()); 922 writeTableRowAndTableReason(reason); 923 } 924 925 /** 926 * writes out the table row values then writes the reason row and inserts a blank line 927 * @param reasonMessage the reason message 928 */ 929 protected void writeTableRowAndTableReason(String reasonMessage) { 930 processFeeTransactionsExceptionReportsWriterService.writeTableRow(processFeeTransactionsRowValues); 931 setExceptionReportTableRowReason(reasonMessage); 932 processFeeTransactionsExceptionReportsWriterService.writeTableRow(processFeeTransactionsExceptionRowReason); 933 processFeeTransactionsExceptionReportsWriterService.writeNewLines(1); 934 } 935 936 /** 937 * sets the exception message with the passed in value. 938 * @param reasonForException The reason that will be set in the exception report 939 */ 940 protected void setExceptionReportTableRowReason(String reasonForException) { 941 942 processFeeTransactionsExceptionRowReason.setColumnHeading1("Reason: " + reasonForException); 943 processFeeTransactionsExceptionRowReason.setColumnHeading2(""); 944 processFeeTransactionsExceptionRowReason.setColumnHeading3(""); 945 } 946 947 948 /** 949 * Gets the processFeeTransactionsExceptionReportsWriterService attribute. 950 * @return Returns the processFeeTransactionsExceptionReportsWriterService. 951 */ 952 protected ReportWriterService getProcessFeeTransactionsExceptionReportsWriterService() { 953 return processFeeTransactionsExceptionReportsWriterService; 954 } 955 956 /** 957 * Sets the processFeeTransactionsExceptionReportsWriterService attribute value. 958 * @param processFeeTransactionsExceptionReportsWriterService The processFeeTransactionsExceptionReportsWriterService to set. 959 */ 960 public void setProcessFeeTransactionsExceptionReportsWriterService(ReportWriterService processFeeTransactionsExceptionReportsWriterService) { 961 this.processFeeTransactionsExceptionReportsWriterService = processFeeTransactionsExceptionReportsWriterService; 962 } 963 964 /** 965 * Gets the processFeeTransactionsTotalProcessedReportsWriterService attribute. 966 * @return Returns the processFeeTransactionsTotalProcessedReportsWriterService. 967 */ 968 public ReportWriterService getProcessFeeTransactionsTotalProcessedReportsWriterService() { 969 return processFeeTransactionsTotalProcessedReportsWriterService; 970 } 971 972 /** 973 * Sets the processFeeTransactionsTotalProcessedReportsWriterService attribute value. 974 * @param processFeeTransactionsTotalProcessedReportsWriterService The processFeeTransactionsTotalProcessedReportsWriterService to set. 975 */ 976 public void setProcessFeeTransactionsTotalProcessedReportsWriterService(ReportWriterService processFeeTransactionsTotalProcessedReportsWriterService) { 977 this.processFeeTransactionsTotalProcessedReportsWriterService = processFeeTransactionsTotalProcessedReportsWriterService; 978 } 979 980 /** 981 * Gets the processFeeTransactionsWaivedAndAccruedFeesReportsWriterService attribute. 982 * @return Returns the processFeeTransactionsWaivedAndAccruedFeesReportsWriterService. 983 */ 984 public ReportWriterService getProcessFeeTransactionsWaivedAndAccruedFeesReportsWriterService() { 985 return processFeeTransactionsWaivedAndAccruedFeesReportsWriterService; 986 } 987 988 /** 989 * Sets the processFeeTransactionsWaivedAndAccruedFeesReportsWriterService attribute value. 990 * @param processFeeTransactionsWaivedAndAccruedFeesReportsWriterService The processFeeTransactionsWaivedAndAccruedFeesReportsWriterService to set. 991 */ 992 public void setProcessFeeTransactionsWaivedAndAccruedFeesReportsWriterService(ReportWriterService processFeeTransactionsWaivedAndAccruedFeesReportsWriterService) { 993 this.processFeeTransactionsWaivedAndAccruedFeesReportsWriterService = processFeeTransactionsWaivedAndAccruedFeesReportsWriterService; 994 } 995 996 /** 997 * Gets the holdingHistoryService attribute. 998 * @return Returns the holdingHistoryService. 999 */ 1000 protected KemidFeeService getKemidFeeService() { 1001 return kemidFeeService; 1002 } 1003 1004 /** 1005 * Sets the kKemidFeeService attribute value. 1006 * @param kemidFeeService The kemidFeeService to set. 1007 */ 1008 public void setKemidFeeService(KemidFeeService kemidFeeService) { 1009 this.kemidFeeService = kemidFeeService; 1010 } 1011 1012 /** 1013 * Gets the feeMethodService attribute. 1014 * @return Returns the feeMethodService. 1015 */ 1016 protected FeeMethodService getFeeMethodService() { 1017 return feeMethodService; 1018 } 1019 1020 /** 1021 * Sets the feeMethodService attribute value. 1022 * @param feeMethodService The feeMethodService to set. 1023 */ 1024 public void setFeeMethodService(FeeMethodService feeMethodService) { 1025 this.feeMethodService = feeMethodService; 1026 } 1027 1028 /** 1029 * Gets the kemService. 1030 * @return kemService 1031 */ 1032 protected KEMService getKemService() { 1033 return kemService; 1034 } 1035 1036 /** 1037 * Sets the kemService. 1038 * @param kemService 1039 */ 1040 public void setKemService(KEMService kemService) { 1041 this.kemService = kemService; 1042 } 1043 1044 /** 1045 * Gets the processFeeTransactionsExceptionReportHeader attribute. 1046 * @return Returns the processFeeTransactionsExceptionReportHeader. 1047 */ 1048 public EndowmentExceptionReportHeader getProcessFeeTransactionsExceptionReportHeader() { 1049 return processFeeTransactionsExceptionReportHeader; 1050 } 1051 1052 /** 1053 * Sets the processFeeTransactionsExceptionReportHeader attribute value. 1054 * @param processFeeTransactionsExceptionReportHeader The processFeeTransactionsExceptionReportHeader to set. 1055 */ 1056 public void setProcessFeeTransactionsExceptionReportHeader(EndowmentExceptionReportHeader processFeeTransactionsExceptionReportHeader) { 1057 this.processFeeTransactionsExceptionReportHeader = processFeeTransactionsExceptionReportHeader; 1058 } 1059 1060 /** 1061 * Gets the processFeeTransactionsTotalProcessedReportHeader attribute. 1062 * @return Returns the processFeeTransactionsTotalProcessedReportHeader. 1063 */ 1064 public FeeProcessingTotalsProcessedReportHeader getProcessFeeTransactionsTotalProcessedReportHeader() { 1065 return processFeeTransactionsTotalProcessedReportHeader; 1066 } 1067 1068 /** 1069 * Sets the processFeeTransactionsTotalProcessedReportHeader attribute value. 1070 * @param processFeeTransactionsTotalProcessedReportHeader The processFeeTransactionsTotalProcessedReportHeader to set. 1071 */ 1072 public void setProcessFeeTransactionsTotalProcessedReportHeader(FeeProcessingTotalsProcessedReportHeader processFeeTransactionsTotalProcessedReportHeader) { 1073 this.processFeeTransactionsTotalProcessedReportHeader = processFeeTransactionsTotalProcessedReportHeader; 1074 } 1075 1076 /** 1077 * Gets the processFeeTransactionsWaivedAndAccruedFeesReportHeader attribute. 1078 * @return Returns the processFeeTransactionsWaivedAndAccruedFeesReportHeader. 1079 */ 1080 public FeeProcessingWaivedAndAccruedReportHeader getProcessFeeTransactionsWaivedAndAccruedFeesReportHeader() { 1081 return processFeeTransactionsWaivedAndAccruedFeesReportHeader; 1082 } 1083 1084 /** 1085 * Sets the processFeeTransactionsWaivedAndAccruedFeesReportHeader attribute value. 1086 * @param processFeeTransactionsWaivedAndAccruedFeesReportHeader The processFeeTransactionsWaivedAndAccruedFeesReportHeader to set. 1087 */ 1088 public void setProcessFeeTransactionsWaivedAndAccruedFeesReportHeader(FeeProcessingWaivedAndAccruedReportHeader processFeeTransactionsWaivedAndAccruedFeesReportHeader) { 1089 this.processFeeTransactionsWaivedAndAccruedFeesReportHeader = processFeeTransactionsWaivedAndAccruedFeesReportHeader; 1090 } 1091 1092 /** 1093 * Gets the processFeeTransactionsRowValues attribute. 1094 * @return Returns the processFeeTransactionsRowValues. 1095 */ 1096 public EndowmentExceptionReportHeader getProcessFeeTransactionsRowValues() { 1097 return processFeeTransactionsRowValues; 1098 } 1099 1100 /** 1101 * Sets the processFeeTransactionsRowValues attribute value. 1102 * @param processFeeTransactionsRowValues The processFeeTransactionsRowValues to set. 1103 */ 1104 public void setProcessFeeTransactionsRowValues(EndowmentExceptionReportHeader processFeeTransactionsRowValues) { 1105 this.processFeeTransactionsRowValues = processFeeTransactionsRowValues; 1106 } 1107 1108 /** 1109 * Gets the processFeeTransactionsExceptionRowReason attribute. 1110 * @return Returns the processFeeTransactionsExceptionRowReason. 1111 */ 1112 public EndowmentExceptionReportHeader getProcessFeeTransactionsExceptionRowReason() { 1113 return processFeeTransactionsExceptionRowReason; 1114 } 1115 1116 /** 1117 * Sets the processFeeTransactionsExceptionRowReason attribute value. 1118 * @param processFeeTransactionsExceptionRowReason The processFeeTransactionsExceptionRowReason to set. 1119 */ 1120 public void setProcessFeeTransactionsExceptionRowReason(EndowmentExceptionReportHeader processFeeTransactionsExceptionRowReason) { 1121 this.processFeeTransactionsExceptionRowReason = processFeeTransactionsExceptionRowReason; 1122 } 1123 1124 /** 1125 * Gets the transactionArchiveDao attribute. 1126 * @return Returns the transactionArchiveDao. 1127 */ 1128 protected TransactionArchiveDao getTransactionArchiveDao() { 1129 return transactionArchiveDao; 1130 } 1131 1132 /** 1133 * Sets the transactionArchiveDao attribute value. 1134 * @param transactionArchiveDao The transactionArchiveDao to set. 1135 */ 1136 public void setTransactionArchiveDao(TransactionArchiveDao transactionArchiveDao) { 1137 this.transactionArchiveDao = transactionArchiveDao; 1138 } 1139 /** 1140 * Gets the holdingHistoryDao attribute. 1141 * @return Returns the holdingHistoryDao. 1142 */ 1143 protected HoldingHistoryDao getHoldingHistoryDao() { 1144 return holdingHistoryDao; 1145 } 1146 1147 /** 1148 * Sets the holdingHistoryDao attribute value. 1149 * @param holdingHistoryDao The holdingHistoryDao to set. 1150 */ 1151 public void setHoldingHistoryDao(HoldingHistoryDao holdingHistoryDao) { 1152 this.holdingHistoryDao = holdingHistoryDao; 1153 } 1154 1155 /** 1156 * Gets the currentTaxLotBalanceDao attribute. 1157 * @return Returns the currentTaxLotBalanceDao. 1158 */ 1159 protected CurrentTaxLotBalanceDao getCurrentTaxLotBalanceDao() { 1160 return currentTaxLotBalanceDao; 1161 } 1162 1163 /** 1164 * Sets the currentTaxLotBalanceDao attribute value. 1165 * @param currentTaxLotBalanceDao The currentTaxLotBalanceDao to set. 1166 */ 1167 public void setCurrentTaxLotBalanceDao(CurrentTaxLotBalanceDao currentTaxLotBalanceDao) { 1168 this.currentTaxLotBalanceDao = currentTaxLotBalanceDao; 1169 } 1170 1171 /** 1172 * Gets the kemidFeeDao attribute. 1173 * @return Returns the kemidFeeDao. 1174 */ 1175 protected KemidFeeDao getKemidFeeDao() { 1176 return kemidFeeDao; 1177 } 1178 1179 /** 1180 * Sets the kemidFeeDao attribute value. 1181 * @param kemidFeeDao The kemidFeeDao to set. 1182 */ 1183 public void setKemidFeeDao(KemidFeeDao kemidFeeDao) { 1184 this.kemidFeeDao = kemidFeeDao; 1185 } 1186 /** 1187 * Sets the documentService attribute value. 1188 * @param documentService The documentService to set. 1189 */ 1190 public void setDocumentService(DocumentService documentService) { 1191 this.documentService = documentService; 1192 } 1193 /** 1194 * Gets the documentService attribute value. 1195 */ 1196 protected DocumentService getDocumentService() { 1197 return documentService; 1198 } 1199 1200 /** 1201 * Gets the kualiRuleService attribute. 1202 * @return Returns the kualiRuleService. 1203 */ 1204 protected KualiRuleService getKualiRuleService() { 1205 return kualiRuleService; 1206 } 1207 1208 /** 1209 * Sets the kualiRuleService attribute value. 1210 * @param kualiRuleService The kualiRuleService to set. 1211 */ 1212 public void setKualiRuleService(KualiRuleService kualiRuleService) { 1213 this.kualiRuleService = kualiRuleService; 1214 } 1215 1216 /** 1217 * Gets the NoteService, lazily initializing if necessary 1218 * @return the NoteService 1219 */ 1220 protected synchronized NoteService getNoteService() { 1221 if (this.noteService == null) { 1222 this.noteService = KNSServiceLocator.getNoteService(); 1223 } 1224 return this.noteService; 1225 } 1226 1227 /** 1228 * Sets the noteService attribute value. 1229 * 1230 * @param noteService The noteService to set. 1231 */ 1232 public void setNoteService(NoteService noteService) { 1233 this.noteService = noteService; 1234 } 1235 1236 /** 1237 * @return Returns the personService. 1238 */ 1239 protected PersonService<Person> getPersonService() { 1240 if(personService==null) 1241 personService = SpringContext.getBean(PersonService.class); 1242 return personService; 1243 } 1244 1245 /** 1246 * Gets the feeProcessingWaivedAndAccruedDetailTotalLine attribute. 1247 * @return Returns the feeProcessingWaivedAndAccruedDetailTotalLine. 1248 */ 1249 protected FeeProcessingWaivedAndAccruedDetailTotalLine getFeeProcessingWaivedAndAccruedDetailTotalLine() { 1250 return feeProcessingWaivedAndAccruedDetailTotalLine; 1251 } 1252 1253 /** 1254 * Sets the feeProcessingWaivedAndAccruedDetailTotalLine attribute value. 1255 * @param feeProcessingWaivedAndAccruedDetailTotalLine The feeProcessingWaivedAndAccruedDetailTotalLine to set. 1256 */ 1257 public void setFeeProcessingWaivedAndAccruedDetailTotalLine(FeeProcessingWaivedAndAccruedDetailTotalLine feeProcessingWaivedAndAccruedDetailTotalLine) { 1258 this.feeProcessingWaivedAndAccruedDetailTotalLine = feeProcessingWaivedAndAccruedDetailTotalLine; 1259 } 1260 1261 /** 1262 * Gets the feeProcessingWaivedAndAccruedSubTotalLine attribute. 1263 * @return Returns the feeProcessingWaivedAndAccruedSubTotalLine. 1264 */ 1265 protected FeeProcessingWaivedAndAccruedSubTotalLine getFeeProcessingWaivedAndAccruedSubTotalLine() { 1266 return feeProcessingWaivedAndAccruedSubTotalLine; 1267 } 1268 1269 /** 1270 * Sets the feeProcessingWaivedAndAccruedSubTotalLine attribute value. 1271 * @param feeProcessingWaivedAndAccruedSubTotalLine The feeProcessingWaivedAndAccruedSubTotalLine to set. 1272 */ 1273 public void setFeeProcessingWaivedAndAccruedSubTotalLine(FeeProcessingWaivedAndAccruedSubTotalLine feeProcessingWaivedAndAccruedSubTotalLine) { 1274 this.feeProcessingWaivedAndAccruedSubTotalLine = feeProcessingWaivedAndAccruedSubTotalLine; 1275 } 1276 1277 /** 1278 * Gets the feeProcessingWaivedAndAccruedGrandTotalLine attribute. 1279 * @return Returns the feeProcessingWaivedAndAccruedGrandTotalLine. 1280 */ 1281 protected FeeProcessingWaivedAndAccruedGrandTotalLine getFeeProcessingWaivedAndAccruedGrandTotalLine() { 1282 return feeProcessingWaivedAndAccruedGrandTotalLine; 1283 } 1284 1285 /** 1286 * Sets the feeProcessingWaivedAndAccruedGrandTotalLine attribute value. 1287 * @param feeProcessingWaivedAndAccruedGrandTotalLine The feeProcessingWaivedAndAccruedGrandTotalLine to set. 1288 */ 1289 public void setFeeProcessingWaivedAndAccruedGrandTotalLine(FeeProcessingWaivedAndAccruedGrandTotalLine feeProcessingWaivedAndAccruedGrandTotalLine) { 1290 this.feeProcessingWaivedAndAccruedGrandTotalLine = feeProcessingWaivedAndAccruedGrandTotalLine; 1291 } 1292 1293 /** 1294 * Gets the feeProcessingTotalsProcessedDetailTotalLine attribute. 1295 * @return Returns the feeProcessingTotalsProcessedDetailTotalLine. 1296 */ 1297 protected FeeProcessingTotalsProcessedDetailTotalLine getFeeProcessingTotalsProcessedDetailTotalLine() { 1298 return feeProcessingTotalsProcessedDetailTotalLine; 1299 } 1300 1301 /** 1302 * Sets the feeProcessingTotalsProcessedDetailTotalLine attribute value. 1303 * @param feeProcessingTotalsProcessedDetailTotalLine The feeProcessingTotalsProcessedDetailTotalLine to set. 1304 */ 1305 public void setFeeProcessingTotalsProcessedDetailTotalLine(FeeProcessingTotalsProcessedDetailTotalLine feeProcessingTotalsProcessedDetailTotalLine) { 1306 this.feeProcessingTotalsProcessedDetailTotalLine = feeProcessingTotalsProcessedDetailTotalLine; 1307 } 1308 1309 /** 1310 * Gets the feeProcessingTotalsProcessedSubTotalLine attribute. 1311 * @return Returns the feeProcessingTotalsProcessedSubTotalLine. 1312 */ 1313 protected FeeProcessingTotalsProcessedSubTotalLine getFeeProcessingTotalsProcessedSubTotalLine() { 1314 return feeProcessingTotalsProcessedSubTotalLine; 1315 } 1316 1317 /** 1318 * Sets the feeProcessingTotalsProcessedSubTotalLine attribute value. 1319 * @param feeProcessingTotalsProcessedSubTotalLine The feeProcessingTotalsProcessedSubTotalLine to set. 1320 */ 1321 public void setFeeProcessingTotalsProcessedSubTotalLine(FeeProcessingTotalsProcessedSubTotalLine feeProcessingTotalsProcessedSubTotalLine) { 1322 this.feeProcessingTotalsProcessedSubTotalLine = feeProcessingTotalsProcessedSubTotalLine; 1323 } 1324 1325 /** 1326 * Gets the feeProcessingTotalsProcessedGrandTotalLine attribute. 1327 * @return Returns the feeProcessingTotalsProcessedGrandTotalLine. 1328 */ 1329 protected FeeProcessingTotalsProcessedGrandTotalLine getFeeProcessingTotalsProcessedGrandTotalLine() { 1330 return feeProcessingTotalsProcessedGrandTotalLine; 1331 } 1332 1333 /** 1334 * Sets the feeProcessingTotalsProcessedGrandTotalLine attribute value. 1335 * @param feeProcessingTotalsProcessedGrandTotalLine The feeProcessingTotalsProcessedGrandTotalLine to set. 1336 */ 1337 public void setFeeProcessingTotalsProcessedGrandTotalLine(FeeProcessingTotalsProcessedGrandTotalLine feeProcessingTotalsProcessedGrandTotalLine) { 1338 this.feeProcessingTotalsProcessedGrandTotalLine = feeProcessingTotalsProcessedGrandTotalLine; 1339 } 1340 1341 /** 1342 * Gets the configService attribute. 1343 * @return Returns the configService. 1344 */ 1345 protected KualiConfigurationService getConfigService() { 1346 return configService; 1347 } 1348 1349 /** 1350 * Sets the configService. 1351 * @param configService 1352 */ 1353 public void setConfigService(KualiConfigurationService configService) { 1354 this.configService = configService; 1355 } 1356 1357 } 1358