View Javadoc
1   /*
2    * Copyright 2006 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.kuali.ole.fp.document;
18  
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.HashSet;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Map;
25  
26  import org.apache.commons.lang.StringUtils;
27  import org.kuali.ole.coa.businessobject.Account;
28  import org.kuali.ole.coa.service.AccountService;
29  import org.kuali.ole.fp.businessobject.BudgetAdjustmentAccountingLine;
30  import org.kuali.ole.fp.businessobject.BudgetAdjustmentSourceAccountingLine;
31  import org.kuali.ole.fp.businessobject.BudgetAdjustmentTargetAccountingLine;
32  import org.kuali.ole.fp.businessobject.FiscalYearFunctionControl;
33  import org.kuali.ole.fp.document.validation.impl.BudgetAdjustmentDocumentRuleConstants;
34  import org.kuali.ole.fp.document.validation.impl.TransferOfFundsDocumentRuleConstants;
35  import org.kuali.ole.fp.service.FiscalYearFunctionControlService;
36  import org.kuali.ole.sys.OLEConstants;
37  import org.kuali.ole.sys.OLEPropertyConstants;
38  import org.kuali.ole.sys.businessobject.AccountResponsibility;
39  import org.kuali.ole.sys.businessobject.AccountingLine;
40  import org.kuali.ole.sys.businessobject.AccountingLineParser;
41  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry;
42  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper;
43  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
44  import org.kuali.ole.sys.businessobject.SourceAccountingLine;
45  import org.kuali.ole.sys.businessobject.SystemOptions;
46  import org.kuali.ole.sys.context.SpringContext;
47  import org.kuali.ole.sys.document.AccountingDocumentBase;
48  import org.kuali.ole.sys.document.AmountTotaling;
49  import org.kuali.ole.sys.document.Correctable;
50  import org.kuali.ole.sys.document.service.AccountingDocumentRuleHelperService;
51  import org.kuali.ole.sys.document.service.DebitDeterminerService;
52  import org.kuali.ole.sys.service.GeneralLedgerPendingEntryService;
53  import org.kuali.ole.sys.service.OptionsService;
54  import org.kuali.ole.sys.service.UniversityDateService;
55  import org.kuali.rice.core.api.parameter.ParameterEvaluatorService;
56  import org.kuali.rice.core.api.util.type.KualiDecimal;
57  import org.kuali.rice.core.api.util.type.KualiInteger;
58  import org.kuali.rice.core.web.format.CurrencyFormatter;
59  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
60  import org.kuali.rice.kew.api.exception.WorkflowException;
61  import org.kuali.rice.kim.api.identity.Person;
62  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
63  import org.kuali.rice.krad.document.Copyable;
64  import org.kuali.rice.krad.util.ObjectUtils;
65  
66  /**
67   * This is the business object that represents the BudgetAdjustment document in Kuali.
68   */
69  public class BudgetAdjustmentDocument extends AccountingDocumentBase implements Copyable, Correctable, AmountTotaling {
70      protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(BudgetAdjustmentDocument.class);
71      
72      protected static final String REQUIRES_FULL_APPROVAL_SPLIT_NODE_NAME = "RequiresFullApproval";
73  
74      protected Integer nextPositionSourceLineNumber;
75      protected Integer nextPositionTargetLineNumber;
76  
77      /**
78       * Default constructor.
79       */
80      public BudgetAdjustmentDocument() {
81          super();
82      }
83  
84  
85      /*******************************************************************************************************************************
86       * BA Documents should only do SF checking on PLEs with a Balance Type of 'CB' - not 'BB' or 'MB'.
87       * 
88       * 
89       * @see org.kuali.ole.sys.document.AccountingDocumentBase#getPendingLedgerEntriesForSufficientFundsChecking()
90       */
91      public List<GeneralLedgerPendingEntry> getPendingLedgerEntriesForSufficientFundsChecking() {
92          List<GeneralLedgerPendingEntry> pendingLedgerEntries = new ArrayList();
93  
94          GeneralLedgerPendingEntrySequenceHelper glpeSequenceHelper = new GeneralLedgerPendingEntrySequenceHelper();
95  
96          BudgetAdjustmentDocument copiedBa = (BudgetAdjustmentDocument) ObjectUtils.deepCopy(this);
97          copiedBa.getGeneralLedgerPendingEntries().clear();
98          for (BudgetAdjustmentAccountingLine fromLine : (List<BudgetAdjustmentAccountingLine>) copiedBa.getSourceAccountingLines()) {
99              copiedBa.generateGeneralLedgerPendingEntries(fromLine, glpeSequenceHelper);
100         }
101 
102         for (GeneralLedgerPendingEntry ple : copiedBa.getGeneralLedgerPendingEntries()) {
103             if (!OLEConstants.BALANCE_TYPE_BASE_BUDGET.equals(ple.getFinancialBalanceTypeCode()) && !OLEConstants.BALANCE_TYPE_MONTHLY_BUDGET.equals(ple.getFinancialBalanceTypeCode())) {
104                 pendingLedgerEntries.add(ple);
105             }
106         }
107         return pendingLedgerEntries;
108     }
109 
110     /**
111      * generic, shared logic used to iniate a ba document
112      */
113     public void initiateDocument() {
114         // setting default posting year. Trying to set currentYear first if it's allowed, if it isn't,
115         // just set first allowed year. Note: allowedYears will never be empty because then
116         // BudgetAdjustmentDocumentAuthorizer.canInitiate would have failed.
117         List allowedYears = SpringContext.getBean(FiscalYearFunctionControlService.class).getBudgetAdjustmentAllowedYears();
118         Integer currentYearParam = SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear();
119 
120         FiscalYearFunctionControl fiscalYearFunctionControl = new FiscalYearFunctionControl();
121         fiscalYearFunctionControl.setUniversityFiscalYear(currentYearParam);
122 
123         // use 'this.postingYear =' because setPostingYear has logic we want to circumvent on initiateDocument
124         if (allowedYears.contains(fiscalYearFunctionControl)) {
125             this.postingYear = currentYearParam;
126         }
127         else {
128             this.postingYear = ((FiscalYearFunctionControl) allowedYears.get(0)).getUniversityFiscalYear();
129         }
130     }
131 
132     /**
133      * @return Integer
134      */
135     public Integer getNextPositionSourceLineNumber() {
136         return nextPositionSourceLineNumber;
137     }
138 
139     /**
140      * @param nextPositionSourceLineNumber
141      */
142     public void setNextPositionSourceLineNumber(Integer nextPositionSourceLineNumber) {
143         this.nextPositionSourceLineNumber = nextPositionSourceLineNumber;
144     }
145 
146     /**
147      * @return Integer
148      */
149     public Integer getNextPositionTargetLineNumber() {
150         return nextPositionTargetLineNumber;
151     }
152 
153     /**
154      * @param nextPositionTargetLineNumber
155      */
156     public void setNextPositionTargetLineNumber(Integer nextPositionTargetLineNumber) {
157         this.nextPositionTargetLineNumber = nextPositionTargetLineNumber;
158     }
159 
160     /**
161      * Returns the total current budget amount from the source lines.
162      * 
163      * @return KualiDecimal
164      */
165     public KualiDecimal getSourceCurrentBudgetTotal() {
166         KualiDecimal currentBudgetTotal = KualiDecimal.ZERO;
167 
168         for (Iterator iter = sourceAccountingLines.iterator(); iter.hasNext();) {
169             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
170             currentBudgetTotal = currentBudgetTotal.add(line.getCurrentBudgetAdjustmentAmount());
171         }
172 
173         return currentBudgetTotal;
174     }
175 
176     /**
177      * This method retrieves the total current budget amount formatted as currency.
178      * 
179      * @return String
180      */
181     public String getCurrencyFormattedSourceCurrentBudgetTotal() {
182         return (String) new CurrencyFormatter().format(getSourceCurrentBudgetTotal());
183     }
184 
185     /**
186      * Returns the total current budget income amount from the source lines.
187      * 
188      * @return KualiDecimal
189      */
190     public KualiDecimal getSourceCurrentBudgetIncomeTotal() {
191         KualiDecimal total = KualiDecimal.ZERO;
192 
193         for (Iterator iter = sourceAccountingLines.iterator(); iter.hasNext();) {
194             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
195             AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
196             if (accountingDocumentRuleUtil.isIncome(line)) {
197                 total = total.add(line.getCurrentBudgetAdjustmentAmount());
198             }
199         }
200 
201         return total;
202     }
203 
204     /**
205      * Returns the total current budget expense amount from the source lines.
206      * 
207      * @return KualiDecimal
208      */
209     public KualiDecimal getSourceCurrentBudgetExpenseTotal() {
210         KualiDecimal total = KualiDecimal.ZERO;
211 
212         for (Iterator iter = sourceAccountingLines.iterator(); iter.hasNext();) {
213             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
214             AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
215             if (accountingDocumentRuleUtil.isExpense(line)) {
216                 total = total.add(line.getCurrentBudgetAdjustmentAmount());
217             }
218         }
219 
220         return total;
221     }
222 
223     /**
224      * Returns the total current budget amount from the target lines.
225      * 
226      * @return KualiDecimal
227      */
228     public KualiDecimal getTargetCurrentBudgetTotal() {
229         KualiDecimal currentBudgetTotal = KualiDecimal.ZERO;
230 
231         for (Iterator iter = targetAccountingLines.iterator(); iter.hasNext();) {
232             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
233             currentBudgetTotal = currentBudgetTotal.add(line.getCurrentBudgetAdjustmentAmount());
234         }
235 
236         return currentBudgetTotal;
237     }
238 
239     /**
240      * This method retrieves the total current budget amount formatted as currency.
241      * 
242      * @return String
243      */
244     public String getCurrencyFormattedTargetCurrentBudgetTotal() {
245         return (String) new CurrencyFormatter().format(getTargetCurrentBudgetTotal());
246     }
247 
248     /**
249      * Returns the total current budget income amount from the target lines.
250      * 
251      * @return KualiDecimal
252      */
253     public KualiDecimal getTargetCurrentBudgetIncomeTotal() {
254         KualiDecimal total = KualiDecimal.ZERO;
255 
256         AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
257         for (Iterator iter = targetAccountingLines.iterator(); iter.hasNext();) {
258             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
259             if (accountingDocumentRuleUtil.isIncome(line)) {
260                 total = total.add(line.getCurrentBudgetAdjustmentAmount());
261             }
262         }
263 
264         return total;
265     }
266 
267     /**
268      * Returns the total current budget expense amount from the target lines.
269      * 
270      * @return KualiDecimal
271      */
272     public KualiDecimal getTargetCurrentBudgetExpenseTotal() {
273         KualiDecimal total = KualiDecimal.ZERO;
274 
275         AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
276         for (Iterator iter = targetAccountingLines.iterator(); iter.hasNext();) {
277             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
278             if (accountingDocumentRuleUtil.isExpense(line)) {
279                 total = total.add(line.getCurrentBudgetAdjustmentAmount());
280             }
281         }
282 
283         return total;
284     }
285 
286     /**
287      * Returns the total base budget amount from the source lines.
288      * 
289      * @return KualiDecimal
290      */
291     public KualiDecimal getSourceBaseBudgetTotal() {
292         KualiDecimal baseBudgetTotal = KualiDecimal.ZERO;
293 
294         for (Iterator iter = sourceAccountingLines.iterator(); iter.hasNext();) {
295             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
296             baseBudgetTotal = baseBudgetTotal.add(line.getBaseBudgetAdjustmentAmount());
297         }
298 
299         return baseBudgetTotal;
300     }
301 
302 
303     /**
304      * This method retrieves the total base budget amount formatted as currency.
305      * 
306      * @return String
307      */
308     public String getCurrencyFormattedSourceBaseBudgetTotal() {
309         return (String) new CurrencyFormatter().format(getSourceBaseBudgetTotal());
310     }
311 
312     /**
313      * Returns the total base budget income amount from the source lines.
314      * 
315      * @return KualiDecimal
316      */
317     public KualiDecimal getSourceBaseBudgetIncomeTotal() {
318         KualiDecimal total = KualiDecimal.ZERO;
319 
320         AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
321         for (Iterator iter = sourceAccountingLines.iterator(); iter.hasNext();) {
322             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
323             if (accountingDocumentRuleUtil.isIncome(line)) {
324                 total = total.add(line.getBaseBudgetAdjustmentAmount());
325             }
326         }
327 
328         return total;
329     }
330 
331     /**
332      * Returns the total base budget expense amount from the source lines.
333      * 
334      * @return KualiDecimal
335      */
336     public KualiDecimal getSourceBaseBudgetExpenseTotal() {
337         KualiDecimal total = KualiDecimal.ZERO;
338 
339         AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
340         for (Iterator iter = sourceAccountingLines.iterator(); iter.hasNext();) {
341             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
342             if (accountingDocumentRuleUtil.isExpense(line)) {
343                 total = total.add(line.getBaseBudgetAdjustmentAmount());
344             }
345         }
346 
347         return total;
348     }
349 
350     /**
351      * Returns the total base budget amount from the target lines.
352      * 
353      * @return KualiDecimal
354      */
355     public KualiDecimal getTargetBaseBudgetTotal() {
356         KualiDecimal baseBudgetTotal = KualiDecimal.ZERO;
357 
358         for (Iterator iter = targetAccountingLines.iterator(); iter.hasNext();) {
359             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
360             baseBudgetTotal = baseBudgetTotal.add(line.getBaseBudgetAdjustmentAmount());
361         }
362 
363         return baseBudgetTotal;
364     }
365 
366     /**
367      * This method retrieves the total base budget amount formatted as currency.
368      * 
369      * @return String
370      */
371     public String getCurrencyFormattedTargetBaseBudgetTotal() {
372         return (String) new CurrencyFormatter().format(getTargetBaseBudgetTotal());
373     }
374 
375     /**
376      * Returns the total base budget income amount from the target lines.
377      * 
378      * @return KualiDecimal
379      */
380     public KualiDecimal getTargetBaseBudgetIncomeTotal() {
381         KualiDecimal total = KualiDecimal.ZERO;
382 
383         AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
384         for (Iterator iter = targetAccountingLines.iterator(); iter.hasNext();) {
385             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
386             if (accountingDocumentRuleUtil.isIncome(line)) {
387                 total = total.add(line.getBaseBudgetAdjustmentAmount());
388             }
389         }
390 
391         return total;
392     }
393 
394     /**
395      * Returns the total base budget expense amount from the target lines.
396      * 
397      * @return KualiDecimal
398      */
399     public KualiDecimal getTargetBaseBudgetExpenseTotal() {
400         KualiDecimal total = KualiDecimal.ZERO;
401 
402         AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
403         for (Iterator iter = targetAccountingLines.iterator(); iter.hasNext();) {
404             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
405             if (accountingDocumentRuleUtil.isExpense(line)) {
406                 total = total.add(line.getBaseBudgetAdjustmentAmount());
407             }
408         }
409 
410         return total;
411     }
412 
413     /**
414      * Same as default implementation but uses getTargetCurrentBudgetTotal and getSourceCurrentBudgetTotal instead.
415      * 
416      * @see org.kuali.ole.sys.document.AccountingDocumentBase#getTotalDollarAmount()
417      * @return KualiDecimal
418      */
419     @Override
420     public KualiDecimal getTotalDollarAmount() {
421         return getTargetCurrentBudgetTotal().equals(KualiDecimal.ZERO) ? getSourceCurrentBudgetTotal().abs() : getTargetCurrentBudgetTotal().abs();
422     }
423 
424     /**
425      * Negate accounting line budget amounts.
426      * 
427      * @see org.kuali.ole.sys.document.AccountingDocumentBase#toErrorCorrection()
428      */
429     @Override
430     public void toErrorCorrection() throws WorkflowException {
431         super.toErrorCorrection();
432 
433         if (this.getSourceAccountingLines() != null) {
434             for (Iterator iter = this.getSourceAccountingLines().iterator(); iter.hasNext();) {
435                 BudgetAdjustmentAccountingLine sourceLine = (BudgetAdjustmentAccountingLine) iter.next();
436                 sourceLine.setBaseBudgetAdjustmentAmount(sourceLine.getBaseBudgetAdjustmentAmount().negated());
437                 sourceLine.setCurrentBudgetAdjustmentAmount(sourceLine.getCurrentBudgetAdjustmentAmount().negated());
438                 sourceLine.setFinancialDocumentMonth1LineAmount(sourceLine.getFinancialDocumentMonth1LineAmount().negated());
439                 sourceLine.setFinancialDocumentMonth2LineAmount(sourceLine.getFinancialDocumentMonth2LineAmount().negated());
440                 sourceLine.setFinancialDocumentMonth3LineAmount(sourceLine.getFinancialDocumentMonth3LineAmount().negated());
441                 sourceLine.setFinancialDocumentMonth4LineAmount(sourceLine.getFinancialDocumentMonth4LineAmount().negated());
442                 sourceLine.setFinancialDocumentMonth5LineAmount(sourceLine.getFinancialDocumentMonth5LineAmount().negated());
443                 sourceLine.setFinancialDocumentMonth6LineAmount(sourceLine.getFinancialDocumentMonth6LineAmount().negated());
444                 sourceLine.setFinancialDocumentMonth7LineAmount(sourceLine.getFinancialDocumentMonth7LineAmount().negated());
445                 sourceLine.setFinancialDocumentMonth8LineAmount(sourceLine.getFinancialDocumentMonth8LineAmount().negated());
446                 sourceLine.setFinancialDocumentMonth9LineAmount(sourceLine.getFinancialDocumentMonth9LineAmount().negated());
447                 sourceLine.setFinancialDocumentMonth10LineAmount(sourceLine.getFinancialDocumentMonth10LineAmount().negated());
448                 sourceLine.setFinancialDocumentMonth11LineAmount(sourceLine.getFinancialDocumentMonth11LineAmount().negated());
449                 sourceLine.setFinancialDocumentMonth12LineAmount(sourceLine.getFinancialDocumentMonth12LineAmount().negated());
450             }
451         }
452 
453         if (this.getTargetAccountingLines() != null) {
454             for (Iterator iter = this.getTargetAccountingLines().iterator(); iter.hasNext();) {
455                 BudgetAdjustmentAccountingLine targetLine = (BudgetAdjustmentAccountingLine) iter.next();
456                 targetLine.setBaseBudgetAdjustmentAmount(targetLine.getBaseBudgetAdjustmentAmount().negated());
457                 targetLine.setCurrentBudgetAdjustmentAmount(targetLine.getCurrentBudgetAdjustmentAmount().negated());
458                 targetLine.setFinancialDocumentMonth1LineAmount(targetLine.getFinancialDocumentMonth1LineAmount().negated());
459                 targetLine.setFinancialDocumentMonth2LineAmount(targetLine.getFinancialDocumentMonth2LineAmount().negated());
460                 targetLine.setFinancialDocumentMonth3LineAmount(targetLine.getFinancialDocumentMonth3LineAmount().negated());
461                 targetLine.setFinancialDocumentMonth4LineAmount(targetLine.getFinancialDocumentMonth4LineAmount().negated());
462                 targetLine.setFinancialDocumentMonth5LineAmount(targetLine.getFinancialDocumentMonth5LineAmount().negated());
463                 targetLine.setFinancialDocumentMonth6LineAmount(targetLine.getFinancialDocumentMonth6LineAmount().negated());
464                 targetLine.setFinancialDocumentMonth7LineAmount(targetLine.getFinancialDocumentMonth7LineAmount().negated());
465                 targetLine.setFinancialDocumentMonth8LineAmount(targetLine.getFinancialDocumentMonth8LineAmount().negated());
466                 targetLine.setFinancialDocumentMonth9LineAmount(targetLine.getFinancialDocumentMonth9LineAmount().negated());
467                 targetLine.setFinancialDocumentMonth10LineAmount(targetLine.getFinancialDocumentMonth10LineAmount().negated());
468                 targetLine.setFinancialDocumentMonth11LineAmount(targetLine.getFinancialDocumentMonth11LineAmount().negated());
469                 targetLine.setFinancialDocumentMonth12LineAmount(targetLine.getFinancialDocumentMonth12LineAmount().negated());
470             }
471         }
472     }
473 
474     /**
475      * The base checks that the posting year is the current year, not a requirement for the ba document.
476      * 
477      * @see org.kuali.rice.krad.document.TransactionalDocumentBase#getAllowsCopy()
478      */
479     @Override
480     public boolean getAllowsCopy() {
481         return true;
482     }
483 
484     /**
485      * @see org.kuali.ole.sys.document.AccountingDocumentBase#getSourceAccountingLinesSectionTitle()
486      */
487     @Override
488     public String getSourceAccountingLinesSectionTitle() {
489         return OLEConstants.BudgetAdjustmentDocumentConstants.SOURCE_BA;
490     }
491 
492     /**
493      * @see org.kuali.ole.sys.document.AccountingDocumentBase#getTargetAccountingLinesSectionTitle()
494      */
495     @Override
496     public String getTargetAccountingLinesSectionTitle() {
497         return OLEConstants.BudgetAdjustmentDocumentConstants.TARGET_BA;
498     }
499 
500     /**
501      * @see org.kuali.rice.krad.document.DocumentBase#populateDocumentForRouting()
502      */
503     @Override
504     public void populateDocumentForRouting() {
505         super.populateDocumentForRouting();
506 
507         // set amount fields of line for routing to current amount field
508         for (Iterator iter = this.getSourceAccountingLines().iterator(); iter.hasNext();) {
509             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
510             line.setAmount(line.getCurrentBudgetAdjustmentAmount());
511         }
512 
513         for (Iterator iter = this.getTargetAccountingLines().iterator(); iter.hasNext();) {
514             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
515             line.setAmount(line.getCurrentBudgetAdjustmentAmount());
516         }
517     }
518 
519     /**
520      * Returns true if accounting line is debit
521      * 
522      * @param financialDocument submitted financial document
523      * @param accountingLine accounting line being evaluated as a debit or not
524      * @see org.kuali.rice.krad.rule.AccountingLineRule#isDebit(org.kuali.rice.krad.document.FinancialDocument,
525      *      org.kuali.rice.krad.bo.AccountingLine)
526      */
527     @Override
528     public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) {
529         try {
530             DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
531             return isDebitUtils.isDebitConsideringType(this, (AccountingLine) postable);
532         }
533         catch (IllegalStateException e) {
534             // for all accounting lines except the transfer lines, the line amount will be 0 and this exception will be thrown
535             return false;
536         }
537     }
538 
539     /**
540      * The budget adjustment document creates GL pending entries much differently that common tp-edocs. The glpes are created for
541      * BB, CB, and MB balance types. Up to 14 entries per line can be created. Along with this, the BA will create TOF entries if
542      * needed to move funding.
543      * 
544      * @param financialDocument submitted accounting document
545      * @param accountingLine validated accounting line
546      * @param sequenceHelper helper class for keeping track of sequence number
547      * @return true if GLPE entries are successfully created.
548      * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#processGenerateGeneralLedgerPendingEntries(org.kuali.rice.krad.document.FinancialDocument,
549      *      org.kuali.rice.krad.bo.AccountingLine, org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
550      */
551     @Override
552     public boolean generateGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
553         AccountingLine accountingLine = (AccountingLine) glpeSourceDetail;
554 
555         // determine if we are on increase or decrease side
556         KualiDecimal amountSign = null;
557         if (accountingLine instanceof SourceAccountingLine) {
558             amountSign = new KualiDecimal(-1);
559         }
560         else {
561             amountSign = new KualiDecimal(1);
562         }
563 
564         BudgetAdjustmentAccountingLine budgetAccountingLine = (BudgetAdjustmentAccountingLine) glpeSourceDetail;
565         Integer currentFiscalYear = SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear();
566         /* Create Base Budget GLPE if base amount != 0 */
567         if (budgetAccountingLine.getBaseBudgetAdjustmentAmount().isNonZero()) {
568             GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry();
569             getGeneralLedgerPendingEntryService().populateExplicitGeneralLedgerPendingEntry(this, accountingLine, sequenceHelper, explicitEntry);
570 
571             /* D/C code is empty for BA, set correct balance type, correct amount */
572             explicitEntry.setTransactionDebitCreditCode("");
573             explicitEntry.setFinancialBalanceTypeCode(OLEConstants.BALANCE_TYPE_BASE_BUDGET);
574             explicitEntry.setTransactionLedgerEntryAmount(budgetAccountingLine.getBaseBudgetAdjustmentAmount().multiply(amountSign));
575             // set fiscal period, if next fiscal year set to 01, else leave to current period
576             if (currentFiscalYear.equals(getPostingYear() - 1)) {
577                 explicitEntry.setUniversityFiscalPeriodCode(BudgetAdjustmentDocumentRuleConstants.MONTH_1_PERIOD_CODE);
578             }
579 
580             customizeExplicitGeneralLedgerPendingEntry(accountingLine, explicitEntry);
581 
582             addPendingEntry(explicitEntry);
583 
584             // increment the sequence counter
585             sequenceHelper.increment();
586         }
587 
588         /* Create Current Budget GLPE if current amount != 0 */
589         if (budgetAccountingLine.getCurrentBudgetAdjustmentAmount().isNonZero()) {
590             GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry();
591             getGeneralLedgerPendingEntryService().populateExplicitGeneralLedgerPendingEntry(this, accountingLine, sequenceHelper, explicitEntry);
592 
593             /* D/C code is empty for BA, set correct balance type, correct amount */
594             explicitEntry.setTransactionDebitCreditCode("");
595             explicitEntry.setFinancialBalanceTypeCode(OLEConstants.BALANCE_TYPE_CURRENT_BUDGET);
596             explicitEntry.setTransactionLedgerEntryAmount(budgetAccountingLine.getCurrentBudgetAdjustmentAmount().multiply(amountSign));
597             // set fiscal period, if next fiscal year set to 01, else leave to current period
598             if (currentFiscalYear.equals(getPostingYear() - 1)) {
599                 explicitEntry.setUniversityFiscalPeriodCode("01");
600             }
601 
602             customizeExplicitGeneralLedgerPendingEntry(accountingLine, explicitEntry);
603 
604             addPendingEntry(explicitEntry);
605 
606             // create monthly lines (MB)
607             if (budgetAccountingLine.getFinancialDocumentMonth1LineAmount().isNonZero()) {
608                 sequenceHelper.increment();
609                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_1_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth1LineAmount().multiply(amountSign));
610             }
611             if (budgetAccountingLine.getFinancialDocumentMonth2LineAmount().isNonZero()) {
612                 sequenceHelper.increment();
613                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_2_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth2LineAmount().multiply(amountSign));
614             }
615             if (budgetAccountingLine.getFinancialDocumentMonth3LineAmount().isNonZero()) {
616                 sequenceHelper.increment();
617                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_3_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth3LineAmount().multiply(amountSign));
618             }
619             if (budgetAccountingLine.getFinancialDocumentMonth4LineAmount().isNonZero()) {
620                 sequenceHelper.increment();
621                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_4_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth4LineAmount().multiply(amountSign));
622             }
623             if (budgetAccountingLine.getFinancialDocumentMonth5LineAmount().isNonZero()) {
624                 sequenceHelper.increment();
625                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_5_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth5LineAmount().multiply(amountSign));
626             }
627             if (budgetAccountingLine.getFinancialDocumentMonth6LineAmount().isNonZero()) {
628                 sequenceHelper.increment();
629                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_6_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth6LineAmount().multiply(amountSign));
630             }
631             if (budgetAccountingLine.getFinancialDocumentMonth7LineAmount().isNonZero()) {
632                 sequenceHelper.increment();
633                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_7_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth7LineAmount().multiply(amountSign));
634             }
635             if (budgetAccountingLine.getFinancialDocumentMonth8LineAmount().isNonZero()) {
636                 sequenceHelper.increment();
637                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_8_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth8LineAmount().multiply(amountSign));
638             }
639             if (budgetAccountingLine.getFinancialDocumentMonth9LineAmount().isNonZero()) {
640                 sequenceHelper.increment();
641                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_9_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth9LineAmount().multiply(amountSign));
642             }
643             if (budgetAccountingLine.getFinancialDocumentMonth10LineAmount().isNonZero()) {
644                 sequenceHelper.increment();
645                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_10_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth10LineAmount().multiply(amountSign));
646             }
647             if (budgetAccountingLine.getFinancialDocumentMonth11LineAmount().isNonZero()) {
648                 sequenceHelper.increment();
649                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_11_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth11LineAmount().multiply(amountSign));
650             }
651             if (budgetAccountingLine.getFinancialDocumentMonth12LineAmount().isNonZero()) {
652                 sequenceHelper.increment();
653                 createMonthlyBudgetGLPE(accountingLine, sequenceHelper, BudgetAdjustmentDocumentRuleConstants.MONTH_12_PERIOD_CODE, budgetAccountingLine.getFinancialDocumentMonth12LineAmount().multiply(amountSign));
654             }
655         }
656         return true;
657     }
658 
659     /**
660      * Helper method for creating monthly budget pending entry lines.
661      * 
662      * @param financialDocument submitted accounting document
663      * @param accountingLine validated accounting line
664      * @param sequenceHelper helper class for keeping track of sequence number
665      * @param fiscalPeriod fiscal year period code
666      * @param monthAmount ledger entry amount for the month
667      */
668     protected void createMonthlyBudgetGLPE(AccountingLine accountingLine, GeneralLedgerPendingEntrySequenceHelper sequenceHelper, String fiscalPeriod, KualiDecimal monthAmount) {
669         GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry();
670         getGeneralLedgerPendingEntryService().populateExplicitGeneralLedgerPendingEntry(this, accountingLine, sequenceHelper, explicitEntry);
671 
672         /* D/C code is empty for BA, set correct balance type, correct amount */
673         explicitEntry.setTransactionDebitCreditCode("");
674         explicitEntry.setFinancialBalanceTypeCode(OLEConstants.BALANCE_TYPE_MONTHLY_BUDGET);
675         explicitEntry.setTransactionLedgerEntryAmount(monthAmount);
676         explicitEntry.setUniversityFiscalPeriodCode(fiscalPeriod);
677 
678         customizeExplicitGeneralLedgerPendingEntry(accountingLine, explicitEntry);
679 
680         addPendingEntry(explicitEntry);
681     }
682 
683     /**
684      * Returns an implementation of the GeneralLedgerPendingEntryService
685      * 
686      * @return an implementation of the GeneralLedgerPendingEntryService
687      */
688     public GeneralLedgerPendingEntryService getGeneralLedgerPendingEntryService() {
689         return SpringContext.getBean(GeneralLedgerPendingEntryService.class);
690     }
691 
692     /**
693      * Generates any necessary tof entries to transfer funds needed to make the budget adjustments. Based on income chart and
694      * accounts. If there is a difference in funds between an income chart and account, a tof entry needs to be created, along with
695      * a budget adjustment entry. Object code used is retrieved by a parameter.
696      * 
697      * @param sequenceHelper helper class for keeping track of sequence number
698      * @return true general ledger pending entries are generated without any problems
699      * @see org.kuali.rice.krad.rule.GenerateGeneralLedgerDocumentPendingEntriesRule#processGenerateDocumentGeneralLedgerPendingEntries(org.kuali.rice.krad.document.FinancialDocument,
700      *      org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
701      */
702     @Override
703     public boolean generateDocumentGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
704         boolean success = true;
705 
706         // check on-off tof flag
707         boolean generateTransfer = SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(BudgetAdjustmentDocument.class, BudgetAdjustmentDocumentRuleConstants.GENERATE_TOF_GLPE_ENTRIES_PARM_NM);
708         String transferObjectCode = SpringContext.getBean(ParameterService.class).getParameterValueAsString(BudgetAdjustmentDocument.class, BudgetAdjustmentDocumentRuleConstants.TRANSFER_OBJECT_CODE_PARM_NM);
709         Integer currentFiscalYear = SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear();
710 
711         if (generateTransfer) {
712             // map of income chart/accounts with balance as value
713             Map<String, KualiDecimal> incomeStreamMap = buildIncomeStreamBalanceMapForTransferOfFundsGeneration();
714             GeneralLedgerPendingEntryService glpeService = SpringContext.getBean(GeneralLedgerPendingEntryService.class);
715             for (Iterator iter = incomeStreamMap.keySet().iterator(); iter.hasNext();) {
716                 String chartAccount = (String) iter.next();
717                 KualiDecimal streamAmount = (KualiDecimal) incomeStreamMap.get(chartAccount);
718                 if (streamAmount.isNonZero()) {
719                     // build dummy accounting line for gl population
720                     AccountingLine accountingLine = null;
721                     try {
722                         accountingLine = (SourceAccountingLine) getSourceAccountingLineClass().newInstance();
723                     }
724                     catch (IllegalAccessException e) {
725                         throw new IllegalArgumentException("unable to access sourceAccountingLineClass", e);
726                     }
727                     catch (InstantiationException e) {
728                         throw new IllegalArgumentException("unable to instantiate sourceAccountingLineClass", e);
729                     }
730 
731                     // set income chart and account in line
732                     String[] incomeString = StringUtils.split(chartAccount, BudgetAdjustmentDocumentRuleConstants.INCOME_STREAM_CHART_ACCOUNT_DELIMITER);
733                     accountingLine.setChartOfAccountsCode(incomeString[0]);
734                     accountingLine.setAccountNumber(incomeString[1]);
735                     accountingLine.setFinancialObjectCode(transferObjectCode);
736 
737                     // ////////////////// first create current budget entry/////////////////////////////////////////
738                     GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry();
739                     glpeService.populateExplicitGeneralLedgerPendingEntry(this, accountingLine, sequenceHelper, explicitEntry);
740 
741                     /* override and set object type to income */
742                     SystemOptions options = SpringContext.getBean(OptionsService.class).getCurrentYearOptions();
743                     explicitEntry.setFinancialObjectTypeCode(options.getFinObjectTypeIncomecashCode());
744 
745                     /* D/C code is empty for BA, set correct balance type, correct amount */
746                     explicitEntry.setTransactionDebitCreditCode("");
747                     explicitEntry.setFinancialBalanceTypeCode(OLEConstants.BALANCE_TYPE_CURRENT_BUDGET);
748                     explicitEntry.setTransactionLedgerEntryAmount(streamAmount);
749 
750                     // set fiscal period, if next fiscal year set to 01, else leave to current period
751                     if (currentFiscalYear.equals(getPostingYear() - 1)) {
752                         explicitEntry.setUniversityFiscalPeriodCode(BudgetAdjustmentDocumentRuleConstants.MONTH_1_PERIOD_CODE);
753                     }
754 
755                     customizeExplicitGeneralLedgerPendingEntry(accountingLine, explicitEntry);
756 
757                     // add the new explicit entry to the document now
758                     addPendingEntry(explicitEntry);
759 
760                     // increment the sequence counter
761                     sequenceHelper.increment();
762 
763 
764                     // ////////////////// now create actual TOF entry //////////////////////////////////////////////
765                     /* set amount in line so Debit/Credit code can be set correctly */
766                     accountingLine.setAmount(streamAmount);
767                     explicitEntry = new GeneralLedgerPendingEntry();
768                     glpeService.populateExplicitGeneralLedgerPendingEntry(this, accountingLine, sequenceHelper, explicitEntry);
769 
770                     /* override and set object type to transfer */
771                     explicitEntry.setFinancialObjectTypeCode(options.getFinancialObjectTypeTransferIncomeCd());
772 
773                     /* set document type to tof */
774                     explicitEntry.setFinancialDocumentTypeCode(getTransferDocumentType());
775 
776                     // set fiscal period, if next fiscal year set to 01, else leave to current period
777                     if (currentFiscalYear.equals(getPostingYear() - 1)) {
778                         explicitEntry.setUniversityFiscalPeriodCode(BudgetAdjustmentDocumentRuleConstants.MONTH_1_PERIOD_CODE);
779                     }
780 
781                     // add the new explicit entry to the document now
782                     addPendingEntry(explicitEntry);
783 
784                     customizeExplicitGeneralLedgerPendingEntry(accountingLine, explicitEntry);
785 
786                     // increment the sequence counter
787                     sequenceHelper.increment();
788 
789                     // ////////////////// now create actual TOF offset //////////////////////////////////////////////
790                     GeneralLedgerPendingEntry offsetEntry = new GeneralLedgerPendingEntry(explicitEntry);
791                     success &= glpeService.populateOffsetGeneralLedgerPendingEntry(getPostingYear(), explicitEntry, sequenceHelper, offsetEntry);
792                     customizeOffsetGeneralLedgerPendingEntry(accountingLine, explicitEntry, offsetEntry);
793                     addPendingEntry(offsetEntry);
794 
795                     // increment the sequence counter
796                     sequenceHelper.increment();
797                 }
798             }
799         }
800         return success;
801     }
802 
803     /**
804      * Builds a map used for balancing current adjustment amounts. The map contains income chart and accounts contained on the
805      * document as the keys, and transfer amounts as the values.  The transfer amount is calculated from (curr_frm_inc - curr_frm_exp) - (curr_to_inc - curr_to_exp)
806      * 
807      * @param baDocument budget adjustment document
808      * @return Map used to balance current amounts
809      */
810     public Map buildIncomeStreamBalanceMapForTransferOfFundsGeneration() {
811         Map<String, KualiDecimal> incomeStreamBalance = new HashMap<String, KualiDecimal>();
812 
813         List<BudgetAdjustmentAccountingLine> accountingLines = new ArrayList<BudgetAdjustmentAccountingLine>();
814         accountingLines.addAll(getSourceAccountingLines());
815         accountingLines.addAll(getTargetAccountingLines());
816             
817         ParameterEvaluatorService parameterEvaluatorService = SpringContext.getBean(ParameterEvaluatorService.class);
818             
819         for (BudgetAdjustmentAccountingLine budgetAccountingLine : accountingLines) {
820             Account baAccount = budgetAccountingLine.getAccount();
821             
822             if(parameterEvaluatorService.getParameterEvaluator(BudgetAdjustmentDocument.class, OLEConstants.BudgetAdjustmentDocumentConstants.CROSS_INCOME_STREAM_GLPE_TRANSFER_GENERATING_FUND_GROUPS, baAccount.getSubFundGroup().getFundGroupCode()).evaluationSucceeds() &&
823                parameterEvaluatorService.getParameterEvaluator(BudgetAdjustmentDocument.class, OLEConstants.BudgetAdjustmentDocumentConstants.CROSS_INCOME_STREAM_GLPE_TRANSFER_GENERATING_SUB_FUND_GROUPS, baAccount.getSubFundGroupCode()).evaluationSucceeds()) {
824                 
825                 String incomeStreamKey = baAccount.getIncomeStreamFinancialCoaCode() + BudgetAdjustmentDocumentRuleConstants.INCOME_STREAM_CHART_ACCOUNT_DELIMITER + baAccount.getIncomeStreamAccountNumber();
826     
827                 // place record in balance map
828                 incomeStreamBalance.put(incomeStreamKey, getIncomeStreamAmount(budgetAccountingLine, incomeStreamBalance.get(incomeStreamKey)));
829             }
830         }
831 
832         return incomeStreamBalance;
833     }
834 
835     /**
836      * Builds a map used for balancing current adjustment amounts. The map contains income chart and accounts contained on the
837      * document as the keys, and transfer amounts as the values. The transfer amount is calculated from (curr_frm_inc - curr_frm_exp) - (curr_to_inc - curr_to_exp)
838      * 
839      * @param baDocument budget adjustment document
840      * @return Map used to balance current amounts
841      */
842     public Map buildIncomeStreamBalanceMapForDocumentBalance() {
843         Map<String, KualiDecimal> incomeStreamBalance = new HashMap<String, KualiDecimal>();
844 
845         List<BudgetAdjustmentAccountingLine> accountingLines = new ArrayList<BudgetAdjustmentAccountingLine>();
846         accountingLines.addAll(getSourceAccountingLines());
847         accountingLines.addAll(getTargetAccountingLines());
848         for (BudgetAdjustmentAccountingLine budgetAccountingLine : accountingLines) {
849             
850             String incomeStreamKey = budgetAccountingLine.getAccount().getIncomeStreamFinancialCoaCode() + BudgetAdjustmentDocumentRuleConstants.INCOME_STREAM_CHART_ACCOUNT_DELIMITER + budgetAccountingLine.getAccount().getIncomeStreamAccountNumber();
851 
852             // place record in balance map
853             incomeStreamBalance.put(incomeStreamKey, getIncomeStreamAmount(budgetAccountingLine, incomeStreamBalance.get(incomeStreamKey)));
854         }
855 
856         return incomeStreamBalance;
857     }
858 
859     /**
860      * 
861      * This method calculates the appropriate income stream amount for an account using the value provided and the provided accounting line.
862      * 
863      * @param budgetAccountingLine
864      * @param incomeStreamAmount
865      * @return
866      */
867     protected KualiDecimal getIncomeStreamAmount(BudgetAdjustmentAccountingLine budgetAccountingLine, KualiDecimal incomeStreamAmount) {
868         if(incomeStreamAmount == null) {
869             incomeStreamAmount = new KualiDecimal(0);
870         }
871 
872         // amounts need to be reversed for source expense lines and target income lines
873         DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
874         if ((budgetAccountingLine instanceof BudgetAdjustmentSourceAccountingLine && isDebitUtils.isExpense((AccountingLine) budgetAccountingLine)) || (budgetAccountingLine instanceof BudgetAdjustmentTargetAccountingLine && isDebitUtils.isIncome((AccountingLine) budgetAccountingLine))) {
875             incomeStreamAmount = incomeStreamAmount.subtract(budgetAccountingLine.getCurrentBudgetAdjustmentAmount());
876         }
877         else {
878             incomeStreamAmount = incomeStreamAmount.add(budgetAccountingLine.getCurrentBudgetAdjustmentAmount());
879         }
880 
881         return incomeStreamAmount;
882     }
883     
884     /**
885      * Returns the document type code for the Transfer of Funds document
886      * 
887      * @return the document type name to be used for the income stream transfer glpe
888      */
889     protected String getTransferDocumentType() {
890         return TransferOfFundsDocumentRuleConstants.TRANSFER_OF_FUNDS_DOC_TYPE_CODE;
891     }
892 
893 
894     /**
895      * @see org.kuali.ole.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(java.lang.String)
896      */
897     @Override
898     public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
899         if (nodeName.equals(BudgetAdjustmentDocument.REQUIRES_FULL_APPROVAL_SPLIT_NODE_NAME)) {
900             return requiresFullApproval();
901         }
902         return super.answerSplitNodeQuestion(nodeName);
903     }
904 
905     /**
906      * Determines if this document can be auto-approved or not. The conditions for auto-approval are: 1) Single account used on document 2) Initiator is
907      * fiscal officer or primary delegate for the account 3) Only current adjustments are being made 4) The fund group for the account
908      * is not contract and grants 5) current income/expense decrease amount must equal increase amount
909      * @return false if auto-approval can occur (and therefore, full approval is not required); true if a full approval is required
910      */
911     //MSU Contribution DTT-3059, DTT-3235 OLEMI-8689 OLECNTRB-941 - Re-implemented this method to execute the rules correctly
912     protected boolean requiresFullApproval() {
913         List<BudgetAdjustmentAccountingLine> accountingLines = new ArrayList<BudgetAdjustmentAccountingLine>();
914         accountingLines.addAll(getSourceAccountingLines());
915         accountingLines.addAll(getTargetAccountingLines());
916 
917         HashSet<String> distinctAccts = new HashSet<String>();
918         HashSet<String> distinctObjs = new HashSet<String>();
919         String accountKey = "";
920         String objCdKey = "";
921 
922         for (BudgetAdjustmentAccountingLine account : accountingLines) {
923             if(account.getBaseBudgetAdjustmentAmount().isNonZero()){
924                 return true;
925             }
926             accountKey = account.getChartOfAccountsCode() + "-" + account.getAccountNumber();
927             objCdKey = account.getPostingYear() + "-" + account.getChartOfAccountsCode() + "-" + account.getFinancialObjectCode();
928             distinctAccts.add(accountKey);
929             distinctObjs.add(objCdKey);
930             if (distinctAccts.size() > 1 || distinctObjs.size() > 1) {
931                 return true;
932             }
933         }
934 
935         String chart = "";
936         String accountNumber = "";
937 
938         // check remaining conditions
939         // initiator should be fiscal officer or primary delegate for account
940         Person initiator = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId());
941         List userAccounts = SpringContext.getBean(AccountService.class).getAccountsThatUserIsResponsibleFor(initiator);
942         //DTT:3059-Loop over all the accounts present on the document and see if user account responsibility includes them
943         for (Iterator iter1 = accountingLines.iterator(); iter1.hasNext();) {
944 
945             BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter1.next();
946             chart = line.getChartOfAccountsCode();
947             accountNumber = line.getAccountNumber();
948 
949             Account userAccount = null;
950             for (Iterator iter2 = userAccounts.iterator(); iter2.hasNext();) {
951                 AccountResponsibility account = (AccountResponsibility) iter2.next();
952                 if (chart.equals(account.getAccount().getChartOfAccountsCode()) && accountNumber.equals(account.getAccount().getAccountNumber())) {
953                     userAccount = account.getAccount();
954                     break;
955                 }
956             }
957 
958             if (userAccount == null) {
959                 return true;
960             }
961             else {
962                 // fund group should not be CG
963                 if (userAccount.isForContractsAndGrants()) {
964                     return true;
965                 }
966 
967                 // current income/expense decrease amount must equal increase amount
968                 if (!getSourceCurrentBudgetIncomeTotal().equals(getTargetCurrentBudgetIncomeTotal()) || !getSourceCurrentBudgetExpenseTotal().equals(getTargetCurrentBudgetExpenseTotal())) {
969                     return true;
970                 }
971             }// End of else block.
972 
973         }// End of for loop
974 
975         return false;
976 
977     }
978 }