/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.gl.batch.service.impl; import java.sql.Date; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.ArrayUtils; import org.kuali.kfs.coa.businessobject.A21SubAccount; import org.kuali.kfs.coa.businessobject.BalanceType; import org.kuali.kfs.coa.businessobject.ObjectCode; import org.kuali.kfs.coa.businessobject.OffsetDefinition; import org.kuali.kfs.coa.businessobject.PriorYearAccount; import org.kuali.kfs.coa.businessobject.SubFundGroup; import org.kuali.kfs.coa.businessobject.SubObjectCode; import org.kuali.kfs.coa.service.A21SubAccountService; import org.kuali.kfs.coa.service.ObjectCodeService; import org.kuali.kfs.coa.service.ObjectTypeService; import org.kuali.kfs.coa.service.OffsetDefinitionService; import org.kuali.kfs.coa.service.SubFundGroupService; import org.kuali.kfs.coa.service.SubObjectCodeService; import org.kuali.kfs.gl.GeneralLedgerConstants; import org.kuali.kfs.gl.batch.EncumbranceForwardStep; import org.kuali.kfs.gl.batch.ScrubberStep; import org.kuali.kfs.gl.batch.service.AccountingCycleCachingService; import org.kuali.kfs.gl.batch.service.EncumbranceClosingOriginEntryGenerationService; import org.kuali.kfs.gl.batch.service.impl.exception.FatalErrorException; import org.kuali.kfs.gl.businessobject.Encumbrance; import org.kuali.kfs.gl.businessobject.OriginEntryFull; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.service.FlexibleOffsetAccountService; import org.kuali.kfs.sys.service.OptionsService; import org.kuali.kfs.sys.service.impl.KfsParameterConstants; import org.kuali.rice.core.api.parameter.ParameterEvaluator; import org.kuali.rice.core.api.parameter.ParameterEvaluatorService; import org.kuali.rice.core.api.util.type.KualiDecimal; import org.kuali.rice.coreservice.framework.parameter.ParameterService; import org.kuali.rice.kns.service.DataDictionaryService; import org.kuali.rice.krad.service.BusinessObjectService; /** * The default implementation of the EncumbranceClosingOriginEntryGenerationService */ public class EncumbranceClosingOriginEntryGenerationServiceImpl implements EncumbranceClosingOriginEntryGenerationService { private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(EncumbranceClosingOriginEntryGenerationServiceImpl.class); protected ParameterService parameterService; protected OffsetDefinitionService offsetDefinitionService; protected ObjectCodeService objectCodeService; protected DataDictionaryService dataDictionaryService; protected FlexibleOffsetAccountService flexibleOffsetAccountService; protected A21SubAccountService a21SubAccountService; protected SubObjectCodeService subObjectCodeService; protected OptionsService optionsService; protected SubFundGroupService subFundGroupService; protected BusinessObjectService businessObjectService; protected AccountingCycleCachingService accountingCycleCachingService; /** * @see org.kuali.kfs.gl.batch.service.EncumbranceClosingOriginEntryGenerationService#createBeginningBalanceEntryOffsetPair(org.kuali.kfs.gl.businessobject.Encumbrance, java.lang.Integer, java.sql.Date) */ @Override public OriginEntryOffsetPair createCostShareBeginningBalanceEntryOffsetPair(Encumbrance encumbrance, Date transactionDate) { final String GL_ACLO = getParameterService().getParameterValueAsString(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, KFSConstants.SystemGroupParameterNames.GL_ANNUAL_CLOSING_DOC_TYPE); final String GL_ORIGINATION_CODE = getParameterService().getParameterValueAsString(KfsParameterConstants.GENERAL_LEDGER_BATCH.class, KFSConstants.SystemGroupParameterNames.GL_ORIGINATION_CODE); OriginEntryOffsetPair pair = new OriginEntryOffsetPair(); // Generate the entry ... OriginEntryFull entry = new OriginEntryFull(encumbrance.getDocumentTypeCode(), encumbrance.getOriginCode()); String description = encumbrance.getTransactionEncumbranceDescription(); String fromDesc = "FR-" + encumbrance.getChartOfAccountsCode() + encumbrance.getAccountNumber(); int descLength = getDataDictionaryService().getAttributeMaxLength(OriginEntryFull.class, KFSPropertyConstants.TRANSACTION_LEDGER_ENTRY_DESC); if ((description.length() + fromDesc.length()) < descLength) { int padLength = descLength - (description.length() + fromDesc.length()); StringBuilder sb = new StringBuilder(); for (int i = 0; i < padLength; i++) { sb.append(' '); } sb.append(fromDesc); fromDesc = sb.toString(); description += fromDesc; } else if ((description.length() + fromDesc.length()) > descLength) { description = description.substring(0, (descLength - fromDesc.length())) + fromDesc; } else { description += fromDesc; } entry.setTransactionLedgerEntryDescription(description); // SpringContext is used because this method is static. A21SubAccount a21SubAccount = getA21SubAccountService().getByPrimaryKey(encumbrance.getChartOfAccountsCode(), encumbrance.getAccountNumber(), encumbrance.getSubAccountNumber()); entry.setUniversityFiscalYear(new Integer(encumbrance.getUniversityFiscalYear().intValue() + 1)); entry.setChartOfAccountsCode(a21SubAccount.getCostShareChartOfAccountCode()); entry.setAccountNumber(a21SubAccount.getCostShareSourceAccountNumber()); entry.setSubAccountNumber(a21SubAccount.getCostShareSourceSubAccountNumber()); // The subAccountNumber is set to dashes in the OriginEntryFull constructor. if (entry.getSubAccountNumber() == null || KFSConstants.EMPTY_STRING.equals(entry.getSubAccountNumber().trim())) { entry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber()); } // ObjectCode finObjCode = accountingCycleCachingService.getObjectCode(encumbrance.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), entry.getFinancialObjectCode()); // if (finObjCode != null) // entry.setFinancialObjectTypeCode(finObjCode.getFinancialObjectTypeCode()); // ObjectCode encumbranceObjectCode = accountingCycleCachingService.getObjectCode(entry.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), encumbrance.getObjectCode()); if (null != encumbranceObjectCode) { String financialObjectLevelCode = encumbranceObjectCode.getFinancialObjectLevelCode(); String financialObjectCode = encumbrance.getObjectCode(); String overriddenObjectCode = overrideCostShareObjectCode(financialObjectLevelCode, financialObjectCode); final ObjectCode overriddenObject = this.getAccountingCycleCachingService().getObjectCode(entry.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), overriddenObjectCode); String param = parameterService.getSubParameterValueAsString(ScrubberStep.class, GeneralLedgerConstants.GlScrubberGroupParameters.COST_SHARE_OBJECT_CODE_BY_LEVEL_PARM_NM, overriddenObject.getFinancialObjectLevelCode()); if (param == null) { param = parameterService.getSubParameterValueAsString(ScrubberStep.class, GeneralLedgerConstants.GlScrubberGroupParameters.COST_SHARE_OBJECT_CODE_BY_LEVEL_PARM_NM, "DEFAULT"); if (param == null) { throw new RuntimeException("Unable to determine cost sharing object code from object level (" + overriddenObject.getFinancialObjectLevelCode() + "). Default entry missing."); } } financialObjectCode = param; // Lookup the new object code ObjectCode newObjectCode = accountingCycleCachingService.getObjectCode(entry.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), financialObjectCode); if (newObjectCode != null) { entry.setFinancialObjectTypeCode(newObjectCode.getFinancialObjectTypeCode()); entry.setFinancialObjectCode(financialObjectCode); } else { LOG.error("Error retrieving ObjectCode("+entry.getUniversityFiscalYear()+"/"+entry.getChartOfAccountsCode()+"/"+financialObjectCode+")"); pair.setFatalErrorFlag(true); return pair; } } else { LOG.error("Error retrieving ObjectCode("+entry.getUniversityFiscalYear()+"/"+entry.getChartOfAccountsCode()+"/"+entry.getFinancialObjectCode()+")"); pair.setFatalErrorFlag(true); return pair; } entry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode()); entry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_COST_SHARE_ENCUMBRANCE); entry.setUniversityFiscalPeriodCode(KFSConstants.PERIOD_CODE_BEGINNING_BALANCE); entry.setTransactionLedgerEntrySequenceNumber(new Integer(0)); entry.setDocumentNumber(encumbrance.getDocumentNumber()); entry.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_COST_SHARE_ENCUMBRANCE); KualiDecimal delta = encumbrance.getAccountLineEncumbranceAmount().subtract(encumbrance.getAccountLineEncumbranceClosedAmount()); if (delta.isPositive()) { entry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE); entry.setTransactionLedgerEntryAmount(delta); } else { entry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE); entry.setTransactionLedgerEntryAmount(delta.negated()); } entry.setTransactionEncumbranceUpdateCode(KFSConstants.ENCUMB_UPDT_DOCUMENT_CD); entry.setProjectCode(KFSConstants.getDashProjectCode()); entry.setTransactionDate(transactionDate); pair.setEntry(entry); // And now the offset ... OriginEntryFull offset = new OriginEntryFull(encumbrance.getDocumentTypeCode(), encumbrance.getOriginCode()); final String GENERATED_TRANSACTION_LEDGER_ENTRY_DESCRIPTION = getParameterService().getParameterValueAsString(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.GENERATED_TRANSACTION_LEDGER_ENTRY_DESCRIPTION); offset.setTransactionLedgerEntryDescription(GENERATED_TRANSACTION_LEDGER_ENTRY_DESCRIPTION); offset.setUniversityFiscalYear(new Integer(encumbrance.getUniversityFiscalYear().intValue() + 1)); offset.setChartOfAccountsCode(a21SubAccount.getCostShareChartOfAccountCode()); offset.setAccountNumber(a21SubAccount.getCostShareSourceAccountNumber()); offset.setSubAccountNumber(a21SubAccount.getCostShareSourceSubAccountNumber()); if (offset.getSubAccountNumber() == null || KFSConstants.EMPTY_STRING.equals(offset.getSubAccountNumber().trim())) { offset.setSubAccountNumber(KFSConstants.getDashSubAccountNumber()); } // Lookup the offset definition for the explicit entry we just created. OffsetDefinition offsetDefinition = getOffsetDefinitionService().getByPrimaryId(entry.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), entry.getFinancialDocumentTypeCode(), entry.getFinancialBalanceTypeCode()); // Set values from the offset definition if it was found. if (null != offsetDefinition) { offset.setFinancialObjectCode(offsetDefinition.getFinancialObjectCode()); offset.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode()); } else { // Log an exception if the offset definition was not found. 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"); pair.setFatalErrorFlag(true); return pair; } offset.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_COST_SHARE_ENCUMBRANCE); // Validate the object code for the explicit entry. ObjectCode objectCode = getObjectCodeService().getByPrimaryId(offset.getUniversityFiscalYear(), offset.getChartOfAccountsCode(), offset.getFinancialObjectCode()); if (null != objectCode) { offset.setFinancialObjectTypeCode(objectCode.getFinancialObjectTypeCode()); } else { 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"); pair.setFatalErrorFlag(true); return pair; } offset.setUniversityFiscalPeriodCode(KFSConstants.PERIOD_CODE_BEGINNING_BALANCE); offset.setDocumentNumber(encumbrance.getDocumentNumber()); offset.setTransactionLedgerEntrySequenceNumber(new Integer(0)); if (delta.isPositive()) { offset.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE); offset.setTransactionLedgerEntryAmount(delta); } else { offset.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE); offset.setTransactionLedgerEntryAmount(delta.negated()); } offset.setTransactionEncumbranceUpdateCode(null); offset.setOrganizationDocumentNumber(null); offset.setProjectCode(KFSConstants.getDashProjectCode()); offset.setTransactionDate(transactionDate); offset.setOrganizationReferenceId(null); offset.setReferenceFinancialDocumentTypeCode(null); offset.setReferenceFinancialSystemOriginationCode(null); offset.setReferenceFinancialDocumentNumber(null); offset.setReversalDate(null); getFlexibleOffsetAccountService().updateOffset(offset); pair.setOffset(offset); return pair; } /** * @see org.kuali.kfs.gl.batch.service.EncumbranceClosingOriginEntryGenerationService#createCostShareBeginningBalanceEntryOffsetPair(org.kuali.kfs.gl.businessobject.Encumbrance, java.sql.Date) */ @Override public OriginEntryOffsetPair createBeginningBalanceEntryOffsetPair(Encumbrance encumbrance, Integer closingFiscalYear, Date transactionDate) { OriginEntryOffsetPair pair = new OriginEntryOffsetPair(); // Build the entry ... OriginEntryFull entry = new OriginEntryFull(encumbrance.getDocumentTypeCode(), encumbrance.getOriginCode()); Integer thisFiscalYear = new Integer(closingFiscalYear.intValue() + 1); entry.setUniversityFiscalYear(thisFiscalYear); entry.setChartOfAccountsCode(encumbrance.getChartOfAccountsCode()); entry.setAccountNumber(encumbrance.getAccountNumber()); entry.setSubAccountNumber(encumbrance.getSubAccountNumber()); ObjectCode objectCode = accountingCycleCachingService.getObjectCode(entry.getUniversityFiscalYear(), entry.getChartOfAccountsCode(), encumbrance.getObjectCode()); if (null != objectCode) { entry.setFinancialObjectTypeCode(objectCode.getFinancialObjectTypeCode()); if (null != objectCode.getNextYearFinancialObjectCode() && !KFSConstants.EMPTY_STRING.equals(objectCode.getNextYearFinancialObjectCode().trim())) { entry.setFinancialObjectCode(objectCode.getNextYearFinancialObjectCode()); } else { entry.setFinancialObjectCode(encumbrance.getObjectCode()); } } else { LOG.error("Error retrieving ObjectCode("+entry.getUniversityFiscalYear()+"/"+entry.getChartOfAccountsCode()+"/"+entry.getFinancialObjectCode()+")"); pair.setFatalErrorFlag(true); return pair; } SubObjectCode subObjectCode = getSubObjectCodeService().getByPrimaryId(encumbrance.getUniversityFiscalYear(), encumbrance.getChartOfAccountsCode(), encumbrance.getAccountNumber(), encumbrance.getObjectCode(), encumbrance.getSubObjectCode()); if (null != subObjectCode) { entry.setFinancialSubObjectCode(subObjectCode.getFinancialSubObjectCode()); } else { entry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode()); } entry.setFinancialBalanceTypeCode(encumbrance.getBalanceTypeCode()); entry.setUniversityFiscalPeriodCode(KFSConstants.PERIOD_CODE_BEGINNING_BALANCE); entry.setDocumentNumber(encumbrance.getDocumentNumber()); entry.setTransactionLedgerEntrySequenceNumber(new Integer(1)); entry.setTransactionLedgerEntryDescription(encumbrance.getTransactionEncumbranceDescription()); entry.setTransactionLedgerEntryAmount(encumbrance.getAccountLineEncumbranceAmount().subtract(encumbrance.getAccountLineEncumbranceClosedAmount())); if (entry.getTransactionLedgerEntryAmount().isNegative()) { entry.setTransactionLedgerEntryAmount(entry.getTransactionLedgerEntryAmount().negated()); entry.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE); } else { entry.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE); } entry.setTransactionDate(transactionDate); entry.setOrganizationDocumentNumber(null); entry.setProjectCode(KFSConstants.getDashProjectCode()); entry.setOrganizationReferenceId(null); entry.setReferenceFinancialDocumentTypeCode(null); entry.setReferenceFinancialSystemOriginationCode(null); entry.setReferenceFinancialDocumentNumber(null); entry.setReversalDate(null); entry.setTransactionEncumbranceUpdateCode(KFSConstants.ENCUMB_UPDT_DOCUMENT_CD); pair.setEntry(entry); final String OBJECT_CODE_FOR_BALANCE_TYPE_INTERNAL_ENCUMBRANCE = getParameterService().getParameterValueAsString(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.OFFSET_OBJECT_CODE_FOR_INTERNAL_ENCUMBRANCE); final String OBJECT_CODE_FOR_BALANCE_TYPE_PRE_ENCUMBRANCE = getParameterService().getParameterValueAsString(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.OFFSET_OBJECT_CODE_FOR_PRE_ENCUMBRANCE); final String OBJECT_CODE_FOR_BALANCE_TYPE_EXTERNAL_ENCUMBRANCE = getParameterService().getParameterValueAsString(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.OFFSET_OBJECT_CODE_FOR_EXTERNAL_ENCUMBRANCE); final String BEGINNING_FUND_TRANSACTION_LEDGER_ENTRY_DESCRIPTION = getParameterService().getParameterValueAsString(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.BEGINNING_FUND_BALANCE_TRANSACTION_LEDGER_ENTRY_DESCRIPTION); // And now build the offset. OriginEntryFull offset = new OriginEntryFull(entry); offset.setTransactionLedgerEntryAmount(entry.getTransactionLedgerEntryAmount()); // KFSConstants.BALANCE_TYPE_INTERNAL_ENCUMBRANCE case... offset.setFinancialObjectCode(OBJECT_CODE_FOR_BALANCE_TYPE_INTERNAL_ENCUMBRANCE); if (KFSConstants.BALANCE_TYPE_PRE_ENCUMBRANCE.equals(entry.getFinancialBalanceTypeCode())) { offset.setFinancialObjectCode(OBJECT_CODE_FOR_BALANCE_TYPE_PRE_ENCUMBRANCE); } else if (KFSConstants.BALANCE_TYPE_EXTERNAL_ENCUMBRANCE.equals(entry.getFinancialBalanceTypeCode())) { offset.setFinancialObjectCode(OBJECT_CODE_FOR_BALANCE_TYPE_EXTERNAL_ENCUMBRANCE); } offset.setFinancialObjectTypeCode(getOptionsService().getCurrentYearOptions().getFinObjectTypeFundBalanceCd()); offset.setTransactionLedgerEntryDescription(BEGINNING_FUND_TRANSACTION_LEDGER_ENTRY_DESCRIPTION); if (KFSConstants.GL_DEBIT_CODE.equals(entry.getTransactionDebitCreditCode())) { offset.setTransactionDebitCreditCode(KFSConstants.GL_CREDIT_CODE); } else { offset.setTransactionDebitCreditCode(KFSConstants.GL_DEBIT_CODE); } getFlexibleOffsetAccountService().updateOffset(offset); pair.setOffset(offset); return pair; } /** * Determine whether or not an encumbrance should be carried forward from one fiscal year to the next. * * @param encumbrance the encumbrance to qualify * @return true if the encumbrance should be rolled forward from the closing fiscal year to the opening fiscal year. */ @Override public boolean shouldForwardEncumbrance(Encumbrance encumbrance) { // null guard if (null == encumbrance) { return false; } if (encumbrance.getAccountLineEncumbranceAmount().equals(encumbrance.getAccountLineEncumbranceClosedAmount())) { return false; } if (getEncumbranceBalanceTypeCodes().contains(encumbrance.getBalanceTypeCode())) { ParameterEvaluator evaluator = /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.FORWARD_ENCUMBRANCE_BALANCE_TYPE_AND_ORIGIN_CODE,encumbrance.getBalanceTypeCode(), encumbrance.getOriginCode()); if (!evaluator.evaluationSucceeds()) { return false; } else if (KFSConstants.BALANCE_TYPE_PRE_ENCUMBRANCE.equals(encumbrance.getBalanceTypeCode())) { // pre-encumbrances are forwarded, but only if they're related to contracts and grants accounts PriorYearAccount priorYearAccount = retrievePriorYearAccount(encumbrance.getChartOfAccountsCode(), encumbrance.getAccountNumber()); // the account on the encumbrance must be valid if (null == priorYearAccount) { LOG.info("No prior year account for chart \"" + encumbrance.getChartOfAccountsCode() + "\" and account \"" + encumbrance.getAccountNumber() + "\""); return false; } // the sub fund group must exist for the prior year account and the // encumbrance must not be closed. return priorYearAccount.isForContractsAndGrants(); } else { // we're still here? because we're an external encumbrance, and we always get forwarded return true; } } // we're still here? because we're not of a valid encumbrance balance type; we don't get forwarded return false; } /** * @return a list of BalanceType codes which correspond to encumbrance balance types */ protected List<String> getEncumbranceBalanceTypeCodes() { List<String> balanceTypeCodes = new ArrayList<String>(); Map<String, Object> keys = new HashMap<String, Object>(); keys.put("active", Boolean.TRUE); keys.put("finBalanceTypeEncumIndicator", Boolean.TRUE); Collection balanceTypes = businessObjectService.findMatching(BalanceType.class, keys); for (Object balanceTypeAsObject : balanceTypes) { ParameterEvaluator evaluator = /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(EncumbranceForwardStep.class, GeneralLedgerConstants.EncumbranceClosingOriginEntry.FORWARDING_ENCUMBRANCE_BALANCE_TYPES, ((BalanceType)balanceTypeAsObject).getCode()); if (evaluator.evaluationSucceeds()) balanceTypeCodes.add(((BalanceType)balanceTypeAsObject).getCode()); } return balanceTypeCodes; } /** * Determine whether or not the encumbrance has been fully relieved. * * @param encumbrance the encumbrance to qualify * @return true if the amount closed on the encumbrance is NOT equal to the amount of the encumbrance itself, e.g. if the * encumbrance has not yet been paid off. */ @Override public boolean isEncumbranceClosed(Encumbrance encumbrance) { if (encumbrance.getAccountLineEncumbranceAmount().doubleValue() == encumbrance.getAccountLineEncumbranceClosedAmount().doubleValue()) { return false; } return true; } /** * Do some validation and make sure that the encumbrance A21SubAccount is a cost share sub-account. * * @param entry not used in this implementation * @param offset not used in this implementation * @param encumbrance the encumbrance whose A21SubAccount must be qualified * @param objectTypeCode the object type code of the generated entries * @return true if the encumbrance is eligible for cost share. * @throws FatalErrorException thrown if a given A21SubAccount, SubFundGroup, or PriorYearAccount record is not found in the database */ @Override public boolean shouldForwardCostShareForEncumbrance(OriginEntryFull entry, OriginEntryFull offset, Encumbrance encumbrance, String objectTypeCode) throws FatalErrorException { PriorYearAccount priorYearAccount = retrievePriorYearAccount(encumbrance.getChartOfAccountsCode(), encumbrance.getAccountNumber()); // the sub fund group for the prior year account must exist. String subFundGroupCode = null; if (null != priorYearAccount) { subFundGroupCode = priorYearAccount.getSubFundGroupCode(); } else { // this message was carried over from the cobol. throw new FatalErrorException("ERROR ACCESSING PRIOR YR ACCT TABLE FOR " + encumbrance.getAccountNumber()); } SubFundGroup subFundGroup = getSubFundGroupService().getByPrimaryId(subFundGroupCode); if (null != subFundGroup) { if (!priorYearAccount.isForContractsAndGrants()) { return false; } } else { throw new FatalErrorException("ERROR ACCESSING SUB FUND GROUP TABLE FOR " + subFundGroupCode); } // I think this is redundant to the statement a few lines above here. // In any case, the sub fund group must not be contracts and grants. if (!priorYearAccount.isForContractsAndGrants()) { return false; } ObjectTypeService objectTypeService = (ObjectTypeService) SpringContext.getBean(ObjectTypeService.class); List<String> expenseObjectCodeTypes = objectTypeService.getCurrentYearExpenseObjectTypes(); String[] encumbranceBalanceTypeCodes = new String[] { KFSConstants.BALANCE_TYPE_EXTERNAL_ENCUMBRANCE, KFSConstants.BALANCE_TYPE_INTERNAL_ENCUMBRANCE, KFSConstants.BALANCE_TYPE_PRE_ENCUMBRANCE }; // the object type code must be an expense and the encumbrance balance type code must correspond to an internal, external or // pre-encumbrance if (!expenseObjectCodeTypes.contains(objectTypeCode) || !ArrayUtils.contains(encumbranceBalanceTypeCodes, encumbrance.getBalanceTypeCode())) { return false; } else if (!encumbrance.getSubAccountNumber().equals(KFSConstants.getDashSubAccountNumber())) { A21SubAccount a21SubAccount = getA21SubAccountService().getByPrimaryKey(encumbrance.getChartOfAccountsCode(), encumbrance.getAccountNumber(), encumbrance.getSubAccountNumber()); if (null == a21SubAccount) { // Error message carried over from cobol. not very well descriptive. // Just indicates that the a21 sub account doesn't exist. throw new FatalErrorException("ERROR ACCESSING A21 SUB ACCOUNT TABLE FOR ENCUMBRANCE " + encumbrance.getChartOfAccountsCode() + "-" + encumbrance.getAccountNumber() + " " + encumbrance.getSubAccountNumber()); } // everything is valid, return true if the a21 sub account is a cost share sub-account return KFSConstants.SubAccountType.COST_SHARE.equals(a21SubAccount.getSubAccountTypeCode()); } else { return false; } } /** * Retrieves a prior year account from the persistence store * @param chartOfAccountsCode the chart of accounts for the prior year account * @param accountNumber the account number for the prior year account * @return the PriorYearAccount */ protected PriorYearAccount retrievePriorYearAccount(String chartOfAccountsCode, String accountNumber) { Map pks = new HashMap(); pks.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, chartOfAccountsCode); pks.put(KFSPropertyConstants.ACCOUNT_NUMBER, accountNumber); return (PriorYearAccount)this.getBusinessObjectService().findByPrimaryKey(PriorYearAccount.class, pks); } /** * * This method eases the institutional customization for Cost Sharing Object Codes for OriginEntries * @param levelCode of the originEntry * @param objectCode of the originEntry * @return the new objectCode */ protected String overrideCostShareObjectCode(String levelCode, String objectCode){ return objectCode; } /** * Gets the parameterService attribute. * @return Returns the parameterService. */ public ParameterService getParameterService() { return parameterService; } /** * Sets the parameterService attribute value. * @param parameterService The parameterService to set. */ public void setParameterService(ParameterService parameterService) { this.parameterService = parameterService; } /** * Gets the offsetDefinitionService attribute. * @return Returns the offsetDefinitionService. */ public OffsetDefinitionService getOffsetDefinitionService() { return offsetDefinitionService; } /** * Sets the offsetDefinitionService attribute value. * @param offsetDefinitionService The offsetDefinitionService to set. */ public void setOffsetDefinitionService(OffsetDefinitionService offsetDefinitionService) { this.offsetDefinitionService = offsetDefinitionService; } /** * Gets the objectCodeService attribute. * @return Returns the objectCodeService. */ public ObjectCodeService getObjectCodeService() { return objectCodeService; } /** * Sets the objectCodeService attribute value. * @param objectCodeService The objectCodeService to set. */ public void setObjectCodeService(ObjectCodeService objectCodeService) { this.objectCodeService = objectCodeService; } /** * Gets the dataDictionaryService attribute. * @return Returns the dataDictionaryService. */ public DataDictionaryService getDataDictionaryService() { return dataDictionaryService; } /** * Sets the dataDictionaryService attribute value. * @param dataDictionaryService The dataDictionaryService to set. */ public void setDataDictionaryService(DataDictionaryService dataDictionaryService) { this.dataDictionaryService = dataDictionaryService; } /** * Gets the flexibleOffsetAccountService attribute. * @return Returns the flexibleOffsetAccountService. */ public FlexibleOffsetAccountService getFlexibleOffsetAccountService() { return flexibleOffsetAccountService; } /** * Sets the flexibleOffsetAccountService attribute value. * @param flexibleOffsetAccountService The flexibleOffsetAccountService to set. */ public void setFlexibleOffsetAccountService(FlexibleOffsetAccountService flexibleOffsetAccountService) { this.flexibleOffsetAccountService = flexibleOffsetAccountService; } /** * Gets the a21SubAccountService attribute. * @return Returns the a21SubAccountService. */ public A21SubAccountService getA21SubAccountService() { return a21SubAccountService; } /** * Sets the a21SubAccountService attribute value. * @param subAccountService The a21SubAccountService to set. */ public void setA21SubAccountService(A21SubAccountService subAccountService) { a21SubAccountService = subAccountService; } /** * Gets the subObjectCodeService attribute. * @return Returns the subObjectCodeService. */ public SubObjectCodeService getSubObjectCodeService() { return subObjectCodeService; } /** * Sets the subObjectCodeService attribute value. * @param subObjectCodeService The subObjectCodeService to set. */ public void setSubObjectCodeService(SubObjectCodeService subObjectCodeService) { this.subObjectCodeService = subObjectCodeService; } /** * Gets the optionsService attribute. * @return Returns the optionsService. */ public OptionsService getOptionsService() { return optionsService; } /** * Sets the optionsService attribute value. * @param optionsService The optionsService to set. */ public void setOptionsService(OptionsService optionsService) { this.optionsService = optionsService; } /** * Gets the subFundGroupService attribute. * @return Returns the subFundGroupService. */ public SubFundGroupService getSubFundGroupService() { return subFundGroupService; } /** * Sets the subFundGroupService attribute value. * @param subFundGroupService The subFundGroupService to set. */ public void setSubFundGroupService(SubFundGroupService subFundGroupService) { this.subFundGroupService = subFundGroupService; } /** * Gets the businessObjectService attribute. * @return Returns the businessObjectService. */ public BusinessObjectService getBusinessObjectService() { return businessObjectService; } /** * Sets the businessObjectService attribute value. * @param businessObjectService The businessObjectService to set. */ public void setBusinessObjectService(BusinessObjectService businessObjectService) { this.businessObjectService = businessObjectService; } /** * Gets the accountingCycleCachingService attribute. * @return Returns the accountingCycleCachingService. */ public AccountingCycleCachingService getAccountingCycleCachingService() { return accountingCycleCachingService; } /** * Sets the accountingCycleCachingService attribute value. * @param accountingCycleCachingService The accountingCycleCachingService to set. */ public void setAccountingCycleCachingService(AccountingCycleCachingService accountingCycleCachingService) { this.accountingCycleCachingService = accountingCycleCachingService; } }