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 }