001: /*
002: * Copyright 2006-2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.workflow.node;
017:
018: import java.util.ArrayList;
019: import java.util.Iterator;
020: import java.util.List;
021:
022: import org.apache.commons.lang.StringUtils;
023: import org.kuali.core.bo.user.AuthenticationUserId;
024: import org.kuali.core.bo.user.UniversalUser;
025: import org.kuali.core.service.DocumentService;
026: import org.kuali.core.service.UniversalUserService;
027: import org.kuali.kfs.bo.AccountResponsibility;
028: import org.kuali.kfs.context.SpringContext;
029: import org.kuali.module.chart.bo.Account;
030: import org.kuali.module.chart.service.AccountService;
031: import org.kuali.module.financial.bo.BudgetAdjustmentAccountingLine;
032: import org.kuali.module.financial.document.BudgetAdjustmentDocument;
033:
034: import edu.iu.uis.eden.engine.RouteContext;
035: import edu.iu.uis.eden.engine.RouteHelper;
036: import edu.iu.uis.eden.engine.node.SplitNode;
037: import edu.iu.uis.eden.engine.node.SplitResult;
038:
039: /**
040: * Checks for conditions on a Budget Adjustment document that allow auto-approval by the initiator. If these conditions are not met,
041: * standard financial routing is performed. The conditions for auto-approval are: 1) Single account used on document 2) Initiator is
042: * fiscal officer or primary delegate for the account 3) Only current adjustments are being made 4) The fund group for the account
043: * is not contract and grants 5) current income/expense decrease amount must equal increase amount
044: */
045: public class BudgetAdjustmentDocumentApprovalNoApprovalSplitNode
046: implements SplitNode {
047:
048: public SplitResult process(RouteContext routeContext,
049: RouteHelper routeHelper) throws Exception {
050: boolean autoApprovalAllowed = true;
051:
052: // retrieve ba document
053: String documentID = routeContext.getDocument()
054: .getRouteHeaderId().toString();
055: BudgetAdjustmentDocument budgetDocument = (BudgetAdjustmentDocument) SpringContext
056: .getBean(DocumentService.class).getByDocumentHeaderId(
057: documentID);
058:
059: // TODO: due to transaction scoping issues, any proxied items in budgetDocument are now irretrievable! Any
060: // attempt to retrieve them will cause OJB to throw an exception. This will be fixed in the
061: // general case in Phase 2.
062:
063: // new list so that sourceAccountingLines isn't modified by addAll statement. Important for
064: // total calculations below.
065: List accountingLines = new ArrayList();
066: accountingLines.addAll(budgetDocument
067: .getSourceAccountingLines());
068: accountingLines.addAll(budgetDocument
069: .getTargetAccountingLines());
070:
071: /* only one account can be present on document and only current adjustments allowed */
072: String chart = "";
073: String accountNumber = "";
074: for (Iterator iter = accountingLines.iterator(); iter.hasNext();) {
075: BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter
076: .next();
077: if (StringUtils.isNotBlank(accountNumber)) {
078: if (!accountNumber.equals(line.getAccountNumber())
079: && !chart.equals(line.getChartOfAccountsCode())) {
080: autoApprovalAllowed = false;
081: break;
082: }
083: }
084:
085: if (line.getBaseBudgetAdjustmentAmount().isNonZero()) {
086: autoApprovalAllowed = false;
087: break;
088: }
089: chart = line.getChartOfAccountsCode();
090: accountNumber = line.getAccountNumber();
091: }
092:
093: // check remaining conditions
094: if (autoApprovalAllowed) {
095: // initiator should be fiscal officer or primary delegate for account
096: UniversalUser initiator = SpringContext.getBean(
097: UniversalUserService.class).getUniversalUser(
098: new AuthenticationUserId(budgetDocument
099: .getDocumentHeader().getWorkflowDocument()
100: .getInitiatorNetworkId()));
101: List userAccounts = SpringContext.getBean(
102: AccountService.class)
103: .getAccountsThatUserIsResponsibleFor(initiator);
104: Account userAccount = null;
105: for (Iterator iter = userAccounts.iterator(); iter
106: .hasNext();) {
107: AccountResponsibility account = (AccountResponsibility) iter
108: .next();
109: if (accountNumber.equals(account.getAccount()
110: .getAccountNumber())
111: && chart.equals(account.getAccount()
112: .getChartOfAccountsCode())) {
113: userAccount = account.getAccount();
114: break;
115: }
116: }
117:
118: if (userAccount == null) {
119: autoApprovalAllowed = false;
120: } else {
121: // fund group should not be CG
122: if (userAccount.isForContractsAndGrants()) {
123: autoApprovalAllowed = false;
124: }
125:
126: // current income/expense decrease amount must equal increase amount
127: if (!budgetDocument
128: .getSourceCurrentBudgetIncomeTotal()
129: .equals(
130: budgetDocument
131: .getTargetCurrentBudgetIncomeTotal())
132: || !budgetDocument
133: .getSourceCurrentBudgetExpenseTotal()
134: .equals(
135: budgetDocument
136: .getTargetCurrentBudgetExpenseTotal())) {
137: autoApprovalAllowed = false;
138: }
139: }
140: }
141:
142: List branchNames = new ArrayList();
143: if (autoApprovalAllowed) {
144: branchNames.add("NoApprovalBranch");
145: } else {
146: branchNames.add("ApprovalBranch");
147: }
148:
149: return new SplitResult(branchNames);
150: }
151: }
|