/* * 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.fp.document.validation.impl; import java.util.List; import org.apache.commons.lang.StringUtils; import org.kuali.kfs.fp.document.DisbursementVoucherConstants; import org.kuali.kfs.fp.document.DisbursementVoucherDocument; import org.kuali.kfs.fp.document.service.DisbursementVoucherTaxService; import org.kuali.kfs.sys.KFSKeyConstants; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.kfs.sys.businessobject.AccountingLine; import org.kuali.kfs.sys.businessobject.SourceAccountingLine; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.document.AccountingDocument; import org.kuali.kfs.sys.document.validation.GenericValidation; import org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent; import org.kuali.rice.core.api.parameter.ParameterEvaluator; import org.kuali.rice.core.api.parameter.ParameterEvaluatorService; import org.kuali.rice.coreservice.framework.parameter.ParameterService; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.MessageMap; import org.kuali.rice.krad.util.ObjectUtils; public class DisbursementVoucherAccountingLineValidation extends GenericValidation { private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DisbursementVoucherAccountingLineValidation.class); private ParameterService parameterService; private AccountingDocument accountingDocumentForValidation; private AccountingLine accountingLineForValidation; protected static final String DV_PAYMENT_REASON_PROPERTY_PATH = KFSPropertyConstants.DV_PAYEE_DETAIL + "." + KFSPropertyConstants.DISB_VCHR_PAYMENT_REASON_CODE; protected static final String DV_PAYEE_ID_NUMBER_PROPERTY_PATH = KFSPropertyConstants.DV_PAYEE_DETAIL + "." + KFSPropertyConstants.DISB_VCHR_PAYEE_ID_NUMBER; /** * @see org.kuali.kfs.sys.document.validation.Validation#validate(org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent) */ public boolean validate(AttributedDocumentEvent event) { LOG.debug("validate start"); boolean valid = true; DisbursementVoucherDocument dvDocument = (DisbursementVoucherDocument) accountingDocumentForValidation; MessageMap errors = GlobalVariables.getMessageMap(); // don't validate generated tax lines if (dvDocument.getDvNonResidentAlienTax() != null) { String lineText = dvDocument.getDvNonResidentAlienTax().getFinancialDocumentAccountingLineText(); List<Integer> taxLineNumbers = SpringContext.getBean(DisbursementVoucherTaxService.class).getNRATaxLineNumbers(lineText); if (taxLineNumbers.contains(accountingLineForValidation.getSequenceNumber())) { return true; } } /* payment reason must be selected before an accounting line can be entered */ if (StringUtils.isBlank(dvDocument.getDvPayeeDetail().getDisbVchrPaymentReasonCode())) { if (!errors.containsMessageKey(KFSKeyConstants.ERROR_DV_ADD_LINE_MISSING_PAYMENT_REASON)) { errors.putErrorWithoutFullErrorPath(KFSPropertyConstants.DOCUMENT + "." + DV_PAYMENT_REASON_PROPERTY_PATH, KFSKeyConstants.ERROR_DV_ADD_LINE_MISSING_PAYMENT_REASON); } valid = false; } /* * payee must be selected before an accounting line can be entered NOTE: This should never be possible given the new flow * that requires selection of the payee prior to DV creation, but I'm leaving the code in for validity sake. See KFSMI-714 * for details on new flow. */ if (StringUtils.isBlank(dvDocument.getDvPayeeDetail().getDisbVchrPayeeIdNumber())) { if (!errors.containsMessageKey(KFSKeyConstants.ERROR_DV_ADD_LINE_MISSING_PAYEE)) { errors.putErrorWithoutFullErrorPath(KFSPropertyConstants.DOCUMENT + "." + DV_PAYEE_ID_NUMBER_PROPERTY_PATH, KFSKeyConstants.ERROR_DV_ADD_LINE_MISSING_PAYEE); } valid = false; } if (valid) { valid = valid & validateAccountNumber(accountingDocumentForValidation, accountingLineForValidation); valid = valid & validateObjectCode(accountingDocumentForValidation, accountingLineForValidation); } return valid; } /** * Checks object codes restrictions, including restrictions in parameters table. * * @param FinancialDocument submitted accounting document * @param accountingLine accounting line in accounting document * @return true if object code exists, is active, and object level and code exist for a provided payment reason */ public boolean validateObjectCode(AccountingDocument financialDocument, AccountingLine accountingLine) { LOG.debug("beginning object code validation "); DisbursementVoucherDocument dvDocument = (DisbursementVoucherDocument) financialDocument; MessageMap errors = GlobalVariables.getMessageMap(); boolean objectCodeAllowed = true; // object code exist done in super, check we have a valid object if (ObjectUtils.isNull(accountingLineForValidation.getAccount()) || ObjectUtils.isNull(accountingLine.getObjectCode())) { return false; } // make sure object code is active if (!accountingLine.getObjectCode().isFinancialObjectActiveCode()) { errors.putError(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, KFSKeyConstants.ERROR_INACTIVE, "Object Code"); objectCodeAllowed = false; } String documentPaymentReason = dvDocument.getDvPayeeDetail().getDisbVchrPaymentReasonCode(); if (StringUtils.isBlank(documentPaymentReason)) { return objectCodeAllowed; } // check object level is in permitted list for payment reason objectCodeAllowed = objectCodeAllowed && /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.VALID_OBJ_LEVEL_BY_PAYMENT_REASON_PARM, DisbursementVoucherConstants.INVALID_OBJ_LEVEL_BY_PAYMENT_REASON_PARM, documentPaymentReason, accountingLine.getObjectCode().getFinancialObjectLevelCode()).evaluateAndAddError(SourceAccountingLine.class, "objectCode.financialObjectLevelCode", KFSPropertyConstants.FINANCIAL_OBJECT_CODE); // check object code is in permitted list for payment reason objectCodeAllowed = objectCodeAllowed && /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.VALID_OBJ_CODE_BY_PAYMENT_REASON_PARM, DisbursementVoucherConstants.INVALID_OBJ_CODE_BY_PAYMENT_REASON_PARM, documentPaymentReason, accountingLine.getFinancialObjectCode()).evaluateAndAddError(SourceAccountingLine.class, KFSPropertyConstants.FINANCIAL_OBJECT_CODE); objectCodeAllowed = objectCodeAllowed && /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.VALID_OBJECT_SUB_TYPES_BY_SUB_FUND_GROUP_PARM, DisbursementVoucherConstants.INVALID_OBJECT_SUB_TYPES_BY_SUB_FUND_GROUP_PARM, accountingLine.getAccount().getSubFundGroupCode(), accountingLine.getObjectCode().getFinancialObjectSubTypeCode()).evaluateAndAddError(SourceAccountingLine.class, "objectCode.financialObjectSubTypeCode", KFSPropertyConstants.FINANCIAL_OBJECT_CODE); return objectCodeAllowed; } /** * Checks account number restrictions, including restrictions in parameters table. * * @param FinancialDocument submitted financial document * @param accountingLine accounting line in submitted accounting document * @return true if account exists, falls within global function code restrictions, and account's sub fund is in permitted list * for payment reason */ public boolean validateAccountNumber(AccountingDocument financialDocument, AccountingLine accountingLine) { LOG.debug("beginning account number validation "); DisbursementVoucherDocument dvDocument = (DisbursementVoucherDocument) financialDocument; MessageMap errors = GlobalVariables.getMessageMap(); String errorKey = KFSPropertyConstants.ACCOUNT_NUMBER; boolean accountNumberAllowed = true; // account exist and object exist done in super, check we have a valid object if (ObjectUtils.isNull(accountingLine.getAccount()) || ObjectUtils.isNull(accountingLine.getObjectCode())) { return false; } // global function code restrictions if (accountNumberAllowed) { ParameterEvaluator evaluator = /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.FUNCTION_CODE_GLOBAL_RESTRICTION_PARM_NM, accountingLine.getAccount().getFinancialHigherEdFunctionCd()); // accountNumberAllowed is true now accountNumberAllowed = evaluator.evaluateAndAddError(SourceAccountingLine.class, "account.financialHigherEdFunctionCd", KFSPropertyConstants.ACCOUNT_NUMBER); } String documentPaymentReason = dvDocument.getDvPayeeDetail().getDisbVchrPaymentReasonCode(); if (StringUtils.isBlank(documentPaymentReason)) { return accountNumberAllowed; } // check sub fund is in permitted list for payment reason accountNumberAllowed = accountNumberAllowed && /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.VALID_SUB_FUND_GROUPS_BY_PAYMENT_REASON_PARM, DisbursementVoucherConstants.INVALID_SUB_FUND_GROUPS_BY_PAYMENT_REASON_PARM, documentPaymentReason, accountingLine.getAccount().getSubFundGroupCode()).evaluateAndAddError(SourceAccountingLine.class, "account.subFundGroupCode", KFSPropertyConstants.ACCOUNT_NUMBER); return accountNumberAllowed; } /** * Sets the accountingDocumentForValidation attribute value. * * @param accountingDocumentForValidation The accountingDocumentForValidation to set. */ public void setAccountingDocumentForValidation(AccountingDocument accountingDocumentForValidation) { this.accountingDocumentForValidation = accountingDocumentForValidation; } /** * Sets the accountingLineForValidation attribute value. * * @param accountingLineForValidation The accountingLineForValidation to set. */ public void setAccountingLineForValidation(AccountingLine accountingLineForValidation) { this.accountingLineForValidation = accountingLineForValidation; } /** * Sets the parameterService attribute value. * @param parameterService The parameterService to set. */ public void setParameterService(ParameterService parameterService) { this.parameterService = parameterService; } /** * Gets the accountingDocumentForValidation attribute. * @return Returns the accountingDocumentForValidation. */ public AccountingDocument getAccountingDocumentForValidation() { return accountingDocumentForValidation; } /** * Gets the accountingLineForValidation attribute. * @return Returns the accountingLineForValidation. */ public AccountingLine getAccountingLineForValidation() { return accountingLineForValidation; } }