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.module.ar.document.service.impl;
017    
018    import java.util.Collection;
019    import java.util.HashMap;
020    import java.util.Map;
021    
022    import org.kuali.kfs.coa.service.ChartService;
023    import org.kuali.kfs.module.ar.ArPropertyConstants;
024    import org.kuali.kfs.module.ar.businessobject.AccountsReceivableDocumentHeader;
025    import org.kuali.kfs.module.ar.businessobject.CashControlDetail;
026    import org.kuali.kfs.module.ar.businessobject.SystemInformation;
027    import org.kuali.kfs.module.ar.document.CashControlDocument;
028    import org.kuali.kfs.module.ar.document.PaymentApplicationDocument;
029    import org.kuali.kfs.module.ar.document.service.AccountsReceivableDocumentHeaderService;
030    import org.kuali.kfs.module.ar.document.service.CashControlDocumentService;
031    import org.kuali.kfs.module.ar.document.service.SystemInformationService;
032    import org.kuali.kfs.sys.KFSConstants;
033    import org.kuali.kfs.sys.KFSKeyConstants;
034    import org.kuali.kfs.sys.businessobject.AccountingLine;
035    import org.kuali.kfs.sys.businessobject.Bank;
036    import org.kuali.kfs.sys.businessobject.ElectronicPaymentClaim;
037    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
038    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper;
039    import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
040    import org.kuali.kfs.sys.businessobject.SystemOptions;
041    import org.kuali.kfs.sys.context.SpringContext;
042    import org.kuali.kfs.sys.document.service.AccountingDocumentRuleHelperService;
043    import org.kuali.kfs.sys.service.BankService;
044    import org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService;
045    import org.kuali.kfs.sys.service.OptionsService;
046    import org.kuali.kfs.sys.service.UniversityDateService;
047    import org.kuali.rice.kew.docsearch.service.SearchableAttributeProcessingService;
048    import org.kuali.rice.kew.exception.WorkflowException;
049    import org.kuali.rice.kew.service.WorkflowDocumentActions;
050    import org.kuali.rice.kns.exception.InfrastructureException;
051    import org.kuali.rice.kns.service.BusinessObjectService;
052    import org.kuali.rice.kns.service.DataDictionaryService;
053    import org.kuali.rice.kns.service.DocumentService;
054    import org.kuali.rice.kns.util.KualiDecimal;
055    import org.kuali.rice.kns.util.ObjectUtils;
056    
057    public class CashControlDocumentServiceImpl implements CashControlDocumentService {
058    
059        private AccountsReceivableDocumentHeaderService accountsReceivableDocumentHeaderService;
060        private DocumentService documentService;
061        private BusinessObjectService businessObjectService;
062        private GeneralLedgerPendingEntryService glpeService;
063        private OptionsService optionsService;
064        private SystemInformationService systemInformationService;
065        private DataDictionaryService dataDictionaryService;
066        private ChartService chartService;
067        private UniversityDateService universityDateService;
068    
069        /**
070         * @see org.kuali.kfs.module.ar.document.service.CashControlDocumentService#createAndSavePaymentApplicationDocument(java.lang.String,
071         *      org.kuali.kfs.module.ar.document.CashControlDocument, org.kuali.kfs.module.ar.businessobject.CashControlDetail)
072         */
073        public PaymentApplicationDocument createAndSavePaymentApplicationDocument(String description, CashControlDocument cashControlDocument, CashControlDetail cashControlDetail) throws WorkflowException {
074    
075            // create a new PaymentApplicationdocument
076            PaymentApplicationDocument doc = (PaymentApplicationDocument) documentService.getNewDocument(PaymentApplicationDocument.class);
077            
078            // set a description to say that this application document has been created by the CashControldocument
079            doc.getDocumentHeader().setDocumentDescription(description);
080    
081            // the line amount for the new PaymentApplicationDocument should be the line amount in the new cash control detail
082            doc.getDocumentHeader().setFinancialDocumentTotalAmount(cashControlDetail.getFinancialDocumentLineAmount());
083    
084            //  re-use the Processing Chart/Org from the CashControlDoc's arDocHeader
085            String processingChartCode = cashControlDocument.getAccountsReceivableDocumentHeader().getProcessingChartOfAccountCode();
086            String processingOrgCode = cashControlDocument.getAccountsReceivableDocumentHeader().getProcessingOrganizationCode();
087            
088            //  create the arDocHeader
089            // NOTE that we re-use the processing chart/org from the CashControl document, rather than 
090            // pull from the current user.  This is done to bypass some challenges in the Lockbox batch process, 
091            // and we dont believe it will impact the processing CashControl processing, as the PayApps created 
092            // always have the same processing chart/org as the cashcontrol doc that creates is
093            AccountsReceivableDocumentHeaderService arDocHeaderService = SpringContext.getBean(AccountsReceivableDocumentHeaderService.class);
094            AccountsReceivableDocumentHeader arDocHeader = arDocHeaderService.getNewAccountsReceivableDocumentHeader(processingChartCode, processingOrgCode);
095            arDocHeader.setDocumentNumber(doc.getDocumentNumber());
096            arDocHeader.setCustomerNumber(cashControlDetail.getCustomerNumber());
097            doc.setAccountsReceivableDocumentHeader(arDocHeader);
098    
099            doc.getDocumentHeader().setOrganizationDocumentNumber(cashControlDocument.getDocumentNumber());
100            
101            // refresh nonupdatable references and save the PaymentApplicationDocument
102            doc.refreshNonUpdateableReferences();
103    
104            // This attribute is transient but is necessary to sort of bootstrap, allowing some validation rules
105            // to succeed before the document is saved again.
106            doc.setCashControlDetail(cashControlDetail);
107            
108    //        AccountsReceivableDocumentHeader accountsReceivableDocumentHeader2 = accountsReceivableDocumentHeaderService.getNewAccountsReceivableDocumentHeaderForCurrentUser();
109    //        accountsReceivableDocumentHeader2.setDocumentNumber(doc.getDocumentNumber());
110    //        accountsReceivableDocumentHeader2.setCustomerNumber(cashControlDetail.getCustomerNumber());
111    //        doc.getNonAppliedHolding().setAccountsReceivableDocumentHeader(accountsReceivableDocumentHeader2);
112    //        doc.getNonAppliedHolding().setCustomerNumber(cashControlDetail.getCustomerNumber());
113    //        doc.getNonAppliedHolding().setReferenceFinancialDocumentNumber(doc.getDocumentNumber());
114            doc.setNonAppliedHolding(null);
115            
116             documentService.saveDocument(doc);       
117            final WorkflowDocumentActions workflowDocumentActions = SpringContext.getBean(WorkflowDocumentActions.class);
118            workflowDocumentActions.indexDocument(new Long(doc.getDocumentNumber()));
119            
120            return doc;
121        }
122    
123        /**
124         * @see org.kuali.kfs.module.ar.document.service.CashControlDocumentService#addNewCashControlDetail(java.lang.String,
125         *      org.kuali.kfs.module.ar.document.CashControlDocument, org.kuali.kfs.module.ar.businessobject.CashControlDetail)
126         */
127        public void addNewCashControlDetail(String description, CashControlDocument cashControlDocument, CashControlDetail cashControlDetail) throws WorkflowException {
128    
129            // add cash control detail
130            cashControlDocument.addCashControlDetail(cashControlDetail);
131    
132            // create a new PaymentApplicationdocument
133            // This has to happen after adding the cash control detail so that payment application saving rules succeed.
134            PaymentApplicationDocument doc = createAndSavePaymentApplicationDocument(description, cashControlDocument, cashControlDetail);
135    
136            // update new cash control detail fields to refer to the new created PaymentApplicationDocument
137            cashControlDetail.setReferenceFinancialDocument(doc);
138            cashControlDetail.setReferenceFinancialDocumentNumber(doc.getDocumentNumber());
139            // newCashControlDetail.setStatus(doc.getDocumentHeader().getWorkflowDocument().getStatusDisplayValue());
140            
141            // Save the cash control document, but do NOT do a full workflow-save, just persist the state
142            doc.populateDocumentForRouting();
143            doc.prepareForSave();
144            documentService.prepareWorkflowDocument(doc);
145     
146            documentService.saveDocument(cashControlDocument);
147            final WorkflowDocumentActions workflowDocumentActions = SpringContext.getBean(WorkflowDocumentActions.class);
148            workflowDocumentActions.indexDocument(new Long(cashControlDocument.getDocumentNumber()));
149      
150            final SearchableAttributeProcessingService searchableAttributeProcessingService = SpringContext.getBean(SearchableAttributeProcessingService.class);
151            searchableAttributeProcessingService.indexDocument(new Long(doc.getDocumentNumber()));
152      
153        }
154    
155        /**
156         * @see org.kuali.kfs.module.ar.document.service.CashControlDocumentService#saveGLPEs(org.kuali.kfs.module.ar.document.CashControlDocument)
157         */
158        public void saveGLPEs(CashControlDocument cashControlDocument) {
159            businessObjectService.save(cashControlDocument.getGeneralLedgerPendingEntries());
160        }
161    
162        /**
163         * @see org.kuali.kfs.module.ar.document.service.CashControlDocumentService#createCashReceiptGLPEs(org.kuali.kfs.module.ar.document.CashControlDocument,
164         *      org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
165         */
166        public boolean createCashReceiptGLPEs(CashControlDocument cashControlDocument, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
167    
168            boolean success = true;
169            AccountingLine accountingLine = null;
170            GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry();
171    
172            Integer currentFiscalYear = universityDateService.getCurrentFiscalYear();
173    
174            // get accounts receivable document header to get processing chart of accounts and organization
175            AccountsReceivableDocumentHeader accountsReceivableDocumentHeader = cashControlDocument.getAccountsReceivableDocumentHeader();
176            String processingChartOfAccountCode = accountsReceivableDocumentHeader.getProcessingChartOfAccountCode();
177            String processingOrganizationCode = accountsReceivableDocumentHeader.getProcessingOrganizationCode();
178    
179            // get system information by processing chart of accounts and organization
180            Map criteria = new HashMap();
181            criteria.put("universityFiscalYear", currentFiscalYear);
182            criteria.put("processingChartOfAccountCode", processingChartOfAccountCode);
183            criteria.put("processingOrganizationCode", processingOrganizationCode);
184            SystemInformation systemInformation = (SystemInformation)SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(SystemInformation.class, criteria);
185            
186            // if there is no system information for this processing chart of accounts and organization return false; glpes cannot be
187            // created
188            if (ObjectUtils.isNull(systemInformation)) {
189                return false;
190            }
191    
192            // get current year options
193            SystemOptions options = optionsService.getCurrentYearOptions();
194    
195            // build an accounting line that will be used to create the glpe 
196            // ignore university clearing sub-object-code KULAR-633
197            accountingLine = buildAccountingLine(systemInformation.getUniversityClearingAccountNumber(), systemInformation.getUniversityClearingSubAccountNumber(), systemInformation.getUniversityClearingObjectCode(), null, systemInformation.getUniversityClearingChartOfAccountsCode(), KFSConstants.GL_CREDIT_CODE, cashControlDocument.getCashControlTotalAmount());
198            // get document type for the glpes
199            String financialSystemDocumentTypeCode = getDataDictionaryService().getDocumentTypeNameByClass(cashControlDocument.getClass());
200            // create and add the new explicit entry based on this accounting line
201            explicitEntry = createAndAddNewExplicitEntry(cashControlDocument, sequenceHelper, accountingLine, options, financialSystemDocumentTypeCode);
202            // create and add the offset entry
203            success &= createAndAddTheOffsetEntry(cashControlDocument, explicitEntry, accountingLine, sequenceHelper);
204    
205            return success;
206        }
207        
208        /**
209         * Creates bank offset GLPEs for the cash control document
210         * @param cashControlDocument the document to create cash control GLPEs for
211         * @param sequenceHelper the sequence helper which will sequence the new GLPEs
212         * @return true if the new bank offset GLPEs were created successfully, false otherwise
213         */
214        public boolean createBankOffsetGLPEs(CashControlDocument cashControlDocument, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
215            boolean success = true;
216            if (SpringContext.getBean(BankService.class).isBankSpecificationEnabled()) {
217                // get associated bank
218                Bank bank = (Bank) SpringContext.getBean(BankService.class).getByPrimaryId(cashControlDocument.getBankCode());
219                GeneralLedgerPendingEntry bankOffsetEntry = new GeneralLedgerPendingEntry();
220                final KualiDecimal totalAmount = glpeService.getOffsetToCashAmount(cashControlDocument).negated();
221                // add additional GLPE's based on bank code
222                if (glpeService.populateBankOffsetGeneralLedgerPendingEntry(bank, totalAmount, cashControlDocument, cashControlDocument.getPostingYear(), sequenceHelper, bankOffsetEntry, ArPropertyConstants.CashControlDocumentFields.BANK_CODE)) {
223                    AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
224                    bankOffsetEntry.setTransactionLedgerEntryDescription(accountingDocumentRuleUtil.formatProperty(KFSKeyConstants.Bank.DESCRIPTION_GLPE_BANK_OFFSET));
225                    cashControlDocument.addPendingEntry(bankOffsetEntry);
226                    sequenceHelper.increment();
227                    GeneralLedgerPendingEntry offsetEntry = new GeneralLedgerPendingEntry(bankOffsetEntry);
228                    success &= glpeService.populateOffsetGeneralLedgerPendingEntry(cashControlDocument.getPostingYear(), bankOffsetEntry, sequenceHelper, offsetEntry);
229                    cashControlDocument.addPendingEntry(offsetEntry);
230                    sequenceHelper.increment();
231                }
232                else {
233                    success = false;
234                }
235            }
236            return success;
237        }
238    
239        /**
240         * @see org.kuali.kfs.module.ar.document.service.CashControlDocumentService#createDistributionOfIncomeAndExpenseGLPEs(org.kuali.kfs.module.ar.document.CashControlDocument, org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
241         */
242        public boolean createDistributionOfIncomeAndExpenseGLPEs(CashControlDocument cashControlDocument, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
243            boolean success = true;
244            
245            AccountingLine accountingLine = null;
246            GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry();
247    
248            Integer currentFiscalYear = universityDateService.getCurrentFiscalYear();
249    
250            // get the accounts receivable document header to get the processing chart of accounts code and organization
251            AccountsReceivableDocumentHeader accountsReceivableDocumentHeader = cashControlDocument.getAccountsReceivableDocumentHeader();
252            String processingChartOfAccountCode = accountsReceivableDocumentHeader.getProcessingChartOfAccountCode();
253            String processingOrganizationCode = accountsReceivableDocumentHeader.getProcessingOrganizationCode();
254    
255            // get system information by processing chart of acccounts and organization
256            Map criteria = new HashMap();
257            criteria.put("universityFiscalYear", currentFiscalYear);
258            criteria.put("processingChartOfAccountCode", processingChartOfAccountCode);
259            criteria.put("processingOrganizationCode", processingOrganizationCode);
260            SystemInformation systemInformation = (SystemInformation)SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(SystemInformation.class, criteria);
261    
262            // if there is no system information set up for this processing chart of accounts and organization return false, glpes
263            // cannot be created
264            if (ObjectUtils.isNull(systemInformation)) {
265                return false;
266            }
267    
268            // get current year options
269            SystemOptions options = optionsService.getCurrentYearOptions();
270            
271            // build dummy accounting line for gl population
272            // ignore university clearing sub-object-code KULAR-633
273            accountingLine = buildAccountingLine(systemInformation.getUniversityClearingAccountNumber(), systemInformation.getUniversityClearingSubAccountNumber(), systemInformation.getUniversityClearingObjectCode(), null, systemInformation.getUniversityClearingChartOfAccountsCode(), KFSConstants.GL_CREDIT_CODE, cashControlDocument.getCashControlTotalAmount());
274            // get document type for the glpes
275            String financialSystemDocumentTypeCode = getDataDictionaryService().getDocumentTypeNameByClass(cashControlDocument.getClass());
276            // create and add the new explicit entry based on this accounting line
277            explicitEntry = createAndAddNewExplicitEntry(cashControlDocument, sequenceHelper, accountingLine, options, financialSystemDocumentTypeCode);
278            // create and add the offset entry
279            success &= createAndAddTheOffsetEntry(cashControlDocument, explicitEntry, accountingLine, sequenceHelper);
280    
281            // get Advance Deposit accounting lines by getting Electronic Payment Claims
282            Map criteria2 = new HashMap();
283            criteria2.put("referenceFinancialDocumentNumber", cashControlDocument.getDocumentNumber());
284            Collection<ElectronicPaymentClaim> electronicPaymentClaims = SpringContext.getBean(BusinessObjectService.class).findMatching(ElectronicPaymentClaim.class, criteria2);
285    
286            // no EFT claims found
287            if (ObjectUtils.isNull(electronicPaymentClaims)) {
288                return false;
289            }
290    
291            // for each Advance Deposit accounting line, create a reverse GLPE in CashControl document.
292            for (ElectronicPaymentClaim electronicPaymentClaim : electronicPaymentClaims ) {
293                Map criteria3= new HashMap();
294                criteria3.put("documentNumber", electronicPaymentClaim.getDocumentNumber());
295                criteria3.put("sequenceNumber", electronicPaymentClaim.getFinancialDocumentLineNumber());
296                criteria3.put("financialDocumentLineTypeCode", "F");
297                SourceAccountingLine advanceDepositAccountingLine = (SourceAccountingLine)SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(SourceAccountingLine.class, criteria3);
298                
299                // build dummy accounting line for gl creation
300                accountingLine = buildAccountingLine(advanceDepositAccountingLine.getAccountNumber(), advanceDepositAccountingLine.getSubAccountNumber(), advanceDepositAccountingLine.getFinancialObjectCode(), advanceDepositAccountingLine.getFinancialSubObjectCode(), advanceDepositAccountingLine.getChartOfAccountsCode(), KFSConstants.GL_DEBIT_CODE, advanceDepositAccountingLine.getAmount());
301                // create and add the new explicit entry based on this accounting line
302                explicitEntry = createAndAddNewExplicitEntry(cashControlDocument, sequenceHelper, accountingLine, options, financialSystemDocumentTypeCode);
303                // create and add the offset entry
304                success &= createAndAddTheOffsetEntry(cashControlDocument, explicitEntry, accountingLine, sequenceHelper);
305            }
306    
307            return success;
308        }
309    
310        /**
311         * @see org.kuali.kfs.module.ar.document.service.CashControlDocumentService#createGeneralErrorCorrectionGLPEs(org.kuali.kfs.module.ar.document.CashControlDocument, org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
312         */
313        public boolean createGeneralErrorCorrectionGLPEs(CashControlDocument cashControlDocument, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
314            boolean success = true;
315    
316            Integer currentFiscalYear = universityDateService.getCurrentFiscalYear();
317            AccountingLine accountingLine = null;
318    
319            // get accounts receivable document header to get processing chart of accounts and organization code
320            AccountsReceivableDocumentHeader accountsReceivableDocumentHeader = cashControlDocument.getAccountsReceivableDocumentHeader();
321            String processingChartOfAccountCode = accountsReceivableDocumentHeader.getProcessingChartOfAccountCode();
322            String processingOrganizationCode = accountsReceivableDocumentHeader.getProcessingOrganizationCode();
323    
324            // get system information by processing chart of accounts and organization code
325            Map criteria = new HashMap();
326            criteria.put("universityFiscalYear", currentFiscalYear);
327            criteria.put("processingChartOfAccountCode", processingChartOfAccountCode);
328            criteria.put("processingOrganizationCode", processingOrganizationCode);
329            SystemInformation systemInformation = (SystemInformation)SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(SystemInformation.class, criteria);
330    
331            // if no system information is set up for this processing chart of accounts and organization code return false, the glpes
332            // cannot be created
333            if (ObjectUtils.isNull(systemInformation)) {
334                return false;
335            }
336    
337            GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry();
338    
339            SystemOptions options = optionsService.getCurrentYearOptions();
340    
341            // build dummy accounting line for gl creation
342            // ignore university clearing sub-object-code KULAR-633
343            accountingLine = buildAccountingLine(systemInformation.getUniversityClearingAccountNumber(), systemInformation.getUniversityClearingSubAccountNumber(), systemInformation.getCreditCardObjectCode(), null, systemInformation.getUniversityClearingChartOfAccountsCode(), KFSConstants.GL_DEBIT_CODE, cashControlDocument.getCashControlTotalAmount());
344            //get document type for the glpes
345            String financialSystemDocumentTypeCode = getDataDictionaryService().getDocumentTypeNameByClass(cashControlDocument.getClass());
346            // create and add the new explicit entry based on this accounting line
347            createAndAddNewExplicitEntry(cashControlDocument, sequenceHelper, accountingLine, options, financialSystemDocumentTypeCode);
348    
349            // build dummy accounting line for gl creation
350            // ignore university clearing sub-object-code KULAR-633
351            accountingLine = buildAccountingLine(systemInformation.getUniversityClearingAccountNumber(), systemInformation.getUniversityClearingSubAccountNumber(), systemInformation.getUniversityClearingObjectCode(), null, systemInformation.getUniversityClearingChartOfAccountsCode(), KFSConstants.GL_CREDIT_CODE, cashControlDocument.getCashControlTotalAmount());
352            // create and add the new explicit entry based on this accounting line
353            createAndAddNewExplicitEntry(cashControlDocument, sequenceHelper, accountingLine, options, financialSystemDocumentTypeCode);
354    
355            return success;
356        }
357    
358        /**
359         * @see org.kuali.kfs.module.ar.document.service.CashControlDocumentService#getLockboxNumber(org.kuali.kfs.module.ar.document.CashControlDocument)
360         */
361        public String getLockboxNumber(CashControlDocument cashControlDocument) {
362    
363            Integer currentFiscalYear = universityDateService.getCurrentFiscalYear();
364            String chartOfAccountsCode = cashControlDocument.getAccountsReceivableDocumentHeader().getProcessingChartOfAccountCode();
365            String processingOrgCode = cashControlDocument.getAccountsReceivableDocumentHeader().getProcessingOrganizationCode();
366            Map criteria = new HashMap();
367            criteria.put("universityFiscalYear", currentFiscalYear);
368            criteria.put("processingChartOfAccountCode", chartOfAccountsCode);
369            criteria.put("processingOrganizationCode", processingOrgCode);
370            SystemInformation systemInformation = (SystemInformation)SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(SystemInformation.class, criteria);
371    
372            return (systemInformation == null) ? null : systemInformation.getLockboxNumber();
373    
374        }
375    
376        /**
377         * This method creates an accounting line.
378         * 
379         * @param systemInformation System Information used to set accounting line data
380         * @param debitOrCredit Tells if it is debit or credit
381         * @param amount The amount
382         * @return The created accounting line
383         */
384        protected AccountingLine buildAccountingLine(String accountNumber, String subAccountNumber, String objectCode, String subObjectCode, String chartOfAccountsCode, String debitOrCredit, KualiDecimal amount) {
385    
386            AccountingLine accountingLine = null;
387    
388            // get new accounting line
389            try {
390                accountingLine = (SourceAccountingLine) SourceAccountingLine.class.newInstance();
391            }
392            catch (IllegalAccessException e) {
393                throw new InfrastructureException("unable to access sourceAccountingLineClass", e);
394            }
395            catch (InstantiationException e) {
396                throw new InfrastructureException("unable to instantiate sourceAccountingLineClass", e);
397            }
398    
399            accountingLine.setAccountNumber(accountNumber);
400            accountingLine.setFinancialObjectCode(objectCode);
401            accountingLine.setSubAccountNumber(subAccountNumber);
402            accountingLine.setChartOfAccountsCode(chartOfAccountsCode);
403            accountingLine.setFinancialSubObjectCode(subObjectCode);
404            accountingLine.setDebitCreditCode(debitOrCredit);
405            accountingLine.setAmount(amount);
406    
407            return accountingLine;
408    
409        }
410    
411        /**
412         * This method creates and adds a new explicit glpe
413         * 
414         * @param cashControlDocument the cash control document
415         * @param sequenceHelper sequence helper
416         * @param accountingLine the accounting line based on which the glpe is created
417         * @param options the current year oprions
418         * @param documentType the document type to be associated with the glpe
419         */
420        protected GeneralLedgerPendingEntry createAndAddNewExplicitEntry(CashControlDocument cashControlDocument, GeneralLedgerPendingEntrySequenceHelper sequenceHelper, AccountingLine accountingLine, SystemOptions options, String documentType) {
421    
422            GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry();
423    
424            glpeService.populateExplicitGeneralLedgerPendingEntry(cashControlDocument, accountingLine, sequenceHelper, explicitEntry);
425    
426            explicitEntry.setFinancialObjectTypeCode(options.getFinancialObjectTypeAssetsCd());
427            explicitEntry.setFinancialDocumentTypeCode(documentType);
428            explicitEntry.setDocumentNumber(cashControlDocument.getDocumentNumber());
429    
430            // add the new explicit entry to the document now
431            cashControlDocument.addPendingEntry(explicitEntry);
432    
433            cashControlDocument.customizeExplicitGeneralLedgerPendingEntry(accountingLine, explicitEntry);
434    
435            // increment the sequence counter
436            sequenceHelper.increment();
437            return explicitEntry;
438    
439        }
440    
441        /**
442         * This method creates and adds an offset entry for the given explicit entry and accounting line.
443         * 
444         * @param cashControlDocument the cash control document
445         * @param explicitEntry the explicit entry for which we create the offset entry
446         * @param accountingLine the accounting line used to populate the offset entry
447         * @param sequenceHelper the sequence helper
448         * @return true if successfuly created and added, false otherwise
449         */
450        protected boolean createAndAddTheOffsetEntry(CashControlDocument cashControlDocument, GeneralLedgerPendingEntry explicitEntry, AccountingLine accountingLine, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
451            boolean success = true;
452    
453            // create offset
454            GeneralLedgerPendingEntry offsetEntry = new GeneralLedgerPendingEntry(explicitEntry);
455            success &= glpeService.populateOffsetGeneralLedgerPendingEntry(cashControlDocument.getPostingYear(), explicitEntry, sequenceHelper, offsetEntry);
456            cashControlDocument.customizeOffsetGeneralLedgerPendingEntry(accountingLine, explicitEntry, offsetEntry);
457    
458            // add the offset
459            cashControlDocument.addPendingEntry(offsetEntry);
460    
461            // increment the sequence counter
462            sequenceHelper.increment();
463    
464            return success;
465        }
466    
467    
468        /**
469         * This method gets the system information servcie
470         * @return the system information service
471         */
472        public SystemInformationService getSystemInformationService() {
473            return systemInformationService;
474        }
475    
476        /**
477         * This method sets the system information service
478         * @param systemInformationService
479         */
480        public void setSystemInformationService(SystemInformationService systemInformationService) {
481            this.systemInformationService = systemInformationService;
482        }
483    
484        /**
485         * This method gets the chart service
486         * @return
487         */
488        public ChartService getChartService() {
489            return chartService;
490        }
491    
492        /**
493         * This method sets the chart service
494         * @param chartService
495         */
496        public void setChartService(ChartService chartService) {
497            this.chartService = chartService;
498        }
499    
500        /**
501         * Gets the dataDictionaryService attribute. 
502         * @return Returns the dataDictionaryService.
503         */
504        public DataDictionaryService getDataDictionaryService() {
505            return dataDictionaryService;
506        }
507    
508        /**
509         * Sets the dataDictionaryService attribute value.
510         * @param dataDictionaryService The dataDictionaryService to set.
511         */
512        public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
513            this.dataDictionaryService = dataDictionaryService;
514        }
515    
516        /**
517         * This method gets the glpe service
518         * @return
519         */
520        public GeneralLedgerPendingEntryService getGlpeService() {
521            return glpeService;
522        }
523    
524        /**
525         * This method sets the glpe service
526         * @param glpeService
527         */
528        public void setGlpeService(GeneralLedgerPendingEntryService glpeService) {
529            this.glpeService = glpeService;
530        }
531    
532        /**
533         * This method gets the business object service
534         * @return the business object service
535         */
536        public BusinessObjectService getBusinessObjectService() {
537            return businessObjectService;
538        }
539    
540        /**
541         * This method sets the business object service
542         * @param businessObjectService
543         */
544        public void setBusinessObjectService(BusinessObjectService businessObjectService) {
545            this.businessObjectService = businessObjectService;
546        }
547    
548        /**
549         * This method gets the option service
550         * @return the option service
551         */
552        public OptionsService getOptionsService() {
553            return optionsService;
554        }
555    
556        /**
557         * This method sets the option service
558         * @param optionsService
559         */
560        public void setOptionsService(OptionsService optionsService) {
561            this.optionsService = optionsService;
562        }
563    
564        /**
565         * This method gets the accounts receivable header
566         * @return the accounts receivable header
567         */
568        public AccountsReceivableDocumentHeaderService getAccountsReceivableDocumentHeaderService() {
569            return accountsReceivableDocumentHeaderService;
570        }
571    
572        /**
573         * This method sets the accounts receivable header
574         * @param accountsReceivableDocumentHeaderService
575         */
576        public void setAccountsReceivableDocumentHeaderService(AccountsReceivableDocumentHeaderService accountsReceivableDocumentHeaderService) {
577            this.accountsReceivableDocumentHeaderService = accountsReceivableDocumentHeaderService;
578        }
579    
580        /**
581         * This method gets the document service
582         * @return the document service
583         */
584        public DocumentService getDocumentService() {
585            return documentService;
586        }
587    
588        /**
589         * This method sets the document service
590         * @param documentService
591         */
592        public void setDocumentService(DocumentService documentService) {
593            this.documentService = documentService;
594        }
595    
596        public UniversityDateService getUniversityDateService() {
597            return universityDateService;
598        }
599    
600        public void setUniversityDateService(UniversityDateService universityDateService) {
601            this.universityDateService = universityDateService;
602        }
603    
604    }