/* * 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.vnd.document.validation.impl; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.kuali.kfs.coa.businessobject.Chart; import org.kuali.kfs.coa.businessobject.Organization; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.KFSKeyConstants; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.service.PostalCodeValidationService; import org.kuali.kfs.vnd.VendorConstants; import org.kuali.kfs.vnd.VendorKeyConstants; import org.kuali.kfs.vnd.VendorParameterConstants; import org.kuali.kfs.vnd.VendorPropertyConstants; import org.kuali.kfs.vnd.businessobject.AddressType; import org.kuali.kfs.vnd.businessobject.OwnershipType; import org.kuali.kfs.vnd.businessobject.VendorAddress; import org.kuali.kfs.vnd.businessobject.VendorAlias; import org.kuali.kfs.vnd.businessobject.VendorCommodityCode; import org.kuali.kfs.vnd.businessobject.VendorContact; import org.kuali.kfs.vnd.businessobject.VendorContract; import org.kuali.kfs.vnd.businessobject.VendorContractOrganization; import org.kuali.kfs.vnd.businessobject.VendorCustomerNumber; import org.kuali.kfs.vnd.businessobject.VendorDefaultAddress; import org.kuali.kfs.vnd.businessobject.VendorDetail; import org.kuali.kfs.vnd.businessobject.VendorHeader; import org.kuali.kfs.vnd.businessobject.VendorType; import org.kuali.kfs.vnd.businessobject.W8TypeOwnershipType; import org.kuali.kfs.vnd.document.service.VendorService; import org.kuali.kfs.vnd.service.CommodityCodeService; import org.kuali.kfs.vnd.service.TaxNumberService; import org.kuali.rice.core.api.datetime.DateTimeService; import org.kuali.rice.core.api.parameter.ParameterEvaluatorService; import org.kuali.rice.core.api.util.type.KualiDecimal; import org.kuali.rice.coreservice.framework.parameter.ParameterService; import org.kuali.rice.kns.datadictionary.validation.fieldlevel.FixedPointValidationPattern; import org.kuali.rice.kns.document.MaintenanceDocument; import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; import org.kuali.rice.kns.service.DataDictionaryService; import org.kuali.rice.krad.bo.PersistableBusinessObject; import org.kuali.rice.krad.datadictionary.AttributeDefinition; import org.kuali.rice.krad.datadictionary.validation.ValidationPattern; import org.kuali.rice.krad.service.BusinessObjectService; import org.kuali.rice.krad.service.PersistenceService; import org.kuali.rice.krad.util.ErrorMessage; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.KRADConstants; import org.kuali.rice.krad.util.ObjectUtils; import org.springframework.util.AutoPopulatingList; /** * Business rules applicable to VendorDetail document. */ public class VendorRule extends MaintenanceDocumentRuleBase { private VendorDetail oldVendor; private VendorDetail newVendor; /** * Overrides the setupBaseConvenienceObjects from the superclass because we cannot use the setupBaseConvenienceObjects from the * superclass. The reason we cannot use the superclass method is because it calls the updateNonUpdateableReferences for * everything and we cannot do that for parent vendors, because we want to update vendor header information only on parent * vendors, so the saving of the vendor header is done manually. If we call the updateNonUpdateableReferences, it is going to * overwrite any changes that the user might have done in the vendor header with the existing values in the database. * * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#setupBaseConvenienceObjects(org.kuali.rice.kns.document.MaintenanceDocument) */ @Override public void setupBaseConvenienceObjects(MaintenanceDocument document) { oldVendor = (VendorDetail) document.getOldMaintainableObject().getBusinessObject(); newVendor = (VendorDetail) document.getNewMaintainableObject().getBusinessObject(); super.setNewBo(newVendor); setupConvenienceObjects(); } /** * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#setupConvenienceObjects() */ @Override public void setupConvenienceObjects() { // setup oldVendor convenience objects, make sure all possible sub-objects are populated refreshSubObjects(oldVendor); // setup newVendor convenience objects, make sure all possible sub-objects are populated refreshSubObjects(newVendor); } /** * Refreshes the references of vendor detail and its sub objects * * @param vendor VendorDetail document */ void refreshSubObjects(VendorDetail vendor) { if (vendor == null) { return; } // If this is a division vendor, we need to do a refreshNonUpdateableReferences // and also refreshes the vendor header, since the user aren't supposed to // make any updates of vendor header's attributes while editing a division vendor if (!vendor.isVendorParentIndicator()) { vendor.refreshNonUpdateableReferences(); vendor.getVendorHeader().refreshNonUpdateableReferences(); } else { // Retrieve the references objects of the vendor header of this vendor. List<String> headerFieldNames = getObjectReferencesListFromBOClass(VendorHeader.class); vendor.getVendorHeader().refreshNonUpdateableReferences(); SpringContext.getBean(PersistenceService.class).retrieveReferenceObjects(vendor.getVendorHeader(), headerFieldNames); // We still need to retrieve all the other references of this vendor in addition to // vendor header. Since this is a parent vendor, whose vendor header saving is handled manually, // we have already retrieved references for vendor header's attributes above, so we should // exclude retrieving reference objects of vendor header. List<String> detailFieldNames = getObjectReferencesListFromBOClass(vendor.getClass()); detailFieldNames.remove(VendorConstants.VENDOR_HEADER_ATTR); SpringContext.getBean(PersistenceService.class).retrieveReferenceObjects(vendor, detailFieldNames); } // refresh addresses if (vendor.getVendorAddresses() != null) { for (VendorAddress address : vendor.getVendorAddresses()) { address.refreshNonUpdateableReferences(); if (address.getVendorDefaultAddresses() != null) { for (VendorDefaultAddress defaultAddress : address.getVendorDefaultAddresses()) { defaultAddress.refreshNonUpdateableReferences(); } } } } // refresh contacts if (vendor.getVendorContacts() != null) { for (VendorContact contact : vendor.getVendorContacts()) { contact.refreshNonUpdateableReferences(); } } // refresh contracts if (vendor.getVendorContracts() != null) { for (VendorContract contract : vendor.getVendorContracts()) { contract.refreshNonUpdateableReferences(); } } } /** * This is currently used as a helper to get a list of object references (e.g. vendorType, vendorOwnershipType, etc) from a * BusinessObject (e.g. VendorHeader, VendorDetail, etc) class dynamically. Feel free to enhance it, refactor it or move it to a * superclass or elsewhere as you see appropriate. * * @param theClass The Class name of the object whose objects references list are extracted * @return List a List of attributes of the class */ private List getObjectReferencesListFromBOClass(Class theClass) { List<String> results = new ArrayList(); for (Field theField : theClass.getDeclaredFields()) { // only get persistable business object references if ( PersistableBusinessObject.class.isAssignableFrom( theField.getType() ) ) { results.add(theField.getName()); } } return results; } /** * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomApproveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) */ @Override protected boolean processCustomApproveDocumentBusinessRules(MaintenanceDocument document) { boolean valid = processValidation(document); return valid & super.processCustomApproveDocumentBusinessRules(document); } /** * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) */ @Override protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) { boolean valid = processValidation(document); return valid & super.processCustomRouteDocumentBusinessRules(document); } /** * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) */ @Override protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) { boolean valid = true; return valid & super.processCustomSaveDocumentBusinessRules(document); } /** * Validates VendorDetail and its VendorContracts. * * @param document MaintenanceDocument instance * @return boolean false or true */ private boolean processValidation(MaintenanceDocument document) { boolean valid = true; valid &= processVendorValidation(document); valid &= processContactValidation(document); if (ObjectUtils.isNotNull(newVendor.getVendorHeader().getVendorType())) { valid &= processAddressValidation(document); valid &= processContractValidation(document); valid &= processCommodityCodeValidation(document); } return valid; } /** * Validates VendorDetail document. * * @param document MaintenanceDocument instance * @return boolean false or true */ boolean processVendorValidation(MaintenanceDocument document) { boolean valid = true; VendorDetail vendorDetail = (VendorDetail) document.getNewMaintainableObject().getBusinessObject(); valid &= validateTaxTypeAndTaxNumberBlankness(vendorDetail); valid &= validateParentVendorTaxNumber(vendorDetail); valid &= validateOwnershipTypeAllowed(vendorDetail); valid &= validateTaxNumberFromTaxNumberService(vendorDetail); valid &= validateRestrictedReasonRequiredness(vendorDetail); valid &= validateInactiveReasonRequiredness(vendorDetail); if (ObjectUtils.isNotNull(vendorDetail.getVendorHeader().getVendorType())) { valid &= validateTaxNumberRequiredness(vendorDetail); } valid &= validateVendorNames(vendorDetail); valid &= validateVendorSoldToNumber(vendorDetail); valid &= validateMinimumOrderAmount(vendorDetail); valid &= validateOwnershipCategory(vendorDetail); valid &= validateVendorWithholdingTaxDates(vendorDetail); valid &= validateVendorW8BenOrW9ReceivedIndicator(vendorDetail); valid &= validateW9Received(vendorDetail); valid &= validateW9SignedDate(vendorDetail); valid &= validateW8SignedDate(vendorDetail); valid &= validateW8Received(vendorDetail); valid &= validateW8Type(vendorDetail); valid &= validateCorpCitizen(vendorDetail); valid &= validateGIINCode(vendorDetail); valid &= validateDOBDate(vendorDetail); valid &= validateSearchAliases(vendorDetail); valid &= validateContracts(vendorDetail); return valid; } private boolean validateContracts(VendorDetail vendorDetail) { boolean success = true; int vendorPos = 0; List<VendorContract> vendorContracts = vendorDetail.getVendorContracts(); for (VendorContract vendorContract : vendorContracts) { List<VendorContractOrganization> organizations = vendorContract.getVendorContractOrganizations(); List<VendorContractOrganization> organizationCopy = new ArrayList<VendorContractOrganization>(organizations); for (VendorContractOrganization organization :organizations ) { String chartCode = organization.getChartOfAccountsCode(); String organizationCode = organization.getOrganizationCode(); if (StringUtils.isNotEmpty(chartCode) && StringUtils.isNotEmpty(organizationCode)) { int counter = 0; int organizationPos = 0; for (VendorContractOrganization org : organizationCopy) { if (chartCode.equalsIgnoreCase(org.getChartOfAccountsCode()) && organizationCode.equalsIgnoreCase(org.getOrganizationCode())) { if (counter++ != 0) { organizationCopy.remove(organization); putFieldError(VendorPropertyConstants.VENDOR_CONTRACT + "[" + vendorPos + "]." + VendorPropertyConstants.VENDOR_CONTRACT_ORGANIZATION + "[" + organizationPos + "]." + VendorPropertyConstants.VENDOR_CUSTOMER_NUMBER_CHART_OF_ACCOUNTS_CODE, VendorKeyConstants.ERROR_DUPLICATE_ENTRY_NOT_ALLOWED,chartCode + " " + organizationCode ); success = false; break; } } } organizationPos++; } vendorPos++; } } return success; } private boolean validateSearchAliases(VendorDetail vendorDetail) { boolean success = true; List<VendorAlias> searchAliases = vendorDetail.getVendorAliases(); List<VendorAlias> aliasList = new ArrayList<VendorAlias>(searchAliases); int pos = 0; for (VendorAlias searchAlias : searchAliases) { String aliasName = searchAlias.getVendorAliasName(); if (aliasName != null) { int counter = 0; for (VendorAlias alias : aliasList) { if (aliasName.equals(alias.getVendorAliasName())) { if (counter++ != 0) { putFieldError(VendorPropertyConstants.VENDOR_SEARCH_ALIASES + "[" + pos + "]." + VendorPropertyConstants.VENDOR_ALIAS_NAME, VendorKeyConstants.ERROR_DUPLICATE_ENTRY_NOT_ALLOWED,aliasName); aliasList.remove(searchAlias); success = false; break; } } } } pos++; } return success; } /** * Validates that if the vendor is set to be inactive, the inactive reason is required. * * @param vendorDetail the VendorDetail object to be validated * @return boolean false if the vendor is inactive and the inactive reason is empty or if the vendor is active and the inactive reason is not empty */ boolean validateInactiveReasonRequiredness(VendorDetail vendorDetail) { boolean activeIndicator = vendorDetail.isActiveIndicator(); boolean emptyInactiveReason = StringUtils.isEmpty(vendorDetail.getVendorInactiveReasonCode()); // return false if the vendor is inactive and the inactive reason is empty if (!activeIndicator && emptyInactiveReason) { putFieldError(VendorPropertyConstants.VENDOR_INACTIVE_REASON, VendorKeyConstants.ERROR_INACTIVE_REASON_REQUIRED); return false; } // return false if the vendor is active and the inactive reason is not empty if (activeIndicator && !emptyInactiveReason) { putFieldError(VendorPropertyConstants.VENDOR_INACTIVE_REASON, VendorKeyConstants.ERROR_INACTIVE_REASON_NOT_ALLOWED); return false; } return true; } /** * Validates that if the vendor is not foreign and if the vendor type's tax number required indicator is true, then the tax * number is required. If the vendor foreign indicator is true, then the tax number is not required regardless of its vendor * type. * * @param vendorDetail the VendorDetail object to be validated * @return boolean false if there is no tax number and the indicator is true. */ boolean validateTaxNumberRequiredness(VendorDetail vendorDetail) { if (!vendorDetail.getVendorHeader().getVendorForeignIndicator() && vendorDetail.getVendorHeader().getVendorType().isVendorTaxNumberRequiredIndicator() && StringUtils.isBlank(vendorDetail.getVendorHeader().getVendorTaxNumber())) { if (vendorDetail.isVendorParentIndicator()) { putFieldError(VendorPropertyConstants.VENDOR_TAX_NUMBER, VendorKeyConstants.ERROR_VENDOR_TYPE_REQUIRES_TAX_NUMBER, vendorDetail.getVendorHeader().getVendorType().getVendorTypeDescription()); } else { putFieldError(VendorPropertyConstants.VENDOR_TAX_NUMBER, VendorKeyConstants.ERROR_VENDOR_PARENT_NEEDS_CHANGED); } return false; } return true; } /** * Validates that, if the vendor is set to be restricted, the restricted reason is required. * * @param vendorDetail The VendorDetail object to be validated * @return boolean false if the vendor is restricted and the restricted reason is empty */ boolean validateRestrictedReasonRequiredness(VendorDetail vendorDetail) { if (ObjectUtils.isNotNull(vendorDetail.getVendorRestrictedIndicator()) && vendorDetail.getVendorRestrictedIndicator() && StringUtils.isEmpty(vendorDetail.getVendorRestrictedReasonText())) { putFieldError(VendorPropertyConstants.VENDOR_RESTRICTED_REASON_TEXT, VendorKeyConstants.ERROR_RESTRICTED_REASON_REQUIRED); return false; } return true; } /** * Validates that if vendor is parent, then tax # and tax type combo should be unique by checking for the existence of vendor(s) * with the same tax # and tax type in the existing vendor header table. Ideally we're also supposed to check for pending * vendors, but at the moment, the pending vendors are under research investigation, so we're only checking the existing vendors * for now. If the vendor is a parent and the validation fails, display the actual error message. If the vendor is not a parent * and the validation fails, display the error message that the parent of this vendor needs to be changed, please contact * Purchasing Dept. * Note: We will require uniqueness on Tax ID + ID type across all active and inactive vendors. * If an inactive vendor exists with the same Tax ID and Tax ID Type, either the existing vendor record * should be reactivated (or the incorrect tax id corrected). * * @param vendorDetail the VendorDetail object to be validated * @return boolean true if the vendorDetail passes the unique tax # and tax type validation. */ boolean validateParentVendorTaxNumber(VendorDetail vendorDetail) { boolean valid = true; boolean isParent = vendorDetail.isVendorParentIndicator(); Map criteria = new HashMap(); criteria.put(VendorPropertyConstants.VENDOR_TAX_TYPE_CODE, vendorDetail.getVendorHeader().getVendorTaxTypeCode()); criteria.put(VendorPropertyConstants.VENDOR_TAX_NUMBER, vendorDetail.getVendorHeader().getVendorTaxNumber()); Map negativeCriteria = new HashMap(); int existingVendor = 0; // If this is editing an existing vendor, we have to include the current vendor's // header generated id in the negative criteria so that the current vendor is // excluded from the search if (ObjectUtils.isNotNull(vendorDetail.getVendorHeaderGeneratedIdentifier())) { negativeCriteria.put(VendorPropertyConstants.VENDOR_HEADER_GENERATED_ID, vendorDetail.getVendorHeaderGeneratedIdentifier()); existingVendor = getBoService().countMatching(VendorDetail.class, criteria, negativeCriteria); } else { // If this is creating a new vendor, we can't include the header generated id // in the negative criteria because it's null, so we'll only look for existing // vendors with the same tax # and tax type regardless of the vendor header generated id. existingVendor = getBoService().countMatching(VendorDetail.class, criteria); } if (existingVendor > 0) { if (isParent) { putFieldError(VendorPropertyConstants.VENDOR_TAX_NUMBER, VendorKeyConstants.ERROR_VENDOR_TAX_TYPE_AND_NUMBER_COMBO_EXISTS); } else { putFieldError(VendorPropertyConstants.VENDOR_TAX_NUMBER, VendorKeyConstants.ERROR_VENDOR_PARENT_NEEDS_CHANGED); } valid &= false; } return valid; } /** * Validates that the following business rules are satisfied: 1. Tax type cannot be blank if the tax # is not blank. 2. Tax type * cannot be set if the tax # is blank. If the vendor is a parent and the validation fails, we'll display an error message * indicating that the tax type cannot be blank if the tax # is not blank or that the tax type cannot be set if the tax # is * blank. If the vendor is not a parent and the validation fails, we'll display an error message indicating that the parent of * this vendor needs to be changed, please contact Purchasing Dept. * * @param vendorDetail the VendorDetail object to be validated * @return boolean true if the vendor Detail passes the validation and false otherwise. */ boolean validateTaxTypeAndTaxNumberBlankness(VendorDetail vendorDetail) { boolean valid = true; boolean isParent = vendorDetail.isVendorParentIndicator(); if (!StringUtils.isBlank(vendorDetail.getVendorHeader().getVendorTaxNumber()) && (StringUtils.isBlank(vendorDetail.getVendorHeader().getVendorTaxTypeCode()))) { if (isParent) { putFieldError(VendorPropertyConstants.VENDOR_TAX_TYPE_CODE, VendorKeyConstants.ERROR_VENDOR_TAX_TYPE_CANNOT_BE_BLANK); } valid &= false; } else if (StringUtils.isBlank(vendorDetail.getVendorHeader().getVendorTaxNumber()) && !StringUtils.isBlank(vendorDetail.getVendorHeader().getVendorTaxTypeCode())) { if (isParent) { putFieldError(VendorPropertyConstants.VENDOR_TAX_TYPE_CODE, VendorKeyConstants.ERROR_VENDOR_TAX_TYPE_CANNOT_BE_SET); } valid &= false; } if (!valid && !isParent) { putFieldError(VendorPropertyConstants.VENDOR_TAX_TYPE_CODE, VendorKeyConstants.ERROR_VENDOR_PARENT_NEEDS_CHANGED); } return valid; } /** * Validates the vendorName, vendorFirstName and vendorLastName fields according to these business rules: 1. At least one of the * three vendor name fields must be filled in. 2. Both of the two ways of entering vendor name (One vendor name field vs * VendorFirstName/VendorLastName) cannot be used 3. If either the vendor first name or the vendor last name have been entered, * the other must be entered. * * @param vendorDetail The VendorDetail object to be validated * @return boolean true if the vendorDetail passes this validation and false otherwise. */ protected boolean validateVendorNames(VendorDetail vendorDetail) { boolean valid = true; if (StringUtils.isBlank(vendorDetail.getVendorName())) { // At least one of the three vendor name fields must be filled in. if (StringUtils.isBlank(vendorDetail.getVendorFirstName()) && StringUtils.isBlank(vendorDetail.getVendorLastName())) { putFieldError(VendorPropertyConstants.VENDOR_NAME, VendorKeyConstants.ERROR_VENDOR_NAME_REQUIRED); valid &= false; } // If either the vendor first name or the vendor last name have been entered, the other must be entered. else if (StringUtils.isBlank(vendorDetail.getVendorFirstName()) || StringUtils.isBlank(vendorDetail.getVendorLastName())) { putFieldError(VendorPropertyConstants.VENDOR_NAME, VendorKeyConstants.ERROR_VENDOR_BOTH_NAME_REQUIRED); valid &= false; } else { String vendorName = vendorDetail.getVendorLastName() + VendorConstants.NAME_DELIM + vendorDetail.getVendorFirstName(); if (vendorName.length() > VendorConstants.MAX_VENDOR_NAME_LENGTH) { putFieldError(VendorPropertyConstants.VENDOR_LAST_NAME, VendorKeyConstants.ERROR_VENDOR_NAME_TOO_LONG); valid &= false; } } } else { // Both of the two ways of entering vendor name (One vendor name field vs VendorFirstName/VendorLastName) cannot be used if (!StringUtils.isBlank(vendorDetail.getVendorFirstName()) || !StringUtils.isBlank(vendorDetail.getVendorLastName())) { putFieldError(VendorPropertyConstants.VENDOR_NAME, VendorKeyConstants.ERROR_VENDOR_NAME_INVALID); valid &= false; } } return valid; } /** * Validates the vendorSoldToNumber field to ensure that it's a valid existing vendor number; * and if so set vendorSoldToName accordingly. * * @param document - the maintenanceDocument being evaluated * @return boolean true if the vendorDetail in the document contains valid vendorSoldToNumber. */ protected boolean validateVendorSoldToNumber(VendorDetail vendorDetail) { boolean valid = true; String vendorSoldToNumber = vendorDetail.getVendorSoldToNumber(); // if vendor number is empty, clear all vendorSoldTo fields if (StringUtils.isEmpty(vendorSoldToNumber)) { vendorDetail.setSoldToVendorDetail(null); vendorDetail.setVendorSoldToGeneratedIdentifier(null); vendorDetail.setVendorSoldToAssignedIdentifier(null); vendorDetail.setVendorSoldToNumber(null); vendorDetail.setVendorSoldToName(null); return valid; } VendorDetail vendorSoldTo = SpringContext.getBean(VendorService.class).getVendorDetail(vendorSoldToNumber); if (vendorSoldTo != null) { // if vendor number is valid, set all vendorSoldTo fields vendorDetail.setSoldToVendorDetail(vendorSoldTo); vendorDetail.setVendorSoldToGeneratedIdentifier(vendorSoldTo.getVendorHeaderGeneratedIdentifier()); vendorDetail.setVendorSoldToAssignedIdentifier(vendorSoldTo.getVendorDetailAssignedIdentifier()); vendorDetail.setVendorSoldToName(vendorSoldTo.getVendorName()); } else { // otherwise clear vendorSoldToName vendorDetail.setSoldToVendorDetail(null); vendorDetail.setVendorSoldToName(null); valid = false; putFieldError(VendorPropertyConstants.VENDOR_SOLD_TO_NUMBER, VendorKeyConstants.VENDOR_SOLD_TO_NUMBER_INVALID); } return valid; } /** * Validates the ownership type codes that aren't allowed for the tax type of the vendor. The rules are : 1. If tax type is * "SSN", then check the ownership type against the allowed types for "SSN" in the Rules table. 2. If tax type is "FEIN", then * check the ownership type against the allowed types for "FEIN" in the Rules table. If the vendor is a parent and the * validation fails, display the actual error message. If the vendor is not a parent and the validation fails, display the error * message that the parent of this vendor needs to be changed, please contact Purchasing Dept. * * @param vendorDetail The VendorDetail object to be validated * @return boolean true if the ownership type is allowed and FALSE otherwise. */ private boolean validateOwnershipTypeAllowed(VendorDetail vendorDetail) { boolean valid = true; boolean isParent = vendorDetail.isVendorParentIndicator(); String ownershipTypeCode = vendorDetail.getVendorHeader().getVendorOwnershipCode(); String taxTypeCode = vendorDetail.getVendorHeader().getVendorTaxTypeCode(); if (StringUtils.isNotEmpty(ownershipTypeCode) && StringUtils.isNotEmpty(taxTypeCode)) { if (VendorConstants.TAX_TYPE_FEIN.equals(taxTypeCode)) { if (!/*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(VendorDetail.class, VendorParameterConstants.FEIN_ALLOWED_OWNERSHIP_TYPES, ownershipTypeCode).evaluationSucceeds()) { valid &= false; } } else if (VendorConstants.TAX_TYPE_SSN.equals(taxTypeCode)) { if (!/*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(VendorDetail.class, VendorParameterConstants.SSN_ALLOWED_OWNERSHIP_TYPES, ownershipTypeCode).evaluationSucceeds()) { valid &= false; } } } if (!valid && isParent) { putFieldError(VendorPropertyConstants.VENDOR_OWNERSHIP_CODE, VendorKeyConstants.ERROR_OWNERSHIP_TYPE_CODE_NOT_ALLOWED, new String[] { vendorDetail.getVendorHeader().getVendorOwnership().getVendorOwnershipDescription(), taxTypeCode }); } else if (!valid && !isParent) { putFieldError(VendorPropertyConstants.VENDOR_OWNERSHIP_CODE, VendorKeyConstants.ERROR_VENDOR_PARENT_NEEDS_CHANGED); } return valid; } /** * Validates that the minimum order amount is less than the maximum allowed amount. * * @param vendorDetail The VendorDetail object to be validated * @return booelan true if the vendorMinimumOrderAmount is less than the maximum allowed amount. */ private boolean validateMinimumOrderAmount(VendorDetail vendorDetail) { boolean valid = true; KualiDecimal minimumOrderAmount = vendorDetail.getVendorMinimumOrderAmount(); if (ObjectUtils.isNotNull(minimumOrderAmount)) { KualiDecimal VENDOR_MIN_ORDER_AMOUNT = new KualiDecimal(SpringContext.getBean(ParameterService.class).getParameterValueAsString(VendorDetail.class, VendorParameterConstants.VENDOR_MIN_ORDER_AMOUNT)); if (ObjectUtils.isNotNull(VENDOR_MIN_ORDER_AMOUNT) && (VENDOR_MIN_ORDER_AMOUNT.compareTo(minimumOrderAmount) < 1) || (minimumOrderAmount.isNegative())) { putFieldError(VendorPropertyConstants.VENDOR_MIN_ORDER_AMOUNT, VendorKeyConstants.ERROR_VENDOR_MAX_MIN_ORDER_AMOUNT, VENDOR_MIN_ORDER_AMOUNT.toString()); valid &= false; } } return valid; } /** * Validates that if the ownership category allowed indicator is false, the vendor does not have ownership category. It will * return false if the vendor contains ownership category. If the vendor is a parent and the validation fails, display the * actual error message. If the vendor is not a parent and the validation fails, display the error message that the parent of * this vendor needs to be changed, please contact Purchasing Dept. * * @param vendorDetail The VendorDetail to be validated * @return boolean true if the vendor does not contain ownership category and false otherwise */ private boolean validateOwnershipCategory(VendorDetail vendorDetail) { boolean valid = true; boolean isParent = vendorDetail.isVendorParentIndicator(); OwnershipType ot = vendorDetail.getVendorHeader().getVendorOwnership(); if (ot != null && !ot.getVendorOwnershipCategoryAllowedIndicator()) { if (ObjectUtils.isNotNull(vendorDetail.getVendorHeader().getVendorOwnershipCategory())) { valid &= false; } } if (!valid && isParent) { putFieldError(VendorPropertyConstants.VENDOR_OWNERSHIP_CATEGORY_CODE, VendorKeyConstants.ERROR_OWNERSHIP_CATEGORY_CODE_NOT_ALLOWED, new String[] { vendorDetail.getVendorHeader().getVendorOwnershipCategory().getVendorOwnershipCategoryDescription(), vendorDetail.getVendorHeader().getVendorOwnership().getVendorOwnershipDescription() }); } else if (!valid && !isParent) { putFieldError(VendorPropertyConstants.VENDOR_OWNERSHIP_CODE, VendorKeyConstants.ERROR_VENDOR_PARENT_NEEDS_CHANGED); } return valid; } /** * Calls the methods in TaxNumberService to validate the tax number for these business rules: 1. Tax number must be 9 digits and * cannot be all zeros (but can be blank). 2. First three digits of a SSN cannot be 000. 3. First three digits of a SSN cannot * be 666. 4. Middle two digits of a SSN cannot be 00. 5. Last four digits of a SSN cannot be 0000. 6. First two digits of a * FEIN cannot be 00. 7. Check system parameters for not allowed tax numbers * * @param vendorDetail The VendorDetail object to be validated * @return boolean true if the tax number is a valid tax number and false otherwise. */ private boolean validateTaxNumberFromTaxNumberService(VendorDetail vendorDetail) { boolean valid = true; boolean isParent = vendorDetail.isVendorParentIndicator(); String taxNumber = vendorDetail.getVendorHeader().getVendorTaxNumber(); String taxType = vendorDetail.getVendorHeader().getVendorTaxTypeCode(); if (!StringUtils.isEmpty(taxType) && !StringUtils.isEmpty(taxNumber)) { valid = SpringContext.getBean(TaxNumberService.class).isValidTaxNumber(taxNumber, taxType); if (!valid && isParent) { putFieldError(VendorPropertyConstants.VENDOR_TAX_NUMBER, VendorKeyConstants.ERROR_TAX_NUMBER_INVALID); } valid = SpringContext.getBean(TaxNumberService.class).isAllowedTaxNumber(taxNumber); if (!valid && isParent) { putFieldError(VendorPropertyConstants.VENDOR_TAX_NUMBER, VendorKeyConstants.ERROR_TAX_NUMBER_NOT_ALLOWED); } } if (!valid && !isParent) { putFieldError(VendorPropertyConstants.VENDOR_TAX_NUMBER, VendorKeyConstants.ERROR_VENDOR_PARENT_NEEDS_CHANGED); } return valid; } /** * Validates commodity code related rules. * * @param document MaintenanceDocument * @return boolean false or true */ boolean processCommodityCodeValidation(MaintenanceDocument document) { boolean valid = true; List<VendorCommodityCode> vendorCommodities = newVendor.getVendorCommodities(); boolean commodityCodeRequired = newVendor.getVendorHeader().getVendorType().isCommodityRequiredIndicator(); if (commodityCodeRequired) { if (vendorCommodities.size() == 0) { //display error that the commodity code is required for this type of vendor. String propertyName = "add." + VendorPropertyConstants.VENDOR_COMMODITIES_CODE_PURCHASING_COMMODITY_CODE; putFieldError(propertyName, VendorKeyConstants.ERROR_VENDOR_COMMODITY_CODE_IS_REQUIRED_FOR_THIS_VENDOR_TYPE); valid = false; } //We only need to validate the default indicator if there is at least //one commodity code for the vendor. else if (vendorCommodities.size() > 0) { valid &= validateCommodityCodeDefaultIndicator(vendorCommodities); } } else if (vendorCommodities.size() > 0) { //If the commodity code is not required, but the vendor contains at least one commodity code, //we have to check that there is only one commodity code with default indicator = Y. int defaultCount = 0; for (int i=0; i < vendorCommodities.size(); i++) { VendorCommodityCode vcc = vendorCommodities.get(i); if (vcc.isCommodityDefaultIndicator()) { defaultCount ++; if (defaultCount > 1) { valid = false; String propertyName = VendorPropertyConstants.VENDOR_COMMODITIES_CODE + "[" + i + "]." + VendorPropertyConstants.VENDOR_COMMODITIES_DEFAULT_INDICATOR; putFieldError(propertyName, VendorKeyConstants.ERROR_VENDOR_COMMODITY_CODE_REQUIRE_ONE_DEFAULT_IND); break; } } } } return valid; } /** * Validates that there is one and only one default indicator selected * for commodity code if the vendor contains at least one commodity code. * * @param vendorCommodities the list of VendorCommodityCode to be validated * @return boolean true or false */ private boolean validateCommodityCodeDefaultIndicator(List<VendorCommodityCode> vendorCommodities) { boolean valid = true; boolean foundDefaultIndicator = false; for (int i=0; i < vendorCommodities.size(); i++) { VendorCommodityCode vcc = vendorCommodities.get(i); if (vcc.isCommodityDefaultIndicator()) { if (!foundDefaultIndicator) { foundDefaultIndicator = true; } else { //display error that there can only be 1 commodity code with default indicator = true. String propertyName = VendorPropertyConstants.VENDOR_COMMODITIES_CODE + "[" + i + "]." + VendorPropertyConstants.VENDOR_COMMODITIES_DEFAULT_INDICATOR; putFieldError(propertyName, VendorKeyConstants.ERROR_VENDOR_COMMODITY_CODE_REQUIRE_ONE_DEFAULT_IND); valid = false; } } } if (!foundDefaultIndicator && vendorCommodities.size() > 0) { //display error that there must be one commodity code selected as the default commodity code for the vendor. String propertyName = VendorPropertyConstants.VENDOR_COMMODITIES_CODE + "[0]." + VendorPropertyConstants.VENDOR_COMMODITIES_DEFAULT_INDICATOR; putFieldError(propertyName, VendorKeyConstants.ERROR_VENDOR_COMMODITY_CODE_REQUIRE_ONE_DEFAULT_IND); valid = false; } return valid; } /** * Validates vendor address fields. * * @param document MaintenanceDocument * @return boolean false or true */ boolean processAddressValidation(MaintenanceDocument document) { boolean valid = true; boolean validAddressType = false; List<VendorAddress> addresses = newVendor.getVendorAddresses(); String vendorTypeCode = newVendor.getVendorHeader().getVendorTypeCode(); String vendorAddressTypeRequiredCode = newVendor.getVendorHeader().getVendorType().getVendorAddressTypeRequiredCode(); for (int i = 0; i < addresses.size(); i++) { VendorAddress address = addresses.get(i); String errorPath = MAINTAINABLE_ERROR_PREFIX + VendorPropertyConstants.VENDOR_ADDRESS + "[" + i + "]"; GlobalVariables.getMessageMap().clearErrorPath(); GlobalVariables.getMessageMap().addToErrorPath(errorPath); this.getDictionaryValidationService().validateBusinessObject(address); if (GlobalVariables.getMessageMap().hasErrors()) { valid = false; } if (address.getVendorAddressTypeCode().equals(vendorAddressTypeRequiredCode)) { validAddressType = true; } valid &= checkAddressCountryEmptyStateZip(address); GlobalVariables.getMessageMap().clearErrorPath(); } // validate Address Type String vendorAddressTabPrefix = KFSConstants.ADD_PREFIX + "." + VendorPropertyConstants.VENDOR_ADDRESS + "."; if (!StringUtils.isBlank(vendorTypeCode) && !StringUtils.isBlank(vendorAddressTypeRequiredCode) && !validAddressType) { String[] parameters = new String[] { vendorTypeCode, vendorAddressTypeRequiredCode }; putFieldError(vendorAddressTabPrefix + VendorPropertyConstants.VENDOR_ADDRESS_TYPE_CODE, VendorKeyConstants.ERROR_ADDRESS_TYPE, parameters); String addressLine1Label = SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(VendorAddress.class, VendorPropertyConstants.VENDOR_ADDRESS_LINE_1); String addressCityLabel = SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(VendorAddress.class, VendorPropertyConstants.VENDOR_ADDRESS_CITY); String addressCountryLabel = SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(VendorAddress.class, VendorPropertyConstants.VENDOR_ADDRESS_COUNTRY); putFieldError(vendorAddressTabPrefix + VendorPropertyConstants.VENDOR_ADDRESS_LINE_1, KFSKeyConstants.ERROR_REQUIRED, addressLine1Label); putFieldError(vendorAddressTabPrefix + VendorPropertyConstants.VENDOR_ADDRESS_CITY, KFSKeyConstants.ERROR_REQUIRED, addressCityLabel); putFieldError(vendorAddressTabPrefix + VendorPropertyConstants.VENDOR_ADDRESS_COUNTRY, KFSKeyConstants.ERROR_REQUIRED, addressCountryLabel); valid = false; } valid &= validateDefaultAddressCampus(newVendor); // Check to see if all divisions have one desired address for this vendor type Map fieldValues = new HashMap(); fieldValues.put(VendorPropertyConstants.VENDOR_HEADER_GENERATED_ID, newVendor.getVendorHeaderGeneratedIdentifier()); // Find all the addresses for this vendor and its divisions: List<VendorAddress> vendorDivisionAddresses = new ArrayList(SpringContext.getBean(BusinessObjectService.class).findMatchingOrderBy(VendorAddress.class, fieldValues, VendorPropertyConstants.VENDOR_DETAIL_ASSIGNED_ID, true)); // This set stores the vendorDetailedAssignedIds for the vendor divisions which is // bascically the division numbers 0, 1, 2, ... HashSet<Integer> vendorDetailedIds = new HashSet(); // This set stores the vendor division numbers of the ones which have one address of the desired type HashSet<Integer> vendorDivisionsIdsWithDesiredAddressType = new HashSet(); for (VendorAddress vendorDivisionAddress : vendorDivisionAddresses) { // We need to exclude the first one Since we already checked for this in valid AddressType above. if (vendorDivisionAddress.getVendorDetailAssignedIdentifier() != 0) { vendorDetailedIds.add(vendorDivisionAddress.getVendorDetailAssignedIdentifier()); if (vendorDivisionAddress.getVendorAddressTypeCode().equalsIgnoreCase(vendorAddressTypeRequiredCode)) { vendorDivisionsIdsWithDesiredAddressType.add(vendorDivisionAddress.getVendorDetailAssignedIdentifier()); } } } // If the number of divisions with the desired address type is less than the number of divisions for his vendor if (vendorDivisionsIdsWithDesiredAddressType.size() < vendorDetailedIds.size()) { Iterator itr = vendorDetailedIds.iterator(); Integer value; String vendorId; while (itr.hasNext()) { value = (Integer) itr.next(); if (!vendorDivisionsIdsWithDesiredAddressType.contains(value)) { vendorId = newVendor.getVendorHeaderGeneratedIdentifier().toString() + '-' + value.toString(); String[] parameters = new String[] { vendorId, vendorTypeCode, vendorAddressTypeRequiredCode }; //divisions without the desired address type should only be an warning GlobalVariables.getMessageMap().putWarningWithoutFullErrorPath(MAINTAINABLE_ERROR_PREFIX + vendorAddressTabPrefix + VendorPropertyConstants.VENDOR_ADDRESS_TYPE_CODE, VendorKeyConstants.ERROR_ADDRESS_TYPE_DIVISIONS, parameters); } } } return valid; } /** * Validates that if US is selected for the country then the state and zip cannot be empty. Also, * zip format validation is added if US is selected. * * @param addresses VendorAddress which is being validated * @return boolean false if the country is United States and there is no state or zip code */ boolean checkAddressCountryEmptyStateZip(VendorAddress address) { //GlobalVariables.getMessageMap().clearErrorPath(); //GlobalVariables.getMessageMap().addToErrorPath(KFSPropertyConstants.DOCUMENT + "." + KFSPropertyConstants.NEW_MAINTAINABLE_OBJECT + "." + VendorPropertyConstants.VENDOR_ADDRESS); boolean valid = SpringContext.getBean(PostalCodeValidationService.class).validateAddress(address.getVendorCountryCode(), address.getVendorStateCode(), address.getVendorZipCode(), VendorPropertyConstants.VENDOR_ADDRESS_STATE, VendorPropertyConstants.VENDOR_ADDRESS_ZIP); //GlobalVariables.getMessageMap().clearErrorPath(); return valid; } /** * Checks if the "allow default indicator" is true or false for this address. * * @param addresses VendorAddress which is being validated * @return boolean false or true */ boolean findAllowDefaultAddressIndicatorHelper(VendorAddress vendorAddress) { AddressType addressType = new AddressType(); addressType = vendorAddress.getVendorAddressType(); if (ObjectUtils.isNull(addressType)) { return false; } // Retrieving the Default Address Indicator for this Address Type: return addressType.getVendorDefaultIndicator(); } /** * If add button is selected on Default Address, checks if the allow default indicator is set to false for this address type * then it does not allow user to select a default address for this address and if it is true then it allows only one campus to * be default for this address. * * @param vendorDetail VendorDetail document * @param addedDefaultAddress VendorDefaultAddress which is being added * @param parent The VendorAddress which we are adding a default address to it * @return boolean false or true */ boolean checkDefaultAddressCampus(VendorDetail vendorDetail, VendorDefaultAddress addedDefaultAddress, VendorAddress parent) { VendorAddress vendorAddress = parent; if (ObjectUtils.isNull(vendorAddress)) { return false; } int j = vendorDetail.getVendorAddresses().indexOf(vendorAddress); String errorPath = MAINTAINABLE_ERROR_PREFIX + VendorPropertyConstants.VENDOR_ADDRESS + "[" + j + "]"; GlobalVariables.getMessageMap().addToErrorPath(errorPath); // Retrieving the Default Address Indicator for this Address Type: boolean allowDefaultAddressIndicator = findAllowDefaultAddressIndicatorHelper(vendorAddress); String addedAddressCampusCode = addedDefaultAddress.getVendorCampusCode(); String addedAddressTypeCode = vendorAddress.getVendorAddressTypeCode(); // if the selected address type does not allow defaults, then the user should not be allowed to // select the default indicator or add any campuses to the address if (allowDefaultAddressIndicator == false) { String[] parameters = new String[] { addedAddressTypeCode }; GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_DEFAULT_ADDRESS + "[" + 0 + "]." + VendorPropertyConstants.VENDOR_DEFAULT_ADDRESS_CAMPUS, VendorKeyConstants.ERROR_ADDRESS_DEFAULT_CAMPUS_NOT_ALLOWED, parameters); return false; } List<VendorDefaultAddress> vendorDefaultAddresses = vendorAddress.getVendorDefaultAddresses(); for (int i = 0; i < vendorDefaultAddresses.size(); i++) { VendorDefaultAddress vendorDefaultAddress = vendorDefaultAddresses.get(i); if (vendorDefaultAddress.getVendorCampusCode().equalsIgnoreCase(addedAddressCampusCode)) { GlobalVariables.getMessageMap().clearErrorPath(); GlobalVariables.getMessageMap().addToErrorPath(errorPath); String[] parameters = new String[] { addedAddressCampusCode, addedAddressTypeCode }; GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_DEFAULT_ADDRESS + "[" + i + "]." + VendorPropertyConstants.VENDOR_DEFAULT_ADDRESS_CAMPUS, VendorKeyConstants.ERROR_ADDRESS_DEFAULT_CAMPUS, parameters); return false; } } return true; } /** * Checks if the allow default indicator is set to false for this address the default indicator cannot be set to true/yes. If * "allow default indicator" is set to true/yes for address type, one address must have the default indicator set (no more, no * less) and only one campus to be set as default for this address. * * @param vendorDetail VendorDetail document * @return boolean false or true */ boolean validateDefaultAddressCampus(VendorDetail vendorDetail) { List<VendorAddress> vendorAddresses = vendorDetail.getVendorAddresses(); String addressTypeCode; String addressTypeDesc; String campusCode; boolean valid = true; boolean previousValue = false; // This is a HashMap to store the default Address Type Codes and their associated default Indicator HashMap addressTypeCodeDefaultIndicator = new HashMap(); // This is a HashMap to store Address Type Codes and Address Campus Codes for Default Addresses HashMap addressTypeDefaultCampus = new HashMap(); // This is a HashSet for storing only the Address Type Codes which have at least one default Indicator set to true HashSet addressTypesHavingDefaultTrue = new HashSet(); int i = 0; for (VendorAddress address : vendorAddresses) { addressTypeCode = address.getVendorAddressTypeCode(); addressTypeDesc = address.getVendorAddressType().getVendorAddressTypeDescription(); String errorPath = MAINTAINABLE_ERROR_PREFIX + VendorPropertyConstants.VENDOR_ADDRESS + "[" + i + "]"; GlobalVariables.getMessageMap().addToErrorPath(errorPath); String[] parameters = new String[] { addressTypeCode }; // If "allow default indicator" is set to true/yes for address type, one address must have the default indicator set (no // more, no less). // For example, if a vendor contains three PO type addresses and the PO address type is set to allow defaults in the // address type table, // then only one of these PO addresses can have the default indicator set to true/yes. if (findAllowDefaultAddressIndicatorHelper(address)) { if (address.isVendorDefaultAddressIndicator()) { addressTypesHavingDefaultTrue.add(addressTypeCode); } if (!addressTypeCodeDefaultIndicator.isEmpty() && addressTypeCodeDefaultIndicator.containsKey(addressTypeCode)) { previousValue = ((Boolean) addressTypeCodeDefaultIndicator.get(addressTypeCode)).booleanValue(); } if (addressTypeCodeDefaultIndicator.put(addressTypeCode, address.isVendorDefaultAddressIndicator()) != null && previousValue && address.isVendorDefaultAddressIndicator()) { GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_DEFAULT_ADDRESS_INDICATOR, VendorKeyConstants.ERROR_ADDRESS_DEFAULT_INDICATOR,addressTypeDesc ); valid = false; } } // If "allow default indicator" is set to false/no for address type, the default indicator cannot be set to true/yes. else { if (address.isVendorDefaultAddressIndicator()) { GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_DEFAULT_ADDRESS_INDICATOR, VendorKeyConstants.ERROR_ADDRESS_DEFAULT_ADDRESS_NOT_ALLOWED, parameters); valid = false; } } List<VendorDefaultAddress> vendorDefaultAddresses = address.getVendorDefaultAddresses(); // If "allow default indicator" is set to true/yes for address type, a campus can only be set on one of each type of // Address. // For example, Bloomington can not be included in the campus list for two PO type addresses. // Each campus can only have one default address. int j = 0; for (VendorDefaultAddress defaultAddress : vendorDefaultAddresses) { campusCode = (String) addressTypeDefaultCampus.put(addressTypeCode, defaultAddress.getVendorCampusCode()); if (StringUtils.isNotBlank(campusCode) && campusCode.equalsIgnoreCase(defaultAddress.getVendorCampusCode())) { String[] newParameters = new String[] { defaultAddress.getVendorCampusCode(), addressTypeCode }; GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_DEFAULT_ADDRESS + "[" + j + "]." + VendorPropertyConstants.VENDOR_DEFAULT_ADDRESS_CAMPUS, VendorKeyConstants.ERROR_ADDRESS_DEFAULT_CAMPUS, newParameters); valid = false; } j++; } i++; GlobalVariables.getMessageMap().removeFromErrorPath(errorPath); } // If "allow default indicator" is set to true/yes for address type, one address must have the default indicator set to true if (!addressTypeCodeDefaultIndicator.isEmpty()) { Set<String> addressTypes = addressTypeCodeDefaultIndicator.keySet(); for (String addressType : addressTypes) { if (!addressTypesHavingDefaultTrue.contains(addressType)) { int addressIndex = 0; for (VendorAddress address : vendorAddresses) { String[] parameters = new String[] { address.getVendorAddressType().getVendorAddressTypeDescription() }; String propertyName = VendorPropertyConstants.VENDOR_ADDRESS + "[" + addressIndex + "]." + VendorPropertyConstants.VENDOR_DEFAULT_ADDRESS_INDICATOR; if (address.getVendorAddressType().getVendorAddressTypeCode().equalsIgnoreCase(addressType)) { putFieldError(propertyName, VendorKeyConstants.ERROR_ADDRESS_DEFAULT_INDICATOR, parameters); break; } addressIndex++; } valid = false; } } } return valid; } /** * A stub method as placeholder for future Contact Validation * * @param document MaintenanceDocument instance * @return boolean false or true */ private boolean processContactValidation(MaintenanceDocument document) { boolean valid = true; int i = 0; for (VendorContact contact : newVendor.getVendorContacts()) { String errorPath = MAINTAINABLE_ERROR_PREFIX + VendorPropertyConstants.VENDOR_CONTACT + "[" + i + "]"; GlobalVariables.getMessageMap().addToErrorPath(errorPath); this.getDictionaryValidationService().validateBusinessObject(contact); Map<String, AutoPopulatingList<ErrorMessage>> errors = GlobalVariables.getMessageMap().getErrorMessages(); if ((errors != null ) && (!errors.isEmpty())) { valid = false; } i++; GlobalVariables.getMessageMap().clearErrorPath(); } return valid; } /** * Validates vendor customer numbers * * @param document MaintenanceDocument instance * @return boolean false or true */ private boolean processCustomerNumberValidation(MaintenanceDocument document) { boolean valid = true; List<VendorCustomerNumber> customerNumbers = newVendor.getVendorCustomerNumbers(); for (VendorCustomerNumber customerNumber : customerNumbers) { valid &= validateVendorCustomerNumber(customerNumber); } return valid; } /** * Validates vendor customer number. The chart and org must exist in the database. * * @param customerNumber VendorCustomerNumber * @return boolean false or true */ boolean validateVendorCustomerNumber(VendorCustomerNumber customerNumber) { boolean valid = true; // The chart and org must exist in the database. String chartOfAccountsCode = customerNumber.getChartOfAccountsCode(); String orgCode = customerNumber.getVendorOrganizationCode(); if (!StringUtils.isBlank(chartOfAccountsCode) && !StringUtils.isBlank(orgCode)) { Map chartOrgMap = new HashMap(); chartOrgMap.put("chartOfAccountsCode", chartOfAccountsCode); if (SpringContext.getBean(BusinessObjectService.class).countMatching(Chart.class, chartOrgMap) < 1) { GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CUSTOMER_NUMBER_CHART_OF_ACCOUNTS_CODE, KFSKeyConstants.ERROR_EXISTENCE, chartOfAccountsCode); valid &= false; } chartOrgMap.put("organizationCode", orgCode); if (SpringContext.getBean(BusinessObjectService.class).countMatching(Organization.class, chartOrgMap) < 1) { GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CUSTOMER_NUMBER_ORGANIZATION_CODE, KFSKeyConstants.ERROR_EXISTENCE, orgCode); valid &= false; } } return valid; } /** * Validates vendor contract. If the vendorContractAllowedIndicator is false, it cannot have vendor contracts, then return false * * @param document MaintenanceDocument * @return boolean false or true */ private boolean processContractValidation(MaintenanceDocument document) { boolean valid = true; List<VendorContract> contracts = newVendor.getVendorContracts(); if (ObjectUtils.isNull(contracts)) { return valid; } // If the vendorContractAllowedIndicator is false, it cannot have vendor contracts, return false; if (contracts.size() > 0 && !newVendor.getVendorHeader().getVendorType().isVendorContractAllowedIndicator()) { valid = false; String errorPath = MAINTAINABLE_ERROR_PREFIX + VendorPropertyConstants.VENDOR_CONTRACT + "[0]"; GlobalVariables.getMessageMap().addToErrorPath(errorPath); GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CONTRACT_NAME, VendorKeyConstants.ERROR_VENDOR_CONTRACT_NOT_ALLOWED); GlobalVariables.getMessageMap().removeFromErrorPath(errorPath); return valid; } for (int i = 0; i < contracts.size(); i++) { VendorContract contract = contracts.get(i); String errorPath = MAINTAINABLE_ERROR_PREFIX + VendorPropertyConstants.VENDOR_CONTRACT + "[" + i + "]"; GlobalVariables.getMessageMap().addToErrorPath(errorPath); valid &= validateVendorContractPOLimitAndExcludeFlagCombination(contract); valid &= validateVendorContractBeginEndDates(contract); valid &= processContractB2BValidation(document, contract, i); if (contract.getOrganizationAutomaticPurchaseOrderLimit() != null) { org.kuali.rice.krad.datadictionary.BusinessObjectEntry entry = SpringContext.getBean(DataDictionaryService.class).getDataDictionary().getBusinessObjectEntry(VendorContract.class.getName()); AttributeDefinition attributeDefinition = entry.getAttributeDefinition(VendorPropertyConstants.VENDOR_CONTRACT_DEFAULT_APO_LIMIT); valid &= validateAPOAmount(contract.getOrganizationAutomaticPurchaseOrderLimit(), attributeDefinition); } GlobalVariables.getMessageMap().removeFromErrorPath(errorPath); } return valid; } /** * Validates that the APO amount is a valid amount according to * the FixedPointValidationPattern (i.e. non negative number with the precision and scale * as defined in the data dictionary). * * @param apoAmount * @param attributeDefinition * @return */ boolean validateAPOAmount(KualiDecimal apoAmount, AttributeDefinition attributeDefinition) { boolean valid = true; if (ObjectUtils.isNotNull(attributeDefinition)) { final ValidationPattern validationPattern = attributeDefinition.getValidationPattern(); if (ObjectUtils.isNotNull(validationPattern) && validationPattern instanceof FixedPointValidationPattern) { FixedPointValidationPattern fixedPointPattern = (FixedPointValidationPattern) validationPattern; if (!fixedPointPattern.matches(apoAmount.toString())) { valid &= false; String scale = Integer.toString(fixedPointPattern.getScale()); String precision = Integer.toString(fixedPointPattern.getPrecision()); GlobalVariables.getMessageMap().putError(attributeDefinition.getName(), attributeDefinition.getValidationPattern().getValidationErrorMessageKey(), attributeDefinition.getLabel(), precision, scale); } } } return valid; } /** * Validates that the proper combination of Exclude Indicator and APO Amount is present on a vendor contract. Do not perform * this validation on Contract add line as the user cannot currently enter the sub-collection of contract-orgs so we should not * force this until the document is submitted. The rules are : 1. Must enter a Default APO Limit or at least one organization * with an APO Amount. 2. If the Exclude Indicator for an organization is N, an organization APO Amount is required. 3. If the * Exclude Indicator for an organization is Y, the organization APO Amount is not allowed. * * @param contract VendorContract * @return boolean true if the proper combination of Exclude Indicator and APO Amount is present, otherwise flase. */ boolean validateVendorContractPOLimitAndExcludeFlagCombination(VendorContract contract) { boolean valid = true; boolean NoOrgHasApoLimit = true; List<VendorContractOrganization> organizations = contract.getVendorContractOrganizations(); if (ObjectUtils.isNotNull(organizations)) { int organizationCounter = 0; for (VendorContractOrganization organization : organizations) { if (ObjectUtils.isNotNull(organization.getVendorContractPurchaseOrderLimitAmount())) { NoOrgHasApoLimit = false; } valid &= validateVendorContractOrganization(organization, organizationCounter); organizationCounter++; } } if (NoOrgHasApoLimit && ObjectUtils.isNull(contract.getOrganizationAutomaticPurchaseOrderLimit())) { // Rule #1 in the above java doc has been violated. GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CONTRACT_DEFAULT_APO_LIMIT, VendorKeyConstants.ERROR_VENDOR_CONTRACT_NO_APO_LIMIT); valid &= false; } return valid; } /** * Validates that: 1. If the VendorContractBeginningDate is entered then the VendorContractEndDate is also entered, and vice * versa. 2. If both dates are entered, the VendorContractBeginningDate is before the VendorContractEndDate. The date fields are * required so we should know that we have valid dates. * * @param contract VendorContract * @return boolean true if the beginning date is before the end date, false if only one date is entered or the beginning date is * after the end date. */ boolean validateVendorContractBeginEndDates(VendorContract contract) { boolean valid = true; if (ObjectUtils.isNotNull(contract.getVendorContractBeginningDate()) && ObjectUtils.isNull(contract.getVendorContractEndDate())) { GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CONTRACT_END_DATE, VendorKeyConstants.ERROR_VENDOR_CONTRACT_BEGIN_DATE_NO_END_DATE); valid &= false; } else { if (ObjectUtils.isNull(contract.getVendorContractBeginningDate()) && ObjectUtils.isNotNull(contract.getVendorContractEndDate())) { GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CONTRACT_BEGIN_DATE, VendorKeyConstants.ERROR_VENDOR_CONTRACT_END_DATE_NO_BEGIN_DATE); valid &= false; } } if (valid && ObjectUtils.isNotNull(contract.getVendorContractBeginningDate()) && ObjectUtils.isNotNull(contract.getVendorContractEndDate())) { if (contract.getVendorContractBeginningDate().after(contract.getVendorContractEndDate())) { GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CONTRACT_BEGIN_DATE, VendorKeyConstants.ERROR_VENDOR_CONTRACT_BEGIN_DATE_AFTER_END); valid &= false; } } return valid; } /** * Validates a vendor contract organization. The rules are : 1. If the Exclude Indicator for the organization is N, an * organization APO Amount is required. 2. If the Exclude Indicator for the organization is Y, an organization APO Amount is not * allowed. 3. The chart and org for the organization must exist in the database. * * @param organization VendorContractOrganization * @return boolean true if these three rules are passed, otherwise false. */ boolean validateVendorContractOrganization(VendorContractOrganization organization, int counter) { boolean valid = true; List<String> previousErrorPaths = GlobalVariables.getMessageMap().getErrorPath(); String errorPath = VendorPropertyConstants.VENDOR_CONTRACT_ORGANIZATION + "[" + counter + "]"; boolean shouldAddToErrorPath = true; // if the error path already contained something like "add." then we don't need to add anything to the error path anymore. for (String previous : previousErrorPaths) { if (previous.startsWith(KRADConstants.ADD_PREFIX)) { shouldAddToErrorPath = false; break; } } if (shouldAddToErrorPath) { GlobalVariables.getMessageMap().addToErrorPath(errorPath); } boolean isExcluded = organization.isVendorContractExcludeIndicator(); if (isExcluded) { if (ObjectUtils.isNotNull(organization.getVendorContractPurchaseOrderLimitAmount())) { // Rule #2 in the above java doc has been violated. GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CONTRACT_ORGANIZATION_APO_LIMIT, VendorKeyConstants.ERROR_VENDOR_CONTRACT_ORG_EXCLUDED_WITH_APO_LIMIT); valid &= false; } } else { // isExcluded = false if (ObjectUtils.isNull(organization.getVendorContractPurchaseOrderLimitAmount())) { // Rule #1 in the above java doc has been violated. GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CONTRACT_ORGANIZATION_APO_LIMIT, VendorKeyConstants.ERROR_VENDOR_CONTRACT_ORG_NOT_EXCLUDED_NO_APO_LIMIT); valid &= false; } } // The chart and org must exist in the database. String chartOfAccountsCode = organization.getChartOfAccountsCode(); String orgCode = organization.getOrganizationCode(); if (!StringUtils.isBlank(chartOfAccountsCode) && !StringUtils.isBlank(orgCode)) { Map chartOrgMap = new HashMap(); chartOrgMap.put("chartOfAccountsCode", chartOfAccountsCode); if (SpringContext.getBean(BusinessObjectService.class).countMatching(Chart.class, chartOrgMap) < 1) { GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CONTRACT_CHART_OF_ACCOUNTS_CODE, KFSKeyConstants.ERROR_EXISTENCE, chartOfAccountsCode); valid &= false; } chartOrgMap.put("organizationCode", orgCode); if (SpringContext.getBean(BusinessObjectService.class).countMatching(Organization.class, chartOrgMap) < 1) { GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CONTRACT_ORGANIZATION_CODE, KFSKeyConstants.ERROR_EXISTENCE, orgCode); valid &= false; } } if (shouldAddToErrorPath && organization.getVendorContractPurchaseOrderLimitAmount() != null) { org.kuali.rice.krad.datadictionary.BusinessObjectEntry entry = SpringContext.getBean(DataDictionaryService.class).getDataDictionary().getBusinessObjectEntry(VendorContractOrganization.class.getName()); AttributeDefinition attributeDefinition = entry.getAttributeDefinition(VendorPropertyConstants.VENDOR_CONTRACT_ORGANIZATION_APO_LIMIT); valid &= validateAPOAmount(organization.getVendorContractPurchaseOrderLimitAmount(), attributeDefinition); } if (shouldAddToErrorPath) { GlobalVariables.getMessageMap().removeFromErrorPath(errorPath); } return valid; } /** * Validates vendor contracts against single B2B restriction on a vendor/campus basis. Only one B2B contract allowed per vendor/campus * * @param document MaintenanceDocument * @return boolean false or true */ private boolean processContractB2BValidation(MaintenanceDocument document, VendorContract contract, int contractPos) { boolean valid = true; List<Integer> indexOfB2BContracts = new ArrayList(); //list of contracts already associated with vendor List<VendorContract> contracts = newVendor.getVendorContracts(); if (ObjectUtils.isNull(contracts)) { return valid; } //find all b2b contracts for comparison if(contractPos == -1){ if(contract.getVendorB2bIndicator()){ for (int i = 0; i < contracts.size(); i++) { VendorContract vndrContract = contracts.get(i); if(vndrContract.getVendorB2bIndicator()){ //check for duplicate campus; vendor is implicitly the same if(contract.getVendorCampusCode().equals(vndrContract.getVendorCampusCode())){ valid &= false; GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CONTRACT_B2B_INDICATOR, VendorKeyConstants.ERROR_VENDOR_CONTRACT_B2B_LIMIT_EXCEEDED, contract.getVendorCampusCode()); } } } } } else { if(contract.getVendorB2bIndicator()){ for (int i = 0; i < contracts.size(); i++) { VendorContract vndrContract = contracts.get(i); if(vndrContract.getVendorB2bIndicator()){ //make sure we're not checking contracts against themselves if(i != contractPos){ //check for duplicate campus; vendor is implicitly the same if(contract.getVendorCampusCode().equals(vndrContract.getVendorCampusCode())){ valid &= false; String [] errorArray = new String []{contract.getVendorContractName(), contract.getVendorCampusCode()}; GlobalVariables.getMessageMap().putError(VendorPropertyConstants.VENDOR_CONTRACT_B2B_INDICATOR, VendorKeyConstants.ERROR_VENDOR_CONTRACT_B2B_LIMIT_EXCEEDED_DB, errorArray); } } } } } } return valid; } /** * Validates business rules for VendorDetail document collection add lines. Add lines are the initial lines on a collections, * i.e. the ones next to the "Add" button * * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#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 VendorAddress) { VendorAddress address = (VendorAddress) bo; success &= checkAddressCountryEmptyStateZip(address); VendorDetail vendorDetail = (VendorDetail) document.getNewMaintainableObject().getBusinessObject(); } if (bo instanceof VendorContract) { VendorContract contract = (VendorContract) bo; success &= validateVendorContractBeginEndDates(contract); success &= processContractB2BValidation(document,contract, -1); } if (bo instanceof VendorContractOrganization) { VendorContractOrganization contractOrg = (VendorContractOrganization) bo; success &= validateVendorContractOrganization(contractOrg, 0); } if (bo instanceof VendorCustomerNumber) { VendorCustomerNumber customerNumber = (VendorCustomerNumber) bo; success &= validateVendorCustomerNumber(customerNumber); } if (bo instanceof VendorDefaultAddress) { VendorDefaultAddress defaultAddress = (VendorDefaultAddress) bo; String parentName = StringUtils.substringBeforeLast(collectionName, "."); VendorAddress parent = (VendorAddress) ObjectUtils.getPropertyValue(this.getNewBo(), parentName); VendorDetail vendorDetail = (VendorDetail) document.getNewMaintainableObject().getBusinessObject(); success &= checkDefaultAddressCampus(vendorDetail, defaultAddress, parent); } if (bo instanceof VendorCommodityCode) { VendorCommodityCode commodityCode = (VendorCommodityCode) bo; String purchasingCommodityCode = commodityCode.getPurchasingCommodityCode(); boolean found = ObjectUtils.isNotNull(commodityCode) && StringUtils.isNotBlank(purchasingCommodityCode) && checkVendorCommodityCode(commodityCode); if (!found) { GlobalVariables.getMessageMap().putError(VendorPropertyConstants.PURCHASING_COMMODITY_CODE, KFSKeyConstants.ERROR_EXISTENCE, purchasingCommodityCode); } success &= found; } return success; } /** * Validates the rule that if a document has a federal witholding tax begin date and end date, the begin date should come before * the end date. * * @param vdDocument VendorDetail * @return boolean false or true */ private boolean validateVendorWithholdingTaxDates(VendorDetail vdDocument) { boolean valid = true; DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class); Date beginDate = vdDocument.getVendorHeader().getVendorFederalWithholdingTaxBeginningDate(); Date endDate = vdDocument.getVendorHeader().getVendorFederalWithholdingTaxEndDate(); if (ObjectUtils.isNotNull(beginDate) && ObjectUtils.isNotNull(endDate)) { if (dateTimeService.dateDiff(beginDate, endDate, false) <= 0) { putFieldError(VendorPropertyConstants.VENDOR_FEDERAL_WITHOLDING_TAX_BEGINNING_DATE, VendorKeyConstants.ERROR_VENDOR_TAX_BEGIN_DATE_AFTER_END); valid &= false; } } return valid; } protected boolean validateGIINCode(VendorDetail vDetail) { boolean valid = true; if (ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorGIIN())) { String giin = vDetail.getVendorHeader().getVendorGIIN(); String giinParm = SpringContext.getBean(ParameterService.class).getParameterValueAsString(VendorDetail.class, VendorParameterConstants.GIIN_NUMBER_FORMAT); if (!giin.matches(giinParm)) { putFieldError(VendorPropertyConstants.VENDOR_GIIN_CODE, VendorKeyConstants.ERROR_VENDOR_GIIN_FORMAT_ERROR); valid &= false; } } return valid; } protected boolean validateW8SignedDate(VendorDetail vDetail) { boolean valid = true; if (ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorW8BenReceivedIndicator()) && vDetail.getVendorHeader().getVendorW8BenReceivedIndicator()) { if (SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(VendorDetail.class, VendorParameterConstants.W8_DATA_REQUIRED_IND)) { DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class); Date today = dateTimeService.getCurrentDate(); if (ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorW8SignedDate())) { Date signedDate = vDetail.getVendorHeader().getVendorW8SignedDate(); if (today.compareTo(signedDate) <= 0) { putFieldError(VendorPropertyConstants.VENDOR_W8SIGNED_DATE, VendorKeyConstants.ERROR_VENDOR_W8ANDW9_SIGNED_AFTER_TODAY); valid &= false; } } else { putFieldError(VendorPropertyConstants.VENDOR_W8SIGNED_DATE, VendorKeyConstants.ERROR_VENDOR_W8SINGED_DATE_REQUIRED); valid &= false; } } } return valid; } protected boolean validateW9SignedDate(VendorDetail vDetail) { boolean valid = true; if (ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorW9ReceivedIndicator()) && vDetail.getVendorHeader().getVendorW9ReceivedIndicator()) { if (SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(VendorDetail.class, VendorParameterConstants.W9_SIGNED_DATE_REQUIRED) && ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorW9ReceivedIndicator())) { DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class); Date today = dateTimeService.getCurrentDate(); if (ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorW9SignedDate())) { Date signedDate = vDetail.getVendorHeader().getVendorW9SignedDate(); if (today.compareTo(signedDate) <= 0) { putFieldError(VendorPropertyConstants.VENDOR_W9SIGNED_DATE, VendorKeyConstants.ERROR_VENDOR_W8ANDW9_SIGNED_AFTER_TODAY); valid &= false; } } else { putFieldError(VendorPropertyConstants.VENDOR_W9SIGNED_DATE, VendorKeyConstants.ERROR_VENDOR_W9SINGED_DATE_REQUIRED); valid &= false; } } } return valid; } protected boolean validateDOBDate(VendorDetail vDetail) { boolean valid = true; DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class); Date today = dateTimeService.getCurrentDate(); if (ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorDOB())) { Date dobDate = vDetail.getVendorHeader().getVendorDOB(); if (ObjectUtils.isNotNull(dobDate)) { if (today.compareTo(dobDate) <= 0) { putFieldError(VendorPropertyConstants.VENDOR_DOB, VendorKeyConstants.ERROR_VENDOR_W8ANDW9_SIGNED_AFTER_TODAY); valid &= false; } } } return valid; } protected boolean validateCorpCitizen(VendorDetail vDetail) { boolean valid = true; if (SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(VendorDetail.class, VendorParameterConstants.W8_DATA_REQUIRED_IND)) { if (ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorW8BenReceivedIndicator()) && vDetail.getVendorHeader().getVendorW8BenReceivedIndicator()) { if (StringUtils.isBlank(vDetail.getVendorHeader().getVendorCorpCitizenCode())) { putFieldError(VendorPropertyConstants.VENDOR_CORP_CITIZEN_CODE, VendorKeyConstants.ERROR_VENDOR_CORP_CTZN_REQUIRED); valid &= false; } } } return valid; } protected boolean validateW8Type(VendorDetail vDetail) { boolean valid = true; if (SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(VendorDetail.class, VendorParameterConstants.W8_DATA_REQUIRED_IND)) { if (ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorOwnershipCode()) && ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorW8TypeCode())) { valid = false; Map fieldValues = new HashMap(); fieldValues.put("vendorOwnershipCode", vDetail.getVendorHeader().getVendorOwnershipCode()); List<W8TypeOwnershipType> vendorW8OwnershipTypes = new ArrayList(SpringContext.getBean(BusinessObjectService.class).findMatching(W8TypeOwnershipType.class, fieldValues)); for (W8TypeOwnershipType w8TypeOwnership : vendorW8OwnershipTypes) { if (w8TypeOwnership.getW8TypeCode().equals(vDetail.getVendorHeader().getVendorW8TypeCode())) { valid = true; break; } } if (!valid) { putFieldError(VendorPropertyConstants.VENDOR_W8_TYPE_CODE, VendorKeyConstants.ERROR_VENDOR_W8_OWNERSHIP_INVALID); } } } return valid; } protected boolean validateW8Received(VendorDetail vDetail) { boolean valid = true; if (ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorW8BenReceivedIndicator()) && vDetail.getVendorHeader().getVendorW8BenReceivedIndicator()) { if (!vDetail.getVendorHeader().getVendorForeignIndicator()) { putFieldError(VendorPropertyConstants.VENDOR_FOREIGN_INDICATOR, VendorKeyConstants.ERROR_VENDOR_FOREIGN_REQUIRED); valid &= false; } if (StringUtils.isBlank(vDetail.getVendorHeader().getVendorW8TypeCode()) && SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(VendorDetail.class, VendorParameterConstants.W8_DATA_REQUIRED_IND)) { putFieldError(VendorPropertyConstants.VENDOR_W8_TYPE_CODE, VendorKeyConstants.ERROR_VENDOR_W8TYPE_REQUIRED); valid &= false; } } else { if (!StringUtils.isBlank(vDetail.getVendorHeader().getVendorW8TypeCode()) || !ObjectUtils.isNull(vDetail.getVendorHeader().getVendorW8SignedDate())) { putFieldError(VendorPropertyConstants.VENDOR_W8_BEN_RECEIVED_INDICATOR, VendorKeyConstants.ERROR_VENDOR_W8TYPE_AND_SIGNED_DATE_INVALID); valid &= false; } } return valid; } protected boolean validateW9Received(VendorDetail vDetail) { boolean valid = true; if (ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorW9ReceivedIndicator()) && !vDetail.getVendorHeader().getVendorW9ReceivedIndicator()) { if (ObjectUtils.isNotNull(vDetail.getVendorHeader().getVendorW9SignedDate())) { putFieldError(VendorPropertyConstants.VENDOR_W9_RECEIVED_INDICATOR, VendorKeyConstants.ERROR_VENDOR_W9SIGNED_DATE_INVALID); valid &= false; } } return valid; } /** * Validates the rule that both w-9 received and w-8 cannot be set to yes * * @param vdDocument VendorDetail * @return boolean false or true */ private boolean validateVendorW8BenOrW9ReceivedIndicator(VendorDetail vdDocument) { boolean valid = true; if (ObjectUtils.isNotNull(vdDocument.getVendorHeader().getVendorW9ReceivedIndicator()) && ObjectUtils.isNotNull(vdDocument.getVendorHeader().getVendorW8BenReceivedIndicator()) && vdDocument.getVendorHeader().getVendorW9ReceivedIndicator() && vdDocument.getVendorHeader().getVendorW8BenReceivedIndicator()) { putFieldError(VendorPropertyConstants.VENDOR_W9_RECEIVED_INDICATOR, VendorKeyConstants.ERROR_VENDOR_W9_AND_W8_RECEIVED_INDICATOR_BOTH_TRUE); valid &= false; } return valid; } /** * Overrides the method in MaintenanceDocumentRuleBase to give error message to the user when * the user tries to add a vendor contract when the vendor type of the vendor does not allow * contract. * * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processAddCollectionLineBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument, java.lang.String, org.kuali.rice.krad.bo.PersistableBusinessObject) */ @Override public boolean processAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject bo) { if (collectionName.equals(VendorPropertyConstants.VENDOR_CONTRACT)) { VendorDetail vendorDetail = (VendorDetail)document.getDocumentBusinessObject(); vendorDetail.getVendorHeader().refreshReferenceObject("vendorType"); VendorType vendorType = vendorDetail.getVendorHeader().getVendorType(); if (!vendorType.isVendorContractAllowedIndicator()) { String propertyName = "add." + collectionName + "." + VendorPropertyConstants.VENDOR_CONTRACT_NAME; putFieldError(propertyName, VendorKeyConstants.ERROR_VENDOR_CONTRACT_NOT_ALLOWED); return false; } } return super.processAddCollectionLineBusinessRules(document, collectionName, bo); } protected boolean checkVendorCommodityCode(VendorCommodityCode commodityCode) { String purchasingCommodityCode = commodityCode.getPurchasingCommodityCode(); CommodityCodeService commodityCodeService = SpringContext.getBean(CommodityCodeService.class); return ObjectUtils.isNotNull(commodityCodeService.getByPrimaryId(purchasingCommodityCode)); } }