001/* 002 * Copyright 2009 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 */ 016package org.kuali.ole.gl.batch.service.impl; 017 018import java.sql.Date; 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Map; 024 025import org.apache.commons.lang.ArrayUtils; 026import org.kuali.ole.coa.businessobject.A21SubAccount; 027import org.kuali.ole.coa.businessobject.BalanceType; 028import org.kuali.ole.coa.businessobject.ObjectCode; 029import org.kuali.ole.coa.businessobject.OffsetDefinition; 030import org.kuali.ole.coa.businessobject.PriorYearAccount; 031import org.kuali.ole.coa.businessobject.SubFundGroup; 032import org.kuali.ole.coa.businessobject.SubObjectCode; 033import org.kuali.ole.coa.service.A21SubAccountService; 034import org.kuali.ole.coa.service.ObjectCodeService; 035import org.kuali.ole.coa.service.ObjectTypeService; 036import org.kuali.ole.coa.service.OffsetDefinitionService; 037import org.kuali.ole.coa.service.SubFundGroupService; 038import org.kuali.ole.coa.service.SubObjectCodeService; 039import org.kuali.ole.gl.GeneralLedgerConstants; 040import org.kuali.ole.gl.batch.EncumbranceForwardStep; 041import org.kuali.ole.gl.batch.ScrubberStep; 042import org.kuali.ole.gl.batch.service.AccountingCycleCachingService; 043import org.kuali.ole.gl.batch.service.EncumbranceClosingOriginEntryGenerationService; 044import org.kuali.ole.gl.batch.service.impl.exception.FatalErrorException; 045import org.kuali.ole.gl.businessobject.Encumbrance; 046import org.kuali.ole.gl.businessobject.OriginEntryFull; 047import org.kuali.ole.sys.OLEConstants; 048import org.kuali.ole.sys.OLEPropertyConstants; 049import org.kuali.ole.sys.context.SpringContext; 050import org.kuali.ole.sys.service.FlexibleOffsetAccountService; 051import org.kuali.ole.sys.service.OptionsService; 052import org.kuali.ole.sys.service.impl.OleParameterConstants; 053import org.kuali.rice.core.api.parameter.ParameterEvaluator; 054import org.kuali.rice.core.api.parameter.ParameterEvaluatorService; 055import org.kuali.rice.core.api.util.type.KualiDecimal; 056import org.kuali.rice.coreservice.framework.parameter.ParameterService; 057import org.kuali.rice.kns.service.DataDictionaryService; 058import org.kuali.rice.krad.service.BusinessObjectService; 059 060/** 061 * The default implementation of the EncumbranceClosingOriginEntryGenerationService 062 */ 063public class EncumbranceClosingOriginEntryGenerationServiceImpl implements EncumbranceClosingOriginEntryGenerationService { 064 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(EncumbranceClosingOriginEntryGenerationServiceImpl.class); 065 protected ParameterService parameterService; 066 protected OffsetDefinitionService offsetDefinitionService; 067 protected ObjectCodeService objectCodeService; 068 protected DataDictionaryService dataDictionaryService; 069 protected FlexibleOffsetAccountService flexibleOffsetAccountService; 070 protected A21SubAccountService a21SubAccountService; 071 protected SubObjectCodeService subObjectCodeService; 072 protected OptionsService optionsService; 073 protected SubFundGroupService subFundGroupService; 074 protected BusinessObjectService businessObjectService; 075 protected AccountingCycleCachingService accountingCycleCachingService; 076 077 /** 078 * @see org.kuali.ole.gl.batch.service.EncumbranceClosingOriginEntryGenerationService#createBeginningBalanceEntryOffsetPair(org.kuali.ole.gl.businessobject.Encumbrance, java.lang.Integer, java.sql.Date) 079 */ 080 @Override 081 public OriginEntryOffsetPair createCostShareBeginningBalanceEntryOffsetPair(Encumbrance encumbrance, Date transactionDate) { 082 final String GL_ACLO = getParameterService().getParameterValueAsString(OleParameterConstants.GENERAL_LEDGER_BATCH.class, OLEConstants.SystemGroupParameterNames.GL_ANNUAL_CLOSING_DOC_TYPE); 083 final String GL_ORIGINATION_CODE = getParameterService().getParameterValueAsString(OleParameterConstants.GENERAL_LEDGER_BATCH.class, OLEConstants.SystemGroupParameterNames.GL_ORIGINATION_CODE); 084 085 OriginEntryOffsetPair pair = new OriginEntryOffsetPair(); 086 087 // Generate the entry ... 088 089 OriginEntryFull entry = new OriginEntryFull(encumbrance.getDocumentTypeCode(), encumbrance.getOriginCode()); 090 091 String description = encumbrance.getTransactionEncumbranceDescription(); 092 String fromDesc = "FR-" + encumbrance.getChartOfAccountsCode() + encumbrance.getAccountNumber(); 093 int descLength = getDataDictionaryService().getAttributeMaxLength(OriginEntryFull.class, OLEPropertyConstants.TRANSACTION_LEDGER_ENTRY_DESC); 094 if ((description.length() + fromDesc.length()) < descLength) { 095 int padLength = descLength - (description.length() + fromDesc.length()); 096 StringBuilder sb = new StringBuilder(); 097 for (int i = 0; i < padLength; i++) { 098 sb.append(' '); 099 } 100 sb.append(fromDesc); 101 fromDesc = sb.toString(); 102 description += fromDesc; 103 } 104 else if ((description.length() + fromDesc.length()) > descLength) { 105 description = description.substring(0, (descLength - fromDesc.length())) + fromDesc; 106 } 107 else { 108 description += fromDesc; 109 } 110 entry.setTransactionLedgerEntryDescription(description); 111 112 // SpringContext is used because this method is static. 113 A21SubAccount a21SubAccount = getA21SubAccountService().getByPrimaryKey(encumbrance.getChartOfAccountsCode(), encumbrance.getAccountNumber(), encumbrance.getSubAccountNumber()); 114 115 entry.setUniversityFiscalYear(new Integer(encumbrance.getUniversityFiscalYear().intValue() + 1)); 116 entry.setChartOfAccountsCode(a21SubAccount.getCostShareChartOfAccountCode()); 117 entry.setAccountNumber(a21SubAccount.getCostShareSourceAccountNumber()); 118 entry.setSubAccountNumber(a21SubAccount.getCostShareSourceSubAccountNumber()); 119 120 // The subAccountNumber is set to dashes in the OriginEntryFull constructor. 121 if (entry.getSubAccountNumber() == null || OLEConstants.EMPTY_STRING.equals(entry.getSubAccountNumber().trim())) { 122 entry.setSubAccountNumber(OLEConstants.getDashSubAccountNumber()); 123 } 124 125// ObjectCode finObjCode = accountingCycleCachingService.getObjectCode(encumbrance.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), entry.getFinancialObjectCode()); 126// if (finObjCode != null) 127// entry.setFinancialObjectTypeCode(finObjCode.getFinancialObjectTypeCode()); 128// 129 130 ObjectCode encumbranceObjectCode = accountingCycleCachingService.getObjectCode(entry.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), encumbrance.getObjectCode()); 131 132 if (null != encumbranceObjectCode) { 133 134 String financialObjectLevelCode = encumbranceObjectCode.getFinancialObjectLevelCode(); 135 String financialObjectCode = encumbrance.getObjectCode(); 136 137 String overriddenObjectCode = overrideCostShareObjectCode(financialObjectLevelCode, financialObjectCode); 138 final ObjectCode overriddenObject = this.getAccountingCycleCachingService().getObjectCode(entry.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), overriddenObjectCode); 139 140 String param = parameterService.getSubParameterValueAsString(ScrubberStep.class, GeneralLedgerConstants.GlScrubberGroupParameters.COST_SHARE_OBJECT_CODE_BY_LEVEL_PARM_NM, overriddenObject.getFinancialObjectLevelCode()); 141 if (param == null) { 142 param = parameterService.getSubParameterValueAsString(ScrubberStep.class, GeneralLedgerConstants.GlScrubberGroupParameters.COST_SHARE_OBJECT_CODE_BY_LEVEL_PARM_NM, "DEFAULT"); 143 if (param == null) { 144 throw new RuntimeException("Unable to determine cost sharing object code from object level (" + overriddenObject.getFinancialObjectLevelCode() + "). Default entry missing."); 145 } 146 } 147 financialObjectCode = param; 148 149 // Lookup the new object code 150 ObjectCode newObjectCode = accountingCycleCachingService.getObjectCode(entry.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), financialObjectCode); 151 if (newObjectCode != null) { 152 entry.setFinancialObjectTypeCode(newObjectCode.getFinancialObjectTypeCode()); 153 entry.setFinancialObjectCode(financialObjectCode); 154 } 155 else { 156 LOG.error("Error retrieving ObjectCode("+entry.getUniversityFiscalYear()+"/"+entry.getChartOfAccountsCode()+"/"+financialObjectCode+")"); 157 pair.setFatalErrorFlag(true); 158 return pair; 159 } 160 } else { 161 162 LOG.error("Error retrieving ObjectCode("+entry.getUniversityFiscalYear()+"/"+entry.getChartOfAccountsCode()+"/"+entry.getFinancialObjectCode()+")"); 163 pair.setFatalErrorFlag(true); 164 return pair; 165 166 } 167 168 169 entry.setFinancialSubObjectCode(OLEConstants.getDashFinancialSubObjectCode()); 170 entry.setFinancialBalanceTypeCode(OLEConstants.BALANCE_TYPE_COST_SHARE_ENCUMBRANCE); 171 172 entry.setUniversityFiscalPeriodCode(OLEConstants.PERIOD_CODE_BEGINNING_BALANCE); 173 entry.setTransactionLedgerEntrySequenceNumber(new Integer(0)); 174 entry.setDocumentNumber(encumbrance.getDocumentNumber()); 175 entry.setFinancialBalanceTypeCode(OLEConstants.BALANCE_TYPE_COST_SHARE_ENCUMBRANCE); 176 177 KualiDecimal delta = encumbrance.getAccountLineEncumbranceAmount().subtract(encumbrance.getAccountLineEncumbranceClosedAmount()); 178 if (delta.isPositive()) { 179 entry.setTransactionDebitCreditCode(OLEConstants.GL_DEBIT_CODE); 180 entry.setTransactionLedgerEntryAmount(delta); 181 } 182 else { 183 entry.setTransactionDebitCreditCode(OLEConstants.GL_CREDIT_CODE); 184 entry.setTransactionLedgerEntryAmount(delta.negated()); 185 } 186 entry.setTransactionEncumbranceUpdateCode(OLEConstants.ENCUMB_UPDT_DOCUMENT_CD); 187 entry.setProjectCode(OLEConstants.getDashProjectCode()); 188 entry.setTransactionDate(transactionDate); 189 190 pair.setEntry(entry); 191 192 // And now the offset ... 193 194 OriginEntryFull offset = new OriginEntryFull(encumbrance.getDocumentTypeCode(), encumbrance.getOriginCode()); 195 final String GENERATED_TRANSACTION_LEDGER_ENTRY_DESCRIPTION = getParameterService().getParameterValueAsString(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.GENERATED_TRANSACTION_LEDGER_ENTRY_DESCRIPTION); 196 offset.setTransactionLedgerEntryDescription(GENERATED_TRANSACTION_LEDGER_ENTRY_DESCRIPTION); 197 198 offset.setUniversityFiscalYear(new Integer(encumbrance.getUniversityFiscalYear().intValue() + 1)); 199 offset.setChartOfAccountsCode(a21SubAccount.getCostShareChartOfAccountCode()); 200 offset.setAccountNumber(a21SubAccount.getCostShareSourceAccountNumber()); 201 offset.setSubAccountNumber(a21SubAccount.getCostShareSourceSubAccountNumber()); 202 if (offset.getSubAccountNumber() == null || OLEConstants.EMPTY_STRING.equals(offset.getSubAccountNumber().trim())) { 203 offset.setSubAccountNumber(OLEConstants.getDashSubAccountNumber()); 204 } 205 // Lookup the offset definition for the explicit entry we just created. 206 OffsetDefinition offsetDefinition = getOffsetDefinitionService().getByPrimaryId(entry.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), entry.getFinancialDocumentTypeCode(), entry.getFinancialBalanceTypeCode()); 207 // Set values from the offset definition if it was found. 208 if (null != offsetDefinition) { 209 210 offset.setFinancialObjectCode(offsetDefinition.getFinancialObjectCode()); 211 offset.setFinancialSubObjectCode(OLEConstants.getDashFinancialSubObjectCode()); 212 } 213 else { // Log an exception if the offset definition was not found. 214 215 LOG.info("FATAL ERROR: One of the following errors occurred (no way to know exactly which):\n\t" + "- OFFSET DEFINITION NOT FOUND\n\t" + "- ERROR ACCESSING OFSD TABLE"); 216 pair.setFatalErrorFlag(true); 217 return pair; 218 219 } 220 offset.setFinancialBalanceTypeCode(OLEConstants.BALANCE_TYPE_COST_SHARE_ENCUMBRANCE); 221 // Validate the object code for the explicit entry. 222 ObjectCode objectCode = getObjectCodeService().getByPrimaryId(offset.getUniversityFiscalYear(), offset.getChartOfAccountsCode(), offset.getFinancialObjectCode()); 223 if (null != objectCode) { 224 offset.setFinancialObjectTypeCode(objectCode.getFinancialObjectTypeCode()); 225 } 226 else { 227 LOG.info("FATAL ERROR: One of the following errors occurred (no way to know exactly which):\n\t" + "- NO OBJECT FOR OBJECT ON OFSD\n\t" + "- ERROR ACCESSING OBJECT TABLE"); 228 pair.setFatalErrorFlag(true); 229 return pair; 230 } 231 offset.setUniversityFiscalPeriodCode(OLEConstants.PERIOD_CODE_BEGINNING_BALANCE); 232 offset.setDocumentNumber(encumbrance.getDocumentNumber()); 233 offset.setTransactionLedgerEntrySequenceNumber(new Integer(0)); 234 if (delta.isPositive()) { 235 offset.setTransactionDebitCreditCode(OLEConstants.GL_CREDIT_CODE); 236 offset.setTransactionLedgerEntryAmount(delta); 237 } 238 else { 239 offset.setTransactionDebitCreditCode(OLEConstants.GL_DEBIT_CODE); 240 offset.setTransactionLedgerEntryAmount(delta.negated()); 241 } 242 243 offset.setTransactionEncumbranceUpdateCode(null); 244 offset.setOrganizationDocumentNumber(null); 245 offset.setProjectCode(OLEConstants.getDashProjectCode()); 246 offset.setTransactionDate(transactionDate); 247 offset.setOrganizationReferenceId(null); 248 offset.setReferenceFinancialDocumentTypeCode(null); 249 offset.setReferenceFinancialSystemOriginationCode(null); 250 offset.setReferenceFinancialDocumentNumber(null); 251 offset.setReversalDate(null); 252 253 getFlexibleOffsetAccountService().updateOffset(offset); 254 255 pair.setOffset(offset); 256 257 return pair; 258 } 259 260 /** 261 * @see org.kuali.ole.gl.batch.service.EncumbranceClosingOriginEntryGenerationService#createCostShareBeginningBalanceEntryOffsetPair(org.kuali.ole.gl.businessobject.Encumbrance, java.sql.Date) 262 */ 263 @Override 264 public OriginEntryOffsetPair createBeginningBalanceEntryOffsetPair(Encumbrance encumbrance, Integer closingFiscalYear, Date transactionDate) { 265 OriginEntryOffsetPair pair = new OriginEntryOffsetPair(); 266 267 // Build the entry ... 268 OriginEntryFull entry = new OriginEntryFull(encumbrance.getDocumentTypeCode(), encumbrance.getOriginCode()); 269 270 Integer thisFiscalYear = new Integer(closingFiscalYear.intValue() + 1); 271 entry.setUniversityFiscalYear(thisFiscalYear); 272 entry.setChartOfAccountsCode(encumbrance.getChartOfAccountsCode()); 273 entry.setAccountNumber(encumbrance.getAccountNumber()); 274 entry.setSubAccountNumber(encumbrance.getSubAccountNumber()); 275 276 ObjectCode objectCode = accountingCycleCachingService.getObjectCode(entry.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), encumbrance.getObjectCode()); 277 278 if (null != objectCode) { 279 280 entry.setFinancialObjectTypeCode(objectCode.getFinancialObjectTypeCode()); 281 282 if (null != objectCode.getNextYearFinancialObjectCode() && !OLEConstants.EMPTY_STRING.equals(objectCode.getNextYearFinancialObjectCode().trim())) { 283 284 entry.setFinancialObjectCode(objectCode.getNextYearFinancialObjectCode()); 285 286 } 287 else { 288 289 entry.setFinancialObjectCode(encumbrance.getObjectCode()); 290 291 } 292 293 } 294 295 296 else { 297 298 LOG.error("Error retrieving ObjectCode("+entry.getUniversityFiscalYear()+"/"+entry.getChartOfAccountsCode()+"/"+entry.getFinancialObjectCode()+")"); 299 pair.setFatalErrorFlag(true); 300 return pair; 301 302 } 303 304 SubObjectCode subObjectCode = getSubObjectCodeService().getByPrimaryId(encumbrance.getUniversityFiscalYear(), encumbrance.getChartOfAccountsCode(), encumbrance.getAccountNumber(), encumbrance.getObjectCode(), encumbrance.getSubObjectCode()); 305 306 if (null != subObjectCode) { 307 308 entry.setFinancialSubObjectCode(subObjectCode.getFinancialSubObjectCode()); 309 310 } 311 else { 312 313 entry.setFinancialSubObjectCode(OLEConstants.getDashFinancialSubObjectCode()); 314 315 } 316 317 entry.setFinancialBalanceTypeCode(encumbrance.getBalanceTypeCode()); 318 entry.setUniversityFiscalPeriodCode(OLEConstants.PERIOD_CODE_BEGINNING_BALANCE); 319 entry.setDocumentNumber(encumbrance.getDocumentNumber()); 320 entry.setTransactionLedgerEntrySequenceNumber(new Integer(1)); 321 entry.setTransactionLedgerEntryDescription(encumbrance.getTransactionEncumbranceDescription()); 322 entry.setTransactionLedgerEntryAmount(encumbrance.getAccountLineEncumbranceAmount().subtract(encumbrance.getAccountLineEncumbranceClosedAmount())); 323 324 if (entry.getTransactionLedgerEntryAmount().isNegative()) { 325 326 entry.setTransactionLedgerEntryAmount(entry.getTransactionLedgerEntryAmount().negated()); 327 entry.setTransactionDebitCreditCode(OLEConstants.GL_CREDIT_CODE); 328 329 } 330 else { 331 332 entry.setTransactionDebitCreditCode(OLEConstants.GL_DEBIT_CODE); 333 334 } 335 336 entry.setTransactionDate(transactionDate); 337 entry.setOrganizationDocumentNumber(null); 338 entry.setProjectCode(OLEConstants.getDashProjectCode()); 339 entry.setOrganizationReferenceId(null); 340 entry.setReferenceFinancialDocumentTypeCode(null); 341 entry.setReferenceFinancialSystemOriginationCode(null); 342 entry.setReferenceFinancialDocumentNumber(null); 343 entry.setReversalDate(null); 344 entry.setTransactionEncumbranceUpdateCode(OLEConstants.ENCUMB_UPDT_DOCUMENT_CD); 345 346 pair.setEntry(entry); 347 348 final String OBJECT_CODE_FOR_BALANCE_TYPE_INTERNAL_ENCUMBRANCE = getParameterService().getParameterValueAsString(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.OFFSET_OBJECT_CODE_FOR_INTERNAL_ENCUMBRANCE); 349 final String OBJECT_CODE_FOR_BALANCE_TYPE_PRE_ENCUMBRANCE = getParameterService().getParameterValueAsString(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.OFFSET_OBJECT_CODE_FOR_PRE_ENCUMBRANCE); 350 final String OBJECT_CODE_FOR_BALANCE_TYPE_EXTERNAL_ENCUMBRANCE = getParameterService().getParameterValueAsString(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.OFFSET_OBJECT_CODE_FOR_EXTERNAL_ENCUMBRANCE); 351 final String BEGINNING_FUND_TRANSACTION_LEDGER_ENTRY_DESCRIPTION = getParameterService().getParameterValueAsString(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.BEGINNING_FUND_BALANCE_TRANSACTION_LEDGER_ENTRY_DESCRIPTION); 352 353 // And now build the offset. 354 OriginEntryFull offset = new OriginEntryFull(entry); 355 offset.setTransactionLedgerEntryAmount(entry.getTransactionLedgerEntryAmount()); 356 // OLEConstants.BALANCE_TYPE_INTERNAL_ENCUMBRANCE case... 357 offset.setFinancialObjectCode(OBJECT_CODE_FOR_BALANCE_TYPE_INTERNAL_ENCUMBRANCE); 358 359 if (OLEConstants.BALANCE_TYPE_PRE_ENCUMBRANCE.equals(entry.getFinancialBalanceTypeCode())) { 360 361 offset.setFinancialObjectCode(OBJECT_CODE_FOR_BALANCE_TYPE_PRE_ENCUMBRANCE); 362 363 } 364 else if (OLEConstants.BALANCE_TYPE_EXTERNAL_ENCUMBRANCE.equals(entry.getFinancialBalanceTypeCode())) { 365 366 offset.setFinancialObjectCode(OBJECT_CODE_FOR_BALANCE_TYPE_EXTERNAL_ENCUMBRANCE); 367 368 } 369 370 offset.setFinancialObjectTypeCode(getOptionsService().getCurrentYearOptions().getFinObjectTypeFundBalanceCd()); 371 offset.setTransactionLedgerEntryDescription(BEGINNING_FUND_TRANSACTION_LEDGER_ENTRY_DESCRIPTION); 372 373 if (OLEConstants.GL_DEBIT_CODE.equals(entry.getTransactionDebitCreditCode())) { 374 375 offset.setTransactionDebitCreditCode(OLEConstants.GL_CREDIT_CODE); 376 377 } 378 else { 379 380 offset.setTransactionDebitCreditCode(OLEConstants.GL_DEBIT_CODE); 381 382 } 383 getFlexibleOffsetAccountService().updateOffset(offset); 384 385 pair.setOffset(offset); 386 387 return pair; 388 } 389 390 /** 391 * Determine whether or not an encumbrance should be carried forward from one fiscal year to the next. 392 * 393 * @param encumbrance the encumbrance to qualify 394 * @return true if the encumbrance should be rolled forward from the closing fiscal year to the opening fiscal year. 395 */ 396 @Override 397 public boolean shouldForwardEncumbrance(Encumbrance encumbrance) { 398 // null guard 399 if (null == encumbrance) { 400 return false; 401 } 402 403 if (encumbrance.getAccountLineEncumbranceAmount().equals(encumbrance.getAccountLineEncumbranceClosedAmount())) { 404 return false; 405 } 406 407 if (getEncumbranceBalanceTypeCodes().contains(encumbrance.getBalanceTypeCode())) { 408 409 ParameterEvaluator evaluator = /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.FORWARD_ENCUMBRANCE_BALANCE_TYPE_AND_ORIGIN_CODE,encumbrance.getBalanceTypeCode(), encumbrance.getOriginCode()); 410 if (!evaluator.evaluationSucceeds()) { 411 return false; 412 } 413 else if (OLEConstants.BALANCE_TYPE_PRE_ENCUMBRANCE.equals(encumbrance.getBalanceTypeCode())) { 414 // pre-encumbrances are forwarded, but only if they're related to contracts and grants accounts 415 PriorYearAccount priorYearAccount = retrievePriorYearAccount(encumbrance.getChartOfAccountsCode(), encumbrance.getAccountNumber()); 416 // the account on the encumbrance must be valid 417 if (null == priorYearAccount) { 418 LOG.info("No prior year account for chart \"" + encumbrance.getChartOfAccountsCode() + "\" and account \"" + encumbrance.getAccountNumber() + "\""); 419 return false; 420 } 421 // the sub fund group must exist for the prior year account and the 422 // encumbrance must not be closed. 423 return priorYearAccount.isForContractsAndGrants(); 424 } 425 else { 426 // we're still here? because we're an external encumbrance, and we always get forwarded 427 return true; 428 } 429 } 430 // we're still here? because we're not of a valid encumbrance balance type; we don't get forwarded 431 return false; 432 433 } 434 435 /** 436 * @return a list of BalanceType codes which correspond to encumbrance balance types 437 */ 438 protected List<String> getEncumbranceBalanceTypeCodes() { 439 List<String> balanceTypeCodes = new ArrayList<String>(); 440 441 442 Map<String, Object> keys = new HashMap<String, Object>(); 443 keys.put("active", Boolean.TRUE); 444 keys.put("finBalanceTypeEncumIndicator", Boolean.TRUE); 445 Collection balanceTypes = businessObjectService.findMatching(BalanceType.class, keys); 446 for (Object balanceTypeAsObject : balanceTypes) { 447 ParameterEvaluator evaluator = /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.FORWARDING_ENCUMBRANCE_BALANCE_TYPES, ((BalanceType)balanceTypeAsObject).getCode()); 448 if (evaluator.evaluationSucceeds()) 449 balanceTypeCodes.add(((BalanceType)balanceTypeAsObject).getCode()); 450 } 451 452 return balanceTypeCodes; 453 } 454 455 /** 456 * Determine whether or not the encumbrance has been fully relieved. 457 * 458 * @param encumbrance the encumbrance to qualify 459 * @return true if the amount closed on the encumbrance is NOT equal to the amount of the encumbrance itself, e.g. if the 460 * encumbrance has not yet been paid off. 461 */ 462 @Override 463 public boolean isEncumbranceClosed(Encumbrance encumbrance) { 464 if (encumbrance.getAccountLineEncumbranceAmount().doubleValue() == encumbrance.getAccountLineEncumbranceClosedAmount().doubleValue()) { 465 return false; 466 } 467 return true; 468 } 469 470 /** 471 * Do some validation and make sure that the encumbrance A21SubAccount is a cost share sub-account. 472 * 473 * @param entry not used in this implementation 474 * @param offset not used in this implementation 475 * @param encumbrance the encumbrance whose A21SubAccount must be qualified 476 * @param objectTypeCode the object type code of the generated entries 477 * @return true if the encumbrance is eligible for cost share. 478 * @throws FatalErrorException thrown if a given A21SubAccount, SubFundGroup, or PriorYearAccount record is not found in the database 479 */ 480 @Override 481 public boolean shouldForwardCostShareForEncumbrance(OriginEntryFull entry, OriginEntryFull offset, Encumbrance encumbrance, String objectTypeCode) throws FatalErrorException { 482 PriorYearAccount priorYearAccount = retrievePriorYearAccount(encumbrance.getChartOfAccountsCode(), encumbrance.getAccountNumber()); 483 484 // the sub fund group for the prior year account must exist. 485 String subFundGroupCode = null; 486 if (null != priorYearAccount) { 487 subFundGroupCode = priorYearAccount.getSubFundGroupCode(); 488 } 489 else { 490 // this message was carried over from the cobol. 491 throw new FatalErrorException("ERROR ACCESSING PRIOR YR ACCT TABLE FOR " + encumbrance.getAccountNumber()); 492 } 493 494 SubFundGroup subFundGroup = getSubFundGroupService().getByPrimaryId(subFundGroupCode); 495 if (null != subFundGroup) { 496 if (!priorYearAccount.isForContractsAndGrants()) { 497 return false; 498 } 499 } 500 else { 501 throw new FatalErrorException("ERROR ACCESSING SUB FUND GROUP TABLE FOR " + subFundGroupCode); 502 } 503 504 // I think this is redundant to the statement a few lines above here. 505 // In any case, the sub fund group must not be contracts and grants. 506 if (!priorYearAccount.isForContractsAndGrants()) { 507 return false; 508 } 509 510 ObjectTypeService objectTypeService = (ObjectTypeService) SpringContext.getBean(ObjectTypeService.class); 511 List<String> expenseObjectCodeTypes = objectTypeService.getCurrentYearExpenseObjectTypes(); 512 513 String[] encumbranceBalanceTypeCodes = new String[] { OLEConstants.BALANCE_TYPE_EXTERNAL_ENCUMBRANCE, OLEConstants.BALANCE_TYPE_INTERNAL_ENCUMBRANCE, OLEConstants.BALANCE_TYPE_PRE_ENCUMBRANCE }; 514 515 // the object type code must be an expense and the encumbrance balance type code must correspond to an internal, external or 516 // pre-encumbrance 517 if (!expenseObjectCodeTypes.contains(objectTypeCode) || !ArrayUtils.contains(encumbranceBalanceTypeCodes, encumbrance.getBalanceTypeCode())) { 518 return false; 519 } 520 else if (!encumbrance.getSubAccountNumber().equals(OLEConstants.getDashSubAccountNumber())) { 521 A21SubAccount a21SubAccount = getA21SubAccountService().getByPrimaryKey(encumbrance.getChartOfAccountsCode(), encumbrance.getAccountNumber(), encumbrance.getSubAccountNumber()); 522 if (null == a21SubAccount) { 523 // Error message carried over from cobol. not very well descriptive. 524 // Just indicates that the a21 sub account doesn't exist. 525 throw new FatalErrorException("ERROR ACCESSING A21 SUB ACCOUNT TABLE FOR ENCUMBRANCE " + encumbrance.getChartOfAccountsCode() + "-" + encumbrance.getAccountNumber() + " " + encumbrance.getSubAccountNumber()); 526 } 527 // everything is valid, return true if the a21 sub account is a cost share sub-account 528 return OLEConstants.SubAccountType.COST_SHARE.equals(a21SubAccount.getSubAccountTypeCode()); 529 } 530 else { 531 return false; 532 } 533 534 } 535 536 /** 537 * Retrieves a prior year account from the persistence store 538 * @param chartOfAccountsCode the chart of accounts for the prior year account 539 * @param accountNumber the account number for the prior year account 540 * @return the PriorYearAccount 541 */ 542 protected PriorYearAccount retrievePriorYearAccount(String chartOfAccountsCode, String accountNumber) { 543 Map pks = new HashMap(); 544 pks.put(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, chartOfAccountsCode); 545 pks.put(OLEPropertyConstants.ACCOUNT_NUMBER, accountNumber); 546 547 return (PriorYearAccount)this.getBusinessObjectService().findByPrimaryKey(PriorYearAccount.class, pks); 548 } 549 550 /** 551 * 552 * This method eases the institutional customization for Cost Sharing Object Codes for OriginEntries 553 * @param levelCode of the originEntry 554 * @param objectCode of the originEntry 555 * @return the new objectCode 556 */ 557 558 protected String overrideCostShareObjectCode(String levelCode, String objectCode){ 559 return objectCode; 560 } 561 562 /** 563 * Gets the parameterService attribute. 564 * @return Returns the parameterService. 565 */ 566 public ParameterService getParameterService() { 567 return parameterService; 568 } 569 570 /** 571 * Sets the parameterService attribute value. 572 * @param parameterService The parameterService to set. 573 */ 574 public void setParameterService(ParameterService parameterService) { 575 this.parameterService = parameterService; 576 } 577 578 /** 579 * Gets the offsetDefinitionService attribute. 580 * @return Returns the offsetDefinitionService. 581 */ 582 public OffsetDefinitionService getOffsetDefinitionService() { 583 return offsetDefinitionService; 584 } 585 586 /** 587 * Sets the offsetDefinitionService attribute value. 588 * @param offsetDefinitionService The offsetDefinitionService to set. 589 */ 590 public void setOffsetDefinitionService(OffsetDefinitionService offsetDefinitionService) { 591 this.offsetDefinitionService = offsetDefinitionService; 592 } 593 594 /** 595 * Gets the objectCodeService attribute. 596 * @return Returns the objectCodeService. 597 */ 598 public ObjectCodeService getObjectCodeService() { 599 return objectCodeService; 600 } 601 602 /** 603 * Sets the objectCodeService attribute value. 604 * @param objectCodeService The objectCodeService to set. 605 */ 606 public void setObjectCodeService(ObjectCodeService objectCodeService) { 607 this.objectCodeService = objectCodeService; 608 } 609 610 /** 611 * Gets the dataDictionaryService attribute. 612 * @return Returns the dataDictionaryService. 613 */ 614 public DataDictionaryService getDataDictionaryService() { 615 return dataDictionaryService; 616 } 617 618 /** 619 * Sets the dataDictionaryService attribute value. 620 * @param dataDictionaryService The dataDictionaryService to set. 621 */ 622 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) { 623 this.dataDictionaryService = dataDictionaryService; 624 } 625 626 /** 627 * Gets the flexibleOffsetAccountService attribute. 628 * @return Returns the flexibleOffsetAccountService. 629 */ 630 public FlexibleOffsetAccountService getFlexibleOffsetAccountService() { 631 return flexibleOffsetAccountService; 632 } 633 634 /** 635 * Sets the flexibleOffsetAccountService attribute value. 636 * @param flexibleOffsetAccountService The flexibleOffsetAccountService to set. 637 */ 638 public void setFlexibleOffsetAccountService(FlexibleOffsetAccountService flexibleOffsetAccountService) { 639 this.flexibleOffsetAccountService = flexibleOffsetAccountService; 640 } 641 642 /** 643 * Gets the a21SubAccountService attribute. 644 * @return Returns the a21SubAccountService. 645 */ 646 public A21SubAccountService getA21SubAccountService() { 647 return a21SubAccountService; 648 } 649 650 /** 651 * Sets the a21SubAccountService attribute value. 652 * @param subAccountService The a21SubAccountService to set. 653 */ 654 public void setA21SubAccountService(A21SubAccountService subAccountService) { 655 a21SubAccountService = subAccountService; 656 } 657 658 /** 659 * Gets the subObjectCodeService attribute. 660 * @return Returns the subObjectCodeService. 661 */ 662 public SubObjectCodeService getSubObjectCodeService() { 663 return subObjectCodeService; 664 } 665 666 /** 667 * Sets the subObjectCodeService attribute value. 668 * @param subObjectCodeService The subObjectCodeService to set. 669 */ 670 public void setSubObjectCodeService(SubObjectCodeService subObjectCodeService) { 671 this.subObjectCodeService = subObjectCodeService; 672 } 673 674 /** 675 * Gets the optionsService attribute. 676 * @return Returns the optionsService. 677 */ 678 public OptionsService getOptionsService() { 679 return optionsService; 680 } 681 682 /** 683 * Sets the optionsService attribute value. 684 * @param optionsService The optionsService to set. 685 */ 686 public void setOptionsService(OptionsService optionsService) { 687 this.optionsService = optionsService; 688 } 689 690 /** 691 * Gets the subFundGroupService attribute. 692 * @return Returns the subFundGroupService. 693 */ 694 public SubFundGroupService getSubFundGroupService() { 695 return subFundGroupService; 696 } 697 698 /** 699 * Sets the subFundGroupService attribute value. 700 * @param subFundGroupService The subFundGroupService to set. 701 */ 702 public void setSubFundGroupService(SubFundGroupService subFundGroupService) { 703 this.subFundGroupService = subFundGroupService; 704 } 705 706 /** 707 * Gets the businessObjectService attribute. 708 * @return Returns the businessObjectService. 709 */ 710 public BusinessObjectService getBusinessObjectService() { 711 return businessObjectService; 712 } 713 714 /** 715 * Sets the businessObjectService attribute value. 716 * @param businessObjectService The businessObjectService to set. 717 */ 718 public void setBusinessObjectService(BusinessObjectService businessObjectService) { 719 this.businessObjectService = businessObjectService; 720 } 721 722 /** 723 * Gets the accountingCycleCachingService attribute. 724 * @return Returns the accountingCycleCachingService. 725 */ 726 public AccountingCycleCachingService getAccountingCycleCachingService() { 727 return accountingCycleCachingService; 728 } 729 730 /** 731 * Sets the accountingCycleCachingService attribute value. 732 * @param accountingCycleCachingService The accountingCycleCachingService to set. 733 */ 734 public void setAccountingCycleCachingService(AccountingCycleCachingService accountingCycleCachingService) { 735 this.accountingCycleCachingService = accountingCycleCachingService; 736 } 737 738}