001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.fp.document.validation.impl; 017 018 import java.util.List; 019 020 import org.apache.commons.lang.StringUtils; 021 import org.kuali.kfs.fp.document.DisbursementVoucherConstants; 022 import org.kuali.kfs.fp.document.DisbursementVoucherDocument; 023 import org.kuali.kfs.fp.document.service.DisbursementVoucherTaxService; 024 import org.kuali.kfs.sys.KFSKeyConstants; 025 import org.kuali.kfs.sys.KFSPropertyConstants; 026 import org.kuali.kfs.sys.businessobject.AccountingLine; 027 import org.kuali.kfs.sys.businessobject.SourceAccountingLine; 028 import org.kuali.kfs.sys.context.SpringContext; 029 import org.kuali.kfs.sys.document.AccountingDocument; 030 import org.kuali.kfs.sys.document.validation.GenericValidation; 031 import org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent; 032 import org.kuali.rice.kns.service.ParameterEvaluator; 033 import org.kuali.rice.kns.service.ParameterService; 034 import org.kuali.rice.kns.util.GlobalVariables; 035 import org.kuali.rice.kns.util.MessageMap; 036 import org.kuali.rice.kns.util.ObjectUtils; 037 038 public class DisbursementVoucherAccountingLineValidation extends GenericValidation { 039 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DisbursementVoucherAccountingLineValidation.class); 040 041 private ParameterService parameterService; 042 043 private AccountingDocument accountingDocumentForValidation; 044 private AccountingLine accountingLineForValidation; 045 046 protected static final String DV_PAYMENT_REASON_PROPERTY_PATH = KFSPropertyConstants.DV_PAYEE_DETAIL + "." + KFSPropertyConstants.DISB_VCHR_PAYMENT_REASON_CODE; 047 protected static final String DV_PAYEE_ID_NUMBER_PROPERTY_PATH = KFSPropertyConstants.DV_PAYEE_DETAIL + "." + KFSPropertyConstants.DISB_VCHR_PAYEE_ID_NUMBER; 048 049 /** 050 * @see org.kuali.kfs.sys.document.validation.Validation#validate(org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent) 051 */ 052 public boolean validate(AttributedDocumentEvent event) { 053 LOG.debug("validate start"); 054 055 boolean valid = true; 056 DisbursementVoucherDocument dvDocument = (DisbursementVoucherDocument) accountingDocumentForValidation; 057 MessageMap errors = GlobalVariables.getMessageMap(); 058 059 // don't validate generated tax lines 060 if (dvDocument.getDvNonResidentAlienTax() != null) { 061 String lineText = dvDocument.getDvNonResidentAlienTax().getFinancialDocumentAccountingLineText(); 062 List<Integer> taxLineNumbers = SpringContext.getBean(DisbursementVoucherTaxService.class).getNRATaxLineNumbers(lineText); 063 064 if (taxLineNumbers.contains(accountingLineForValidation.getSequenceNumber())) { 065 return true; 066 } 067 } 068 069 /* payment reason must be selected before an accounting line can be entered */ 070 if (StringUtils.isBlank(dvDocument.getDvPayeeDetail().getDisbVchrPaymentReasonCode())) { 071 if (!errors.containsMessageKey(KFSKeyConstants.ERROR_DV_ADD_LINE_MISSING_PAYMENT_REASON)) { 072 errors.putErrorWithoutFullErrorPath(KFSPropertyConstants.DOCUMENT + "." + DV_PAYMENT_REASON_PROPERTY_PATH, KFSKeyConstants.ERROR_DV_ADD_LINE_MISSING_PAYMENT_REASON); 073 } 074 valid = false; 075 } 076 077 /* 078 * payee must be selected before an accounting line can be entered NOTE: This should never be possible given the new flow 079 * that requires selection of the payee prior to DV creation, but I'm leaving the code in for validity sake. See KFSMI-714 080 * for details on new flow. 081 */ 082 if (StringUtils.isBlank(dvDocument.getDvPayeeDetail().getDisbVchrPayeeIdNumber())) { 083 if (!errors.containsMessageKey(KFSKeyConstants.ERROR_DV_ADD_LINE_MISSING_PAYEE)) { 084 errors.putErrorWithoutFullErrorPath(KFSPropertyConstants.DOCUMENT + "." + DV_PAYEE_ID_NUMBER_PROPERTY_PATH, KFSKeyConstants.ERROR_DV_ADD_LINE_MISSING_PAYEE); 085 } 086 valid = false; 087 } 088 089 if (valid) { 090 valid = valid & validateAccountNumber(accountingDocumentForValidation, accountingLineForValidation); 091 valid = valid & validateObjectCode(accountingDocumentForValidation, accountingLineForValidation); 092 } 093 094 return valid; 095 } 096 097 /** 098 * Checks object codes restrictions, including restrictions in parameters table. 099 * 100 * @param FinancialDocument submitted accounting document 101 * @param accountingLine accounting line in accounting document 102 * @return true if object code exists, is active, and object level and code exist for a provided payment reason 103 */ 104 public boolean validateObjectCode(AccountingDocument financialDocument, AccountingLine accountingLine) { 105 LOG.debug("beginning object code validation "); 106 107 DisbursementVoucherDocument dvDocument = (DisbursementVoucherDocument) financialDocument; 108 MessageMap errors = GlobalVariables.getMessageMap(); 109 110 boolean objectCodeAllowed = true; 111 112 // object code exist done in super, check we have a valid object 113 if (ObjectUtils.isNull(accountingLineForValidation.getAccount()) || ObjectUtils.isNull(accountingLine.getObjectCode())) { 114 return false; 115 } 116 117 // make sure object code is active 118 if (!accountingLine.getObjectCode().isFinancialObjectActiveCode()) { 119 errors.putError(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, KFSKeyConstants.ERROR_INACTIVE, "Object Code"); 120 objectCodeAllowed = false; 121 } 122 123 String documentPaymentReason = dvDocument.getDvPayeeDetail().getDisbVchrPaymentReasonCode(); 124 if (StringUtils.isBlank(documentPaymentReason)) { 125 return objectCodeAllowed; 126 } 127 128 // check object level is in permitted list for payment reason 129 objectCodeAllowed = objectCodeAllowed && parameterService.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); 130 131 // check object code is in permitted list for payment reason 132 objectCodeAllowed = objectCodeAllowed && parameterService.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); 133 134 objectCodeAllowed = objectCodeAllowed && parameterService.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); 135 136 return objectCodeAllowed; 137 } 138 139 /** 140 * Checks account number restrictions, including restrictions in parameters table. 141 * 142 * @param FinancialDocument submitted financial document 143 * @param accountingLine accounting line in submitted accounting document 144 * @return true if account exists, falls within global function code restrictions, and account's sub fund is in permitted list 145 * for payment reason 146 */ 147 public boolean validateAccountNumber(AccountingDocument financialDocument, AccountingLine accountingLine) { 148 LOG.debug("beginning account number validation "); 149 150 DisbursementVoucherDocument dvDocument = (DisbursementVoucherDocument) financialDocument; 151 MessageMap errors = GlobalVariables.getMessageMap(); 152 153 String errorKey = KFSPropertyConstants.ACCOUNT_NUMBER; 154 boolean accountNumberAllowed = true; 155 156 // account exist and object exist done in super, check we have a valid object 157 if (ObjectUtils.isNull(accountingLine.getAccount()) || ObjectUtils.isNull(accountingLine.getObjectCode())) { 158 return false; 159 } 160 161 // global function code restrictions 162 if (accountNumberAllowed) { 163 ParameterEvaluator evaluator = parameterService.getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.FUNCTION_CODE_GLOBAL_RESTRICTION_PARM_NM, accountingLine.getAccount().getFinancialHigherEdFunctionCd()); 164 // accountNumberAllowed is true now 165 accountNumberAllowed = evaluator.evaluateAndAddError(SourceAccountingLine.class, "account.financialHigherEdFunctionCd", KFSPropertyConstants.ACCOUNT_NUMBER); 166 } 167 168 String documentPaymentReason = dvDocument.getDvPayeeDetail().getDisbVchrPaymentReasonCode(); 169 if (StringUtils.isBlank(documentPaymentReason)) { 170 return accountNumberAllowed; 171 } 172 173 // check sub fund is in permitted list for payment reason 174 accountNumberAllowed = accountNumberAllowed && parameterService.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); 175 176 return accountNumberAllowed; 177 } 178 179 /** 180 * Sets the accountingDocumentForValidation attribute value. 181 * 182 * @param accountingDocumentForValidation The accountingDocumentForValidation to set. 183 */ 184 public void setAccountingDocumentForValidation(AccountingDocument accountingDocumentForValidation) { 185 this.accountingDocumentForValidation = accountingDocumentForValidation; 186 } 187 188 /** 189 * Sets the accountingLineForValidation attribute value. 190 * 191 * @param accountingLineForValidation The accountingLineForValidation to set. 192 */ 193 public void setAccountingLineForValidation(AccountingLine accountingLineForValidation) { 194 this.accountingLineForValidation = accountingLineForValidation; 195 } 196 197 /** 198 * Sets the parameterService attribute value. 199 * @param parameterService The parameterService to set. 200 */ 201 public void setParameterService(ParameterService parameterService) { 202 this.parameterService = parameterService; 203 } 204 205 /** 206 * Gets the accountingDocumentForValidation attribute. 207 * @return Returns the accountingDocumentForValidation. 208 */ 209 public AccountingDocument getAccountingDocumentForValidation() { 210 return accountingDocumentForValidation; 211 } 212 213 /** 214 * Gets the accountingLineForValidation attribute. 215 * @return Returns the accountingLineForValidation. 216 */ 217 public AccountingLine getAccountingLineForValidation() { 218 return accountingLineForValidation; 219 } 220 221 }