/*
* 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 static org.kuali.kfs.sys.KualiTestAssertionUtils.assertGlobalMessageMapContains;
import static org.kuali.kfs.sys.KualiTestAssertionUtils.assertGlobalMessageMapEmpty;
import static org.kuali.kfs.sys.fixture.UserNameFixture.khuntley;
import java.sql.Date;
import java.util.Calendar;
import org.kuali.kfs.coa.businessobject.AccountDelegate;
import org.kuali.kfs.sys.ConfigureContext;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSKeyConstants;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.rice.core.api.datetime.DateTimeService;
import org.kuali.rice.core.api.util.type.KualiDecimal;
import org.kuali.rice.kns.document.MaintenanceDocument;
/**
* This class...
*/
@ConfigureContext(session = khuntley)
public class DelegateRuleTest extends ChartRuleTestBase {
protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DelegateRuleTest.class);
private static final String ERROR_PREFIX = "document.newMaintainableObject.";
private static final String CHART_GOOD_1 = "UA";
private static final String ACCOUNT_GOOD_1 = "1912201";
private static final String DOCTYPE_GOOD_1 = KFSConstants.ROOT_DOCUMENT_TYPE;
private static final int BAD_FROM_AMT = -25;
private static final int BAD_TO_AMT = -40;
private static final int GOOD_FROM_AMT = 25;
private static final int GOOD_TO_AMT = 25;
private static final int BAD_TO_AMT_LESS_THAN = 5;
// delegate user's - need four
// one that is good - has both A for status and P for type
private static final String USERID_GOOD_1 = "1545104915";// ABARRING = BARRINGER,ALONZO E
// one that has something else for status and P for type
private static final String USERID_BAD_1 = "2419205388"; // SROOD=ROOD,SAM N : status=D
// one that has A for status and something else for type
private static final String USERID_BAD_2 = "1659102154"; // AAVILES=AVILES,ANTON F
// one that has neither A nor P for status and type
private static final String USERID_BAD_3 = "4533105209"; // AIAUCOIN=AUCOIN,AMELIA I
// values for testing primary routing
// has doctype "all" for chart BL and account 223146
private static final String DOCTYPE_ALL_CHART = "BL";
private static final String DOCTYPE_ALL_ACCT = "2231466";
// has doctype CREQ for chart BL and account 1031400
private static final String DOCTYPE_SPECIFIC_CHART = "BL";
private static final String DOCTYPE_SPECIFIC_ACCT = "1031400";
private static final String DOCTYPE_SPECIFIC_DT_VALUE = "CREQ";
// this one is an available chart/account combo that should succeed for specific
// choose anything but CREQ or AV for doctype
private static final String DOCTYPE_OPEN_SPECIFIC_CHART = "BA";
private static final String DOCTYPE_OPEN_SPECIFIC_ACCT = "9020174";
private static final String DOCTYPE_OPEN_SPECFIC_DT_VALUE = "IB";
// this one is an available chart/account combo for doctype "all"
private static final String DOCTYPE_OPEN_ALL_CHART = "UA";
private static final String DOCTYPE_OPEN_ALL_ACCT = "1912201";
private static final String DOCTYPE_OPEN_ALL_DT_VALUE = KFSConstants.ROOT_DOCUMENT_TYPE;
private static final String DOCTYPE_ALL = KFSConstants.ROOT_DOCUMENT_TYPE;
private AccountDelegate newDelegate;
private AccountDelegate oldDelegate;
private MaintenanceDocument maintDoc;
/**
* This method creates a delegate with a minimal set of known-good values.
*
* @return
*/
private AccountDelegate goodDelegate1() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(CHART_GOOD_1);
delegate.setAccountNumber(ACCOUNT_GOOD_1);
delegate.setFinancialDocumentTypeCode(DOCTYPE_GOOD_1);
delegate.setAccountDelegateSystemId(USERID_GOOD_1);
delegate.refresh();
return delegate;
}
private AccountDelegate goodDelegate2() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(CHART_GOOD_1);
delegate.setAccountNumber(ACCOUNT_GOOD_1);
delegate.setFinancialDocumentTypeCode(DOCTYPE_GOOD_1);
delegate.setAccountDelegateSystemId(USERID_GOOD_1);
Date today = new Date(SpringContext.getBean(DateTimeService.class).getCurrentDate().getTime());
delegate.setAccountDelegateStartDate(today);
delegate.refresh();
return delegate;
}
private AccountDelegate badDelegate1() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(CHART_GOOD_1);
delegate.setAccountNumber(ACCOUNT_GOOD_1);
delegate.setFinancialDocumentTypeCode(DOCTYPE_GOOD_1);
delegate.setAccountDelegateSystemId(USERID_BAD_1);
delegate.refresh();
return delegate;
}
private AccountDelegate badDelegate2() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(CHART_GOOD_1);
delegate.setAccountNumber(ACCOUNT_GOOD_1);
delegate.setFinancialDocumentTypeCode(DOCTYPE_GOOD_1);
delegate.setAccountDelegateSystemId(USERID_BAD_2);
delegate.refresh();
return delegate;
}
private AccountDelegate badDelegate3() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(CHART_GOOD_1);
delegate.setAccountNumber(ACCOUNT_GOOD_1);
delegate.setFinancialDocumentTypeCode(DOCTYPE_GOOD_1);
delegate.setAccountDelegateSystemId(USERID_BAD_3);
delegate.refresh();
return delegate;
}
private AccountDelegate badDelegate4() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(CHART_GOOD_1);
delegate.setAccountNumber(ACCOUNT_GOOD_1);
delegate.setFinancialDocumentTypeCode(DOCTYPE_GOOD_1);
delegate.setAccountDelegateSystemId(USERID_GOOD_1);
delegate.setFinDocApprovalFromThisAmt(new KualiDecimal(BAD_FROM_AMT));
delegate.refresh();
return delegate;
}
private AccountDelegate badDelegate5() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(CHART_GOOD_1);
delegate.setAccountNumber(ACCOUNT_GOOD_1);
delegate.setFinancialDocumentTypeCode(DOCTYPE_GOOD_1);
delegate.setAccountDelegateSystemId(USERID_GOOD_1);
delegate.setFinDocApprovalToThisAmount(new KualiDecimal(BAD_TO_AMT));
delegate.refresh();
return delegate;
}
private AccountDelegate badDelegate6() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(CHART_GOOD_1);
delegate.setAccountNumber(ACCOUNT_GOOD_1);
delegate.setFinancialDocumentTypeCode(DOCTYPE_GOOD_1);
delegate.setAccountDelegateSystemId(USERID_GOOD_1);
delegate.setFinDocApprovalToThisAmount(new KualiDecimal(GOOD_FROM_AMT));
delegate.setFinDocApprovalToThisAmount(null);
delegate.refresh();
return delegate;
}
private AccountDelegate badDelegate8() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(CHART_GOOD_1);
delegate.setAccountNumber(ACCOUNT_GOOD_1);
delegate.setFinancialDocumentTypeCode(DOCTYPE_GOOD_1);
delegate.setAccountDelegateSystemId(USERID_GOOD_1);
delegate.setFinDocApprovalFromThisAmt(new KualiDecimal(GOOD_FROM_AMT));
delegate.setFinDocApprovalToThisAmount(new KualiDecimal(BAD_TO_AMT_LESS_THAN));
delegate.refresh();
return delegate;
}
@SuppressWarnings("deprecation")
private AccountDelegate delegateWithDocTypeAll() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(DOCTYPE_ALL_CHART);
delegate.setAccountNumber(DOCTYPE_ALL_ACCT);
delegate.setFinancialDocumentTypeCode(DOCTYPE_ALL);
delegate.setAccountsDelegatePrmrtIndicator(true);
delegate.setAccountDelegateSystemId(USERID_GOOD_1);
delegate.refresh();
return delegate;
}
@SuppressWarnings("deprecation")
private AccountDelegate delegateWithSpecificTypeClosedAllSpecified() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(DOCTYPE_SPECIFIC_CHART);
delegate.setAccountNumber(DOCTYPE_SPECIFIC_ACCT);
delegate.setFinancialDocumentTypeCode(DOCTYPE_ALL);
delegate.setAccountsDelegatePrmrtIndicator(true);
delegate.setAccountDelegateSystemId(USERID_GOOD_1);
delegate.refresh();
return delegate;
}
@SuppressWarnings("deprecation")
private AccountDelegate delegateWithSpecificTypeClosed() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(DOCTYPE_SPECIFIC_CHART);
delegate.setAccountNumber(DOCTYPE_SPECIFIC_ACCT);
delegate.setFinancialDocumentTypeCode(DOCTYPE_SPECIFIC_DT_VALUE);
delegate.setAccountsDelegatePrmrtIndicator(true);
delegate.setAccountDelegateSystemId(USERID_GOOD_1);
delegate.refresh();
return delegate;
}
@SuppressWarnings("deprecation")
private AccountDelegate delegateWithAllDocTypeOpen() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(DOCTYPE_OPEN_ALL_CHART);
delegate.setAccountNumber(DOCTYPE_OPEN_ALL_ACCT);
delegate.setFinancialDocumentTypeCode(DOCTYPE_OPEN_ALL_DT_VALUE);
delegate.setAccountsDelegatePrmrtIndicator(true);
delegate.setAccountDelegateSystemId(USERID_GOOD_1);
delegate.refresh();
return delegate;
}
@SuppressWarnings("deprecation")
private AccountDelegate delegateWithSpecificDocTypeOpen() {
AccountDelegate delegate = new AccountDelegate();
delegate.setChartOfAccountsCode(DOCTYPE_OPEN_SPECIFIC_CHART);
delegate.setAccountNumber(DOCTYPE_OPEN_SPECIFIC_ACCT);
delegate.setFinancialDocumentTypeCode(DOCTYPE_OPEN_SPECFIC_DT_VALUE);
delegate.setAccountsDelegatePrmrtIndicator(true);
delegate.setAccountDelegateSystemId(USERID_GOOD_1);
delegate.refresh();
return delegate;
}
/**
* This method tests a Delegate that we have setup with all known good values for the required fields, and nothing or the
* default for the other fields. This test should always pass, if it does not, then none of the following tests are meaningful,
* as the baseline is broken.
*/
public void testCheckSimpleRules_validDelegate() {
DelegateRule rule = new DelegateRule();
newDelegate = goodDelegate1();
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(maintDoc, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
// run the business rules
rule.checkSimpleRules();
assertGlobalMessageMapEmpty();
}
public void testCheckSimpleRulesStartDateRule_startDateToday() {
DelegateRule rule = new DelegateRule();
newDelegate = goodDelegate2();
// new delegate with start-date same as today
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(maintDoc, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
// run the business rules
rule.checkSimpleRules();
assertGlobalMessageMapEmpty();
}
public void testCheckSimpleRulesStartDateRule_startDateTomorrow() {
DelegateRule rule = new DelegateRule();
Calendar cal = SpringContext.getBean(DateTimeService.class).getCurrentCalendar();
cal.add(Calendar.DATE, 1);
Date ts = new Date(cal.getTimeInMillis());
newDelegate = goodDelegate2();
newDelegate.setAccountDelegateStartDate(ts);
// new delegate with start-date same as today
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(maintDoc, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
// run the business rules
rule.checkSimpleRules();
assertGlobalMessageMapEmpty();
}
public void testCheckSimpleRulesStartDateRule_startDateYesterday() {
DelegateRule rule = new DelegateRule();
Calendar cal = SpringContext.getBean(DateTimeService.class).getCurrentCalendar();
cal.add(Calendar.DATE, -1);
Date ts = new Date(cal.getTimeInMillis());
newDelegate = goodDelegate2();
newDelegate.setAccountDelegateStartDate(ts);
// new delegate with start-date same as today
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(maintDoc, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
// run the business rules
rule.checkSimpleRules();
assertGlobalMessageMapEmpty();
}
public void testCheckSimpleRulesStartDateRule_invalidFromAmt() {
DelegateRule rule = new DelegateRule();
newDelegate = badDelegate4();
// new delegate with start-date same as today
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(maintDoc, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
// run the business rules
rule.checkSimpleRules();
assertGlobalMessageMapContains(ERROR_PREFIX + "finDocApprovalFromThisAmt", KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_FROM_AMOUNT_NONNEGATIVE);
}
public void testCheckSimpleRulesStartDateRule_invalidToAmt() {
DelegateRule rule = new DelegateRule();
newDelegate = badDelegate5();
// new delegate with start-date same as today
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(maintDoc, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
// run the business rules
rule.checkSimpleRules();
assertGlobalMessageMapContains(ERROR_PREFIX + "finDocApprovalToThisAmount", KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_TO_AMOUNT_MORE_THAN_FROM_OR_ZERO);
}
public void testCheckSimpleRulesStartDateRule_validFromAmtLessThanToAmt() {
DelegateRule rule = new DelegateRule();
newDelegate = badDelegate8();
// new delegate with start-date same as today
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(maintDoc, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
// run the business rules
rule.checkSimpleRules();
assertGlobalMessageMapContains(ERROR_PREFIX + "finDocApprovalToThisAmount", KFSKeyConstants.ERROR_DOCUMENT_ACCTDELEGATEMAINT_TO_AMOUNT_MORE_THAN_FROM_OR_ZERO);
}
/**
* This test makes sure that a good user delegate passes the Delegate User Rules
*/
public void testcheckDelegateUserRules_goodDelegate() {
DelegateRule rule = new DelegateRule();
newDelegate = goodDelegate1();
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(newDelegate, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
rule.checkDelegateUserRules(maintDoc);
assertGlobalMessageMapEmpty();
}
public void testcheckDelegateUserRules_badDelegate1() {
DelegateRule rule = new DelegateRule();
newDelegate = badDelegate1();
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(newDelegate, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
rule.checkDelegateUserRules(maintDoc);
assertGlobalMessageMapContains(ERROR_PREFIX + "accountDelegate.principalName", KFSKeyConstants.ERROR_USER_MISSING_PERMISSION);
}
public void testcheckDelegateUserRules_badDelegate2() {
DelegateRule rule = new DelegateRule();
newDelegate = badDelegate2();
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(newDelegate, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
rule.checkDelegateUserRules(maintDoc);
assertGlobalMessageMapEmpty();
}
public void testcheckDelegateUserRules_badDelegate3() {
DelegateRule rule = new DelegateRule();
newDelegate = badDelegate3();
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(newDelegate, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
rule.checkDelegateUserRules(maintDoc);
assertGlobalMessageMapContains(ERROR_PREFIX + "accountDelegate.principalName", KFSKeyConstants.ERROR_USER_MISSING_PERMISSION);
}
/**
* This method simulates a user trying to create a delegate marked as primary when there is already an account with All
* Documents for the doctype for the chart/account combo
*/
public void testCheckOnlyOnePrimaryRoute_allPrimaryAlreadyExists() {
DelegateRule rule = new DelegateRule();
newDelegate = delegateWithDocTypeAll();
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(newDelegate, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
rule.checkOnlyOnePrimaryRoute(maintDoc);
assertGlobalMessageMapEmpty();
}
/**
* This method will simulate a user is trying to create a delegate that routes with DocumentType of ALL, but a chart/account
* combo that has a primary route for a specific doctype already exists
*/
public void testCheckOnlyOnePrimaryRoute_specificPrimaryAlreadyExistsAllFails() {
DelegateRule rule = new DelegateRule();
newDelegate = delegateWithSpecificTypeClosedAllSpecified();
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(newDelegate, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
rule.checkOnlyOnePrimaryRoute(maintDoc);
assertGlobalMessageMapEmpty();
}
/**
* This method will simulate a user who is trying to create a delegate that routes with a specific doctype that is already taken
* in the db
*/
public void testCheckOnlyOnePrimaryRoute_specificPrimaryAlreadyExistsSpecificFails() {
DelegateRule rule = new DelegateRule();
newDelegate = delegateWithSpecificTypeClosed();
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(newDelegate, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
rule.checkOnlyOnePrimaryRoute(maintDoc);
assertGlobalMessageMapEmpty();
}
/**
* This method will simulate a user who is trying to create a delegate that routes with a doctype of all and should succeed
*/
public void testCheckOnlyOnePrimaryRoute_allPrimaryDoesNotExist() {
DelegateRule rule = new DelegateRule();
newDelegate = delegateWithAllDocTypeOpen();
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(newDelegate, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
rule.checkOnlyOnePrimaryRoute(maintDoc);
assertGlobalMessageMapEmpty();
}
/**
* This method will simulate a user who is trying to create a delegate that routes with a doctype of a21 should succeed
*/
public void testCheckOnlyOnePrimaryRoute_specificPrimaryDoesNotExist() {
DelegateRule rule = new DelegateRule();
newDelegate = delegateWithSpecificDocTypeOpen();
maintDoc = newMaintDoc(newDelegate);
rule = (DelegateRule) setupMaintDocRule(newDelegate, rule.getClass());
// now we need to setup the convenience objects so that the rule has the right
// delegate values
rule.setupConvenienceObjects(maintDoc);
// confirm that there are no errors to begin with
assertGlobalMessageMapEmpty();
rule.checkOnlyOnePrimaryRoute(maintDoc);
assertGlobalMessageMapEmpty();
}
}