/* * 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.sys.service.impl; import static org.kuali.kfs.sys.KFSConstants.BALANCE_TYPE_ACTUAL; import static org.kuali.kfs.sys.KFSConstants.BLANK_SPACE; import static org.kuali.kfs.sys.KFSConstants.GL_CREDIT_CODE; import static org.kuali.kfs.sys.KFSConstants.GL_DEBIT_CODE; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.kuali.kfs.coa.businessobject.Account; import org.kuali.kfs.coa.businessobject.Chart; import org.kuali.kfs.coa.businessobject.ObjectCode; import org.kuali.kfs.coa.businessobject.OffsetDefinition; import org.kuali.kfs.coa.businessobject.SubAccount; import org.kuali.kfs.coa.businessobject.SubObjectCode; import org.kuali.kfs.coa.service.AccountService; import org.kuali.kfs.coa.service.BalanceTypeService; import org.kuali.kfs.coa.service.ChartService; 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.fp.businessobject.OffsetAccount; import org.kuali.kfs.gl.businessobject.Balance; import org.kuali.kfs.gl.businessobject.Encumbrance; import org.kuali.kfs.gl.service.SufficientFundsService; import org.kuali.kfs.gl.service.SufficientFundsServiceConstants; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.KFSKeyConstants; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.kfs.sys.businessobject.Bank; import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry; import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper; import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail; import org.kuali.kfs.sys.businessobject.SystemOptions; import org.kuali.kfs.sys.businessobject.UniversityDate; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.dataaccess.GeneralLedgerPendingEntryDao; import org.kuali.kfs.sys.document.GeneralLedgerPendingEntrySource; import org.kuali.kfs.sys.document.GeneralLedgerPostingDocument; import org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleBaseConstants; import org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE; import org.kuali.kfs.sys.service.FlexibleOffsetAccountService; import org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService; import org.kuali.kfs.sys.service.HomeOriginationService; import org.kuali.kfs.sys.service.OptionsService; import org.kuali.kfs.sys.service.UniversityDateService; import org.kuali.rice.core.api.datetime.DateTimeService; 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; import org.kuali.rice.krad.service.KualiRuleService; import org.kuali.rice.krad.service.PersistenceStructureService; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.ObjectUtils; import org.springframework.transaction.annotation.Transactional; /** * This class is the service implementation for the GeneralLedgerPendingEntry structure. This is the default implementation, that is * delivered with Kuali. */ @Transactional public class GeneralLedgerPendingEntryServiceImpl implements GeneralLedgerPendingEntryService { private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(GeneralLedgerPendingEntryServiceImpl.class); protected GeneralLedgerPendingEntryDao generalLedgerPendingEntryDao; protected KualiRuleService kualiRuleService; protected ChartService chartService; protected OptionsService optionsService; protected ParameterService parameterService; protected BalanceTypeService balanceTypeService; protected DateTimeService dateTimeService; protected DataDictionaryService dataDictionaryService; protected PersistenceStructureService persistenceStructureService; protected UniversityDateService universityDateService; protected AccountService accountService; protected SufficientFundsService sufficientFundsService; protected FlexibleOffsetAccountService flexibleOffsetAccountService; protected OffsetDefinitionService offsetDefinitionService; protected ObjectTypeService objectTypeService; /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getExpenseSummary(java.util.List, java.lang.String, * java.lang.String, boolean, boolean) */ @Override public KualiDecimal getExpenseSummary(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, String sufficientFundsObjectCode, boolean isDebit, boolean isYearEnd) { LOG.debug("getExpenseSummary() started"); ObjectTypeService objectTypeService = getObjectTypeService(); List<String> objectTypes = objectTypeService.getExpenseObjectTypes(universityFiscalYear); // FIXME! - cache this list - balance type code will not change during the lifetime of the server SystemOptions options = optionsService.getOptions(universityFiscalYear); Collection balanceTypeCodes = new ArrayList(); balanceTypeCodes.add(options.getActualFinancialBalanceTypeCd()); return generalLedgerPendingEntryDao.getTransactionSummary(universityFiscalYear, chartOfAccountsCode, accountNumber, objectTypes, balanceTypeCodes, sufficientFundsObjectCode, isDebit, isYearEnd); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getEncumbranceSummary(java.lang.Integer, java.lang.String, * java.lang.String, java.lang.String, boolean, boolean) */ @Override public KualiDecimal getEncumbranceSummary(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, String sufficientFundsObjectCode, boolean isDebit, boolean isYearEnd) { LOG.debug("getEncumbranceSummary() started"); // FIXME! - this ObjectTypeService should be injected ObjectTypeService objectTypeService = getObjectTypeService(); List<String> objectTypes = objectTypeService.getExpenseObjectTypes(universityFiscalYear); SystemOptions options = optionsService.getOptions(universityFiscalYear); // FIXME! - cache this list - balance type code will not change during the lifetime of the server List<String> balanceTypeCodes = balanceTypeService.getEncumbranceBalanceTypes(universityFiscalYear); return generalLedgerPendingEntryDao.getTransactionSummary(universityFiscalYear, chartOfAccountsCode, accountNumber, objectTypes, balanceTypeCodes, sufficientFundsObjectCode, isDebit, isYearEnd); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getBudgetSummary(java.lang.Integer, java.lang.String, * java.lang.String, java.lang.String, boolean) */ @Override public KualiDecimal getBudgetSummary(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, String sufficientFundsObjectCode, boolean isYearEnd) { LOG.debug("getBudgetSummary() started"); ObjectTypeService objectTypeService = getObjectTypeService(); List<String> objectTypes = objectTypeService.getExpenseObjectTypes(universityFiscalYear); SystemOptions options = optionsService.getOptions(universityFiscalYear); // FIXME! - cache this list - balance type code will not change during the lifetime of the server Collection balanceTypeCodes = new ArrayList(); balanceTypeCodes.add(options.getBudgetCheckingBalanceTypeCd()); return generalLedgerPendingEntryDao.getTransactionSummary(universityFiscalYear, chartOfAccountsCode, accountNumber, objectTypes, balanceTypeCodes, sufficientFundsObjectCode, isYearEnd); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getCashSummary(java.util.Collection, java.lang.String, * java.lang.String, boolean) */ @Override public KualiDecimal getCashSummary(List universityFiscalYears, String chartOfAccountsCode, String accountNumber, boolean isDebit) { LOG.debug("getCashSummary() started"); Chart c = chartService.getByPrimaryId(chartOfAccountsCode); // Note, we are getting the options from the first fiscal year in the list. We are assuming that the // balance type code for actual is the same in all the years in the list. SystemOptions options = optionsService.getOptions((Integer) universityFiscalYears.get(0)); // FIXME! - cache this list - will not change during the lifetime of the server Collection objectCodes = new ArrayList(); objectCodes.add(c.getFinancialCashObjectCode()); // FIXME! - cache this list - balance type code will not change during the lifetime of the server Collection balanceTypeCodes = new ArrayList(); balanceTypeCodes.add(options.getActualFinancialBalanceTypeCd()); return generalLedgerPendingEntryDao.getTransactionSummary(universityFiscalYears, chartOfAccountsCode, accountNumber, objectCodes, balanceTypeCodes, isDebit); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getActualSummary(java.util.List, java.lang.String, * java.lang.String, boolean) */ @Override public KualiDecimal getActualSummary(List universityFiscalYears, String chartOfAccountsCode, String accountNumber, boolean isDebit) { LOG.debug("getActualSummary() started"); List<String> codes = new ArrayList<String>( parameterService.getParameterValuesAsString(KfsParameterConstants.FINANCIAL_SYSTEM_ALL.class, SufficientFundsServiceConstants.SUFFICIENT_FUNDS_OBJECT_CODE_SPECIALS) ); // Note, we are getting the options from the first fiscal year in the list. We are assuming that the // balance type code for actual is the same in all the years in the list. SystemOptions options = optionsService.getOptions((Integer) universityFiscalYears.get(0)); // FIXME! - cache this list - balance type code will not change during the lifetime of the server Collection balanceTypeCodes = new ArrayList(); balanceTypeCodes.add(options.getActualFinancialBalanceTypeCd()); return generalLedgerPendingEntryDao.getTransactionSummary(universityFiscalYears, chartOfAccountsCode, accountNumber, codes, balanceTypeCodes, isDebit); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getByPrimaryId(java.lang.Integer, java.lang.String) */ @Override public GeneralLedgerPendingEntry getByPrimaryId(Integer transactionEntrySequenceId, String documentHeaderId) { LOG.debug("getByPrimaryId() started"); Map<String, Object> keys = new HashMap<String, Object>(); keys.put(KFSPropertyConstants.DOCUMENT_NUMBER, documentHeaderId); keys.put("transactionLedgerEntrySequenceNumber", transactionEntrySequenceId); return SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(GeneralLedgerPendingEntry.class, keys); } @Override public void fillInFiscalPeriodYear(GeneralLedgerPendingEntry glpe) { LOG.debug("fillInFiscalPeriodYear() started"); // TODO Handle year end documents if ((glpe.getUniversityFiscalPeriodCode() == null) || (glpe.getUniversityFiscalYear() == null)) { UniversityDate ud = universityDateService.getCurrentUniversityDate(); glpe.setUniversityFiscalYear(ud.getUniversityFiscalYear()); glpe.setUniversityFiscalPeriodCode(ud.getUniversityFiscalAccountingPeriod()); } } /** * Invokes generateEntries method on the financial document. * * @param document - document whose pending entries need generated * @return whether the business rules succeeded */ @Override public boolean generateGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySource glpeSource) { boolean success = true; // we must clear them first before creating new ones glpeSource.clearAnyGeneralLedgerPendingEntries(); if (LOG.isDebugEnabled()) { LOG.debug("deleting existing gl pending ledger entries for document " + glpeSource.getDocumentHeader().getDocumentNumber()); } delete(glpeSource.getDocumentHeader().getDocumentNumber()); if (LOG.isDebugEnabled()) { LOG.debug("generating gl pending ledger entries for document " + glpeSource.getDocumentHeader().getDocumentNumber()); } GeneralLedgerPendingEntrySequenceHelper sequenceHelper = new GeneralLedgerPendingEntrySequenceHelper(); for (GeneralLedgerPendingEntrySourceDetail glpeSourceDetail : glpeSource.getGeneralLedgerPendingEntrySourceDetails()) { success &= glpeSource.generateGeneralLedgerPendingEntries(glpeSourceDetail, sequenceHelper); sequenceHelper.increment(); } // doc specific pending entries generation success &= glpeSource.generateDocumentGeneralLedgerPendingEntries(sequenceHelper); return success; } /** * This populates an empty GeneralLedgerPendingEntry explicitEntry object instance with default values. * * @param accountingDocument * @param accountingLine * @param sequenceHelper * @param explicitEntry */ @Override public void populateExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySource glpeSource, GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntry explicitEntry) { if (LOG.isDebugEnabled()) { LOG.debug("populateExplicitGeneralLedgerPendingEntry(AccountingDocument, AccountingLine, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - start"); } explicitEntry.setFinancialDocumentTypeCode(glpeSource.getFinancialDocumentTypeCode()); explicitEntry.setVersionNumber(new Long(1)); explicitEntry.setTransactionLedgerEntrySequenceNumber(new Integer(sequenceHelper.getSequenceCounter())); Timestamp transactionTimestamp = new Timestamp(dateTimeService.getCurrentDate().getTime()); explicitEntry.setTransactionDate(new java.sql.Date(transactionTimestamp.getTime())); explicitEntry.setTransactionEntryProcessedTs(transactionTimestamp); explicitEntry.setAccountNumber(glpeSourceDetail.getAccountNumber()); Account account = getAccountService().getByPrimaryIdWithCaching(glpeSourceDetail.getChartOfAccountsCode(), glpeSourceDetail.getAccountNumber()); ObjectCode objectCode = SpringContext.getBean(ObjectCodeService.class).getByPrimaryIdWithCaching( glpeSource.getPostingYear(), glpeSourceDetail.getChartOfAccountsCode(), glpeSourceDetail.getFinancialObjectCode()); if ( account != null ) { if ( LOG.isDebugEnabled() ) { LOG.debug("GLPE: Testing to see what should be used for SF Object Code: " + glpeSourceDetail ); } String sufficientFundsCode = account.getAccountSufficientFundsCode(); if (StringUtils.isBlank(sufficientFundsCode)) { sufficientFundsCode = KFSConstants.SF_TYPE_NO_CHECKING; if ( LOG.isDebugEnabled() ) { LOG.debug("Code was blank on the account - using 'N'"); } } if (objectCode != null) { if ( LOG.isDebugEnabled() ) { LOG.debug("SF Code / Object: " + sufficientFundsCode + " / " + objectCode); } String sifficientFundsObjectCode = getSufficientFundsService().getSufficientFundsObjectCode(objectCode, sufficientFundsCode); explicitEntry.setAcctSufficientFundsFinObjCd(sifficientFundsObjectCode); } else { LOG.debug( "Object code object was null, skipping setting of SF object field." ); } } if ( objectCode != null ) { explicitEntry.setFinancialObjectTypeCode(objectCode.getFinancialObjectTypeCode()); } explicitEntry.setFinancialDocumentApprovedCode(KFSConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.NOT_PROCESSED); explicitEntry.setTransactionEncumbranceUpdateCode(BLANK_SPACE); explicitEntry.setFinancialBalanceTypeCode(BALANCE_TYPE_ACTUAL); // this is the default that most documents use explicitEntry.setChartOfAccountsCode(glpeSourceDetail.getChartOfAccountsCode()); explicitEntry.setTransactionDebitCreditCode(glpeSource.isDebit(glpeSourceDetail) ? KFSConstants.GL_DEBIT_CODE : KFSConstants.GL_CREDIT_CODE); explicitEntry.setFinancialSystemOriginationCode(SpringContext.getBean(HomeOriginationService.class).getHomeOrigination().getFinSystemHomeOriginationCode()); explicitEntry.setDocumentNumber(glpeSourceDetail.getDocumentNumber()); explicitEntry.setFinancialObjectCode(glpeSourceDetail.getFinancialObjectCode()); explicitEntry.setOrganizationDocumentNumber(glpeSource.getDocumentHeader().getOrganizationDocumentNumber()); explicitEntry.setOrganizationReferenceId(glpeSourceDetail.getOrganizationReferenceId()); explicitEntry.setProjectCode(getEntryValue(glpeSourceDetail.getProjectCode(), GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankProjectCode())); explicitEntry.setReferenceFinancialDocumentNumber(getEntryValue(glpeSourceDetail.getReferenceNumber(), BLANK_SPACE)); explicitEntry.setReferenceFinancialDocumentTypeCode(getEntryValue(glpeSourceDetail.getReferenceTypeCode(), BLANK_SPACE)); explicitEntry.setReferenceFinancialSystemOriginationCode(getEntryValue(glpeSourceDetail.getReferenceOriginCode(), BLANK_SPACE)); explicitEntry.setSubAccountNumber(getEntryValue(glpeSourceDetail.getSubAccountNumber(), GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankSubAccountNumber())); explicitEntry.setFinancialSubObjectCode(getEntryValue(glpeSourceDetail.getFinancialSubObjectCode(), GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialSubObjectCode())); explicitEntry.setTransactionEntryOffsetIndicator(false); explicitEntry.setTransactionLedgerEntryAmount(glpeSource.getGeneralLedgerPendingEntryAmountForDetail(glpeSourceDetail)); explicitEntry.setTransactionLedgerEntryDescription(getEntryValue(glpeSourceDetail.getFinancialDocumentLineDescription(), glpeSource.getDocumentHeader().getDocumentDescription())); explicitEntry.setUniversityFiscalPeriodCode(null); // null here, is assigned during batch or in specific document rule // classes explicitEntry.setUniversityFiscalYear(glpeSource.getPostingYear()); // TODO wait for core budget year data structures to be put in place // explicitEntry.setBudgetYear(accountingLine.getBudgetYear()); // explicitEntry.setBudgetYearFundingSourceCode(budgetYearFundingSourceCode); if (LOG.isDebugEnabled()) { LOG.debug("populateExplicitGeneralLedgerPendingEntry(AccountingDocument, AccountingLine, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - end"); } } /** * Convenience method to build a GLPE without a generalLedgerPendingEntrySourceDetail * * @param document a GeneralLedgerPostingDocument * @param account the account for use in the GLPE * @param objectCode the object code for use in the GLPE * @param subAccountNumber the sub account number for use in the GLPE * @param subObjectCode the subobject code for use in the GLPE * @param organizationReferenceId the organization reference id to use in the GLPE * @param projectCode the project code to use in the GLPE * @param referenceNumber the reference number to use in the GLPE * @param referenceTypeCode the reference type code to use in the GLPE * @param referenceOriginCode the reference origin code to use in the GLPE * @param description the description to put in the GLPE * @param isDebit true if the GLPE represents a debit, false if it represents a credit * @param amount the amount of the GLPE * @param sequenceHelper the sequence helper to use * @return a populated general ledger pending entry */ @Override public GeneralLedgerPendingEntry buildGeneralLedgerPendingEntry(GeneralLedgerPostingDocument document, Account account, ObjectCode objectCode, String subAccountNumber, String subObjectCode, String organizationReferenceId, String projectCode, String referenceNumber, String referenceTypeCode, String referenceOriginCode, String description, boolean isDebit, KualiDecimal amount, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) { if (LOG.isDebugEnabled()) { LOG.debug("populateExplicitGeneralLedgerPendingEntry(AccountingDocument, AccountingLine, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - start"); } GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry(); explicitEntry.setFinancialDocumentTypeCode(document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName()); explicitEntry.setVersionNumber(new Long(1)); explicitEntry.setTransactionLedgerEntrySequenceNumber(new Integer(sequenceHelper.getSequenceCounter())); Timestamp transactionTimestamp = new Timestamp(dateTimeService.getCurrentDate().getTime()); explicitEntry.setTransactionDate(new java.sql.Date(transactionTimestamp.getTime())); explicitEntry.setTransactionEntryProcessedTs(transactionTimestamp); explicitEntry.setAccountNumber(account.getAccountNumber()); if (account.getAccountSufficientFundsCode() == null) { account.setAccountSufficientFundsCode(KFSConstants.SF_TYPE_NO_CHECKING); } // FIXME! - inject the sufficient funds service explicitEntry.setAcctSufficientFundsFinObjCd(getSufficientFundsService().getSufficientFundsObjectCode(objectCode, account.getAccountSufficientFundsCode())); explicitEntry.setFinancialDocumentApprovedCode(KFSConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.NOT_PROCESSED); explicitEntry.setTransactionEncumbranceUpdateCode(BLANK_SPACE); explicitEntry.setFinancialBalanceTypeCode(BALANCE_TYPE_ACTUAL); // this is the default that most documents use explicitEntry.setChartOfAccountsCode(account.getChartOfAccountsCode()); explicitEntry.setTransactionDebitCreditCode(isDebit ? KFSConstants.GL_DEBIT_CODE : KFSConstants.GL_CREDIT_CODE); // FIXME! - Home origination service should be injected and the result cached - this value never changes explicitEntry.setFinancialSystemOriginationCode(SpringContext.getBean(HomeOriginationService.class).getHomeOrigination().getFinSystemHomeOriginationCode()); explicitEntry.setDocumentNumber(document.getDocumentNumber()); explicitEntry.setFinancialObjectCode(objectCode.getFinancialObjectCode()); explicitEntry.setFinancialObjectTypeCode(objectCode.getFinancialObjectTypeCode()); explicitEntry.setOrganizationDocumentNumber(document.getDocumentHeader().getOrganizationDocumentNumber()); explicitEntry.setOrganizationReferenceId(organizationReferenceId); explicitEntry.setProjectCode(getEntryValue(projectCode, GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankProjectCode())); explicitEntry.setReferenceFinancialDocumentNumber(getEntryValue(referenceNumber, BLANK_SPACE)); explicitEntry.setReferenceFinancialDocumentTypeCode(getEntryValue(referenceTypeCode, BLANK_SPACE)); explicitEntry.setReferenceFinancialSystemOriginationCode(getEntryValue(referenceOriginCode, BLANK_SPACE)); explicitEntry.setSubAccountNumber(getEntryValue(subAccountNumber, GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankSubAccountNumber())); explicitEntry.setFinancialSubObjectCode(getEntryValue(subObjectCode, GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialSubObjectCode())); explicitEntry.setTransactionEntryOffsetIndicator(false); explicitEntry.setTransactionLedgerEntryAmount(amount); explicitEntry.setTransactionLedgerEntryDescription(getEntryValue(description, document.getDocumentHeader().getDocumentDescription())); explicitEntry.setUniversityFiscalPeriodCode(null); // null here, is assigned during batch or in specific document rule // classes explicitEntry.setUniversityFiscalYear(document.getPostingYear()); if (LOG.isDebugEnabled()) { LOG.debug("populateExplicitGeneralLedgerPendingEntry(AccountingDocument, AccountingLine, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - end"); } return explicitEntry; } /** * This populates an GeneralLedgerPendingEntry offsetEntry object instance with values that differ from the values supplied in * the explicit entry that it was cloned from. Note that the entries do not contain BOs now. * * @param universityFiscalYear * @param explicitEntry * @param sequenceHelper * @param offsetEntry Cloned from the explicit entry * @return whether the offset generation is successful */ @Override public boolean populateOffsetGeneralLedgerPendingEntry(Integer universityFiscalYear, GeneralLedgerPendingEntry explicitEntry, GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntry offsetEntry) { LOG.debug("populateOffsetGeneralLedgerPendingEntry(Integer, GeneralLedgerPendingEntry, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - start"); boolean success = true; // lookup offset object info OffsetDefinition offsetDefinition = getOffsetDefinitionService().getByPrimaryId(universityFiscalYear, explicitEntry.getChartOfAccountsCode(), explicitEntry.getFinancialDocumentTypeCode(), explicitEntry.getFinancialBalanceTypeCode()); if (ObjectUtils.isNull(offsetDefinition)) { success = false; GlobalVariables.getMessageMap().putError(KFSConstants.GENERAL_LEDGER_PENDING_ENTRIES_TAB_ERRORS, KFSKeyConstants.ERROR_DOCUMENT_NO_OFFSET_DEFINITION, universityFiscalYear.toString(), explicitEntry.getChartOfAccountsCode(), explicitEntry.getFinancialDocumentTypeCode(), explicitEntry.getFinancialBalanceTypeCode()); } else { OffsetAccount flexibleOffsetAccount = getFlexibleOffsetAccountService().getByPrimaryIdIfEnabled(explicitEntry.getChartOfAccountsCode(), explicitEntry.getAccountNumber(), getOffsetFinancialObjectCode(offsetDefinition)); flexOffsetAccountIfNecessary(flexibleOffsetAccount, offsetEntry); } // update offset entry fields that are different from the explicit entry that it was created from offsetEntry.setTransactionLedgerEntrySequenceNumber(new Integer(sequenceHelper.getSequenceCounter())); offsetEntry.setTransactionDebitCreditCode(getOffsetEntryDebitCreditCode(explicitEntry)); String offsetObjectCode = getOffsetFinancialObjectCode(offsetDefinition); offsetEntry.setFinancialObjectCode(offsetObjectCode); if (offsetObjectCode.equals(AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode())) { // no BO, so punt offsetEntry.setAcctSufficientFundsFinObjCd(AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode()); } else { // Need current ObjectCode and Account BOs to get sufficient funds code. (Entries originally have no BOs.) // todo: private or other methods to get these BOs, instead of using the entry and leaving some BOs filled in? offsetEntry.refreshReferenceObject(KFSPropertyConstants.FINANCIAL_OBJECT); offsetEntry.refreshReferenceObject(KFSPropertyConstants.ACCOUNT); ObjectCode financialObject = offsetEntry.getFinancialObject(); // The ObjectCode reference may be invalid because a flexible offset account changed its chart code. if (ObjectUtils.isNull(financialObject)) { throw new RuntimeException("offset object code " + offsetEntry.getUniversityFiscalYear() + "-" + offsetEntry.getChartOfAccountsCode() + "-" + offsetEntry.getFinancialObjectCode()); } Account account = getAccountService().getByPrimaryId(offsetEntry.getChartOfAccountsCode(), offsetEntry.getAccountNumber()); if ( account != null ) { offsetEntry.setAcctSufficientFundsFinObjCd(getSufficientFundsService().getSufficientFundsObjectCode(financialObject, account.getAccountSufficientFundsCode())); } } offsetEntry.setFinancialObjectTypeCode(getOffsetFinancialObjectTypeCode(offsetDefinition)); offsetEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode()); offsetEntry.setTransactionEntryOffsetIndicator(true); offsetEntry.setTransactionLedgerEntryDescription(KFSConstants.GL_PE_OFFSET_STRING); offsetEntry.setFinancialSystemOriginationCode(explicitEntry.getFinancialSystemOriginationCode()); LOG.debug("populateOffsetGeneralLedgerPendingEntry(Integer, GeneralLedgerPendingEntry, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - end"); return success; } /** * Applies the given flexible offset account to the given offset entry. Does nothing if flexibleOffsetAccount is null or its COA * and account number are the same as the offset entry's. * * @param flexibleOffsetAccount may be null * @param offsetEntry may be modified */ protected void flexOffsetAccountIfNecessary(OffsetAccount flexibleOffsetAccount, GeneralLedgerPendingEntry offsetEntry) { LOG.debug("flexOffsetAccountIfNecessary(OffsetAccount, GeneralLedgerPendingEntry) - start"); if (flexibleOffsetAccount == null) { LOG.debug("flexOffsetAccountIfNecessary(OffsetAccount, GeneralLedgerPendingEntry) - end"); return; // They are not required and may also be disabled. } String flexCoa = flexibleOffsetAccount.getFinancialOffsetChartOfAccountCode(); String flexAccountNumber = flexibleOffsetAccount.getFinancialOffsetAccountNumber(); if (flexCoa.equals(offsetEntry.getChartOfAccountsCode()) && flexAccountNumber.equals(offsetEntry.getAccountNumber())) { LOG.debug("flexOffsetAccountIfNecessary(OffsetAccount, GeneralLedgerPendingEntry) - end"); return; // no change, so leave sub-account as is } if (ObjectUtils.isNull(flexibleOffsetAccount.getFinancialOffsetAccount())) { throw new RuntimeException("flexible offset account " + flexCoa + "-" + flexAccountNumber); } offsetEntry.setChartOfAccountsCode(flexCoa); offsetEntry.setAccountNumber(flexAccountNumber); // COA and account number are part of the sub-account's key, so the original sub-account would be invalid. offsetEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber()); LOG.debug("flexOffsetAccountIfNecessary(OffsetAccount, GeneralLedgerPendingEntry) - end"); } /** * Helper method that determines the offset entry's financial object type code. * * @param offsetDefinition * @return String */ protected String getOffsetFinancialObjectTypeCode(OffsetDefinition offsetDefinition) { LOG.debug("getOffsetFinancialObjectTypeCode(OffsetDefinition) - start"); if (null != offsetDefinition && null != offsetDefinition.getFinancialObject()) { String returnString = getEntryValue(offsetDefinition.getFinancialObject().getFinancialObjectTypeCode(), AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectType()); LOG.debug("getOffsetFinancialObjectTypeCode(OffsetDefinition) - end"); return returnString; } else { LOG.debug("getOffsetFinancialObjectTypeCode(OffsetDefinition) - end"); return AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectType(); } } /** * Helper method that determines the debit/credit code for the offset entry. If the explicit was a debit, the offset is a * credit. Otherwise, it's opposite. * * @param explicitEntry * @return String */ protected String getOffsetEntryDebitCreditCode(GeneralLedgerPendingEntry explicitEntry) { LOG.debug("getOffsetEntryDebitCreditCode(GeneralLedgerPendingEntry) - start"); String offsetDebitCreditCode = KFSConstants.GL_BUDGET_CODE; if (KFSConstants.GL_DEBIT_CODE.equals(explicitEntry.getTransactionDebitCreditCode())) { offsetDebitCreditCode = KFSConstants.GL_CREDIT_CODE; } else if (KFSConstants.GL_CREDIT_CODE.equals(explicitEntry.getTransactionDebitCreditCode())) { offsetDebitCreditCode = KFSConstants.GL_DEBIT_CODE; } LOG.debug("getOffsetEntryDebitCreditCode(GeneralLedgerPendingEntry) - end"); return offsetDebitCreditCode; } /** * Helper method that determines the offset entry's financial object code. * * @param offsetDefinition * @return String */ protected String getOffsetFinancialObjectCode(OffsetDefinition offsetDefinition) { LOG.debug("getOffsetFinancialObjectCode(OffsetDefinition) - start"); if (null != offsetDefinition) { String returnString = getEntryValue(offsetDefinition.getFinancialObjectCode(), AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode()); LOG.debug("getOffsetFinancialObjectCode(OffsetDefinition) - end"); return returnString; } else { LOG.debug("getOffsetFinancialObjectCode(OffsetDefinition) - end"); return AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode(); } } /** * This populates an empty GeneralLedgerPendingEntry instance with default values for a bank offset. A global error will be * posted as a side-effect if the given bank has not defined the necessary bank offset relations. * * @param bank * @param depositAmount * @param financialDocument * @param universityFiscalYear * @param sequenceHelper * @param bankOffsetEntry * @param errorPropertyName * @return whether the entry was populated successfully */ @Override public boolean populateBankOffsetGeneralLedgerPendingEntry(Bank bank, KualiDecimal depositAmount, GeneralLedgerPostingDocument financialDocument, Integer universityFiscalYear, GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntry bankOffsetEntry, String errorPropertyName) { bankOffsetEntry.setFinancialDocumentTypeCode(dataDictionaryService.getDocumentTypeNameByClass(financialDocument.getClass())); bankOffsetEntry.setVersionNumber(1L); bankOffsetEntry.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter()); Timestamp transactionTimestamp = new Timestamp(dateTimeService.getCurrentDate().getTime()); bankOffsetEntry.setTransactionDate(new java.sql.Date(transactionTimestamp.getTime())); bankOffsetEntry.setTransactionEntryProcessedTs(transactionTimestamp); Account cashOffsetAccount = bank.getCashOffsetAccount(); if (ObjectUtils.isNull(cashOffsetAccount)) { GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_NO_ACCOUNT, new String[] { bank.getBankCode() }); return false; } if (!cashOffsetAccount.isActive()) { GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_ACCOUNT_CLOSED, new String[] { bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber() }); return false; } if (cashOffsetAccount.isExpired()) { GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_ACCOUNT_EXPIRED, new String[] { bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber() }); return false; } bankOffsetEntry.setChartOfAccountsCode(bank.getCashOffsetFinancialChartOfAccountCode()); bankOffsetEntry.setAccountNumber(bank.getCashOffsetAccountNumber()); bankOffsetEntry.setFinancialDocumentApprovedCode(AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.NO); bankOffsetEntry.setTransactionEncumbranceUpdateCode(BLANK_SPACE); bankOffsetEntry.setFinancialBalanceTypeCode(BALANCE_TYPE_ACTUAL); bankOffsetEntry.setTransactionDebitCreditCode(depositAmount.isPositive() ? GL_DEBIT_CODE : GL_CREDIT_CODE); bankOffsetEntry.setFinancialSystemOriginationCode(SpringContext.getBean(HomeOriginationService.class).getHomeOrigination().getFinSystemHomeOriginationCode()); bankOffsetEntry.setDocumentNumber(financialDocument.getDocumentNumber()); ObjectCode cashOffsetObject = bank.getCashOffsetObject(); if (ObjectUtils.isNull(cashOffsetObject)) { GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_NO_OBJECT_CODE, new String[] { bank.getBankCode() }); return false; } if (!cashOffsetObject.isFinancialObjectActiveCode()) { GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_INACTIVE_OBJECT_CODE, new String[] { bank.getBankCode(), cashOffsetObject.getFinancialObjectCode() }); return false; } bankOffsetEntry.setFinancialObjectCode(bank.getCashOffsetObjectCode()); bankOffsetEntry.setFinancialObjectTypeCode(bank.getCashOffsetObject().getFinancialObjectTypeCode()); bankOffsetEntry.setOrganizationDocumentNumber(financialDocument.getDocumentHeader().getOrganizationDocumentNumber()); bankOffsetEntry.setOrganizationReferenceId(null); bankOffsetEntry.setProjectCode(KFSConstants.getDashProjectCode()); bankOffsetEntry.setReferenceFinancialDocumentNumber(null); bankOffsetEntry.setReferenceFinancialDocumentTypeCode(null); bankOffsetEntry.setReferenceFinancialSystemOriginationCode(null); if (StringUtils.isBlank(bank.getCashOffsetSubAccountNumber())) { bankOffsetEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber()); } else { SubAccount cashOffsetSubAccount = bank.getCashOffsetSubAccount(); if (ObjectUtils.isNull(cashOffsetSubAccount)) { GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_NONEXISTENT_SUB_ACCOUNT, new String[] { bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber(), bank.getCashOffsetSubAccountNumber() }); return false; } if (!cashOffsetSubAccount.isActive()) { GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_INACTIVE_SUB_ACCOUNT, new String[] { bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber(), bank.getCashOffsetSubAccountNumber() }); return false; } bankOffsetEntry.setSubAccountNumber(bank.getCashOffsetSubAccountNumber()); } if (StringUtils.isBlank(bank.getCashOffsetSubObjectCode())) { bankOffsetEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode()); } else { SubObjectCode cashOffsetSubObject = bank.getCashOffsetSubObject(); if (ObjectUtils.isNull(cashOffsetSubObject)) { GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_NONEXISTENT_SUB_OBJ, new String[] { bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber(), cashOffsetObject.getFinancialObjectCode(), bank.getCashOffsetSubObjectCode() }); return false; } if (!cashOffsetSubObject.isActive()) { GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_INACTIVE_SUB_OBJ, new String[] { bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber(), cashOffsetObject.getFinancialObjectCode(), bank.getCashOffsetSubObjectCode() }); return false; } bankOffsetEntry.setFinancialSubObjectCode(bank.getCashOffsetSubObjectCode()); } bankOffsetEntry.setTransactionEntryOffsetIndicator(true); bankOffsetEntry.setTransactionLedgerEntryAmount(depositAmount.abs()); bankOffsetEntry.setUniversityFiscalPeriodCode(null); // null here, is assigned during batch or in specific document rule bankOffsetEntry.setUniversityFiscalYear(universityFiscalYear); bankOffsetEntry.setAcctSufficientFundsFinObjCd(getSufficientFundsService().getSufficientFundsObjectCode(cashOffsetObject, cashOffsetAccount.getAccountSufficientFundsCode())); return true; } /** * @see org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService#save(org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry) */ @Override public void save(GeneralLedgerPendingEntry generalLedgerPendingEntry) { LOG.debug("save() started"); SpringContext.getBean(BusinessObjectService.class).save(generalLedgerPendingEntry); } @Override public void delete(String documentHeaderId) { LOG.debug("delete() started"); this.generalLedgerPendingEntryDao.delete(documentHeaderId); } @Override public void deleteByFinancialDocumentApprovedCode(String financialDocumentApprovedCode) { LOG.debug("deleteByFinancialDocumentApprovedCode() started"); this.generalLedgerPendingEntryDao.deleteByFinancialDocumentApprovedCode(financialDocumentApprovedCode); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findApprovedPendingLedgerEntries() */ @Override public Iterator findApprovedPendingLedgerEntries() { LOG.debug("findApprovedPendingLedgerEntries() started"); return generalLedgerPendingEntryDao.findApprovedPendingLedgerEntries(); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntries(org.kuali.kfs.gl.businessobject.Encumbrance, * boolean) */ @Override public Iterator findPendingLedgerEntries(Encumbrance encumbrance, boolean isApproved) { LOG.debug("findPendingLedgerEntries() started"); return generalLedgerPendingEntryDao.findPendingLedgerEntries(encumbrance, isApproved); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#hasPendingGeneralLedgerEntry(org.kuali.kfs.coa.businessobject.Account) */ @Override public boolean hasPendingGeneralLedgerEntry(Account account) { LOG.debug("hasPendingGeneralLedgerEntry() started"); return generalLedgerPendingEntryDao.countPendingLedgerEntries(account) > 0; } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntries(Balance, boolean, boolean) */ @Override public Iterator findPendingLedgerEntries(Balance balance, boolean isApproved, boolean isConsolidated) { LOG.debug("findPendingLedgerEntries() started"); return generalLedgerPendingEntryDao.findPendingLedgerEntries(balance, isApproved, isConsolidated); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntriesForEntry(java.util.Map, boolean) */ @Override public Iterator findPendingLedgerEntriesForEntry(Map fieldValues, boolean isApproved) { LOG.debug("findPendingLedgerEntriesForEntry() started"); UniversityDate currentUniversityDate = universityDateService.getCurrentUniversityDate(); String currentFiscalPeriodCode = currentUniversityDate.getUniversityFiscalAccountingPeriod(); Integer currentFiscalYear = currentUniversityDate.getUniversityFiscalYear(); List<String> encumbranceBalanceTypes = getEncumbranceBalanceTypes(fieldValues, currentFiscalYear); return generalLedgerPendingEntryDao.findPendingLedgerEntriesForEntry(fieldValues, isApproved, currentFiscalPeriodCode, currentFiscalYear, encumbranceBalanceTypes); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntriesForEncumbrance(Map, boolean) */ @Override public Iterator findPendingLedgerEntriesForEncumbrance(Map fieldValues, boolean isApproved) { LOG.debug("findPendingLedgerEntriesForEncumbrance() started"); UniversityDate currentUniversityDate = universityDateService.getCurrentUniversityDate(); String currentFiscalPeriodCode = currentUniversityDate.getUniversityFiscalAccountingPeriod(); Integer currentFiscalYear = currentUniversityDate.getUniversityFiscalYear(); SystemOptions currentYearOptions = optionsService.getCurrentYearOptions(); List<String> encumbranceBalanceTypes = getEncumbranceBalanceTypes(fieldValues, currentFiscalYear); return generalLedgerPendingEntryDao.findPendingLedgerEntriesForEncumbrance(fieldValues, isApproved, currentFiscalPeriodCode, currentFiscalYear, currentYearOptions, encumbranceBalanceTypes); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntriesForCashBalance(java.util.Map, * boolean) */ @Override public Iterator findPendingLedgerEntriesForCashBalance(Map fieldValues, boolean isApproved) { LOG.debug("findPendingLedgerEntriesForCashBalance() started"); UniversityDate currentUniversityDate = universityDateService.getCurrentUniversityDate(); String currentFiscalPeriodCode = currentUniversityDate.getUniversityFiscalAccountingPeriod(); Integer currentFiscalYear = currentUniversityDate.getUniversityFiscalYear(); List<String> encumbranceBalanceTypes = getEncumbranceBalanceTypes(fieldValues, currentFiscalYear); return generalLedgerPendingEntryDao.findPendingLedgerEntriesForCashBalance(fieldValues, isApproved, currentFiscalPeriodCode, currentFiscalYear, encumbranceBalanceTypes); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntriesForBalance(java.util.Map, boolean) */ @Override public Iterator findPendingLedgerEntriesForBalance(Map fieldValues, boolean isApproved) { LOG.debug("findPendingLedgerEntriesForBalance() started"); UniversityDate currentUniversityDate = universityDateService.getCurrentUniversityDate(); String currentFiscalPeriodCode = currentUniversityDate.getUniversityFiscalAccountingPeriod(); Integer currentFiscalYear = currentUniversityDate.getUniversityFiscalYear(); List<String> encumbranceBalanceTypes = getEncumbranceBalanceTypes(fieldValues, currentFiscalYear); return generalLedgerPendingEntryDao.findPendingLedgerEntriesForBalance(fieldValues, isApproved, currentFiscalPeriodCode, currentFiscalYear, encumbranceBalanceTypes); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntriesForAccountBalance(java.util.Map, * boolean, boolean) */ @Override public Iterator findPendingLedgerEntriesForAccountBalance(Map fieldValues, boolean isApproved) { LOG.debug("findPendingLedgerEntriesForAccountBalance() started"); UniversityDate currentUniversityDate = universityDateService.getCurrentUniversityDate(); String currentFiscalPeriodCode = currentUniversityDate.getUniversityFiscalAccountingPeriod(); Integer currentFiscalYear = currentUniversityDate.getUniversityFiscalYear(); List<String> encumbranceBalanceTypes = getEncumbranceBalanceTypes(fieldValues, currentFiscalYear); return generalLedgerPendingEntryDao.findPendingLedgerEntriesForAccountBalance(fieldValues, isApproved, currentFiscalPeriodCode, currentFiscalYear, encumbranceBalanceTypes); } /** * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntrySummaryForAccountBalance(java.util.Map, * boolean, boolean) */ @Override public Iterator findPendingLedgerEntrySummaryForAccountBalance(Map fieldValues, boolean isApproved) { LOG.debug("findPendingLedgerEntrySummaryForAccountBalance() started"); UniversityDate currentUniversityDate = universityDateService.getCurrentUniversityDate(); String currentFiscalPeriodCode = currentUniversityDate.getUniversityFiscalAccountingPeriod(); Integer currentFiscalYear = currentUniversityDate.getUniversityFiscalYear(); List<String> encumbranceBalanceTypes = getEncumbranceBalanceTypes(fieldValues, currentFiscalYear); return generalLedgerPendingEntryDao.findPendingLedgerEntrySummaryForAccountBalance(fieldValues, isApproved, currentFiscalPeriodCode, currentFiscalYear, encumbranceBalanceTypes); } @Override public Collection findPendingEntries(Map fieldValues, boolean isApproved) { LOG.debug("findPendingEntries() started"); UniversityDate currentUniversityDate = universityDateService.getCurrentUniversityDate(); String currentFiscalPeriodCode = currentUniversityDate.getUniversityFiscalAccountingPeriod(); Integer currentFiscalYear = currentUniversityDate.getUniversityFiscalYear(); List<String> encumbranceBalanceTypes = getEncumbranceBalanceTypes(fieldValues, currentFiscalYear); return generalLedgerPendingEntryDao.findPendingEntries(fieldValues, isApproved, currentFiscalPeriodCode, currentFiscalYear, encumbranceBalanceTypes); } /** * A helper method that checks the intended target value for null and empty strings. If the intended target value is not null or * an empty string, it returns that value, ohterwise, it returns a backup value. * * @param targetValue * @param backupValue * @return String */ protected final String getEntryValue(String targetValue, String backupValue) { LOG.debug("getEntryValue(String, String) - start"); if (StringUtils.isNotBlank(targetValue)) { LOG.debug("getEntryValue(String, String) - end"); return targetValue; } else { LOG.debug("getEntryValue(String, String) - end"); return backupValue; } } /** * Determines if the given GeneralLedgerPendingEntry represents offsets to cash * * @param generalLedgerPendingEntry the GeneralLedgerPendingEntry to check * @return true if the GeneralLedgerPendingEntry represents an offset to cash; false otherwise */ @Override public boolean isOffsetToCash(GeneralLedgerPendingEntry generalLedgerPendingEntry) { if (generalLedgerPendingEntry.isTransactionEntryOffsetIndicator()) { final Chart entryChart = chartService.getByPrimaryId(generalLedgerPendingEntry.getChartOfAccountsCode()); if (!ObjectUtils.isNull(entryChart)) { return (entryChart.getFinancialCashObjectCode().equals(generalLedgerPendingEntry.getFinancialObjectCode())); } } return false; } /** * Adds up the amounts of all cash to offset GeneralLedgerPendingEntry records on the given AccountingDocument * * @param glPostingDocument the accounting document total the offset to cash amount for * @return the offset to cash amount, where debited values have been subtracted and credited values have been added */ @Override public KualiDecimal getOffsetToCashAmount(GeneralLedgerPostingDocument glPostingDocument) { KualiDecimal total = KualiDecimal.ZERO; for (GeneralLedgerPendingEntry glpe : glPostingDocument.getGeneralLedgerPendingEntries()) { if (isOffsetToCash(glpe)) { if (glpe.getTransactionDebitCreditCode().equals(KFSConstants.GL_DEBIT_CODE)) { total = total.subtract(glpe.getTransactionLedgerEntryAmount()); } else if (glpe.getTransactionDebitCreditCode().equals(KFSConstants.GL_CREDIT_CODE)) { total = total.add(glpe.getTransactionLedgerEntryAmount()); } } } return total; } /** * @see org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService#getEncumbranceBalanceTypes(java.util.Map, java.lang.Integer) */ @Override public List<String> getEncumbranceBalanceTypes(Map fieldValues, Integer currentFiscalYear) { String fiscalYearFromForm = null; if (fieldValues.containsKey(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR)) { fiscalYearFromForm = (String) fieldValues.get(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR); } boolean includeNullFiscalYearInLookup = null != currentFiscalYear && currentFiscalYear.toString().equals(fiscalYearFromForm); // handle encumbrance balance type Map<String, Object> localFieldValues = new HashMap(); localFieldValues.putAll(fieldValues); if (includeNullFiscalYearInLookup) { localFieldValues.remove(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR); } // parse the fiscal year (it's not a required field on the lookup screens String universityFiscalYearStr = (String) localFieldValues.get(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR); if (StringUtils.isNotBlank(universityFiscalYearStr)) { Integer universityFiscalYear = new Integer(universityFiscalYearStr); return balanceTypeService.getEncumbranceBalanceTypes(universityFiscalYear); } else { return balanceTypeService.getCurrentYearEncumbranceBalanceTypes(); } } public void setBalanceTypeService(BalanceTypeService balanceTypeService) { this.balanceTypeService = balanceTypeService; } public void setChartService(ChartService chartService) { this.chartService = chartService; } public void setGeneralLedgerPendingEntryDao(GeneralLedgerPendingEntryDao generalLedgerPendingEntryDao) { this.generalLedgerPendingEntryDao = generalLedgerPendingEntryDao; } public void setParameterService(ParameterService parameterService) { this.parameterService = parameterService; } public void setKualiRuleService(KualiRuleService kualiRuleService) { this.kualiRuleService = kualiRuleService; } public void setOptionsService(OptionsService optionsService) { this.optionsService = optionsService; } /** * Sets the dateTimeService attribute value. * * @param dateTimeService The dateTimeService to set. */ public void setDateTimeService(DateTimeService dateTimeService) { this.dateTimeService = dateTimeService; } /** * Sets the dataDictionaryService attribute value. * * @param dataDictionaryService The dataDictionaryService to set. */ public void setDataDictionaryService(DataDictionaryService dataDictionaryService) { this.dataDictionaryService = dataDictionaryService; } /** * Gets the persistenceStructureService attribute. * * @return Returns the persistenceStructureService. */ public PersistenceStructureService getPersistenceStructureService() { return persistenceStructureService; } /** * Sets the persistenceStructureService attribute value. * * @param persistenceStructureService The persistenceStructureService to set. */ public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) { this.persistenceStructureService = persistenceStructureService; } /** * Sets the universityDateService. * * @param universityDateService */ public void setUniversityDateService(UniversityDateService universityDateService) { this.universityDateService = universityDateService; } public AccountService getAccountService() { return accountService; } public void setAccountService(AccountService accountService) { this.accountService = accountService; } public SufficientFundsService getSufficientFundsService() { return sufficientFundsService; } public void setSufficientFundsService(SufficientFundsService sufficientFundsService) { this.sufficientFundsService = sufficientFundsService; } public FlexibleOffsetAccountService getFlexibleOffsetAccountService() { return flexibleOffsetAccountService; } public void setFlexibleOffsetAccountService(FlexibleOffsetAccountService flexibleOffsetAccountService) { this.flexibleOffsetAccountService = flexibleOffsetAccountService; } public OffsetDefinitionService getOffsetDefinitionService() { return offsetDefinitionService; } public void setOffsetDefinitionService(OffsetDefinitionService offsetDefinitionService) { this.offsetDefinitionService = offsetDefinitionService; } public ObjectTypeService getObjectTypeService() { return objectTypeService; } public void setObjectTypeService(ObjectTypeService objectTypeService) { this.objectTypeService = objectTypeService; } }