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