/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.coa.document.validation.impl;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.coa.businessobject.AccountGlobalDetail;
import org.kuali.kfs.sys.KFSKeyConstants;
import org.kuali.kfs.sys.document.validation.impl.KfsMaintenanceDocumentRuleBase;
import org.kuali.rice.krad.util.GlobalVariables;
/**
* This class contains common Business Rule functionality for Global Documents.
*/
public class GlobalDocumentRuleBase extends KfsMaintenanceDocumentRuleBase {
/**
* Constructs a GlobalDocumentRuleBase.java.
*/
public GlobalDocumentRuleBase() {
super();
}
/**
* This method checks whether the set of Account Change Detail records on this document all are under the same Chart of
* Accounts. It will set the appropriate field error if it did fail, and return the result.
*
* @param accountGlobalDetails
* @return True if the test passed with no errors, False if any errors occurred.
*/
protected boolean checkOnlyOneChartErrorWrapper(List<AccountGlobalDetail> accountGlobalDetails) {
CheckOnlyOneChartResult result = checkOnlyOneChart(accountGlobalDetails);
if (!result.success) {
putFieldError("accountGlobalDetails[" + result.firstLineNumber + "].chartOfAccountsCode", KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY);
putFieldError("accountGlobalDetails[" + result.failedLineNumber + "].chartOfAccountsCode", KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY);
}
return result.success;
}
/**
* This method checks whether the set of Account Change Detail records on this document all are under the same Chart of
* Accounts. It will return a failed CheckOnlyOneChartResult if so. Note that this method doesnt actually set any errors, it
* just returns whether or not the test succeeded, and where it failed if it failed.
*
* @param accountGlobalDetails The popualted accountGlobalDocument to test.
* @return A populated CheckOnlyOneChartResult object. This will contain whether the test succeeded or failed, and if failed,
* what lines the failures occurred on.
*/
protected CheckOnlyOneChartResult checkOnlyOneChart(List<AccountGlobalDetail> accountGlobalDetails) {
// if there is not enough information to do the test, then exit happily with no failure
if (accountGlobalDetails == null) {
return new CheckOnlyOneChartResult(true);
}
if (accountGlobalDetails.isEmpty()) {
return new CheckOnlyOneChartResult(true);
}
// test to see if there is more than one chart listed, ignores blank chartcodes
int compareLineNumber = 0;
int firstChartLineNumber = 0;
String firstChart = "";
for (AccountGlobalDetail account : accountGlobalDetails) {
if (StringUtils.isBlank(firstChart)) {
if (StringUtils.isNotBlank(account.getChartOfAccountsCode())) {
firstChart = account.getChartOfAccountsCode();
firstChartLineNumber = compareLineNumber;
}
}
else {
if (StringUtils.isNotBlank(account.getChartOfAccountsCode())) {
if (!firstChart.equalsIgnoreCase(account.getChartOfAccountsCode())) {
return new CheckOnlyOneChartResult(false, firstChartLineNumber, compareLineNumber);
}
}
}
compareLineNumber++;
}
return new CheckOnlyOneChartResult(true);
}
/**
* This class is used internally to represent the result of the CheckOnlyOneChart method.
*/
protected class CheckOnlyOneChartResult {
public int firstLineNumber;
public int failedLineNumber;
public boolean success;
/**
* Constructs a CheckOnlyOneChartResult
*/
public CheckOnlyOneChartResult() {
firstLineNumber = -1;
failedLineNumber = -1;
success = true;
}
/**
* Constructs a CheckOnlyOneChartResult
*
* @param success
*/
public CheckOnlyOneChartResult(boolean success) {
this();
this.success = success;
}
/**
* Constructs a CheckOnlyOneChartResult
*
* @param success
* @param firstLineNumber
* @param failedLineNumber
*/
public CheckOnlyOneChartResult(boolean success, int firstLineNumber, int failedLineNumber) {
this.success = success;
this.firstLineNumber = firstLineNumber;
this.failedLineNumber = failedLineNumber;
}
}
/**
* This method tests whether the line being added has a different Chart of Accounts Code from any of the existing lines. It will
* set an Error and return false if this is the case.
*
* @param newAccountLine
* @param accountGlobalDetails
* @return True if the line being added has the exact same chart as all the existing lines, False if not.
*/
protected boolean checkOnlyOneChartAddLineErrorWrapper(AccountGlobalDetail newAccountLine, List<AccountGlobalDetail> accountGlobalDetails) {
boolean success = checkOnlyOneChartAddLine(newAccountLine, accountGlobalDetails);
if (!success) {
// putGlobalError(KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY_ADDNEW);
// TODO: KULCOA-1091 Need to add this error to the add line, but this doesn't work right, as the
// error message comes out at the bottom, and the field doesn't get highlighted.
// putFieldError("newAccountGlobalDetail.chartOfAccountsCode",
// KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY);
// added to prevent error from showing at the top of the document, but rather in the Account Detail Edit section
GlobalVariables.getMessageMap().putError("chartOfAccountsCode", KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY_ADDNEW);
}
return success;
}
/**
* This method tests whether a new line can be added, based on the rule that says all the accounts being used must belong to the
* same chart. If the line being added differs from any existing line's Chart code, it will return false. Note that this
* document does not actually set any errors, it just reports success or failure.
*
* @param newAccountLine
* @param accountGlobalDetails
* @return True if no errors are found, False if the line being added has a different Chart code than any of the existing lines.
*/
protected boolean checkOnlyOneChartAddLine(AccountGlobalDetail newAccountLine, List<AccountGlobalDetail> accountGlobalDetails) {
if (newAccountLine == null || accountGlobalDetails == null) {
return true;
}
if (accountGlobalDetails.isEmpty()) {
return true;
}
String newChart = newAccountLine.getChartOfAccountsCode();
if (StringUtils.isBlank(newChart)) {
return true;
}
for (AccountGlobalDetail account : accountGlobalDetails) {
if (StringUtils.isNotBlank(account.getChartOfAccountsCode())) {
if (!newChart.equalsIgnoreCase(account.getChartOfAccountsCode())) {
return false;
}
}
}
return true;
}
}