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 static org.kuali.kfs.sys.KFSKeyConstants.ERROR_DOCUMENT_FUND_GROUP_SET_DOES_NOT_BALANCE;
019    
020    import java.util.ArrayList;
021    import java.util.Iterator;
022    import java.util.List;
023    
024    import org.kuali.kfs.fp.document.TransferOfFundsDocument;
025    import org.kuali.kfs.sys.businessobject.AccountingLine;
026    import org.kuali.kfs.sys.document.AccountingDocument;
027    import org.kuali.kfs.sys.document.validation.GenericValidation;
028    import org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent;
029    import org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleBaseConstants;
030    import org.kuali.rice.kns.service.ParameterEvaluator;
031    import org.kuali.rice.kns.service.ParameterService;
032    import org.kuali.rice.kns.util.GlobalVariables;
033    import org.kuali.rice.kns.util.KualiDecimal;
034    
035    /**
036     * Validation for Transfer of Funds document that tests if the fund groups represented by a given document are in balance.
037     */
038    public class TransferOfFundsFundGroupsBalancedValidation extends GenericValidation {
039        private AccountingDocument accountingDocumentForValidation;
040        private ParameterService parameterService;
041    
042        /**
043         * This is a helper method that wraps the fund group balancing check. This check can be configured by updating the 
044         * application parameter table that is associated with this check. See the document's specification for details.
045         * @see org.kuali.kfs.sys.document.validation.Validation#validate(org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent)
046         */
047        public boolean validate(AttributedDocumentEvent event) {
048            return isFundGroupSetBalanceValid(accountingDocumentForValidation, TransferOfFundsDocument.class, AccountingDocumentRuleBaseConstants.APPLICATION_PARAMETER.FUND_GROUP_BALANCING_SET);
049        }
050        
051        /**
052         * This method will make sure that totals for a specified set of fund groups is valid across the two different accounting line
053         * sections.
054         * 
055         * @param tranDoc
056         * @param fundGroupCodes An array of the fund group codes that will be considered for balancing.
057         * @return True if they balance; false otherwise.
058         */
059        protected boolean isFundGroupSetBalanceValid(AccountingDocument tranDoc, Class componentClass, String parameterName) {
060            // don't need to do any of this if there's no parameter
061            if (!getParameterService().parameterExists(componentClass, parameterName)) {
062                return true;
063            }
064    
065            List lines = new ArrayList();
066    
067            lines.addAll(tranDoc.getSourceAccountingLines());
068            lines.addAll(tranDoc.getTargetAccountingLines());
069    
070            KualiDecimal sourceLinesTotal = KualiDecimal.ZERO;
071            KualiDecimal targetLinesTotal = KualiDecimal.ZERO;
072    
073            // iterate over each accounting line and if it has an account with a
074            // fund group that should be balanced, then add that lines amount to the bucket
075            for (Iterator i = lines.iterator(); i.hasNext();) {
076                AccountingLine line = (AccountingLine) i.next();
077                String fundGroupCode = line.getAccount().getSubFundGroup().getFundGroupCode();
078    
079                ParameterEvaluator evaluator = getParameterService().getParameterEvaluator(componentClass, parameterName, fundGroupCode);
080                if (evaluator.evaluationSucceeds()) {
081                    KualiDecimal glpeLineAmount = tranDoc.getGeneralLedgerPendingEntryAmountForDetail(line);
082                    if (line.isSourceAccountingLine()) {
083                        sourceLinesTotal = sourceLinesTotal.add(glpeLineAmount);
084                    }
085                    else {
086                        targetLinesTotal = targetLinesTotal.add(glpeLineAmount);
087                    }
088                }
089            }
090    
091            // check that the amounts balance across sections
092            boolean isValid = true;
093    
094            if (sourceLinesTotal.compareTo(targetLinesTotal) != 0) {
095                isValid = false;
096    
097                // creating an evaluator to just format the fund codes into a nice string
098                ParameterEvaluator evaluator = getParameterService().getParameterEvaluator(componentClass, parameterName, "");
099                GlobalVariables.getMessageMap().putError("document.sourceAccountingLines", ERROR_DOCUMENT_FUND_GROUP_SET_DOES_NOT_BALANCE, new String[] { tranDoc.getSourceAccountingLinesSectionTitle(), tranDoc.getTargetAccountingLinesSectionTitle(), evaluator.getParameterValuesForMessage() });
100            }
101    
102            return isValid;
103        }
104    
105        /**
106         * Gets the accountingDocumentForValidation attribute. 
107         * @return Returns the accountingDocumentForValidation.
108         */
109        public AccountingDocument getAccountingDocumentForValidation() {
110            return accountingDocumentForValidation;
111        }
112    
113        /**
114         * Sets the accountingDocumentForValidation attribute value.
115         * @param accountingDocumentForValidation The accountingDocumentForValidation to set.
116         */
117        public void setAccountingDocumentForValidation(AccountingDocument accountingDocumentForValidation) {
118            this.accountingDocumentForValidation = accountingDocumentForValidation;
119        }
120    
121        /**
122         * Gets the parameterService attribute. 
123         * @return Returns the parameterService.
124         */
125        public ParameterService getParameterService() {
126            return parameterService;
127        }
128    
129        /**
130         * Sets the parameterService attribute value.
131         * @param parameterService The parameterService to set.
132         */
133        public void setParameterService(ParameterService parameterService) {
134            this.parameterService = parameterService;
135        }
136    }