/*
* 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));
}
}