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.gl.batch.service.impl; 017 018 import java.sql.Date; 019 import java.util.ArrayList; 020 import java.util.Collection; 021 import java.util.HashMap; 022 import java.util.Iterator; 023 import java.util.List; 024 import java.util.Map; 025 026 import org.kuali.kfs.coa.businessobject.Account; 027 import org.kuali.kfs.coa.service.AccountService; 028 import org.kuali.kfs.gl.GeneralLedgerConstants; 029 import org.kuali.kfs.gl.batch.SufficientFundsAccountUpdateStep; 030 import org.kuali.kfs.gl.batch.service.SufficientFundsAccountUpdateService; 031 import org.kuali.kfs.gl.businessobject.Balance; 032 import org.kuali.kfs.gl.businessobject.SufficientFundBalances; 033 import org.kuali.kfs.gl.businessobject.SufficientFundRebuild; 034 import org.kuali.kfs.gl.dataaccess.BalanceDao; 035 import org.kuali.kfs.gl.dataaccess.SufficientFundBalancesDao; 036 import org.kuali.kfs.gl.dataaccess.SufficientFundRebuildDao; 037 import org.kuali.kfs.gl.service.SufficientFundsService; 038 import org.kuali.kfs.sys.KFSConstants; 039 import org.kuali.kfs.sys.KFSKeyConstants; 040 import org.kuali.kfs.sys.KFSPropertyConstants; 041 import org.kuali.kfs.sys.Message; 042 import org.kuali.kfs.sys.businessobject.SystemOptions; 043 import org.kuali.kfs.sys.context.SpringContext; 044 import org.kuali.kfs.sys.dataaccess.OptionsDao; 045 import org.kuali.kfs.sys.service.ReportWriterService; 046 import org.kuali.rice.kns.service.BusinessObjectService; 047 import org.kuali.rice.kns.service.DateTimeService; 048 import org.kuali.rice.kns.service.KualiConfigurationService; 049 import org.kuali.rice.kns.service.ParameterService; 050 import org.kuali.rice.kns.util.KualiDecimal; 051 import org.springframework.transaction.annotation.Transactional; 052 053 /** 054 * The default implementation of SufficientFundsAccountUpdateService 055 */ 056 @Transactional 057 public class SufficientFundsAccountUpdateServiceImpl implements SufficientFundsAccountUpdateService { 058 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SufficientFundsAccountUpdateServiceImpl.class); 059 060 private DateTimeService dateTimeService; 061 private KualiConfigurationService kualiConfigurationService; 062 private BalanceDao balanceDao; 063 private SufficientFundBalancesDao sufficientFundBalancesDao; 064 private SufficientFundRebuildDao sufficientFundRebuildDao; 065 private SufficientFundsService sufficientFundsService; 066 private OptionsDao optionsDao; 067 private AccountService accountService; 068 private ReportWriterService reportWriterService; 069 private BusinessObjectService boService; 070 071 private Date runDate; 072 private SystemOptions options; 073 074 Map batchError; 075 List reportSummary; 076 List<Message> transactionErrors; 077 078 private Integer universityFiscalYear; 079 private int sfrbRecordsConvertedCount = 0; 080 private int sfrbRecordsReadCount = 0; 081 private int sfrbRecordsDeletedCount = 0; 082 private int sfrbNotDeletedCount = 0; 083 private int sfblDeletedCount = 0; 084 private int sfblInsertedCount = 0; 085 private int sfblUpdatedCount = 0; 086 private int warningCount = 0; 087 088 089 private SufficientFundBalances currentSfbl = null; 090 091 /** 092 * Constructs a SufficientFundsAccountUpdateServiceImpl instance 093 */ 094 public SufficientFundsAccountUpdateServiceImpl() { 095 super(); 096 } 097 098 /** 099 * Returns the fiscal year, set in a parameter, of sufficient funds to rebuild 100 * 101 * @return the fiscal year 102 */ 103 protected Integer getFiscalYear() { 104 String val = SpringContext.getBean(ParameterService.class).getParameterValue(SufficientFundsAccountUpdateStep.class, GeneralLedgerConstants.FISCAL_YEAR_PARM); 105 return Integer.parseInt(val); 106 } 107 108 /** 109 * Rebuilds all necessary sufficient funds balances. 110 * @see org.kuali.kfs.gl.batch.service.SufficientFundsAccountUpdateService#rebuildSufficientFunds() 111 */ 112 public void rebuildSufficientFunds() { // driver 113 List <SufficientFundRebuild> rebuildSfrbList = new ArrayList<SufficientFundRebuild>(); 114 115 LOG.debug("rebuildSufficientFunds() started"); 116 117 universityFiscalYear = getFiscalYear(); 118 initService(); 119 120 //need to add time info - batch util? 121 runDate = dateTimeService.getCurrentSqlDate(); 122 123 // Get all the O types and convert them to A types 124 if (LOG.isDebugEnabled()) { 125 LOG.debug("rebuildSufficientFunds() Converting O types to A types"); 126 } 127 Map criteria = new HashMap(); 128 criteria.put(KFSPropertyConstants.ACCOUNT_FINANCIAL_OBJECT_TYPE_CODE, KFSConstants.SF_TYPE_OBJECT); 129 130 for (Iterator iter = boService.findMatching(SufficientFundRebuild.class, criteria).iterator(); iter.hasNext();) { 131 SufficientFundRebuild sfrb = (SufficientFundRebuild) iter.next(); 132 ++sfrbRecordsReadCount; 133 134 transactionErrors = new ArrayList<Message>(); 135 136 convertOtypeToAtypes(sfrb); 137 138 if (transactionErrors.size() > 0) { 139 reportWriterService.writeError(sfrb, transactionErrors); 140 rebuildSfrbList.add(sfrb); 141 } 142 } 143 criteria.clear(); 144 145 // Get all the A types and process them 146 LOG.debug("rebuildSufficientFunds() Calculating SF balances for all A types"); 147 148 criteria.put(KFSPropertyConstants.ACCOUNT_FINANCIAL_OBJECT_TYPE_CODE, KFSConstants.SF_TYPE_ACCOUNT); 149 150 for (Iterator iter = boService.findMatching(SufficientFundRebuild.class, criteria).iterator(); iter.hasNext();) { 151 SufficientFundRebuild sfrb = (SufficientFundRebuild) iter.next(); 152 ++sfrbRecordsReadCount; 153 154 transactionErrors = new ArrayList<Message>(); 155 156 calculateSufficientFundsByAccount(sfrb); 157 158 if (transactionErrors.size() > 0) { 159 reportWriterService.writeError(sfrb, transactionErrors); 160 rebuildSfrbList.add(sfrb); 161 } 162 163 } 164 sufficientFundRebuildDao.purgeSufficientFundRebuild(); 165 boService.save( rebuildSfrbList); 166 167 // Look at all the left over rows. There shouldn't be any left if all are O's and A's without error. 168 // Write out error messages for any that aren't A or O 169 LOG.debug("rebuildSufficientFunds() Handle any non-A and non-O types"); 170 for (Iterator iter = boService.findAll(SufficientFundRebuild.class).iterator(); iter.hasNext();) { 171 SufficientFundRebuild sfrb = (SufficientFundRebuild) iter.next(); 172 173 if ((!KFSConstants.SF_TYPE_ACCOUNT.equals(sfrb.getAccountFinancialObjectTypeCode())) && (!KFSConstants.SF_TYPE_OBJECT.equals(sfrb.getAccountFinancialObjectTypeCode()))) { 174 ++sfrbRecordsReadCount; 175 transactionErrors = new ArrayList<Message>(); 176 addTransactionError(kualiConfigurationService.getPropertyString(KFSKeyConstants.ERROR_INVALID_SF_OBJECT_TYPE_CODE)); 177 ++warningCount; 178 ++sfrbNotDeletedCount; 179 reportWriterService.writeError(sfrb, transactionErrors); 180 } 181 } 182 183 // write out report and errors 184 if (LOG.isDebugEnabled()) { 185 LOG.debug("rebuildSufficientFunds() Create report"); 186 } 187 188 // write out statistics 189 reportWriterService.writeStatisticLine(" SFRB RECORDS CONVERTED FROM OBJECT TO ACCOUNT %,9d\n", sfrbRecordsConvertedCount); 190 reportWriterService.writeStatisticLine(" POST CONVERSION SFRB RECORDS READ %,9d\n", sfrbRecordsReadCount); 191 reportWriterService.writeStatisticLine(" SFRB RECORDS DELETED %,9d\n", sfrbRecordsDeletedCount); 192 reportWriterService.writeStatisticLine(" SFRB RECORDS KEPT DUE TO ERRORS %,9d\n", sfrbNotDeletedCount); 193 reportWriterService.writeStatisticLine(" SFBL RECORDS DELETED %,9d\n", sfblDeletedCount); 194 reportWriterService.writeStatisticLine(" SFBL RECORDS ADDED %,9d\n", sfblInsertedCount); 195 reportWriterService.writeStatisticLine(" SFBL RECORDS UDPATED %,9d\n", sfblUpdatedCount); 196 } 197 198 /** 199 * Initializes the process at the beginning of a run. 200 */ 201 protected void initService() { 202 batchError = new HashMap(); 203 reportSummary = new ArrayList(); 204 205 runDate = new Date(dateTimeService.getCurrentDate().getTime()); 206 207 options = optionsDao.getByPrimaryId(universityFiscalYear); 208 209 if (options == null) { 210 throw new IllegalStateException(kualiConfigurationService.getPropertyString(KFSKeyConstants.ERROR_UNIV_DATE_NOT_FOUND)); 211 } 212 } 213 214 /** 215 * Given an O SF rebuild type, it will look up all of the matching balances in the table and add each account it finds as an A 216 * SF rebuild type. 217 * 218 * @param sfrb the sufficient fund rebuild record to convert 219 */ 220 public void convertOtypeToAtypes(SufficientFundRebuild sfrb) { 221 ++sfrbRecordsConvertedCount; 222 Collection fundBalances = sufficientFundBalancesDao.getByObjectCode(universityFiscalYear, sfrb.getChartOfAccountsCode(), sfrb.getAccountNumberFinancialObjectCode()); 223 Map criteria = new HashMap(); 224 225 for (Iterator fundBalancesIter = fundBalances.iterator(); fundBalancesIter.hasNext();) { 226 SufficientFundBalances sfbl = (SufficientFundBalances) fundBalancesIter.next(); 227 criteria.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, sfbl.getChartOfAccountsCode()); 228 criteria.put(KFSPropertyConstants.ACCOUNT_FINANCIAL_OBJECT_TYPE_CODE, KFSConstants.SF_TYPE_ACCOUNT); 229 criteria.put(KFSPropertyConstants.ACCOUNT_NUMBER_FINANCIAL_OBJECT_CODE, sfbl.getAccountNumber()); 230 231 SufficientFundRebuild altSfrb = (SufficientFundRebuild)boService.findByPrimaryKey(SufficientFundRebuild.class, criteria); 232 if (altSfrb == null) { 233 altSfrb = new SufficientFundRebuild(); 234 altSfrb.setAccountFinancialObjectTypeCode(KFSConstants.SF_TYPE_ACCOUNT); 235 altSfrb.setAccountNumberFinancialObjectCode(sfbl.getAccountNumber()); 236 altSfrb.setChartOfAccountsCode(sfbl.getChartOfAccountsCode()); 237 boService.save(altSfrb); 238 } 239 criteria.clear(); 240 } 241 } 242 243 /** 244 * Updates sufficient funds balances for the given account 245 * 246 * @param sfrb the sufficient fund rebuild record, with a chart and account number 247 */ 248 public void calculateSufficientFundsByAccount(SufficientFundRebuild sfrb) { 249 Account sfrbAccount = accountService.getByPrimaryId(sfrb.getChartOfAccountsCode(), sfrb.getAccountNumberFinancialObjectCode()); 250 if (sfrbAccount == null) { 251 String msg = "Account found in SufficientFundsRebuild table that is not in Accounts table [" + sfrb.getChartOfAccountsCode() + "-" + sfrb.getAccountNumberFinancialObjectCode() + "]."; 252 LOG.error(msg); 253 throw new RuntimeException(msg); 254 } 255 if ((sfrbAccount.getAccountSufficientFundsCode() != null) 256 && (KFSConstants.SF_TYPE_ACCOUNT.equals(sfrbAccount.getAccountSufficientFundsCode()) 257 || KFSConstants.SF_TYPE_CASH_AT_ACCOUNT.equals(sfrbAccount.getAccountSufficientFundsCode()) 258 || KFSConstants.SF_TYPE_CONSOLIDATION.equals(sfrbAccount.getAccountSufficientFundsCode()) 259 || KFSConstants.SF_TYPE_LEVEL.equals(sfrbAccount.getAccountSufficientFundsCode()) 260 || KFSConstants.SF_TYPE_OBJECT.equals(sfrbAccount.getAccountSufficientFundsCode()) 261 || KFSConstants.SF_TYPE_NO_CHECKING.equals(sfrbAccount.getAccountSufficientFundsCode()))) { 262 ++sfrbRecordsDeletedCount; 263 sfblDeletedCount += sufficientFundBalancesDao.deleteByAccountNumber(universityFiscalYear, sfrb.getChartOfAccountsCode(), sfrbAccount.getAccountNumber()); 264 265 if (KFSConstants.SF_TYPE_NO_CHECKING.equalsIgnoreCase(sfrbAccount.getAccountSufficientFundsCode())) { 266 // nothing to do here, no errors either, just return 267 return; 268 } 269 270 Iterator balancesIterator = balanceDao.findAccountBalances(universityFiscalYear, sfrb.getChartOfAccountsCode(), sfrb.getAccountNumberFinancialObjectCode(), sfrbAccount.getAccountSufficientFundsCode()); 271 272 if (balancesIterator == null) { 273 addTransactionError(kualiConfigurationService.getPropertyString(KFSKeyConstants.ERROR_BALANCE_NOT_FOUND_FOR) + universityFiscalYear + ")"); 274 ++warningCount; 275 ++sfrbNotDeletedCount; 276 return; 277 } 278 279 String currentFinObjectCd = ""; 280 while (balancesIterator.hasNext()) { 281 Balance balance = (Balance) balancesIterator.next(); 282 String tempFinObjectCd = sufficientFundsService.getSufficientFundsObjectCode(balance.getFinancialObject(), sfrbAccount.getAccountSufficientFundsCode()); 283 284 if (!tempFinObjectCd.equals(currentFinObjectCd)) { 285 // we have a change or are on the last record, write out the data if there is any 286 currentFinObjectCd = tempFinObjectCd; 287 288 if (currentSfbl != null && amountsAreNonZero(currentSfbl)) { 289 sufficientFundBalancesDao.save(currentSfbl); 290 ++sfblInsertedCount; 291 } 292 293 currentSfbl = new SufficientFundBalances(); 294 currentSfbl.setUniversityFiscalYear(universityFiscalYear); 295 currentSfbl.setChartOfAccountsCode(sfrb.getChartOfAccountsCode()); 296 currentSfbl.setAccountNumber(sfrbAccount.getAccountNumber()); 297 currentSfbl.setFinancialObjectCode(currentFinObjectCd); 298 currentSfbl.setAccountSufficientFundsCode(sfrbAccount.getAccountSufficientFundsCode()); 299 currentSfbl.setAccountActualExpenditureAmt(KualiDecimal.ZERO); 300 currentSfbl.setAccountEncumbranceAmount(KualiDecimal.ZERO); 301 currentSfbl.setCurrentBudgetBalanceAmount(KualiDecimal.ZERO); 302 } 303 304 if (sfrbAccount.isForContractsAndGrants()) { 305 balance.setAccountLineAnnualBalanceAmount(balance.getAccountLineAnnualBalanceAmount().add(balance.getContractsGrantsBeginningBalanceAmount())); 306 } 307 308 if (KFSConstants.SF_TYPE_CASH_AT_ACCOUNT.equals(sfrbAccount.getAccountSufficientFundsCode())) { 309 processCash(sfrbAccount, balance); 310 } 311 else { 312 processObjectOrAccount(sfrbAccount, balance); 313 } 314 } 315 316 // save the last one 317 if (currentSfbl != null && amountsAreNonZero(currentSfbl)) { 318 sufficientFundBalancesDao.save(currentSfbl); 319 ++sfblInsertedCount; 320 } 321 } 322 else { 323 addTransactionError(kualiConfigurationService.getPropertyString(KFSKeyConstants.ERROR_INVALID_ACCOUNT_SF_CODE_FOR)); 324 ++warningCount; 325 ++sfrbNotDeletedCount; 326 return; 327 } 328 } 329 330 /** 331 * Determines if all sums associated with a sufficient funds balance are zero 332 * 333 * @param sfbl the sufficient funds balance to check 334 * @return true if all sums in the balance are zero, false otherwise 335 */ 336 protected boolean amountsAreNonZero(SufficientFundBalances sfbl) { 337 boolean zero = true; 338 zero &= KualiDecimal.ZERO.equals(sfbl.getAccountActualExpenditureAmt()); 339 zero &= KualiDecimal.ZERO.equals(sfbl.getAccountEncumbranceAmount()); 340 zero &= KualiDecimal.ZERO.equals(sfbl.getCurrentBudgetBalanceAmount()); 341 return !zero; 342 } 343 344 /** 345 * Determines how best to process the given balance 346 * 347 * @param sfrbAccount the account of the current sufficient funds balance rebuild record 348 * @param balance the cash encumbrance balance to update the sufficient funds balance with 349 */ 350 protected void processObjectOrAccount(Account sfrbAccount, Balance balance) { 351 if (options.getFinObjTypeExpenditureexpCd().equals(balance.getObjectTypeCode()) || options.getFinObjTypeExpendNotExpCode().equals(balance.getObjectTypeCode()) || options.getFinObjTypeExpNotExpendCode().equals(balance.getObjectTypeCode()) || options.getFinancialObjectTypeTransferExpenseCd().equals(balance.getObjectTypeCode())) { 352 if (options.getActualFinancialBalanceTypeCd().equals(balance.getBalanceTypeCode())) { 353 processObjtAcctActual(balance); 354 } 355 else if (options.getExtrnlEncumFinBalanceTypCd().equals(balance.getBalanceTypeCode()) || options.getIntrnlEncumFinBalanceTypCd().equals(balance.getBalanceTypeCode()) || options.getPreencumbranceFinBalTypeCd().equals(balance.getBalanceTypeCode()) || options.getCostShareEncumbranceBalanceTypeCd().equals(balance.getBalanceTypeCode())) { 356 processObjtAcctEncmbrnc(balance); 357 } 358 else if (options.getBudgetCheckingBalanceTypeCd().equals(balance.getBalanceTypeCode())) { 359 processObjtAcctBudget(balance); 360 } 361 } 362 } 363 364 /** 365 * Updates the current sufficient fund balance record with a non-cash actual balance 366 * 367 * @param balance the cash encumbrance balance to update the sufficient funds balance with 368 */ 369 protected void processObjtAcctActual(Balance balance) { 370 currentSfbl.setAccountActualExpenditureAmt(currentSfbl.getAccountActualExpenditureAmt().add(balance.getAccountLineAnnualBalanceAmount())); 371 } 372 373 /** 374 * Updates the current sufficient fund balance record with a non-cash encumbrance balance 375 * 376 * @param balance the cash encumbrance balance to update the sufficient funds balance with 377 */ 378 protected void processObjtAcctEncmbrnc(Balance balance) { 379 currentSfbl.setAccountEncumbranceAmount(currentSfbl.getAccountEncumbranceAmount().add(balance.getAccountLineAnnualBalanceAmount())); 380 currentSfbl.setAccountEncumbranceAmount(currentSfbl.getAccountEncumbranceAmount().add(balance.getBeginningBalanceLineAmount())); 381 } 382 383 /** 384 * Updates the current sufficient fund balance record with a non-cash budget balance 385 * 386 * @param balance the cash encumbrance balance to update the sufficient funds balance with 387 */ 388 protected void processObjtAcctBudget(Balance balance) { 389 currentSfbl.setCurrentBudgetBalanceAmount(currentSfbl.getCurrentBudgetBalanceAmount().add(balance.getAccountLineAnnualBalanceAmount())); 390 currentSfbl.setCurrentBudgetBalanceAmount(currentSfbl.getCurrentBudgetBalanceAmount().add(balance.getBeginningBalanceLineAmount())); 391 } 392 393 /** 394 * Determines how best to process a cash balance 395 * 396 * @param sfrbAccount the account of the current sufficient funds balance record 397 * @param balance the cash encumbrance balance to update the sufficient funds balance with 398 */ 399 protected void processCash(Account sfrbAccount, Balance balance) { 400 if (balance.getBalanceTypeCode().equals(options.getActualFinancialBalanceTypeCd())) { 401 if (balance.getObjectCode().equals(sfrbAccount.getChartOfAccounts().getFinancialCashObjectCode()) || balance.getObjectCode().equals(sfrbAccount.getChartOfAccounts().getFinAccountsPayableObjectCode())) { 402 processCashActual(sfrbAccount, balance); 403 } 404 } 405 else if (balance.getBalanceTypeCode().equals(options.getExtrnlEncumFinBalanceTypCd()) || balance.getBalanceTypeCode().equals(options.getIntrnlEncumFinBalanceTypCd()) || balance.getBalanceTypeCode().equals(options.getPreencumbranceFinBalTypeCd()) || options.getCostShareEncumbranceBalanceTypeCd().equals(balance.getBalanceTypeCode())) { 406 if (balance.getObjectTypeCode().equals(options.getFinObjTypeExpenditureexpCd()) || balance.getObjectTypeCode().equals(options.getFinObjTypeExpendNotExpCode()) || options.getFinancialObjectTypeTransferExpenseCd().equals(balance.getObjectTypeCode()) || options.getFinObjTypeExpNotExpendCode().equals(balance.getObjectTypeCode())) { 407 processCashEncumbrance(balance); 408 } 409 } 410 } 411 412 /** 413 * Updates the current sufficient fund balance record with a cash actual balance 414 * 415 * @param sfrbAccount the account of the current sufficient funds balance record 416 * @param balance the cash encumbrance balance to update the sufficient funds balance with 417 */ 418 protected void processCashActual(Account sfrbAccount, Balance balance) { 419 if (balance.getObjectCode().equals(sfrbAccount.getChartOfAccounts().getFinancialCashObjectCode())) { 420 currentSfbl.setCurrentBudgetBalanceAmount(currentSfbl.getCurrentBudgetBalanceAmount().add(balance.getAccountLineAnnualBalanceAmount())); 421 currentSfbl.setCurrentBudgetBalanceAmount(currentSfbl.getCurrentBudgetBalanceAmount().add(balance.getBeginningBalanceLineAmount())); 422 } 423 if (balance.getObjectCode().equals(sfrbAccount.getChartOfAccounts().getFinAccountsPayableObjectCode())) { 424 currentSfbl.setCurrentBudgetBalanceAmount(currentSfbl.getCurrentBudgetBalanceAmount().subtract(balance.getAccountLineAnnualBalanceAmount())); 425 currentSfbl.setCurrentBudgetBalanceAmount(currentSfbl.getCurrentBudgetBalanceAmount().subtract(balance.getBeginningBalanceLineAmount())); 426 } 427 } 428 429 /** 430 * Updates the current sufficient funds balance with a cash encumbrance balance 431 * 432 * @param balance the cash encumbrance balance to update the sufficient funds balance with 433 */ 434 protected void processCashEncumbrance(Balance balance) { 435 currentSfbl.setAccountEncumbranceAmount(currentSfbl.getAccountEncumbranceAmount().add(balance.getAccountLineAnnualBalanceAmount())); 436 currentSfbl.setAccountEncumbranceAmount(currentSfbl.getAccountEncumbranceAmount().add(balance.getBeginningBalanceLineAmount())); 437 } 438 439 /** 440 * Adds an error message to this instance's List of error messages 441 * @param errorMessage the error message to keep 442 */ 443 protected void addTransactionError(String errorMessage) { 444 transactionErrors.add(new Message(errorMessage, Message.TYPE_WARNING)); 445 } 446 447 public void setDateTimeService(DateTimeService dateTimeService) { 448 this.dateTimeService = dateTimeService; 449 } 450 451 public void setKualiConfigurationService(KualiConfigurationService kualiConfigurationService) { 452 this.kualiConfigurationService = kualiConfigurationService; 453 } 454 455 public void setBalanceDao(BalanceDao balanceDao) { 456 this.balanceDao = balanceDao; 457 } 458 459 public void setSufficientFundBalancesDao(SufficientFundBalancesDao sufficientFundBalancesDao) { 460 this.sufficientFundBalancesDao = sufficientFundBalancesDao; 461 } 462 463 public void setOptionsDao(OptionsDao optionsDao) { 464 this.optionsDao = optionsDao; 465 } 466 467 public void setReportWriterService(ReportWriterService sfrs) { 468 reportWriterService = sfrs; 469 } 470 471 public void setAccountService(AccountService accountService) { 472 this.accountService = accountService; 473 } 474 475 public void setSufficientFundsService(SufficientFundsService sfs) { 476 sufficientFundsService = sfs; 477 } 478 479 public void setBusinessObjectService(BusinessObjectService bos) { 480 boService = bos; 481 } 482 483 public void setSufficientFundRebuildDao(SufficientFundRebuildDao sufficientFundRebuildDao) { 484 this.sufficientFundRebuildDao = sufficientFundRebuildDao; 485 } 486 }