/*
* 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.service.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.coa.businessobject.Account;
import org.kuali.kfs.coa.businessobject.AccountGuideline;
import org.kuali.kfs.coa.businessobject.Chart;
import org.kuali.kfs.coa.businessobject.IndirectCostRecoveryAccount;
import org.kuali.kfs.coa.service.AccountService;
import org.kuali.kfs.coa.service.ChartService;
import org.kuali.kfs.integration.cg.dto.AccountCreationStatusDTO;
import org.kuali.kfs.integration.cg.dto.AccountParametersDTO;
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.module.external.kc.service.AccountCreationService;
import org.kuali.kfs.module.external.kc.service.AccountDefaultsService;
import org.kuali.kfs.module.external.kc.util.GlobalVariablesExtractHelper;
import org.kuali.kfs.module.external.kc.util.KcUtils;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSKeyConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.rice.coreservice.framework.parameter.ParameterService;
import org.kuali.rice.kew.api.exception.WorkflowException;
import org.kuali.rice.kim.api.identity.Person;
import org.kuali.rice.kim.api.identity.PersonService;
import org.kuali.rice.kns.datadictionary.validation.charlevel.AlphaNumericValidationPattern;
import org.kuali.rice.kns.document.MaintenanceDocument;
import org.kuali.rice.kns.document.authorization.DocumentAuthorizer;
import org.kuali.rice.kns.document.authorization.MaintenanceDocumentAuthorizerBase;
import org.kuali.rice.kns.service.DataDictionaryService;
import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
import org.kuali.rice.krad.UserSession;
import org.kuali.rice.krad.datadictionary.AttributeDefinition;
import org.kuali.rice.krad.datadictionary.validation.ValidationPattern;
import org.kuali.rice.krad.document.Document;
import org.kuali.rice.krad.exception.ValidationException;
import org.kuali.rice.krad.rules.rule.event.BlanketApproveDocumentEvent;
import org.kuali.rice.krad.rules.rule.event.RouteDocumentEvent;
import org.kuali.rice.krad.rules.rule.event.SaveDocumentEvent;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.service.DocumentService;
import org.kuali.rice.krad.service.KualiRuleService;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
import org.kuali.rice.krad.util.ObjectUtils;
public class AccountCreationServiceImpl implements AccountCreationService {
protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountCreationServiceImpl.class);
protected static final String ACCT_PREFIX_RESTRICTION = "PREFIXES";
protected DocumentService documentService;
protected ParameterService parameterService;
protected DataDictionaryService dataDictionaryService;
protected BusinessObjectService businessObjectService;
protected AccountDefaultsService accountDefaultsService;
protected KualiRuleService kualiRuleService;
protected MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
protected AccountService accountService;
protected ChartService chartService;
protected PersonService personService;
/**
* This is the web service method that creates a new account 1. Creates an account object using the parameters from KC and the
* default Account table 2. Creates an account automatic maintenance document and puts the account object into it 3. Returns the
* status object
*
* @param AccountAutoCreateDefaults
* @return AccountCreationStatusDTO
*/
@Override
public AccountCreationStatusDTO createAccount(AccountParametersDTO accountParameters) {
AccountCreationStatusDTO accountCreationStatus = new AccountCreationStatusDTO();
accountCreationStatus.setErrorMessages(new ArrayList<String>());
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_SUCCESS);
// check to see if the user has the permission to create account
String principalId = accountParameters.getPrincipalId();
LOG.debug("principalId ::::"+ principalId);
if (!isValidUser(principalId)) {
this.setFailStatus(accountCreationStatus, KcUtils.getErrorMessage(KcConstants.AccountCreationService.ERROR_KC_DOCUMENT_INVALID_USER, new String[]{principalId}));
return accountCreationStatus;
}
// get the defaults table
String unitNumber = accountParameters.getUnit();
AccountAutoCreateDefaults defaults = getAccountDefaultsService().getAccountDefaults(unitNumber);
if (defaults == null) {
this.setFailStatus(accountCreationStatus, KcConstants.AccountCreationService.ERROR_KC_ACCOUNT_PARAMS_UNIT_NOT_DEFINED);
return accountCreationStatus;
}
try {
// create an account object
Account account = createAccountObject(accountParameters, defaults);
//if invalid chart/account number, failure status and return to KC
if (! isValidAccount(account, accountCreationStatus)) {
return accountCreationStatus;
}
// create an account automatic maintenance document
createAutomaticCGAccountMaintenanceDocument(account, accountCreationStatus);
} catch (Exception ex ) {
this.setFailStatus(accountCreationStatus, KcConstants.AccountCreationService.ERROR_KC_DOCUMENT_ACCOUNT_GENERATION_PROBLEM);
return accountCreationStatus;
}
// set required values to AccountCreationStatus
if (accountCreationStatus.getStatus().equals(KcConstants.KcWebService.STATUS_KC_SUCCESS)) {
accountCreationStatus.setAccountNumber(accountParameters.getAccountNumber());
accountCreationStatus.setChartOfAccountsCode(defaults.getChartOfAccountsCode());
}
return accountCreationStatus;
}
/**
* This method creates an account to be used for automatic maintenance document
*
* @param AccountParametersDTO
* @return Account
*/
public Account createAccountObject(AccountParametersDTO parameters, AccountAutoCreateDefaults defaults) {
Account account = new Account();
// * Account: required but off campus indicator, closed, fringe benefit indicator, fringe benefit COA, endowment
account.setChartOfAccountsCode(defaults.getChartOfAccountsCode());
account.setOrganizationCode(defaults.getOrganizationCode());
account.setAccountNumber(parameters.getAccountNumber()); // what if account number is null?
account.setAccountName(parameters.getAccountName());
account.setAccountPhysicalCampusCode(defaults.getAccountPhysicalCampusCode());
if (parameters.getExpirationDate() != null) {
account.setAccountExpirationDate(new java.sql.Date(parameters.getExpirationDate().getTime()));
}
if (parameters.getEffectiveDate() != null) {
account.setAccountEffectiveDate(new java.sql.Date(parameters.getEffectiveDate().getTime()));
}
boolean isKCOverrideKFS = parameterService.getParameterValueAsBoolean(Account.class, KcConstants.AccountCreationService.PARAMETER_KC_OVERRIDES_KFS_DEFAULT_ACCOUNT_IND);
if (isKCOverrideKFS) {
// set the right address based on the system parameter RESEARCH_ADMIN_ACCOUNT_ADDRESS_TYPE
List<String> addressTypes = new ArrayList<String>( parameterService.getParameterValuesAsString(Account.class, KcConstants.AccountCreationService.PARAMETER_KC_ACCOUNT_ADDRESS_TYPE) );
for (String addressType : addressTypes) {
if (addressType.equals(KcConstants.AccountCreationService.PI_ADDRESS_TYPE) && (!StringUtils.isBlank(parameters.getDefaultAddressStreetAddress()))) {
account.setAccountStreetAddress(parameters.getDefaultAddressStreetAddress());
account.setAccountCityName(parameters.getDefaultAddressCityName());
account.setAccountStateCode(parameters.getDefaultAddressStateCode());
account.setAccountZipCode(parameters.getDefaultAddressZipCode());
break;
}
else if (addressType.equals(KcConstants.AccountCreationService.ADMIN_ADDRESS_TYPE) && (!StringUtils.isBlank(parameters.getAdminContactAddressStreetAddress()))) {
account.setAccountStreetAddress(parameters.getAdminContactAddressStreetAddress());
account.setAccountCityName(parameters.getAdminContactAddressCityName());
account.setAccountStateCode(parameters.getAdminContactAddressStateCode());
account.setAccountZipCode(parameters.getAdminContactAddressZipCode());
break;
}
}
} else {
// use default address
account.setAccountStreetAddress(defaults.getAccountStreetAddress());
account.setAccountCityName(defaults.getAccountCityName());
account.setAccountStateCode(defaults.getAccountStateCode());
account.setAccountZipCode(defaults.getAccountZipCode());
}
//set the following from parameters
account.setAccountOffCampusIndicator(parameters.isOffCampusIndicator());
account.setFinancialHigherEdFunctionCd(parameters.getHigherEdFunctionCode());
account.setAcctIndirectCostRcvyTypeCd(parameters.getIndirectCostTypeCode());
account.setFinancialIcrSeriesIdentifier(parameters.getIndirectCostRate());
account.setAccountGuideline(new AccountGuideline());
account.getAccountGuideline().setAccountExpenseGuidelineText(parameters.getExpenseGuidelineText());
account.getAccountGuideline().setAccountIncomeGuidelineText(parameters.getIncomeGuidelineText());
account.getAccountGuideline().setAccountPurposeText(parameters.getPurposeText());
account.setClosed(false);
account.setAccountTypeCode(defaults.getAccountTypeCode());
account.setSubFundGroupCode(defaults.getSubFundGroupCode());
account.setAccountsFringesBnftIndicator(defaults.isAccountsFringesBnftIndicator());
account.setReportsToAccountNumber(defaults.getReportsToAccountNumber());
account.setReportsToChartOfAccountsCode(defaults.getReportsToChartOfAccountsCode());
account.setAccountRestrictedStatusCode("R");
account.setAccountRestrictedStatusDate(null);
account.setEndowmentIncomeChartOfAccounts(null);
account.setEndowmentIncomeAccountNumber(null);
// * Accounts Responsibility: required - fiscal officer principal name, account supervisor principal name, account manager
// principal name, budget record level, account sufficient funds
account.setAccountFiscalOfficerSystemIdentifier(defaults.getAccountFiscalOfficerSystemIdentifier());
account.setAccountsSupervisorySystemsIdentifier(defaults.getAccountsSupervisorySystemsIdentifier());
account.setAccountManagerSystemIdentifier(defaults.getAccountManagerSystemIdentifier());
account.setContinuationFinChrtOfAcctCd(defaults.getContinuationFinChrtOfAcctCd());
account.setContinuationAccountNumber(defaults.getContinuationAccountNumber());
account.setIncomeStreamAccountNumber(defaults.getIncomeStreamAccountNumber());
account.setIncomeStreamChartOfAccounts(defaults.getIncomeStreamChartOfAccounts());
account.setIncomeStreamFinancialCoaCode(defaults.getIncomeStreamFinancialCoaCode());
account.setBudgetRecordingLevelCode(defaults.getBudgetRecordingLevelCode());
account.setAccountSufficientFundsCode(defaults.getAccountSufficientFundsCode());
account.setPendingAcctSufficientFundsIndicator(defaults.isPendingAcctSufficientFundsIndicator());
account.setExtrnlFinEncumSufficntFndIndicator(defaults.isExtrnlFinEncumSufficntFndIndicator());
account.setIntrnlFinEncumSufficntFndIndicator(defaults.isIntrnlFinEncumSufficntFndIndicator());
account.setFinPreencumSufficientFundIndicator(defaults.isFinPreencumSufficientFundIndicator());
account.setFinancialObjectivePrsctrlIndicator(defaults.isFinancialObjectivePrsctrlIndicator());
// * Contract and Grants: not required
account.setContractControlFinCoaCode(null);
account.setContractControlAccountNumber(null);
account.setContractsAndGrantsAccountResponsibilityId(defaults.getContractsAndGrantsAccountResponsibilityId());
account.setAccountCfdaNumber(parameters.getCfdaNumber());
// set up ICR distribution
for (IndirectCostRecoveryAutoDefAccount indirectCostRecoveryAutoDefAccount : defaults.getIndirectCostRecoveryAutoDefAccounts()) {
account.getIndirectCostRecoveryAccounts().add(createIndirectCostRecoveryAccount(indirectCostRecoveryAutoDefAccount, account.getChartOfAccountsCode(), account.getAccountNumber()));
}
return account;
}
/** create an indirect cost recovery distribution account based on default
*
*/
protected IndirectCostRecoveryAccount createIndirectCostRecoveryAccount(IndirectCostRecoveryAutoDefAccount indirectCostRecoveryAutoDefAccount, String chartCode, String acctNumber) {
IndirectCostRecoveryAccount indirectCostRecoveryAccount = new IndirectCostRecoveryAccount();
indirectCostRecoveryAccount.setChartOfAccountsCode(chartCode);
indirectCostRecoveryAccount.setAccountNumber(acctNumber);
indirectCostRecoveryAccount.setIndirectCostRecoveryAccount(indirectCostRecoveryAutoDefAccount.getIndirectCostRecoveryAccount());
indirectCostRecoveryAccount.setIndirectCostRecoveryChartOfAccounts(indirectCostRecoveryAutoDefAccount.getIndirectCostRecoveryChartOfAccounts());
indirectCostRecoveryAccount.setIndirectCostRecoveryAccountNumber(indirectCostRecoveryAutoDefAccount.getIndirectCostRecoveryAccountNumber());
indirectCostRecoveryAccount.setIndirectCostRecoveryFinCoaCode(indirectCostRecoveryAutoDefAccount.getIndirectCostRecoveryFinCoaCode());
indirectCostRecoveryAccount.setAccountLinePercent(indirectCostRecoveryAutoDefAccount.getAccountLinePercent());
indirectCostRecoveryAccount.setActive(indirectCostRecoveryAutoDefAccount.isActive());
return indirectCostRecoveryAccount;
}
protected void setFailStatus(AccountCreationStatusDTO accountCreationStatus, String message) {
accountCreationStatus.getErrorMessages().add(message);
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_FAILURE);
}
/**
* This method will create a maintenance document for CG account create, set its description and then sets the account business
* object in it. The document will then be tried to route, save or blanket approve automatically based on the system parameter.
* If successful, the method returns the newly created document number to the caller.
*
* @return documentNumber returns the documentNumber
* @see org.kuali.kfs.coa.document.service.CreateAccountService#createAutomaticCGAccountMaintenanceDocument()
*/
protected void createAutomaticCGAccountMaintenanceDocument(Account account, AccountCreationStatusDTO accountCreationStatus) {
// create a new maintenance document
MaintenanceDocument maintenanceAccountDocument = (MaintenanceDocument) createCGAccountMaintenanceDocument(accountCreationStatus);
if (ObjectUtils.isNotNull(maintenanceAccountDocument)) {
// set document header description...
maintenanceAccountDocument.getDocumentHeader().setDocumentDescription(KcConstants.AccountCreationService.AUTOMATCICG_ACCOUNT_MAINTENANCE_DOCUMENT_DESCRIPTION);
// set the account object in the maintenance document.
maintenanceAccountDocument.getNewMaintainableObject().setBusinessObject(account);
maintenanceAccountDocument.getNewMaintainableObject().setMaintenanceAction(KRADConstants.MAINTENANCE_NEW_ACTION);
// the maintenance document will now be routed based on the system parameter value for routing.
createRouteAutomaticCGAccountDocument(maintenanceAccountDocument, accountCreationStatus);
}
}
/**
* This method processes the workflow document actions like save, route and blanket approve depending on the
* ACCOUNT_AUTO_CREATE_ROUTE system parameter value. If the system parameter value is not of save or submit or blanketapprove,
* put an error message and quit. Throws an document WorkflowException if the specific document action fails to perform.
*
* @param maintenanceAccountDocument, errorMessages
* @return
*/
protected void createRouteAutomaticCGAccountDocument(MaintenanceDocument maintenanceAccountDocument, AccountCreationStatusDTO accountCreationStatus) {
try {
String accountAutoCreateRouteValue = getParameterService().getParameterValueAsString(Account.class, KcConstants.AccountCreationService.PARAMETER_KC_ACCOUNT_ADMIN_AUTO_CREATE_ACCOUNT_WORKFLOW_ACTION);
// if the accountAutoCreateRouteValue is not save or submit or blanketApprove then put an error message and quit.
if (!accountAutoCreateRouteValue.equalsIgnoreCase(KFSConstants.WORKFLOW_DOCUMENT_SAVE) && !accountAutoCreateRouteValue.equalsIgnoreCase("submit") && !accountAutoCreateRouteValue.equalsIgnoreCase(KFSConstants.WORKFLOW_DOCUMENT_BLANKET_APPROVE)) {
this.setFailStatus( accountCreationStatus, KcConstants.AccountCreationService.ERROR_KC_DOCUMENT_SYSTEM_PARAMETER_INCORRECT_DOCUMENT_ACTION_VALUE);
LOG.error("Incorrect document status::::: " + accountCreationStatus.getErrorMessages().toString());
return;
}
if (accountAutoCreateRouteValue.equalsIgnoreCase(KFSConstants.WORKFLOW_DOCUMENT_SAVE)) {
//attempt to save if apply rules were successful and there are no errors
boolean rulesPassed = kualiRuleService.applyRules(new SaveDocumentEvent(maintenanceAccountDocument));
LOG.debug("global variable messages ::: " + GlobalVariables.getMessageMap().getErrorMessages().toString());
if( rulesPassed && GlobalVariables.getMessageMap().hasNoErrors()){
getDocumentService().saveDocument(maintenanceAccountDocument);
}else{
//get errors from apply rules invocation, also clears global variables
LOG.info("rule fail formatting errors messages " ) ;
accountCreationStatus.setErrorMessages(GlobalVariablesExtractHelper.extractGlobalVariableErrors());
try{
//save document, and catch VE's as we want to do this silently
getDocumentService().saveDocument(maintenanceAccountDocument);
}catch(ValidationException ve){}
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_SUCCESS);
LOG.error( KcUtils.getErrorMessage(KcConstants.AccountCreationService.ERROR_KC_DOCUMENT_ACCOUNT_RULES_EXCEPTION, new String[]{maintenanceAccountDocument.getDocumentNumber()}));
}
}
else if (accountAutoCreateRouteValue.equalsIgnoreCase(KFSConstants.WORKFLOW_DOCUMENT_BLANKET_APPROVE)) {
//attempt to blanket approve if apply rules were successful and there are no errors
boolean rulesPassed = kualiRuleService.applyRules(new BlanketApproveDocumentEvent(maintenanceAccountDocument));
if( rulesPassed && GlobalVariables.getMessageMap().hasNoErrors()){
getDocumentService().blanketApproveDocument(maintenanceAccountDocument, "", null);
}else{
//get errors from apply rules invocation, also clears global variables
accountCreationStatus.setErrorMessages(GlobalVariablesExtractHelper.extractGlobalVariableErrors());
try{
//save document, and catch VE's as we want to do this silently
getDocumentService().saveDocument(maintenanceAccountDocument);
}catch(ValidationException ve){}
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_SUCCESS);
LOG.error( KcUtils.getErrorMessage(KcConstants.AccountCreationService.ERROR_KC_DOCUMENT_ACCOUNT_RULES_EXCEPTION, new String[]{maintenanceAccountDocument.getDocumentNumber()}));
}
}
else if (accountAutoCreateRouteValue.equalsIgnoreCase("submit")) {
//attempt to route if apply rules were successful and there are no errors
boolean rulesPassed = kualiRuleService.applyRules(new RouteDocumentEvent(maintenanceAccountDocument));
if( rulesPassed && GlobalVariables.getMessageMap().hasNoErrors()){
getDocumentService().routeDocument(maintenanceAccountDocument, "", null);
}else{
//get errors from apply rules invocation, also clears global variables
accountCreationStatus.setErrorMessages(GlobalVariablesExtractHelper.extractGlobalVariableErrors());
try{
//save document, and catch VE's as we want to do this silently
getDocumentService().saveDocument(maintenanceAccountDocument);
}catch(ValidationException ve){}
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_SUCCESS);
LOG.error( KcUtils.getErrorMessage(KcConstants.AccountCreationService.ERROR_KC_DOCUMENT_ACCOUNT_RULES_EXCEPTION, new String[]{maintenanceAccountDocument.getDocumentNumber()}));
}
}
// set the document number
accountCreationStatus.setDocumentNumber(maintenanceAccountDocument.getDocumentNumber());
}
catch (WorkflowException wfe) {
LOG.error( KcUtils.getErrorMessage(KcConstants.AccountCreationService.ERROR_KC_DOCUMENT_WORKFLOW_EXCEPTION_DOCUMENT_ACTIONS, null) + ": " + wfe.getMessage());
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_FAILURE);
accountCreationStatus.getErrorMessages().add( KcUtils.getErrorMessage(KcConstants.AccountCreationService.WARNING_KC_DOCUMENT_WORKFLOW_EXCEPTION_DOCUMENT_ACTIONS, null) + ": " + wfe.getMessage());
try {
// save it even though it fails to route or blanket approve the document
try{
getDocumentService().saveDocument(maintenanceAccountDocument);
}catch(ValidationException ve){
//ok to catch validation exceptions at this point
}
accountCreationStatus.setDocumentNumber(maintenanceAccountDocument.getDocumentNumber());
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_SUCCESS);
}
catch (WorkflowException e) {
LOG.error( KcUtils.getErrorMessage(KcConstants.AccountCreationService.WARNING_KC_DOCUMENT_WORKFLOW_EXCEPTION_DOCUMENT_ACTIONS, null) + ": " + e.getMessage());
accountCreationStatus.setErrorMessages(GlobalVariablesExtractHelper.extractGlobalVariableErrors());
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_FAILURE);
}
}
catch (Exception ex) {
LOG.error("Unknown exception occurred: " + ex.getMessage());
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_FAILURE);
accountCreationStatus.setErrorMessages(GlobalVariablesExtractHelper.extractGlobalVariableErrors());
accountCreationStatus.getErrorMessages().add(KcUtils.getErrorMessage(KcConstants.AccountCreationService.WARNING_KC_DOCUMENT_WORKFLOW_EXCEPTION_DOCUMENT_ACTIONS, null) + ": " + ex.getMessage());
try {
// save it even though it fails to route or blanket approve the document
try{
getDocumentService().saveDocument(maintenanceAccountDocument);
}catch(ValidationException ve){
//ok to catch validation exceptions at this point
}
accountCreationStatus.setDocumentNumber(maintenanceAccountDocument.getDocumentNumber());
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_SUCCESS);
}
catch (WorkflowException e) {
LOG.error( KcUtils.getErrorMessage(KcConstants.AccountCreationService.WARNING_KC_DOCUMENT_WORKFLOW_EXCEPTION_DOCUMENT_ACTIONS, null) + ": " + e.getMessage());
accountCreationStatus.setErrorMessages(GlobalVariablesExtractHelper.extractGlobalVariableErrors());
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_FAILURE);
}
}
}
/**
* This method will use the DocumentService to create a new document. The documentTypeName is gathered by using
* MaintenanceDocumentDictionaryService which uses Account class to get the document type name.
*
* @param AccountCreationStatusDTO
* @return document returns a new document for the account document type or null if there is an exception thrown.
*/
public Document createCGAccountMaintenanceDocument(AccountCreationStatusDTO accountCreationStatus) {
boolean internalUserSession = false;
try {
if (GlobalVariables.getUserSession() == null) {
internalUserSession = true;
GlobalVariables.setUserSession(new UserSession(KFSConstants.SYSTEM_USER));
GlobalVariables.clear();
}
Document document = getDocumentService().getNewDocument(maintenanceDocumentDictionaryService.getDocumentTypeName(Account.class));
return document;
}
catch (Exception e) {
accountCreationStatus.setErrorMessages(GlobalVariablesExtractHelper.extractGlobalVariableErrors());
accountCreationStatus.setStatus(KcConstants.KcWebService.STATUS_KC_FAILURE);
return null;
}
finally {
// if a user session was established for this call, clear it our
if (internalUserSession) {
GlobalVariables.clear();
GlobalVariables.setUserSession(null);
}
}
}
/**
* Check to see if the main link between KFS and KC is valid, namely the chart and account number.
* If these two values have some kind of error, then we don't want to generate an Account document
* and we'll want to return a failure to KC.
*
*
* @param account
* @param accountCreationStatus
* @return
*/
protected boolean isValidAccount(Account account, AccountCreationStatusDTO accountCreationStatus) {
boolean isValid = true;
String errorMessage = "";
String strSize = "";
if (account == null) {
//account was not created
setFailStatus(accountCreationStatus, KcConstants.AccountCreationService.ERROR_KC_DOCUMENT_ACCOUNT_GENERATION_PROBLEM);
return false;
}
if (StringUtils.isBlank(account.getChartOfAccountsCode()) || StringUtils.isBlank(account.getAccountNumber())){
//chart of accounts or account number blank
setFailStatus(accountCreationStatus, KcConstants.AccountCreationService.ERROR_KC_DOCUMENT_ACCOUNT_MISSING_CHART_OR_ACCT_NBR);
return false;
}
if (!isValidChartCode(account.getChartOfAccountsCode())) {
//the chart of accounts code is not valid
setFailStatus( accountCreationStatus, KcConstants.AccountCreationService.AUTOMATCICG_ACCOUNT_MAINTENANCE_CHART_NOT_DEFINED);
return false;
}
if (!isValidAccountNumberLength(account.getAccountNumber(), accountCreationStatus)){
//the account number is an inappropriate length
//error set in method
return false;
}
if (!checkUniqueAccountNumber(account.getAccountNumber())){
//account is not unique
setFailStatus( accountCreationStatus, KcUtils.getErrorMessage(KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ACCT_NMBR_NOT_UNIQUE, new String[]{account.getAccountNumber()}));
return false;
}
if (isValidChartAccount(account.getChartOfAccountsCode(), account.getAccountNumber())) {
//the chart and account already exist
setFailStatus( accountCreationStatus, KcConstants.AccountCreationService.AUTOMATCICG_ACCOUNT_MAINTENANCE_ACCT_ALREADY_DEFINED);
return false;
}
if (!checkAccountNumberPrefix(account.getAccountNumber(), accountCreationStatus)){
//account begins with invalid prefix
//error set in method
return false;
}
return isValid;
}
@Override
public boolean accountsCanCrossCharts() {
return accountService.accountsCanCrossCharts();
}
@Override
public boolean isValidAccount(String accountNumber) {
Collection<Account> accounts = accountService.getAccountsForAccountNumber(accountNumber);
return (accounts != null && !accounts.isEmpty());
}
@Override
public boolean isValidChartCode(String chartOfAccountsCode) {
Chart chart = chartService.getByPrimaryId(chartOfAccountsCode);
return (chart != null);
}
@Override
public boolean isValidChartAccount(String chartOfAccountsCode, String accountNumber) {
Account account = accountService.getByPrimaryId(chartOfAccountsCode, accountNumber);
return (account != null);
}
/**
* Checks an account numbers exact length
*
* @param accountNumber
* @param size to be returned
* @return
*/
protected boolean isValidAccountNumberLength(String accountNumber, AccountCreationStatusDTO accountCreationStatus){
boolean isValid = false;
int fieldSize = -1;
//grab account number length from DD and set size
final org.kuali.rice.krad.datadictionary.BusinessObjectEntry entry = dataDictionaryService.getDataDictionary().getBusinessObjectEntry(Account.class.getName());
AttributeDefinition attributeDefinition = entry.getAttributeDefinition(KFSPropertyConstants.ACCOUNT_NUMBER);
if(ObjectUtils.isNotNull(attributeDefinition)){
final ValidationPattern validationPattern = attributeDefinition.getValidationPattern();
if(ObjectUtils.isNotNull(validationPattern) && validationPattern instanceof AlphaNumericValidationPattern){
AlphaNumericValidationPattern alphaPattern = (AlphaNumericValidationPattern)validationPattern;
fieldSize = alphaPattern.getExactLength();
}
}
//skip if account number null
if(ObjectUtils.isNotNull(accountNumber)){
//data dictionary defined size must equal length of incoming value
if(fieldSize == accountNumber.length()){
isValid = true;
}
}
if(isValid == false){
setFailStatus( accountCreationStatus, KcUtils.getErrorMessage(KcConstants.AccountCreationService.ERROR_KR_ALPHANUMERIC_VALIDATION_EXACT_LENGTH, new String[]{"account number", String.valueOf(fieldSize)}));
}
return isValid;
}
/**
* This method tests whether the accountNumber passed in is prefixed with an allowed prefix, or an illegal one. The illegal
* prefixes are passed in as an array of strings.
*
* @param accountNumber - The Account Number to be tested.
* @return false if the accountNumber starts with any of the illegalPrefixes, true otherwise
*/
protected boolean checkAccountNumberPrefix(String accountNumber, AccountCreationStatusDTO accountCreationStatus){
boolean success = true;
// Enforce institutionally specified restrictions on account number prefixes
// (e.g. the account number cannot begin with a 3 or with 00.)
// Only bother trying if there is an account string to test
if (!StringUtils.isBlank(accountNumber)) {
List<String> illegalValues = new ArrayList<String>( getParameterService().getParameterValuesAsString(Account.class, ACCT_PREFIX_RESTRICTION) );
for (String illegalValue : illegalValues) {
if (accountNumber.startsWith(illegalValue)) {
success = false;
setFailStatus( accountCreationStatus, KcUtils.getErrorMessage(KFSKeyConstants.ERROR_DOCUMENT_ACCMAINT_ACCT_NMBR_NOT_ALLOWED, new String[] { accountNumber, illegalValue }));
}
}
}
return success;
}
/**
* If accounts can't cross charts, then we need to make sure the account number is unique.
*
* @param accountNumber
* @return
*/
protected boolean checkUniqueAccountNumber(String accountNumber) {
boolean success = true;
// while account is not allowed to cross chart
//and with an account number that already exists
if (!accountService.accountsCanCrossCharts() &&
!accountService.getAccountsForAccountNumber(accountNumber).isEmpty()) {
success = false;
}
return success;
}
/**
* This method check to see if the user can create the account maintenance document and set the user session
*
* @param String principalId
* @return boolean
*/
protected boolean isValidUser(String principalId) {
if (principalId == null) {
return false;
}
Person user = personService.getPerson(principalId);
if (user == null) {
return false;
}
DocumentAuthorizer documentAuthorizer = new MaintenanceDocumentAuthorizerBase();
if (documentAuthorizer.canInitiate(maintenanceDocumentDictionaryService.getDocumentTypeName(Account.class), user)) {
// set the user session so that the user name can be displayed in the saved document
GlobalVariables.setUserSession(new UserSession(user.getPrincipalName()));
return true;
}
LOG.error(KcUtils.getErrorMessage(KcConstants.AccountCreationService.ERROR_KC_DOCUMENT_INVALID_USER, new String[]{principalId}));
return false;
}
/**
* Gets the documentService attribute.
*
* @return Current value of documentService.
*/
protected DocumentService getDocumentService() {
return documentService;
}
/**
* Sets the documentService attribute value.
*
* @param documentService
*/
public void setDocumentService(DocumentService documentService) {
this.documentService = documentService;
}
/**
* Gets the parameterService attribute.
*
* @return Returns the parameterService.
*/
protected ParameterService getParameterService() {
return parameterService;
}
/**
* Sets the parameterService attribute value.
*
* @param parameterService The parameterService to set.
*/
public void setParameterService(ParameterService parameterService) {
this.parameterService = parameterService;
}
protected DataDictionaryService getDataDictionaryService() {
return dataDictionaryService;
}
public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
this.dataDictionaryService = dataDictionaryService;
}
/**
* Sets the businessObjectService attribute value.
*
* @param businessObjectService The businessObjectService to set.
*/
public void setBusinessObjectService(BusinessObjectService businessObjectService) {
this.businessObjectService = businessObjectService;
}
/**
* Gets the businessObjectService attribute.
*
* @return Returns the businessObjectService.
*/
protected BusinessObjectService getBusinessObjectService() {
return businessObjectService;
}
public AccountDefaultsService getAccountDefaultsService() {
return accountDefaultsService;
}
public void setAccountDefaultsService(AccountDefaultsService accountDefaultsService) {
this.accountDefaultsService = accountDefaultsService;
}
public KualiRuleService getKualiRuleService() {
return kualiRuleService;
}
public void setKualiRuleService(KualiRuleService kualiRuleService) {
this.kualiRuleService = kualiRuleService;
}
public MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
return maintenanceDocumentDictionaryService;
}
public void setMaintenanceDocumentDictionaryService(MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService) {
this.maintenanceDocumentDictionaryService = maintenanceDocumentDictionaryService;
}
public AccountService getAccountService() {
return accountService;
}
public void setAccountService(AccountService accountService) {
this.accountService = accountService;
}
public ChartService getChartService() {
return chartService;
}
public void setChartService(ChartService chartService) {
this.chartService = chartService;
}
public PersonService getPersonService() {
return personService;
}
public void setPersonService(PersonService personService) {
this.personService = personService;
}
}