001    /*
002     * Copyright 2011 The Kuali Foundation.
003     * 
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     * http://www.opensource.org/licenses/ecl2.php
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.kfs.fp.document.validation.impl;
017    
018    import java.util.ArrayList;
019    import java.util.Iterator;
020    import java.util.List;
021    
022    import org.kuali.kfs.coa.businessobject.SubFundGroup;
023    import org.kuali.kfs.fp.businessobject.BudgetAdjustmentAccountingLine;
024    import org.kuali.kfs.fp.document.BudgetAdjustmentDocument;
025    import org.kuali.kfs.sys.KFSConstants;
026    import org.kuali.kfs.sys.KFSKeyConstants;
027    import org.kuali.kfs.sys.document.service.AccountingLineRuleHelperService;
028    import org.kuali.kfs.sys.document.validation.GenericValidation;
029    import org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent;
030    import org.kuali.rice.kns.util.GlobalVariables;
031    import org.kuali.rice.kns.util.MessageMap;
032    
033    /**
034     * Validation for Budget Adjustment document that checks that the fund groups are correctly adjusted.
035     */
036    public class BudgetAdjustmentFundGroupAdjustmentRestrictionValidation extends GenericValidation {
037        private BudgetAdjustmentDocument accountingDocumentForValidation;
038        AccountingLineRuleHelperService accountingLineRuleHelperService;
039        
040        /**
041         * Retrieves the fund group and sub fund group for each accounting line. Then verifies that the codes associated with the
042         * 'Budget Adjustment Restriction Code' field are met.
043         * @see org.kuali.kfs.sys.document.validation.Validation#validate(org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent)
044         */
045        public boolean validate(AttributedDocumentEvent event) {
046            MessageMap errors = GlobalVariables.getMessageMap();
047    
048            boolean isAdjustmentAllowed = true;
049    
050            List accountingLines = new ArrayList();
051            accountingLines.addAll(getAccountingDocumentForValidation().getSourceAccountingLines());
052            accountingLines.addAll(getAccountingDocumentForValidation().getTargetAccountingLines());
053    
054            // fund group is global restriction
055            boolean restrictedToSubFund = false;
056            boolean restrictedToChart = false;
057            boolean restrictedToOrg = false;
058            boolean restrictedToAccount = false;
059    
060            // fields to help with error messages
061            String accountRestrictingSubFund = "";
062            String accountRestrictingChart = "";
063            String accountRestrictingOrg = "";
064            String accountRestrictingAccount = "";
065    
066            // first find the restriction level required by the fund or sub funds used on document
067            String restrictionLevel = "";
068            for (Iterator iter = accountingLines.iterator(); iter.hasNext();) {
069                BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
070                SubFundGroup subFund = line.getAccount().getSubFundGroup();
071                if (!KFSConstants.BudgetAdjustmentDocumentConstants.ADJUSTMENT_RESTRICTION_LEVEL_NONE.equals(subFund.getFundGroupBudgetAdjustmentRestrictionLevelCode())) {
072                    restrictionLevel = subFund.getFundGroupBudgetAdjustmentRestrictionLevelCode();
073                    restrictedToSubFund = true;
074                    accountRestrictingSubFund = line.getAccountNumber();
075                }
076                else {
077                    restrictionLevel = subFund.getFundGroup().getFundGroupBudgetAdjustmentRestrictionLevelCode();
078                }
079    
080                if (KFSConstants.BudgetAdjustmentDocumentConstants.ADJUSTMENT_RESTRICTION_LEVEL_CHART.equals(restrictionLevel)) {
081                    restrictedToChart = true;
082                    accountRestrictingChart = line.getAccountNumber();
083                }
084                else if (KFSConstants.BudgetAdjustmentDocumentConstants.ADJUSTMENT_RESTRICTION_LEVEL_ORGANIZATION.equals(restrictionLevel)) {
085                    restrictedToOrg = true;
086                    accountRestrictingOrg = line.getAccountNumber();
087                }
088                else if (KFSConstants.BudgetAdjustmentDocumentConstants.ADJUSTMENT_RESTRICTION_LEVEL_ACCOUNT.equals(restrictionLevel)) {
089                    restrictedToAccount = true;
090                    accountRestrictingAccount = line.getAccountNumber();
091                }
092    
093                // if we have a sub fund restriction, this overrides anything coming later
094                if (restrictedToSubFund) {
095                    break;
096                }
097            }
098    
099            String fundLabel = accountingLineRuleHelperService.getFundGroupCodeLabel();
100            String subFundLabel = accountingLineRuleHelperService.getSubFundGroupCodeLabel();
101            String chartLabel = accountingLineRuleHelperService.getChartLabel();
102            String orgLabel = accountingLineRuleHelperService.getOrganizationCodeLabel();
103            String acctLabel = accountingLineRuleHelperService.getAccountLabel();
104    
105            /*
106             * now iterate through the accounting lines again and check each record against the previous to verify the restrictions are
107             * met
108             */
109            BudgetAdjustmentAccountingLine previousLine = null;
110            for (Iterator iter = accountingLines.iterator(); iter.hasNext();) {
111                BudgetAdjustmentAccountingLine line = (BudgetAdjustmentAccountingLine) iter.next();
112    
113                if (previousLine != null) {
114                    String currentFundGroup = line.getAccount().getSubFundGroup().getFundGroupCode();
115                    String previousFundGroup = previousLine.getAccount().getSubFundGroup().getFundGroupCode();
116    
117                    if (!currentFundGroup.equals(previousFundGroup)) {
118                        errors.putErrorWithoutFullErrorPath(KFSConstants.ACCOUNTING_LINE_ERRORS, KFSKeyConstants.ERROR_DOCUMENT_BA_MIXED_FUND_GROUPS);
119                        isAdjustmentAllowed = false;
120                        break;
121                    }
122    
123                    if (restrictedToSubFund) {
124                        if (!line.getAccount().getSubFundGroupCode().equals(previousLine.getAccount().getSubFundGroupCode())) {
125                            errors.putErrorWithoutFullErrorPath(KFSConstants.ACCOUNTING_LINE_ERRORS, KFSKeyConstants.ERROR_DOCUMENT_BA_RESTRICTION_LEVELS, new String[] { accountRestrictingSubFund, subFundLabel });
126                            isAdjustmentAllowed = false;
127                            break;
128                        }
129                    }
130    
131                    if (restrictedToChart) {
132                        if (!line.getChartOfAccountsCode().equals(previousLine.getChartOfAccountsCode())) {
133                            if (restrictedToSubFund) {
134                                errors.putErrorWithoutFullErrorPath(KFSConstants.ACCOUNTING_LINE_ERRORS, KFSKeyConstants.ERROR_DOCUMENT_BA_RESTRICTION_LEVELS, new String[] { accountRestrictingChart, subFundLabel + " and " + chartLabel });
135                            }
136                            else {
137                                errors.putErrorWithoutFullErrorPath(KFSConstants.ACCOUNTING_LINE_ERRORS, KFSKeyConstants.ERROR_DOCUMENT_BA_RESTRICTION_LEVELS, new String[] { accountRestrictingChart, fundLabel + " and " + chartLabel });
138                            }
139                            isAdjustmentAllowed = false;
140                            break;
141                        }
142                    }
143    
144                    if (restrictedToOrg) {
145                        if (!line.getAccount().getOrganizationCode().equals(previousLine.getAccount().getOrganizationCode())) {
146                            if (restrictedToSubFund) {
147                                errors.putErrorWithoutFullErrorPath(KFSConstants.ACCOUNTING_LINE_ERRORS, KFSKeyConstants.ERROR_DOCUMENT_BA_RESTRICTION_LEVELS, new String[] { accountRestrictingOrg, subFundLabel + " and " + orgLabel });
148                            }
149                            else {
150                                errors.putErrorWithoutFullErrorPath(KFSConstants.ACCOUNTING_LINE_ERRORS, KFSKeyConstants.ERROR_DOCUMENT_BA_RESTRICTION_LEVELS, new String[] { accountRestrictingOrg, fundLabel + " and " + orgLabel });
151                            }
152                            isAdjustmentAllowed = false;
153                            break;
154                        }
155                    }
156    
157                    if (restrictedToAccount) {
158                        if (!line.getAccountNumber().equals(previousLine.getAccountNumber())) {
159                            errors.putErrorWithoutFullErrorPath(KFSConstants.ACCOUNTING_LINE_ERRORS, KFSKeyConstants.ERROR_DOCUMENT_BA_RESTRICTION_LEVELS, new String[] { accountRestrictingAccount, acctLabel });
160                            isAdjustmentAllowed = false;
161                            break;
162                        }
163                    }
164                }
165    
166                previousLine = line;
167            }
168    
169            return isAdjustmentAllowed;
170        }
171    
172        /**
173         * Gets the accountingDocumentForValidation attribute. 
174         * @return Returns the accountingDocumentForValidation.
175         */
176        public BudgetAdjustmentDocument getAccountingDocumentForValidation() {
177            return accountingDocumentForValidation;
178        }
179    
180        /**
181         * Sets the accountingDocumentForValidation attribute value.
182         * @param accountingDocumentForValidation The accountingDocumentForValidation to set.
183         */
184        public void setAccountingDocumentForValidation(BudgetAdjustmentDocument accountingDocumentForValidation) {
185            this.accountingDocumentForValidation = accountingDocumentForValidation;
186        }
187    
188        /**
189         * Gets the accountingLineRuleHelperService attribute. 
190         * @return Returns the accountingLineRuleHelperService.
191         */
192        public AccountingLineRuleHelperService getAccountingLineRuleHelperService() {
193            return accountingLineRuleHelperService;
194        }
195    
196        /**
197         * Sets the accountingLineRuleHelperService attribute value.
198         * @param accountingLineRuleHelperService The accountingLineRuleHelperService to set.
199         */
200        public void setAccountingLineRuleHelperService(AccountingLineRuleHelperService accountingLineRuleHelperService) {
201            this.accountingLineRuleHelperService = accountingLineRuleHelperService;
202        }
203    }