/*
* 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.module.external.kc.document.validation.impl;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.coa.businessobject.Account;
import org.kuali.kfs.coa.businessobject.FundGroup;
import org.kuali.kfs.coa.businessobject.SubFundGroup;
import org.kuali.kfs.coa.service.AccountService;
import org.kuali.kfs.gl.service.BalanceService;
import org.kuali.kfs.integration.cg.ContractsAndGrantsModuleService;
import org.kuali.kfs.integration.cg.ContractsAndGrantsUnit;
import org.kuali.kfs.module.external.kc.KcConstants;
import org.kuali.kfs.module.external.kc.businessobject.AccountAutoCreateDefaults;
import org.kuali.kfs.module.external.kc.businessobject.IndirectCostRecoveryAutoDefAccount;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSKeyConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService;
import org.kuali.rice.core.api.parameter.ParameterEvaluatorService;
import org.kuali.rice.coreservice.framework.parameter.ParameterService;
import org.kuali.rice.kim.api.identity.Person;
import org.kuali.rice.kns.document.MaintenanceDocument;
import org.kuali.rice.kns.service.DictionaryValidationService;
import org.kuali.rice.krad.bo.PersistableBusinessObject;
import org.kuali.rice.krad.service.KualiModuleService;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.ObjectUtils;
/**
* Business rule(s) applicable to AccountMaintenance documents.
*/
public class AccountAutoCreateDefaultsRule extends org.kuali.kfs.coa.document.validation.impl.AccountRule {
protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountAutoCreateDefaultsRule.class);
protected static ParameterService parameterService;
protected static final String ACCT_PREFIX_RESTRICTION = "PREFIXES";
protected static final String ACCT_CAPITAL_SUBFUNDGROUP = "CAPITAL_SUB_FUND_GROUPS";
protected AccountAutoCreateDefaults oldAccountAutoCreateDefaults;
protected AccountAutoCreateDefaults newAccountAutoCreateDefaults;
public AccountAutoCreateDefaultsRule() {
// Pseudo-inject some services.
//
// This approach is being used to make it simpler to convert the Rule classes
// to spring-managed with these services injected by Spring at some later date.
// When this happens, just remove these calls to the setters with
// SpringContext, and configure the bean defs for spring.
this.setGeneralLedgerPendingEntryService(SpringContext.getBean(GeneralLedgerPendingEntryService.class));
this.setBalanceService(SpringContext.getBean(BalanceService.class));
this.setAccountService(SpringContext.getBean(AccountService.class));
this.setContractsAndGrantsModuleService(SpringContext.getBean(ContractsAndGrantsModuleService.class));
}
/**
* This method sets the convenience objects like newAccountAutoCreateDefaults and oldAccountAutoCreateDefaults, so you have
* short and easy handles to the new and old objects contained in the maintenance document. It also calls the
* BusinessObjectBase.refresh(), which will attempt to load all sub-objects from the DB by their primary keys, if available.
*/
@Override
public void setupConvenienceObjects() {
// setup oldAccountAutoCreateDefaults convenience objects, make sure all possible sub-objects are populated
oldAccountAutoCreateDefaults = (AccountAutoCreateDefaults) super.getOldBo();
// setup newAccountAutoCreateDefaults convenience objects, make sure all possible sub-objects are populated
newAccountAutoCreateDefaults = (AccountAutoCreateDefaults) super.getNewBo();
setBoFieldPath(KFSPropertyConstants.INDIRECT_COST_RECOVERY_ACCOUNTS);
}
/**
* This method calls the route rules but does not fail if any of them fail (this only happens on routing)
*
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
*/
@Override
protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) {
LOG.info("processCustomSaveDocumentBusinessRules called");
// call the route rules to report all of the messages, but ignore the result
processCustomRouteDocumentBusinessRules(document);
// Save always succeeds, even if there are business rule failures
return true;
}
/**
* This method calls the following rules: checkAccountGuidelinesValidation checkEmptyValues checkGeneralRules checkCloseAccount
* checkContractsAndGrants checkExpirationDate checkFundGroup checkSubFundGroup checkFiscalOfficerIsValidKualiUser this rule
* will fail on routing
*
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
*/
@Override
protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
// default to success
boolean success = true;
LOG.info("processCustomRouteDocumentBusinessRules called");
setupConvenienceObjects();
success &= checkEmptyValues(document);
success &= checkGeneralRules(document);
success &= checkContractsAndGrants(document);
success &= checkIncomeStreamAccountRule();
success &= checkRequiredKcUnit(newAccountAutoCreateDefaults, document.isNew());
// process for IndirectCostRecovery Account
success &= checkIndirectCostRecoveryAccountDistributions();
return success;
}
/**
* @see org.kuali.kfs.coa.document.validation.impl.IndirectCostRecoveryAccountsRule#processCustomAddCollectionLineBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument, java.lang.String, org.kuali.rice.krad.bo.PersistableBusinessObject)
*/
@Override
public boolean processCustomAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject bo) {
boolean success = true;
// this incoming bo needs to be refreshed because it doesn't have its subobjects setup
bo.refreshNonUpdateableReferences();
if (bo instanceof IndirectCostRecoveryAutoDefAccount) {
IndirectCostRecoveryAutoDefAccount account = (IndirectCostRecoveryAutoDefAccount) bo;
success &= checkIndirectCostRecoveryAccount(account);
}
return success;
}
@Override
protected boolean checkEmptyValues(MaintenanceDocument maintenanceDocument) {
LOG.info("checkEmptyValues called");
boolean success = true;
// this set confirms that all fields which are grouped (ie, foreign keys of a reference
// object), must either be none filled out, or all filled out.
success &= checkForPartiallyFilledOutReferenceForeignKeys("continuationAccount");
success &= checkForPartiallyFilledOutReferenceForeignKeys("incomeStreamAccount");
success &= checkForPartiallyFilledOutReferenceForeignKeys("reportsToAccount");
return success;
}
@Override
protected boolean checkGeneralRules(MaintenanceDocument maintenanceDocument) {
LOG.info("checkGeneralRules called");
Person fiscalOfficer = newAccountAutoCreateDefaults.getAccountFiscalOfficerUser();
Person accountManager = newAccountAutoCreateDefaults.getAccountManagerUser();
Person accountSupervisor = newAccountAutoCreateDefaults.getAccountSupervisoryUser();
boolean success = true;
// check FringeBenefit account rules
success &= checkFringeBenefitAccountRule();
if (ObjectUtils.isNotNull(fiscalOfficer)
&& StringUtils.isNotBlank(fiscalOfficer.getPrincipalId())
&& !getDocumentHelperService().getDocumentAuthorizer(maintenanceDocument).isAuthorized(maintenanceDocument, KFSConstants.PermissionNames.SERVE_AS_FISCAL_OFFICER.namespace, KFSConstants.PermissionNames.SERVE_AS_FISCAL_OFFICER.name, fiscalOfficer.getPrincipalId())) {
super.putFieldError("accountFiscalOfficerUser.principalName", KFSKeyConstants.ERROR_USER_MISSING_PERMISSION, new String[] { fiscalOfficer.getName(), KFSConstants.PermissionNames.SERVE_AS_FISCAL_OFFICER.namespace, KFSConstants.PermissionNames.SERVE_AS_FISCAL_OFFICER.name });
success = false;
}
if (ObjectUtils.isNotNull(accountSupervisor)
&& StringUtils.isNotBlank(accountSupervisor.getPrincipalId())
&& !getDocumentHelperService().getDocumentAuthorizer(maintenanceDocument).isAuthorized(maintenanceDocument, KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_SUPERVISOR.namespace, KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_SUPERVISOR.name, accountSupervisor.getPrincipalId())) {
super.putFieldError("accountSupervisoryUser.principalName", KFSKeyConstants.ERROR_USER_MISSING_PERMISSION, new String[] { accountSupervisor.getName(), KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_SUPERVISOR.namespace, KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_SUPERVISOR.name });
success = false;
}
if (ObjectUtils.isNotNull(accountManager)
&& StringUtils.isNotBlank(accountManager.getPrincipalId())
&& !getDocumentHelperService().getDocumentAuthorizer(maintenanceDocument).isAuthorized(maintenanceDocument, KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_MANAGER.namespace, KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_MANAGER.name, accountManager.getPrincipalId())) {
super.putFieldError("accountManagerUser.principalName", KFSKeyConstants.ERROR_USER_MISSING_PERMISSION, new String[] { accountManager.getName(), KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_MANAGER.namespace, KFSConstants.PermissionNames.SERVE_AS_ACCOUNT_MANAGER.name });
success = false;
}
// the supervisor cannot be the same as the fiscal officer or account manager.
if (isSupervisorSameAsFiscalOfficer()) {
success &= false;
putFieldError("accountsSupervisorySystemsIdentifier", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ACCT_SUPER_CANNOT_BE_FISCAL_OFFICER);
}
if (isSupervisorSameAsManager()) {
success &= false;
putFieldError("accountManagerSystemIdentifier", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ACCT_SUPER_CANNOT_BE_ACCT_MGR);
}
// disallow continuation account being expired
if (isContinuationAccountExpired()) {
success &= false;
putFieldError("continuationAccountNumber", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ACCOUNT_EXPIRED_CONTINUATION);
}
return success;
}
protected boolean checkFringeBenefitAccountRule() {
boolean result = true;
// if this account is selected as a Fringe Benefit Account, then we have nothing
// to test, so exit
if (newAccountAutoCreateDefaults.isAccountsFringesBnftIndicator()) {
return true;
}
// if fringe benefit is not selected ... continue processing
// fringe benefit account number is required
if (StringUtils.isBlank(newAccountAutoCreateDefaults.getReportsToAccountNumber())) {
putFieldError("reportsToAccountNumber", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_RPTS_TO_ACCT_REQUIRED_IF_FRINGEBENEFIT_FALSE);
result &= false;
}
// fringe benefit chart of accounts code is required
if (StringUtils.isBlank(newAccountAutoCreateDefaults.getReportsToChartOfAccountsCode())) {
putFieldError("reportsToChartOfAccountsCode", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_RPTS_TO_ACCT_REQUIRED_IF_FRINGEBENEFIT_FALSE);
result &= false;
}
// if either of the fringe benefit account fields are not present, then we're done
if (result == false) {
return result;
}
// attempt to load the fringe benefit account
Account fringeBenefitAccount = accountService.getByPrimaryId(newAccountAutoCreateDefaults.getReportsToChartOfAccountsCode(), newAccountAutoCreateDefaults.getReportsToAccountNumber());
// fringe benefit account must exist
if (fringeBenefitAccount == null) {
putFieldError("reportsToAccountNumber", KFSKeyConstants.ERROR_EXISTENCE, getFieldLabel(Account.class, "reportsToAccountNumber"));
return false;
}
// fringe benefit account must be active
if (!fringeBenefitAccount.isActive()) {
putFieldError("reportsToAccountNumber", KFSKeyConstants.ERROR_INACTIVE, getFieldLabel(Account.class, "reportsToAccountNumber"));
result &= false;
}
// make sure the fringe benefit account specified is set to fringe benefits = Y
if (!fringeBenefitAccount.isAccountsFringesBnftIndicator()) {
putFieldError("reportsToAccountNumber", KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_RPTS_TO_ACCT_MUST_BE_FLAGGED_FRINGEBENEFIT, fringeBenefitAccount.getChartOfAccountsCode() + "-" + fringeBenefitAccount.getAccountNumber());
result &= false;
}
return result;
}
protected boolean isSupervisorSameAsFiscalOfficer() {
return areTwoUsersTheSame(newAccountAutoCreateDefaults.getAccountSupervisoryUser(), newAccountAutoCreateDefaults.getAccountFiscalOfficerUser());
}
protected boolean isSupervisorSameAsManager() {
return areTwoUsersTheSame(newAccountAutoCreateDefaults.getAccountSupervisoryUser(), newAccountAutoCreateDefaults.getAccountManagerUser());
}
protected boolean isContinuationAccountExpired() {
boolean result = false;
String chartCode = newAccountAutoCreateDefaults.getContinuationFinChrtOfAcctCd();
String accountNumber = newAccountAutoCreateDefaults.getContinuationAccountNumber();
// if either chartCode or accountNumber is not entered, then we
// can't continue, so exit
if (StringUtils.isBlank(chartCode) || StringUtils.isBlank(accountNumber)) {
return result;
}
// attempt to retrieve the continuation account from the DB
Account continuation = accountService.getByPrimaryId(chartCode, accountNumber);
// if the object doesn't exist, then we can't continue, so exit
if (ObjectUtils.isNull(continuation)) {
return result;
}
// at this point, we have a valid continuation account, so we just need to
// know whether its expired or not
result = continuation.isExpired();
return result;
}
@Override
protected boolean checkContractsAndGrants(MaintenanceDocument maintenanceDocument) {
LOG.info("checkContractsAndGrants called");
boolean success = true;
// Certain C&G fields are required if the Account belongs to the CG Fund Group
success &= checkCgRequiredFields();
// Income Stream account is required if this account is CG fund group,
// or GF (general fund) fund group (with some exceptions)
success &= checkIncomeStreamValid();
// check if the new account has a valid responsibility id
if (!ObjectUtils.isNull(newAccountAutoCreateDefaults)) {
Account account = new Account();
account.setContractsAndGrantsAccountResponsibilityId(newAccountAutoCreateDefaults.getContractsAndGrantsAccountResponsibilityId());
final boolean hasValidAccountResponsibility = contractsAndGrantsModuleService.hasValidAccountReponsiblityIdIfNotNull(account);
if (!hasValidAccountResponsibility) {
success &= hasValidAccountResponsibility;
putFieldError("contractsAndGrantsAccountResponsibilityId", KFSKeyConstants.ERROR_DOCUMENT_ACCTMAINT_INVALID_CG_RESPONSIBILITY, new String[] { newAccountAutoCreateDefaults.getContractsAndGrantsAccountResponsibilityId().toString(), newAccountAutoCreateDefaults.getChartOfAccountsCode(), "" });
}
}
return success;
}
protected boolean checkCgRequiredFields() {
boolean result = true;
// Certain C&G fields are required if the Account belongs to the CG Fund Group
if (ObjectUtils.isNotNull(newAccountAutoCreateDefaults.getSubFundGroup())) {
if (getSubFundGroupService().isForContractsAndGrants(newAccountAutoCreateDefaults.getSubFundGroup())) {
// check the ICR collection exists
result &= checkICRCollectionExistWithErrorMessage(true, KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ICR_CHART_CODE_CANNOT_BE_EMPTY, replaceTokens(KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ICR_CHART_CODE_CANNOT_BE_EMPTY));
} else {
// this is not a C&G fund group. So users should not fill in any fields in the C&G tab.
result &= checkICRCollectionExistWithErrorMessage(false, KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_CG_FIELDS_FILLED_FOR_NON_CG_ACCOUNT, replaceTokens(KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_CG_FIELDS_FILLED_FOR_NON_CG_ACCOUNT));
}
}
return result;
}
protected boolean checkIncomeStreamValid() {
// if the subFundGroup object is null, we can't test, so exit
if (ObjectUtils.isNull(newAccountAutoCreateDefaults.getSubFundGroup())) {
return true;
}
String subFundGroupCode = newAccountAutoCreateDefaults.getSubFundGroupCode().trim();
String fundGroupCode = newAccountAutoCreateDefaults.getSubFundGroup().getFundGroupCode().trim();
boolean valid = true;
if (/*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(Account.class, KFSConstants.ChartApcParms.INCOME_STREAM_ACCOUNT_REQUIRING_FUND_GROUPS, fundGroupCode).evaluationSucceeds()) {
if (/*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(Account.class, KFSConstants.ChartApcParms.INCOME_STREAM_ACCOUNT_REQUIRING_SUB_FUND_GROUPS, subFundGroupCode).evaluationSucceeds()) {
if (StringUtils.isBlank(newAccountAutoCreateDefaults.getIncomeStreamFinancialCoaCode())) {
putFieldError(KFSPropertyConstants.INCOME_STREAM_CHART_OF_ACCOUNTS_CODE, KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_INCOME_STREAM_ACCT_COA_CANNOT_BE_EMPTY, new String[] { getDdService().getAttributeLabel(FundGroup.class, KFSConstants.FUND_GROUP_CODE_PROPERTY_NAME), fundGroupCode, getDdService().getAttributeLabel(SubFundGroup.class, KFSConstants.SUB_FUND_GROUP_CODE_PROPERTY_NAME), subFundGroupCode });
valid = false;
}
if (StringUtils.isBlank(newAccountAutoCreateDefaults.getIncomeStreamAccountNumber())) {
putFieldError(KFSPropertyConstants.INCOME_STREAM_ACCOUNT_NUMBER, KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_INCOME_STREAM_ACCT_NBR_CANNOT_BE_EMPTY, new String[] { getDdService().getAttributeLabel(FundGroup.class, KFSConstants.FUND_GROUP_CODE_PROPERTY_NAME), fundGroupCode, getDdService().getAttributeLabel(SubFundGroup.class, KFSConstants.SUB_FUND_GROUP_CODE_PROPERTY_NAME), subFundGroupCode });
valid = false;
}
}
}
return valid;
}
protected boolean checkCGFieldNotFilledIn(String propertyName) {
boolean success = true;
Object value = ObjectUtils.getPropertyValue(newAccountAutoCreateDefaults, propertyName);
if ((value instanceof String && !StringUtils.isBlank(value.toString())) || (value != null)) {
success = false;
putFieldError(propertyName, KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_CG_FIELDS_FILLED_FOR_NON_CG_ACCOUNT, new String[] { newAccountAutoCreateDefaults.getSubFundGroupCode() });
}
return success;
}
@Override
protected boolean checkIncomeStreamAccountRule() {
// KFSMI-4877: if fund group is in system parameter values then income stream account number must exist.
if (ObjectUtils.isNotNull(newAccountAutoCreateDefaults.getSubFundGroup()) && StringUtils.isNotBlank(newAccountAutoCreateDefaults.getSubFundGroup().getFundGroupCode())) {
if (ObjectUtils.isNull(newAccountAutoCreateDefaults.getIncomeStreamAccount())) {
String incomeStreamRequiringFundGroupCode = SpringContext.getBean(ParameterService.class).getParameterValueAsString(Account.class, KFSConstants.ChartApcParms.INCOME_STREAM_ACCOUNT_REQUIRING_FUND_GROUPS);
if (StringUtils.containsIgnoreCase(newAccountAutoCreateDefaults.getSubFundGroup().getFundGroupCode(), incomeStreamRequiringFundGroupCode)) {
GlobalVariables.getMessageMap().putError(KFSPropertyConstants.ACCOUNT_NUMBER, KFSKeyConstants.ERROR_DOCUMENT_BA_NO_INCOME_STREAM_ACCOUNT, "");
return false;
}
}
}
return true;
}
/**
* This method checks to make sure that the kcUnit field exists and is entered correctly
*
* @param newAccountAutoCreateDefaults
* @return true/false
*/
protected boolean checkRequiredKcUnit(AccountAutoCreateDefaults newAccountAutoCreateDefaults, boolean isNew) {
boolean result = true;
try {
ContractsAndGrantsUnit unitDTO = newAccountAutoCreateDefaults.getUnitDTO();
unitDTO = SpringContext.getBean(KualiModuleService.class).getResponsibleModuleService(ContractsAndGrantsUnit.class).retrieveExternalizableBusinessObjectIfNecessary(newAccountAutoCreateDefaults, unitDTO, "unitDTO");
if (unitDTO == null) {
putFieldError(KcConstants.AccountCreationDefaults.KcUnit, KcConstants.AccountCreationService.ERROR_KC_ACCOUNT_PARAMS_UNIT_NOTFOUND, newAccountAutoCreateDefaults.getKcUnit());
result &= false;
}
// in the case of new accounts check if KcUnit exists already in accountAutoCreateDefaults table - if so reject
if (isNew) {
// check for new copy and new conditions
String kcUnit = newAccountAutoCreateDefaults.getKcUnit();
if ((kcUnit != null)) {
HashMap<String, String> map = new HashMap<String, String>();
map.put(KcConstants.AccountCreationDefaults.KcUnit, kcUnit);
Collection<AccountAutoCreateDefaults> accountAutoCreateDefaultList = getBoService().findMatching(AccountAutoCreateDefaults.class, map);
if (accountAutoCreateDefaultList == null || (!accountAutoCreateDefaultList.isEmpty())) {
putFieldError(KcConstants.AccountCreationDefaults.KcUnit, KcConstants.AccountCreationService.ERROR_KC_ACCOUNT_ALREADY_DEFINED, newAccountAutoCreateDefaults.getKcUnit());
result &= false;
}
}
}
return result;
}
catch (Exception ex) {
putFieldError(KcConstants.AccountCreationDefaults.KcUnit, KcConstants.AccountCreationService.ERROR_KC_ACCOUNT_PARAMS_UNIT_NOTFOUND, newAccountAutoCreateDefaults.getKcUnit());
return false;
}
}
/**
* Sets the contractsAndGrantsModuleService attribute value.
*
* @param contractsAndGrantsModuleService The contractsAndGrantsModuleService to set.
*/
@Override
public void setContractsAndGrantsModuleService(ContractsAndGrantsModuleService contractsAndGrantsModuleService) {
this.contractsAndGrantsModuleService = contractsAndGrantsModuleService;
}
@Override
public ParameterService getParameterService() {
if (parameterService == null) {
parameterService = SpringContext.getBean(ParameterService.class);
}
return parameterService;
}
/**
* @see org.kuali.kfs.coa.document.validation.impl.IndirectCostRecoveryAccountsRule#checkICRCollectionExist(boolean)
*/
@Override
protected boolean checkICRCollectionExist(boolean expectFilled) {
boolean success = true;
List<IndirectCostRecoveryAutoDefAccount> indirectCostRecoveryAccountList = newAccountAutoCreateDefaults.getIndirectCostRecoveryAutoDefAccounts();
success = expectFilled != newAccountAutoCreateDefaults.getIndirectCostRecoveryAutoDefAccounts().isEmpty();
//double check each of the account/coa codes are not blank
if (!success && expectFilled){
for (IndirectCostRecoveryAutoDefAccount account : indirectCostRecoveryAccountList){
success &= StringUtils.isNotBlank(account.getIndirectCostRecoveryAccountNumber())
&& StringUtils.isNotBlank(account.getIndirectCostRecoveryFinCoaCode());
}
}
return success;
}
/**
* @see org.kuali.kfs.coa.document.validation.impl.IndirectCostRecoveryAccountsRule#checkIndirectCostRecoveryAccountDistributions()
*/
@Override
protected boolean checkIndirectCostRecoveryAccountDistributions() {
boolean result = true;
List<IndirectCostRecoveryAutoDefAccount> indirectCostRecoveryAccountList = newAccountAutoCreateDefaults.getActiveIndirectCostRecoveryAccounts();
if (ObjectUtils.isNull(indirectCostRecoveryAccountList) || (indirectCostRecoveryAccountList.size() == 0)) {
return result;
}
DictionaryValidationService dvService = super.getDictionaryValidationService();
int i=0;
BigDecimal totalDistribution = BigDecimal.ZERO;
for (IndirectCostRecoveryAutoDefAccount icra : indirectCostRecoveryAccountList){
String errorPath = MAINTAINABLE_ERROR_PREFIX + boFieldPath + "[" + i++ + "]";
GlobalVariables.getMessageMap().addToErrorPath(errorPath);
checkIndirectCostRecoveryAccount(icra);
GlobalVariables.getMessageMap().removeFromErrorPath(errorPath);
totalDistribution = totalDistribution.add(icra.getAccountLinePercent());
}
//check the total distribution is 100
if (totalDistribution.compareTo(BD100) != 0){
putFieldError(boFieldPath, KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ICR_ACCOUNT_TOTAL_NOT_100_PERCENT);
result &= false;
}
return result;
}
protected boolean checkIndirectCostRecoveryAccount(IndirectCostRecoveryAutoDefAccount icra) {
boolean success = true;
//check for empty values on the ICR account
// The chart and account must exist in the database.
String chartOfAccountsCode = icra.getIndirectCostRecoveryFinCoaCode();
String accountNumber = icra.getIndirectCostRecoveryAccountNumber();
BigDecimal icraAccountLinePercentage = ObjectUtils.isNotNull(icra.getAccountLinePercent()) ? icra.getAccountLinePercent() : BigDecimal.ZERO;
return checkIndirectCostRecoveryAccount(chartOfAccountsCode, accountNumber, icraAccountLinePercentage);
}
}