001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.sys.service.impl; 017 018 import static org.kuali.kfs.sys.KFSConstants.BALANCE_TYPE_ACTUAL; 019 import static org.kuali.kfs.sys.KFSConstants.BLANK_SPACE; 020 import static org.kuali.kfs.sys.KFSConstants.GL_CREDIT_CODE; 021 import static org.kuali.kfs.sys.KFSConstants.GL_DEBIT_CODE; 022 023 import java.sql.Timestamp; 024 import java.util.ArrayList; 025 import java.util.Collection; 026 import java.util.Iterator; 027 import java.util.List; 028 import java.util.Map; 029 030 import org.apache.commons.lang.StringUtils; 031 import org.kuali.kfs.coa.businessobject.Account; 032 import org.kuali.kfs.coa.businessobject.Chart; 033 import org.kuali.kfs.coa.businessobject.ObjectCode; 034 import org.kuali.kfs.coa.businessobject.OffsetDefinition; 035 import org.kuali.kfs.coa.businessobject.SubAccount; 036 import org.kuali.kfs.coa.businessobject.SubObjectCode; 037 import org.kuali.kfs.coa.service.BalanceTypeService; 038 import org.kuali.kfs.coa.service.ChartService; 039 import org.kuali.kfs.coa.service.ObjectTypeService; 040 import org.kuali.kfs.coa.service.OffsetDefinitionService; 041 import org.kuali.kfs.fp.businessobject.OffsetAccount; 042 import org.kuali.kfs.gl.businessobject.Balance; 043 import org.kuali.kfs.gl.businessobject.Encumbrance; 044 import org.kuali.kfs.gl.service.SufficientFundsService; 045 import org.kuali.kfs.gl.service.SufficientFundsServiceConstants; 046 import org.kuali.kfs.sys.KFSConstants; 047 import org.kuali.kfs.sys.KFSKeyConstants; 048 import org.kuali.kfs.sys.KFSPropertyConstants; 049 import org.kuali.kfs.sys.businessobject.Bank; 050 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry; 051 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper; 052 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail; 053 import org.kuali.kfs.sys.businessobject.SystemOptions; 054 import org.kuali.kfs.sys.businessobject.UniversityDate; 055 import org.kuali.kfs.sys.context.SpringContext; 056 import org.kuali.kfs.sys.dataaccess.GeneralLedgerPendingEntryDao; 057 import org.kuali.kfs.sys.document.AccountingDocument; 058 import org.kuali.kfs.sys.document.GeneralLedgerPendingEntrySource; 059 import org.kuali.kfs.sys.document.GeneralLedgerPostingDocument; 060 import org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleBaseConstants; 061 import org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE; 062 import org.kuali.kfs.sys.service.FlexibleOffsetAccountService; 063 import org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService; 064 import org.kuali.kfs.sys.service.HomeOriginationService; 065 import org.kuali.kfs.sys.service.OptionsService; 066 import org.kuali.kfs.sys.service.UniversityDateService; 067 import org.kuali.rice.kns.exception.ReferentialIntegrityException; 068 import org.kuali.rice.kns.service.DataDictionaryService; 069 import org.kuali.rice.kns.service.DateTimeService; 070 import org.kuali.rice.kns.service.KualiRuleService; 071 import org.kuali.rice.kns.service.ParameterService; 072 import org.kuali.rice.kns.service.PersistenceStructureService; 073 import org.kuali.rice.kns.util.GlobalVariables; 074 import org.kuali.rice.kns.util.KualiDecimal; 075 import org.kuali.rice.kns.util.ObjectUtils; 076 import org.springframework.transaction.annotation.Transactional; 077 078 /** 079 * This class is the service implementation for the GeneralLedgerPendingEntry structure. This is the default implementation, that is 080 * delivered with Kuali. 081 */ 082 @Transactional 083 public class GeneralLedgerPendingEntryServiceImpl implements GeneralLedgerPendingEntryService { 084 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(GeneralLedgerPendingEntryServiceImpl.class); 085 086 private GeneralLedgerPendingEntryDao generalLedgerPendingEntryDao; 087 private KualiRuleService kualiRuleService; 088 private ChartService chartService; 089 private OptionsService optionsService; 090 private ParameterService parameterService; 091 private BalanceTypeService balanceTypeService; 092 private DateTimeService dateTimeService; 093 private DataDictionaryService dataDictionaryService; 094 private PersistenceStructureService persistenceStructureService; 095 096 /** 097 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getExpenseSummary(java.util.List, java.lang.String, 098 * java.lang.String, boolean, boolean) 099 */ 100 public KualiDecimal getExpenseSummary(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, String sufficientFundsObjectCode, boolean isDebit, boolean isYearEnd) { 101 LOG.debug("getExpenseSummary() started"); 102 103 ObjectTypeService objectTypeService = (ObjectTypeService) SpringContext.getBean(ObjectTypeService.class); 104 List<String> objectTypes = objectTypeService.getExpenseObjectTypes(universityFiscalYear); 105 106 SystemOptions options = optionsService.getOptions(universityFiscalYear); 107 108 Collection balanceTypeCodes = new ArrayList(); 109 balanceTypeCodes.add(options.getActualFinancialBalanceTypeCd()); 110 111 return generalLedgerPendingEntryDao.getTransactionSummary(universityFiscalYear, chartOfAccountsCode, accountNumber, objectTypes, balanceTypeCodes, sufficientFundsObjectCode, isDebit, isYearEnd); 112 } 113 114 /** 115 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getEncumbranceSummary(java.lang.Integer, java.lang.String, 116 * java.lang.String, java.lang.String, boolean, boolean) 117 */ 118 public KualiDecimal getEncumbranceSummary(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, String sufficientFundsObjectCode, boolean isDebit, boolean isYearEnd) { 119 LOG.debug("getEncumbranceSummary() started"); 120 121 ObjectTypeService objectTypeService = (ObjectTypeService) SpringContext.getBean(ObjectTypeService.class); 122 List<String> objectTypes = objectTypeService.getExpenseObjectTypes(universityFiscalYear); 123 124 SystemOptions options = optionsService.getOptions(universityFiscalYear); 125 126 List<String> balanceTypeCodes = balanceTypeService.getEncumbranceBalanceTypes(universityFiscalYear); 127 128 129 return generalLedgerPendingEntryDao.getTransactionSummary(universityFiscalYear, chartOfAccountsCode, accountNumber, objectTypes, balanceTypeCodes, sufficientFundsObjectCode, isDebit, isYearEnd); 130 } 131 132 /** 133 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getBudgetSummary(java.lang.Integer, java.lang.String, 134 * java.lang.String, java.lang.String, boolean) 135 */ 136 public KualiDecimal getBudgetSummary(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, String sufficientFundsObjectCode, boolean isYearEnd) { 137 LOG.debug("getBudgetSummary() started"); 138 139 ObjectTypeService objectTypeService = (ObjectTypeService) SpringContext.getBean(ObjectTypeService.class); 140 List<String> objectTypes = objectTypeService.getExpenseObjectTypes(universityFiscalYear); 141 142 SystemOptions options = optionsService.getOptions(universityFiscalYear); 143 144 Collection balanceTypeCodes = new ArrayList(); 145 balanceTypeCodes.add(options.getBudgetCheckingBalanceTypeCd()); 146 147 return generalLedgerPendingEntryDao.getTransactionSummary(universityFiscalYear, chartOfAccountsCode, accountNumber, objectTypes, balanceTypeCodes, sufficientFundsObjectCode, isYearEnd); 148 } 149 150 /** 151 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getCashSummary(java.util.Collection, java.lang.String, 152 * java.lang.String, boolean) 153 */ 154 public KualiDecimal getCashSummary(List universityFiscalYears, String chartOfAccountsCode, String accountNumber, boolean isDebit) { 155 LOG.debug("getCashSummary() started"); 156 157 Chart c = chartService.getByPrimaryId(chartOfAccountsCode); 158 159 // Note, we are getting the options from the first fiscal year in the list. We are assuming that the 160 // balance type code for actual is the same in all the years in the list. 161 SystemOptions options = optionsService.getOptions((Integer) universityFiscalYears.get(0)); 162 163 Collection objectCodes = new ArrayList(); 164 objectCodes.add(c.getFinancialCashObjectCode()); 165 166 Collection balanceTypeCodes = new ArrayList(); 167 balanceTypeCodes.add(options.getActualFinancialBalanceTypeCd()); 168 169 return generalLedgerPendingEntryDao.getTransactionSummary(universityFiscalYears, chartOfAccountsCode, accountNumber, objectCodes, balanceTypeCodes, isDebit); 170 } 171 172 /** 173 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getActualSummary(java.util.List, java.lang.String, 174 * java.lang.String, boolean) 175 */ 176 public KualiDecimal getActualSummary(List universityFiscalYears, String chartOfAccountsCode, String accountNumber, boolean isDebit) { 177 LOG.debug("getActualSummary() started"); 178 179 List<String> codes = parameterService.getParameterValues(KfsParameterConstants.FINANCIAL_SYSTEM_ALL.class, SufficientFundsServiceConstants.SUFFICIENT_FUNDS_OBJECT_CODE_SPECIALS); 180 181 // Note, we are getting the options from the first fiscal year in the list. We are assuming that the 182 // balance type code for actual is the same in all the years in the list. 183 SystemOptions options = optionsService.getOptions((Integer) universityFiscalYears.get(0)); 184 185 Collection balanceTypeCodes = new ArrayList(); 186 balanceTypeCodes.add(options.getActualFinancialBalanceTypeCd()); 187 188 return generalLedgerPendingEntryDao.getTransactionSummary(universityFiscalYears, chartOfAccountsCode, accountNumber, codes, balanceTypeCodes, isDebit); 189 } 190 191 /** 192 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#getByPrimaryId(java.lang.Integer, java.lang.String) 193 */ 194 public GeneralLedgerPendingEntry getByPrimaryId(Integer transactionEntrySequenceId, String documentHeaderId) { 195 LOG.debug("getByPrimaryId() started"); 196 197 return generalLedgerPendingEntryDao.getByPrimaryId(documentHeaderId, transactionEntrySequenceId); 198 } 199 200 public void fillInFiscalPeriodYear(GeneralLedgerPendingEntry glpe) { 201 LOG.debug("fillInFiscalPeriodYear() started"); 202 203 // TODO Handle year end documents 204 205 if ((glpe.getUniversityFiscalPeriodCode() == null) || (glpe.getUniversityFiscalYear() == null)) { 206 UniversityDate ud = SpringContext.getBean(UniversityDateService.class).getCurrentUniversityDate(); 207 208 glpe.setUniversityFiscalYear(ud.getUniversityFiscalYear()); 209 glpe.setUniversityFiscalPeriodCode(ud.getUniversityFiscalAccountingPeriod()); 210 } 211 } 212 213 /** 214 * Invokes generateEntries method on the financial document. 215 * 216 * @param document - document whose pending entries need generated 217 * @return whether the business rules succeeded 218 */ 219 public boolean generateGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySource glpeSource) { 220 boolean success = true; 221 222 // we must clear them first before creating new ones 223 glpeSource.clearAnyGeneralLedgerPendingEntries(); 224 225 if ( LOG.isDebugEnabled() ) { 226 LOG.debug("deleting existing gl pending ledger entries for document " + glpeSource.getDocumentHeader().getDocumentNumber()); 227 } 228 delete(glpeSource.getDocumentHeader().getDocumentNumber()); 229 230 if ( LOG.isDebugEnabled() ) { 231 LOG.debug("generating gl pending ledger entries for document " + glpeSource.getDocumentHeader().getDocumentNumber()); 232 } 233 234 GeneralLedgerPendingEntrySequenceHelper sequenceHelper = new GeneralLedgerPendingEntrySequenceHelper(); 235 for (GeneralLedgerPendingEntrySourceDetail glpeSourceDetail : glpeSource.getGeneralLedgerPendingEntrySourceDetails()) { 236 success &= glpeSource.generateGeneralLedgerPendingEntries(glpeSourceDetail, sequenceHelper); 237 sequenceHelper.increment(); 238 } 239 240 // doc specific pending entries generation 241 success &= glpeSource.generateDocumentGeneralLedgerPendingEntries(sequenceHelper); 242 return success; 243 } 244 245 /** 246 * This populates an empty GeneralLedgerPendingEntry explicitEntry object instance with default values. 247 * 248 * @param accountingDocument 249 * @param accountingLine 250 * @param sequenceHelper 251 * @param explicitEntry 252 */ 253 public void populateExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySource glpeSource, GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntry explicitEntry) { 254 if (LOG.isDebugEnabled()) { 255 LOG.debug("populateExplicitGeneralLedgerPendingEntry(AccountingDocument, AccountingLine, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - start"); 256 } 257 258 explicitEntry.setFinancialDocumentTypeCode(glpeSource.getFinancialDocumentTypeCode()); 259 explicitEntry.setVersionNumber(new Long(1)); 260 explicitEntry.setTransactionLedgerEntrySequenceNumber(new Integer(sequenceHelper.getSequenceCounter())); 261 Timestamp transactionTimestamp = new Timestamp(SpringContext.getBean(DateTimeService.class).getCurrentDate().getTime()); 262 explicitEntry.setTransactionDate(new java.sql.Date(transactionTimestamp.getTime())); 263 explicitEntry.setTransactionEntryProcessedTs(new java.sql.Timestamp(transactionTimestamp.getTime())); 264 explicitEntry.setAccountNumber(glpeSourceDetail.getAccountNumber()); 265 266 if (ObjectUtils.isNull(glpeSourceDetail.getAccount()) && getPersistenceStructureService().hasReference(glpeSourceDetail.getClass(), KFSPropertyConstants.ACCOUNT)) { 267 glpeSourceDetail.refreshReferenceObject(KFSPropertyConstants.ACCOUNT); 268 } 269 270 if ((ObjectUtils.isNull(glpeSourceDetail.getObjectCode()) || StringUtils.isBlank(glpeSourceDetail.getObjectCode().getFinancialObjectTypeCode())) && getPersistenceStructureService().hasReference(glpeSourceDetail.getClass(), KFSPropertyConstants.OBJECT_CODE) ) { 271 glpeSourceDetail.refreshReferenceObject(KFSPropertyConstants.OBJECT_CODE); 272 } 273 274 if (ObjectUtils.isNotNull(glpeSourceDetail.getAccount())) { 275 if(StringUtils.isBlank(glpeSourceDetail.getAccount().getAccountSufficientFundsCode())) { 276 glpeSourceDetail.getAccount().setAccountSufficientFundsCode(KFSConstants.SF_TYPE_NO_CHECKING); 277 } 278 279 String sufficientFundsCode = glpeSourceDetail.getAccount().getAccountSufficientFundsCode(); 280 ObjectCode objectCode = glpeSourceDetail.getObjectCode(); 281 if(ObjectUtils.isNotNull(objectCode)) { 282 String sifficientFundsObjectCode = SpringContext.getBean(SufficientFundsService.class).getSufficientFundsObjectCode(objectCode, sufficientFundsCode); 283 explicitEntry.setAcctSufficientFundsFinObjCd(sifficientFundsObjectCode); 284 } 285 } 286 287 if (!ObjectUtils.isNull(glpeSourceDetail.getObjectCode())) { 288 explicitEntry.setFinancialObjectTypeCode(glpeSourceDetail.getObjectCode().getFinancialObjectTypeCode()); 289 } 290 291 explicitEntry.setFinancialDocumentApprovedCode(GENERAL_LEDGER_PENDING_ENTRY_CODE.NO); 292 explicitEntry.setTransactionEncumbranceUpdateCode(BLANK_SPACE); 293 explicitEntry.setFinancialBalanceTypeCode(BALANCE_TYPE_ACTUAL); // this is the default that most documents use 294 explicitEntry.setChartOfAccountsCode(glpeSourceDetail.getChartOfAccountsCode()); 295 explicitEntry.setTransactionDebitCreditCode(glpeSource.isDebit(glpeSourceDetail) ? KFSConstants.GL_DEBIT_CODE : KFSConstants.GL_CREDIT_CODE); 296 explicitEntry.setFinancialSystemOriginationCode(SpringContext.getBean(HomeOriginationService.class).getHomeOrigination().getFinSystemHomeOriginationCode()); 297 explicitEntry.setDocumentNumber(glpeSourceDetail.getDocumentNumber()); 298 explicitEntry.setFinancialObjectCode(glpeSourceDetail.getFinancialObjectCode()); 299 300 explicitEntry.setOrganizationDocumentNumber(glpeSource.getDocumentHeader().getOrganizationDocumentNumber()); 301 explicitEntry.setOrganizationReferenceId(glpeSourceDetail.getOrganizationReferenceId()); 302 explicitEntry.setProjectCode(getEntryValue(glpeSourceDetail.getProjectCode(), GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankProjectCode())); 303 explicitEntry.setReferenceFinancialDocumentNumber(getEntryValue(glpeSourceDetail.getReferenceNumber(), BLANK_SPACE)); 304 explicitEntry.setReferenceFinancialDocumentTypeCode(getEntryValue(glpeSourceDetail.getReferenceTypeCode(), BLANK_SPACE)); 305 explicitEntry.setReferenceFinancialSystemOriginationCode(getEntryValue(glpeSourceDetail.getReferenceOriginCode(), BLANK_SPACE)); 306 explicitEntry.setSubAccountNumber(getEntryValue(glpeSourceDetail.getSubAccountNumber(), GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankSubAccountNumber())); 307 explicitEntry.setFinancialSubObjectCode(getEntryValue(glpeSourceDetail.getFinancialSubObjectCode(), GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialSubObjectCode())); 308 explicitEntry.setTransactionEntryOffsetIndicator(false); 309 explicitEntry.setTransactionLedgerEntryAmount(glpeSource.getGeneralLedgerPendingEntryAmountForDetail(glpeSourceDetail)); 310 explicitEntry.setTransactionLedgerEntryDescription(getEntryValue(glpeSourceDetail.getFinancialDocumentLineDescription(), glpeSource.getDocumentHeader().getDocumentDescription())); 311 explicitEntry.setUniversityFiscalPeriodCode(null); // null here, is assigned during batch or in specific document rule 312 // classes 313 explicitEntry.setUniversityFiscalYear(glpeSource.getPostingYear()); 314 // TODO wait for core budget year data structures to be put in place 315 // explicitEntry.setBudgetYear(accountingLine.getBudgetYear()); 316 // explicitEntry.setBudgetYearFundingSourceCode(budgetYearFundingSourceCode); 317 318 if (LOG.isDebugEnabled()) { 319 LOG.debug("populateExplicitGeneralLedgerPendingEntry(AccountingDocument, AccountingLine, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - end"); 320 } 321 } 322 323 /** 324 * Convenience method to build a GLPE without a generalLedgerPendingEntrySourceDetail 325 * @param document a GeneralLedgerPostingDocument 326 * @param account the account for use in the GLPE 327 * @param objectCode the object code for use in the GLPE 328 * @param subAccountNumber the sub account number for use in the GLPE 329 * @param subObjectCode the subobject code for use in the GLPE 330 * @param organizationReferenceId the organization reference id to use in the GLPE 331 * @param projectCode the project code to use in the GLPE 332 * @param referenceNumber the reference number to use in the GLPE 333 * @param referenceTypeCode the reference type code to use in the GLPE 334 * @param referenceOriginCode the reference origin code to use in the GLPE 335 * @param description the description to put in the GLPE 336 * @param isDebit true if the GLPE represents a debit, false if it represents a credit 337 * @param amount the amount of the GLPE 338 * @param sequenceHelper the sequence helper to use 339 * @return a populated general ledger pending entry 340 */ 341 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) { 342 if (LOG.isDebugEnabled()) { 343 LOG.debug("populateExplicitGeneralLedgerPendingEntry(AccountingDocument, AccountingLine, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - start"); 344 } 345 346 GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry(); 347 explicitEntry.setFinancialDocumentTypeCode(document.getDocumentHeader().getWorkflowDocument().getDocumentType()); 348 explicitEntry.setVersionNumber(new Long(1)); 349 explicitEntry.setTransactionLedgerEntrySequenceNumber(new Integer(sequenceHelper.getSequenceCounter())); 350 Timestamp transactionTimestamp = new Timestamp(SpringContext.getBean(DateTimeService.class).getCurrentDate().getTime()); 351 explicitEntry.setTransactionDate(new java.sql.Date(transactionTimestamp.getTime())); 352 explicitEntry.setTransactionEntryProcessedTs(new java.sql.Timestamp(transactionTimestamp.getTime())); 353 explicitEntry.setAccountNumber(account.getAccountNumber()); 354 if (account.getAccountSufficientFundsCode() == null) { 355 account.setAccountSufficientFundsCode(KFSConstants.SF_TYPE_NO_CHECKING); 356 } 357 explicitEntry.setAcctSufficientFundsFinObjCd(SpringContext.getBean(SufficientFundsService.class).getSufficientFundsObjectCode(objectCode, account.getAccountSufficientFundsCode())); 358 explicitEntry.setFinancialDocumentApprovedCode(GENERAL_LEDGER_PENDING_ENTRY_CODE.NO); 359 explicitEntry.setTransactionEncumbranceUpdateCode(BLANK_SPACE); 360 explicitEntry.setFinancialBalanceTypeCode(BALANCE_TYPE_ACTUAL); // this is the default that most documents use 361 explicitEntry.setChartOfAccountsCode(account.getChartOfAccountsCode()); 362 explicitEntry.setTransactionDebitCreditCode(isDebit ? KFSConstants.GL_DEBIT_CODE : KFSConstants.GL_CREDIT_CODE); 363 explicitEntry.setFinancialSystemOriginationCode(SpringContext.getBean(HomeOriginationService.class).getHomeOrigination().getFinSystemHomeOriginationCode()); 364 explicitEntry.setDocumentNumber(document.getDocumentNumber()); 365 explicitEntry.setFinancialObjectCode(objectCode.getFinancialObjectCode()); 366 explicitEntry.setFinancialObjectTypeCode(objectCode.getFinancialObjectTypeCode()); 367 explicitEntry.setOrganizationDocumentNumber(document.getDocumentHeader().getOrganizationDocumentNumber()); 368 explicitEntry.setOrganizationReferenceId(organizationReferenceId); 369 explicitEntry.setProjectCode(getEntryValue(projectCode, GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankProjectCode())); 370 explicitEntry.setReferenceFinancialDocumentNumber(getEntryValue(referenceNumber, BLANK_SPACE)); 371 explicitEntry.setReferenceFinancialDocumentTypeCode(getEntryValue(referenceTypeCode, BLANK_SPACE)); 372 explicitEntry.setReferenceFinancialSystemOriginationCode(getEntryValue(referenceOriginCode, BLANK_SPACE)); 373 explicitEntry.setSubAccountNumber(getEntryValue(subAccountNumber, GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankSubAccountNumber())); 374 explicitEntry.setFinancialSubObjectCode(getEntryValue(subObjectCode, GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialSubObjectCode())); 375 explicitEntry.setTransactionEntryOffsetIndicator(false); 376 explicitEntry.setTransactionLedgerEntryAmount(amount); 377 explicitEntry.setTransactionLedgerEntryDescription(getEntryValue(description, document.getDocumentHeader().getDocumentDescription())); 378 explicitEntry.setUniversityFiscalPeriodCode(null); // null here, is assigned during batch or in specific document rule 379 // classes 380 explicitEntry.setUniversityFiscalYear(document.getPostingYear()); 381 382 if (LOG.isDebugEnabled()) { 383 LOG.debug("populateExplicitGeneralLedgerPendingEntry(AccountingDocument, AccountingLine, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - end"); 384 } 385 386 return explicitEntry; 387 } 388 389 /** 390 * This populates an GeneralLedgerPendingEntry offsetEntry object instance with values that differ from the values supplied in 391 * the explicit entry that it was cloned from. Note that the entries do not contain BOs now. 392 * 393 * @param universityFiscalYear 394 * @param explicitEntry 395 * @param sequenceHelper 396 * @param offsetEntry Cloned from the explicit entry 397 * @return whether the offset generation is successful 398 */ 399 public boolean populateOffsetGeneralLedgerPendingEntry(Integer universityFiscalYear, GeneralLedgerPendingEntry explicitEntry, GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntry offsetEntry) { 400 LOG.debug("populateOffsetGeneralLedgerPendingEntry(Integer, GeneralLedgerPendingEntry, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - start"); 401 402 boolean success = true; 403 404 // lookup offset object info 405 OffsetDefinition offsetDefinition = SpringContext.getBean(OffsetDefinitionService.class).getByPrimaryId(universityFiscalYear, explicitEntry.getChartOfAccountsCode(), explicitEntry.getFinancialDocumentTypeCode(), explicitEntry.getFinancialBalanceTypeCode()); 406 if (ObjectUtils.isNull(offsetDefinition)) { 407 success = false; 408 GlobalVariables.getMessageMap().putError(KFSConstants.GENERAL_LEDGER_PENDING_ENTRIES_TAB_ERRORS, KFSKeyConstants.ERROR_DOCUMENT_NO_OFFSET_DEFINITION, universityFiscalYear.toString(), explicitEntry.getChartOfAccountsCode(), explicitEntry.getFinancialDocumentTypeCode(), explicitEntry.getFinancialBalanceTypeCode()); 409 } 410 else { 411 OffsetAccount flexibleOffsetAccount = SpringContext.getBean(FlexibleOffsetAccountService.class).getByPrimaryIdIfEnabled(explicitEntry.getChartOfAccountsCode(), explicitEntry.getAccountNumber(), getOffsetFinancialObjectCode(offsetDefinition)); 412 flexOffsetAccountIfNecessary(flexibleOffsetAccount, offsetEntry); 413 } 414 415 // update offset entry fields that are different from the explicit entry that it was created from 416 offsetEntry.setTransactionLedgerEntrySequenceNumber(new Integer(sequenceHelper.getSequenceCounter())); 417 offsetEntry.setTransactionDebitCreditCode(getOffsetEntryDebitCreditCode(explicitEntry)); 418 419 String offsetObjectCode = getOffsetFinancialObjectCode(offsetDefinition); 420 offsetEntry.setFinancialObjectCode(offsetObjectCode); 421 if (offsetObjectCode.equals(AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode())) { 422 // no BO, so punt 423 offsetEntry.setAcctSufficientFundsFinObjCd(AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode()); 424 } 425 else { 426 // Need current ObjectCode and Account BOs to get sufficient funds code. (Entries originally have no BOs.) 427 // todo: private or other methods to get these BOs, instead of using the entry and leaving some BOs filled in? 428 offsetEntry.refreshReferenceObject(KFSPropertyConstants.FINANCIAL_OBJECT); 429 offsetEntry.refreshReferenceObject(KFSPropertyConstants.ACCOUNT); 430 ObjectCode financialObject = offsetEntry.getFinancialObject(); 431 // The ObjectCode reference may be invalid because a flexible offset account changed its chart code. 432 if (ObjectUtils.isNull(financialObject)) { 433 throw new ReferentialIntegrityException("offset object code " + offsetEntry.getUniversityFiscalYear() + "-" + offsetEntry.getChartOfAccountsCode() + "-" + offsetEntry.getFinancialObjectCode()); 434 } 435 offsetEntry.setAcctSufficientFundsFinObjCd(SpringContext.getBean(SufficientFundsService.class).getSufficientFundsObjectCode(financialObject, offsetEntry.getAccount().getAccountSufficientFundsCode())); 436 } 437 438 offsetEntry.setFinancialObjectTypeCode(getOffsetFinancialObjectTypeCode(offsetDefinition)); 439 offsetEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode()); 440 offsetEntry.setTransactionEntryOffsetIndicator(true); 441 offsetEntry.setTransactionLedgerEntryDescription(KFSConstants.GL_PE_OFFSET_STRING); 442 offsetEntry.setFinancialSystemOriginationCode(explicitEntry.getFinancialSystemOriginationCode()); 443 444 LOG.debug("populateOffsetGeneralLedgerPendingEntry(Integer, GeneralLedgerPendingEntry, GeneralLedgerPendingEntrySequenceHelper, GeneralLedgerPendingEntry) - end"); 445 return success; 446 } 447 448 /** 449 * Applies the given flexible offset account to the given offset entry. Does nothing if flexibleOffsetAccount is null or its COA 450 * and account number are the same as the offset entry's. 451 * 452 * @param flexibleOffsetAccount may be null 453 * @param offsetEntry may be modified 454 */ 455 protected void flexOffsetAccountIfNecessary(OffsetAccount flexibleOffsetAccount, GeneralLedgerPendingEntry offsetEntry) { 456 LOG.debug("flexOffsetAccountIfNecessary(OffsetAccount, GeneralLedgerPendingEntry) - start"); 457 458 if (flexibleOffsetAccount == null) { 459 LOG.debug("flexOffsetAccountIfNecessary(OffsetAccount, GeneralLedgerPendingEntry) - end"); 460 return; // They are not required and may also be disabled. 461 } 462 String flexCoa = flexibleOffsetAccount.getFinancialOffsetChartOfAccountCode(); 463 String flexAccountNumber = flexibleOffsetAccount.getFinancialOffsetAccountNumber(); 464 if (flexCoa.equals(offsetEntry.getChartOfAccountsCode()) && flexAccountNumber.equals(offsetEntry.getAccountNumber())) { 465 LOG.debug("flexOffsetAccountIfNecessary(OffsetAccount, GeneralLedgerPendingEntry) - end"); 466 return; // no change, so leave sub-account as is 467 } 468 if (ObjectUtils.isNull(flexibleOffsetAccount.getFinancialOffsetAccount())) { 469 throw new ReferentialIntegrityException("flexible offset account " + flexCoa + "-" + flexAccountNumber); 470 } 471 offsetEntry.setChartOfAccountsCode(flexCoa); 472 offsetEntry.setAccountNumber(flexAccountNumber); 473 // COA and account number are part of the sub-account's key, so the original sub-account would be invalid. 474 offsetEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber()); 475 476 LOG.debug("flexOffsetAccountIfNecessary(OffsetAccount, GeneralLedgerPendingEntry) - end"); 477 } 478 479 /** 480 * Helper method that determines the offset entry's financial object type code. 481 * 482 * @param offsetDefinition 483 * @return String 484 */ 485 protected String getOffsetFinancialObjectTypeCode(OffsetDefinition offsetDefinition) { 486 LOG.debug("getOffsetFinancialObjectTypeCode(OffsetDefinition) - start"); 487 488 if (null != offsetDefinition && null != offsetDefinition.getFinancialObject()) { 489 String returnString = getEntryValue(offsetDefinition.getFinancialObject().getFinancialObjectTypeCode(), AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectType()); 490 LOG.debug("getOffsetFinancialObjectTypeCode(OffsetDefinition) - end"); 491 return returnString; 492 } 493 else { 494 LOG.debug("getOffsetFinancialObjectTypeCode(OffsetDefinition) - end"); 495 return AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectType(); 496 } 497 498 } 499 500 /** 501 * Helper method that determines the debit/credit code for the offset entry. If the explicit was a debit, the offset is a 502 * credit. Otherwise, it's opposite. 503 * 504 * @param explicitEntry 505 * @return String 506 */ 507 protected String getOffsetEntryDebitCreditCode(GeneralLedgerPendingEntry explicitEntry) { 508 LOG.debug("getOffsetEntryDebitCreditCode(GeneralLedgerPendingEntry) - start"); 509 510 String offsetDebitCreditCode = KFSConstants.GL_BUDGET_CODE; 511 if (KFSConstants.GL_DEBIT_CODE.equals(explicitEntry.getTransactionDebitCreditCode())) { 512 offsetDebitCreditCode = KFSConstants.GL_CREDIT_CODE; 513 } 514 else if (KFSConstants.GL_CREDIT_CODE.equals(explicitEntry.getTransactionDebitCreditCode())) { 515 offsetDebitCreditCode = KFSConstants.GL_DEBIT_CODE; 516 } 517 518 LOG.debug("getOffsetEntryDebitCreditCode(GeneralLedgerPendingEntry) - end"); 519 return offsetDebitCreditCode; 520 } 521 522 /** 523 * Helper method that determines the offset entry's financial object code. 524 * 525 * @param offsetDefinition 526 * @return String 527 */ 528 protected String getOffsetFinancialObjectCode(OffsetDefinition offsetDefinition) { 529 LOG.debug("getOffsetFinancialObjectCode(OffsetDefinition) - start"); 530 531 if (null != offsetDefinition) { 532 String returnString = getEntryValue(offsetDefinition.getFinancialObjectCode(), AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode()); 533 LOG.debug("getOffsetFinancialObjectCode(OffsetDefinition) - end"); 534 return returnString; 535 } 536 else { 537 LOG.debug("getOffsetFinancialObjectCode(OffsetDefinition) - end"); 538 return AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialObjectCode(); 539 } 540 541 } 542 543 /** 544 * This populates an empty GeneralLedgerPendingEntry instance with default values for a bank offset. A global error will be 545 * posted as a side-effect if the given bank has not defined the necessary bank offset relations. 546 * 547 * @param bank 548 * @param depositAmount 549 * @param financialDocument 550 * @param universityFiscalYear 551 * @param sequenceHelper 552 * @param bankOffsetEntry 553 * @param errorPropertyName 554 * @return whether the entry was populated successfully 555 */ 556 public boolean populateBankOffsetGeneralLedgerPendingEntry(Bank bank, KualiDecimal depositAmount, GeneralLedgerPostingDocument financialDocument, Integer universityFiscalYear, GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntry bankOffsetEntry, String errorPropertyName) { 557 bankOffsetEntry.setFinancialDocumentTypeCode(dataDictionaryService.getDocumentTypeNameByClass(financialDocument.getClass())); 558 bankOffsetEntry.setVersionNumber(1L); 559 bankOffsetEntry.setTransactionLedgerEntrySequenceNumber(sequenceHelper.getSequenceCounter()); 560 Timestamp transactionTimestamp = new Timestamp(dateTimeService.getCurrentDate().getTime()); 561 bankOffsetEntry.setTransactionDate(new java.sql.Date(transactionTimestamp.getTime())); 562 bankOffsetEntry.setTransactionEntryProcessedTs(new java.sql.Timestamp(transactionTimestamp.getTime())); 563 Account cashOffsetAccount = bank.getCashOffsetAccount(); 564 565 if (ObjectUtils.isNull(cashOffsetAccount)) { 566 GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_NO_ACCOUNT, new String[] { bank.getBankCode() }); 567 return false; 568 } 569 570 if (!cashOffsetAccount.isActive()) { 571 GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_ACCOUNT_CLOSED, new String[] {bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber() }); 572 return false; 573 } 574 575 if (cashOffsetAccount.isExpired()) { 576 GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_ACCOUNT_EXPIRED, new String[] { bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber() }); 577 return false; 578 } 579 580 bankOffsetEntry.setChartOfAccountsCode(bank.getCashOffsetFinancialChartOfAccountCode()); 581 bankOffsetEntry.setAccountNumber(bank.getCashOffsetAccountNumber()); 582 bankOffsetEntry.setFinancialDocumentApprovedCode(AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE.NO); 583 bankOffsetEntry.setTransactionEncumbranceUpdateCode(BLANK_SPACE); 584 bankOffsetEntry.setFinancialBalanceTypeCode(BALANCE_TYPE_ACTUAL); 585 bankOffsetEntry.setTransactionDebitCreditCode(depositAmount.isPositive() ? GL_DEBIT_CODE : GL_CREDIT_CODE); 586 bankOffsetEntry.setFinancialSystemOriginationCode(SpringContext.getBean(HomeOriginationService.class).getHomeOrigination().getFinSystemHomeOriginationCode()); 587 bankOffsetEntry.setDocumentNumber(financialDocument.getDocumentNumber()); 588 589 ObjectCode cashOffsetObject = bank.getCashOffsetObject(); 590 if (ObjectUtils.isNull(cashOffsetObject)) { 591 GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_NO_OBJECT_CODE, new String[] { bank.getBankCode()}); 592 return false; 593 } 594 595 if (!cashOffsetObject.isFinancialObjectActiveCode()) { 596 GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_INACTIVE_OBJECT_CODE, new String[] { bank.getBankCode(), cashOffsetObject.getFinancialObjectCode() }); 597 return false; 598 } 599 600 bankOffsetEntry.setFinancialObjectCode(bank.getCashOffsetObjectCode()); 601 bankOffsetEntry.setFinancialObjectTypeCode(bank.getCashOffsetObject().getFinancialObjectTypeCode()); 602 bankOffsetEntry.setOrganizationDocumentNumber(financialDocument.getDocumentHeader().getOrganizationDocumentNumber()); 603 bankOffsetEntry.setOrganizationReferenceId(null); 604 bankOffsetEntry.setProjectCode(KFSConstants.getDashProjectCode()); 605 bankOffsetEntry.setReferenceFinancialDocumentNumber(null); 606 bankOffsetEntry.setReferenceFinancialDocumentTypeCode(null); 607 bankOffsetEntry.setReferenceFinancialSystemOriginationCode(null); 608 609 if (StringUtils.isBlank(bank.getCashOffsetSubAccountNumber())) { 610 bankOffsetEntry.setSubAccountNumber(KFSConstants.getDashSubAccountNumber()); 611 } 612 else { 613 SubAccount cashOffsetSubAccount = bank.getCashOffsetSubAccount(); 614 if (ObjectUtils.isNull(cashOffsetSubAccount)) { 615 GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_NONEXISTENT_SUB_ACCOUNT, new String[] { bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber(), bank.getCashOffsetSubAccountNumber() }); 616 return false; 617 } 618 619 if (!cashOffsetSubAccount.isActive()) { 620 GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_INACTIVE_SUB_ACCOUNT, new String[] { bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber(), bank.getCashOffsetSubAccountNumber() }); 621 return false; 622 } 623 624 bankOffsetEntry.setSubAccountNumber(bank.getCashOffsetSubAccountNumber()); 625 } 626 627 if (StringUtils.isBlank(bank.getCashOffsetSubObjectCode())) { 628 bankOffsetEntry.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode()); 629 } 630 else { 631 SubObjectCode cashOffsetSubObject = bank.getCashOffsetSubObject(); 632 if (ObjectUtils.isNull(cashOffsetSubObject)) { 633 GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_NONEXISTENT_SUB_OBJ, new String[] { bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber(), cashOffsetObject.getFinancialObjectCode(), bank.getCashOffsetSubObjectCode() }); 634 return false; 635 } 636 637 if (!cashOffsetSubObject.isActive()) { 638 GlobalVariables.getMessageMap().putError(errorPropertyName, KFSKeyConstants.ERROR_DOCUMENT_BANK_OFFSET_INACTIVE_SUB_OBJ, new String[] { bank.getBankCode(), cashOffsetAccount.getChartOfAccountsCode(), cashOffsetAccount.getAccountNumber(), cashOffsetObject.getFinancialObjectCode(), bank.getCashOffsetSubObjectCode() }); 639 return false; 640 } 641 642 bankOffsetEntry.setFinancialSubObjectCode(bank.getCashOffsetSubObjectCode()); 643 } 644 645 bankOffsetEntry.setTransactionEntryOffsetIndicator(true); 646 bankOffsetEntry.setTransactionLedgerEntryAmount(depositAmount.abs()); 647 bankOffsetEntry.setUniversityFiscalPeriodCode(null); // null here, is assigned during batch or in specific document rule 648 bankOffsetEntry.setUniversityFiscalYear(universityFiscalYear); 649 bankOffsetEntry.setAcctSufficientFundsFinObjCd(SpringContext.getBean(SufficientFundsService.class).getSufficientFundsObjectCode(cashOffsetObject, cashOffsetAccount.getAccountSufficientFundsCode())); 650 651 return true; 652 } 653 654 /** 655 * @see org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService#save(org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry) 656 */ 657 public void save(GeneralLedgerPendingEntry generalLedgerPendingEntry) { 658 LOG.debug("save() started"); 659 660 generalLedgerPendingEntryDao.save(generalLedgerPendingEntry); 661 } 662 663 public void delete(String documentHeaderId) { 664 LOG.debug("delete() started"); 665 666 this.generalLedgerPendingEntryDao.delete(documentHeaderId); 667 } 668 669 public void deleteByFinancialDocumentApprovedCode(String financialDocumentApprovedCode) { 670 LOG.debug("deleteByFinancialDocumentApprovedCode() started"); 671 672 this.generalLedgerPendingEntryDao.deleteByFinancialDocumentApprovedCode(financialDocumentApprovedCode); 673 } 674 675 /** 676 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findApprovedPendingLedgerEntries() 677 */ 678 public Iterator findApprovedPendingLedgerEntries() { 679 LOG.debug("findApprovedPendingLedgerEntries() started"); 680 681 return generalLedgerPendingEntryDao.findApprovedPendingLedgerEntries(); 682 } 683 684 /** 685 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntries(org.kuali.kfs.gl.businessobject.Encumbrance, 686 * boolean) 687 */ 688 public Iterator findPendingLedgerEntries(Encumbrance encumbrance, boolean isApproved) { 689 LOG.debug("findPendingLedgerEntries() started"); 690 691 return generalLedgerPendingEntryDao.findPendingLedgerEntries(encumbrance, isApproved); 692 } 693 694 /** 695 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#hasPendingGeneralLedgerEntry(org.kuali.kfs.coa.businessobject.Account) 696 */ 697 public boolean hasPendingGeneralLedgerEntry(Account account) { 698 LOG.debug("hasPendingGeneralLedgerEntry() started"); 699 700 return generalLedgerPendingEntryDao.countPendingLedgerEntries(account) > 0; 701 } 702 703 /** 704 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntries(Balance, boolean, boolean) 705 */ 706 public Iterator findPendingLedgerEntries(Balance balance, boolean isApproved, boolean isConsolidated) { 707 LOG.debug("findPendingLedgerEntries() started"); 708 709 return generalLedgerPendingEntryDao.findPendingLedgerEntries(balance, isApproved, isConsolidated); 710 } 711 712 /** 713 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntriesForEntry(java.util.Map, boolean) 714 */ 715 public Iterator findPendingLedgerEntriesForEntry(Map fieldValues, boolean isApproved) { 716 LOG.debug("findPendingLedgerEntriesForEntry() started"); 717 718 return generalLedgerPendingEntryDao.findPendingLedgerEntriesForEntry(fieldValues, isApproved); 719 } 720 721 /** 722 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntriesForEncumbrance(Map, boolean) 723 */ 724 public Iterator findPendingLedgerEntriesForEncumbrance(Map fieldValues, boolean isApproved) { 725 LOG.debug("findPendingLedgerEntriesForEncumbrance() started"); 726 727 return generalLedgerPendingEntryDao.findPendingLedgerEntriesForEncumbrance(fieldValues, isApproved); 728 } 729 730 /** 731 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntriesForCashBalance(java.util.Map, 732 * boolean) 733 */ 734 public Iterator findPendingLedgerEntriesForCashBalance(Map fieldValues, boolean isApproved) { 735 LOG.debug("findPendingLedgerEntriesForCashBalance() started"); 736 737 return generalLedgerPendingEntryDao.findPendingLedgerEntriesForCashBalance(fieldValues, isApproved); 738 } 739 740 /** 741 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntriesForBalance(java.util.Map, boolean) 742 */ 743 public Iterator findPendingLedgerEntriesForBalance(Map fieldValues, boolean isApproved) { 744 LOG.debug("findPendingLedgerEntriesForBalance() started"); 745 746 return generalLedgerPendingEntryDao.findPendingLedgerEntriesForBalance(fieldValues, isApproved); 747 } 748 749 /** 750 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntriesForAccountBalance(java.util.Map, 751 * boolean, boolean) 752 */ 753 public Iterator findPendingLedgerEntriesForAccountBalance(Map fieldValues, boolean isApproved) { 754 LOG.debug("findPendingLedgerEntriesForAccountBalance() started"); 755 756 return generalLedgerPendingEntryDao.findPendingLedgerEntriesForAccountBalance(fieldValues, isApproved); 757 } 758 759 /** 760 * @see org.kuali.module.gl.service.GeneralLedgerPendingEntryService#findPendingLedgerEntrySummaryForAccountBalance(java.util.Map, 761 * boolean, boolean) 762 */ 763 public Iterator findPendingLedgerEntrySummaryForAccountBalance(Map fieldValues, boolean isApproved) { 764 LOG.debug("findPendingLedgerEntrySummaryForAccountBalance() started"); 765 766 return generalLedgerPendingEntryDao.findPendingLedgerEntrySummaryForAccountBalance(fieldValues, isApproved); 767 } 768 769 public Collection findPendingEntries(Map fieldValues, boolean isApproved) { 770 LOG.debug("findPendingEntries() started"); 771 772 return generalLedgerPendingEntryDao.findPendingEntries(fieldValues, isApproved); 773 } 774 775 /** 776 * A helper method that checks the intended target value for null and empty strings. If the intended target value is not null or 777 * an empty string, it returns that value, ohterwise, it returns a backup value. 778 * 779 * @param targetValue 780 * @param backupValue 781 * @return String 782 */ 783 protected final String getEntryValue(String targetValue, String backupValue) { 784 LOG.debug("getEntryValue(String, String) - start"); 785 786 if (StringUtils.isNotBlank(targetValue)) { 787 LOG.debug("getEntryValue(String, String) - end"); 788 return targetValue; 789 } 790 else { 791 LOG.debug("getEntryValue(String, String) - end"); 792 return backupValue; 793 } 794 } 795 796 /** 797 * Determines if the given GeneralLedgerPendingEntry represents offsets to cash 798 * @param generalLedgerPendingEntry the GeneralLedgerPendingEntry to check 799 * @return true if the GeneralLedgerPendingEntry represents an offset to cash; false otherwise 800 */ 801 public boolean isOffsetToCash(GeneralLedgerPendingEntry generalLedgerPendingEntry) { 802 if (generalLedgerPendingEntry.isTransactionEntryOffsetIndicator()) { 803 final Chart entryChart = chartService.getByPrimaryId(generalLedgerPendingEntry.getChartOfAccountsCode()); 804 if (!ObjectUtils.isNull(entryChart)) { 805 return (entryChart.getFinancialCashObjectCode().equals(generalLedgerPendingEntry.getFinancialObjectCode())); 806 } 807 } 808 return false; 809 } 810 811 /** 812 * Adds up the amounts of all cash to offset GeneralLedgerPendingEntry records on the given AccountingDocument 813 * @param glPostingDocument the accounting document total the offset to cash amount for 814 * @return the offset to cash amount, where debited values have been subtracted and credited values have been added 815 */ 816 public KualiDecimal getOffsetToCashAmount(GeneralLedgerPostingDocument glPostingDocument) { 817 KualiDecimal total = KualiDecimal.ZERO; 818 for (GeneralLedgerPendingEntry glpe : glPostingDocument.getGeneralLedgerPendingEntries()) { 819 if (isOffsetToCash(glpe)) { 820 if (glpe.getTransactionDebitCreditCode().equals(KFSConstants.GL_DEBIT_CODE)) { 821 total = total.subtract(glpe.getTransactionLedgerEntryAmount()); 822 } else if (glpe.getTransactionDebitCreditCode().equals(KFSConstants.GL_CREDIT_CODE)) { 823 total = total.add(glpe.getTransactionLedgerEntryAmount()); 824 } 825 } 826 } 827 return total; 828 } 829 830 public void setBalanceTypeService(BalanceTypeService balanceTypeService) { 831 this.balanceTypeService = balanceTypeService; 832 } 833 834 public void setChartService(ChartService chartService) { 835 this.chartService = chartService; 836 } 837 838 public void setGeneralLedgerPendingEntryDao(GeneralLedgerPendingEntryDao generalLedgerPendingEntryDao) { 839 this.generalLedgerPendingEntryDao = generalLedgerPendingEntryDao; 840 } 841 842 public void setParameterService(ParameterService parameterService) { 843 this.parameterService = parameterService; 844 } 845 846 public void setKualiRuleService(KualiRuleService kualiRuleService) { 847 this.kualiRuleService = kualiRuleService; 848 } 849 850 public void setOptionsService(OptionsService optionsService) { 851 this.optionsService = optionsService; 852 } 853 854 /** 855 * Sets the dateTimeService attribute value. 856 * 857 * @param dateTimeService The dateTimeService to set. 858 */ 859 public void setDateTimeService(DateTimeService dateTimeService) { 860 this.dateTimeService = dateTimeService; 861 } 862 863 /** 864 * Sets the dataDictionaryService attribute value. 865 * @param dataDictionaryService The dataDictionaryService to set. 866 */ 867 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) { 868 this.dataDictionaryService = dataDictionaryService; 869 } 870 871 /** 872 * Gets the persistenceStructureService attribute. 873 * @return Returns the persistenceStructureService. 874 */ 875 public PersistenceStructureService getPersistenceStructureService() { 876 return persistenceStructureService; 877 } 878 879 /** 880 * Sets the persistenceStructureService attribute value. 881 * @param persistenceStructureService The persistenceStructureService to set. 882 */ 883 public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) { 884 this.persistenceStructureService = persistenceStructureService; 885 } 886 887 }