001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.module.purap.document.validation.impl; 017 018 import java.math.BigDecimal; 019 import java.util.HashMap; 020 import java.util.Map; 021 022 import org.apache.commons.lang.StringUtils; 023 import org.kuali.kfs.module.purap.PurapKeyConstants; 024 import org.kuali.kfs.module.purap.PurapPropertyConstants; 025 import org.kuali.kfs.module.purap.PurapConstants.ItemFields; 026 import org.kuali.kfs.module.purap.PurapConstants.ItemTypeCodes; 027 import org.kuali.kfs.module.purap.businessobject.PurApItem; 028 import org.kuali.kfs.module.purap.businessobject.PurchasingItemBase; 029 import org.kuali.kfs.sys.KFSKeyConstants; 030 import org.kuali.kfs.sys.KFSPropertyConstants; 031 import org.kuali.kfs.sys.businessobject.UnitOfMeasure; 032 import org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent; 033 import org.kuali.kfs.vnd.businessobject.CommodityCode; 034 import org.kuali.rice.kns.service.BusinessObjectService; 035 import org.kuali.rice.kns.service.DataDictionaryService; 036 import org.kuali.rice.kns.util.GlobalVariables; 037 import org.kuali.rice.kns.util.ObjectUtils; 038 039 public class PurchasingAddItemValidation extends PurchasingAccountsPayableAddItemValidation { 040 041 private BusinessObjectService businessObjectService; 042 private DataDictionaryService dataDictionaryService; 043 044 public boolean validate(AttributedDocumentEvent event) { 045 boolean valid=true; 046 GlobalVariables.getMessageMap().addToErrorPath(PurapPropertyConstants.NEW_PURCHASING_ITEM_LINE); 047 //refresh itemType 048 PurApItem refreshedItem = getItemForValidation(); 049 refreshedItem.refreshReferenceObject("itemType"); 050 super.setItemForValidation(refreshedItem); 051 052 valid &= super.validate(event); 053 valid &= validateItemUnitPrice(getItemForValidation()); 054 valid &= validateUnitOfMeasure(getItemForValidation()); 055 if (getItemForValidation().getItemType().isLineItemIndicator()) { 056 valid &= validateItemDescription(getItemForValidation()); 057 valid &= validateItemQuantity(getItemForValidation()); 058 valid &= validateCommodityCodes(getItemForValidation(), commodityCodeIsRequired()); 059 } 060 GlobalVariables.getMessageMap().removeFromErrorPath(PurapPropertyConstants.NEW_PURCHASING_ITEM_LINE); 061 062 return valid; 063 } 064 065 /** 066 * Validates whether the commodity code existed on the item, and if existed, whether the 067 * commodity code on the item existed in the database, and if so, whether the commodity 068 * code is active. Display error if any of these 3 conditions are not met. 069 * 070 * @param item The PurApItem containing the commodity code to be validated. 071 * @return boolean false if the validation fails and true otherwise. 072 */ 073 protected boolean validateCommodityCodes(PurApItem item, boolean commodityCodeRequired) { 074 boolean valid = true; 075 String identifierString = item.getItemIdentifierString(); 076 PurchasingItemBase purItem = (PurchasingItemBase) item; 077 078 //This validation is only needed if the commodityCodeRequired system parameter is true 079 if (commodityCodeRequired && StringUtils.isBlank(purItem.getPurchasingCommodityCode()) ) { 080 //This is the case where the commodity code is required but the item does not currently contain the commodity code. 081 valid = false; 082 String attributeLabel = dataDictionaryService. 083 getDataDictionary().getBusinessObjectEntry(CommodityCode.class.getName()). 084 getAttributeDefinition(PurapPropertyConstants.ITEM_COMMODITY_CODE).getLabel(); 085 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_COMMODITY_CODE, KFSKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + identifierString); 086 } 087 else if (StringUtils.isNotBlank(purItem.getPurchasingCommodityCode())) { 088 //Find out whether the commodity code has existed in the database 089 Map<String,String> fieldValues = new HashMap<String, String>(); 090 fieldValues.put(PurapPropertyConstants.ITEM_COMMODITY_CODE, purItem.getPurchasingCommodityCode()); 091 if (businessObjectService.countMatching(CommodityCode.class, fieldValues) != 1) { 092 //This is the case where the commodity code on the item does not exist in the database. 093 valid = false; 094 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_COMMODITY_CODE, PurapKeyConstants.PUR_COMMODITY_CODE_INVALID, " in " + identifierString); 095 } 096 else { 097 valid &= validateThatCommodityCodeIsActive(item); 098 } 099 } 100 101 return valid; 102 } 103 104 /** 105 * Validates the unit price for all applicable item types. It validates that the unit price field was 106 * entered on the item, and that the price is in the right range for the item type. 107 * 108 * @param purDocument the purchasing document to be validated 109 * @return boolean false if there is any validation that fails. 110 */ 111 public boolean validateItemUnitPrice(PurApItem item) { 112 boolean valid = true; 113 if (item.getItemType().isLineItemIndicator()) { 114 if (ObjectUtils.isNull(item.getItemUnitPrice())) { 115 valid = false; 116 String attributeLabel = dataDictionaryService. 117 getDataDictionary().getBusinessObjectEntry(item.getClass().getName()). 118 getAttributeDefinition(PurapPropertyConstants.ITEM_UNIT_PRICE).getLabel(); 119 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_UNIT_PRICE, KFSKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + item.getItemIdentifierString()); 120 } 121 } 122 123 if (ObjectUtils.isNotNull(item.getItemUnitPrice())) { 124 if ((BigDecimal.ZERO.compareTo(item.getItemUnitPrice()) > 0) && ((!item.getItemTypeCode().equals(ItemTypeCodes.ITEM_TYPE_ORDER_DISCOUNT_CODE)) && (!item.getItemTypeCode().equals(ItemTypeCodes.ITEM_TYPE_TRADE_IN_CODE)))) { 125 // If the item type is not full order discount or trade in items, don't allow negative unit price. 126 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_UNIT_PRICE, PurapKeyConstants.ERROR_ITEM_AMOUNT_BELOW_ZERO, ItemFields.UNIT_COST, item.getItemIdentifierString()); 127 valid = false; 128 } 129 else if ((BigDecimal.ZERO.compareTo(item.getItemUnitPrice()) < 0) && ((item.getItemTypeCode().equals(ItemTypeCodes.ITEM_TYPE_ORDER_DISCOUNT_CODE)) || (item.getItemTypeCode().equals(ItemTypeCodes.ITEM_TYPE_TRADE_IN_CODE)))) { 130 // If the item type is full order discount or trade in items, its unit price must be negative. 131 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_UNIT_PRICE, PurapKeyConstants.ERROR_ITEM_AMOUNT_NOT_BELOW_ZERO, ItemFields.UNIT_COST, item.getItemIdentifierString()); 132 valid = false; 133 } 134 } 135 136 return valid; 137 } 138 139 /** 140 * Validates that if the item type is quantity based, the unit of measure is required. 141 * 142 * @param item the item to be validated 143 * @return boolean false if the item type is quantity based and the unit of measure is empty. 144 */ 145 public boolean validateUnitOfMeasure(PurApItem item) { 146 boolean valid = true; 147 PurchasingItemBase purItem = (PurchasingItemBase) item; 148 // Validations for quantity based item type 149 if (purItem.getItemType().isQuantityBasedGeneralLedgerIndicator()) { 150 String uomCode = purItem.getItemUnitOfMeasureCode(); 151 if (StringUtils.isEmpty(uomCode)) { 152 valid = false; 153 String attributeLabel = dataDictionaryService. 154 getDataDictionary().getBusinessObjectEntry(item.getClass().getName()). 155 getAttributeDefinition(KFSPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE). 156 getLabel(); 157 GlobalVariables.getMessageMap().putError(KFSPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, KFSKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + item.getItemIdentifierString()); 158 } 159 else { 160 //Find out whether the unit of measure code has existed in the database 161 Map<String,String> fieldValues = new HashMap<String, String>(); 162 fieldValues.put(KFSPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, purItem.getItemUnitOfMeasureCode()); 163 if (businessObjectService.countMatching(UnitOfMeasure.class, fieldValues) != 1) { 164 //This is the case where the unit of measure code on the item does not exist in the database. 165 valid = false; 166 GlobalVariables.getMessageMap().putError(KFSPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, PurapKeyConstants.PUR_ITEM_UNIT_OF_MEASURE_CODE_INVALID, " in " + item.getItemIdentifierString()); 167 } 168 } 169 } 170 171 return valid; 172 } 173 174 /** 175 * Checks that a description was entered for the item. 176 * 177 * @param item 178 * @return 179 */ 180 public boolean validateItemDescription(PurApItem item) { 181 boolean valid = true; 182 if (StringUtils.isEmpty(item.getItemDescription())) { 183 valid = false; 184 String attributeLabel = dataDictionaryService. 185 getDataDictionary().getBusinessObjectEntry(item.getClass().getName()). 186 getAttributeDefinition(PurapPropertyConstants.ITEM_DESCRIPTION).getLabel(); 187 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_DESCRIPTION, KFSKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + item.getItemIdentifierString()); 188 } 189 return valid; 190 } 191 192 /** 193 * Validates that if the item type is quantity based, the item quantity is required and if the item type is amount based, the 194 * quantity is not allowed. 195 * 196 * @param item the item to be validated 197 * @return boolean false if there's any validation that fails. 198 */ 199 public boolean validateItemQuantity(PurApItem item) { 200 boolean valid = true; 201 PurchasingItemBase purItem = (PurchasingItemBase) item; 202 if (purItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && (ObjectUtils.isNull(purItem.getItemQuantity()))) { 203 valid = false; 204 String attributeLabel = dataDictionaryService. 205 getDataDictionary().getBusinessObjectEntry(item.getClass().getName()). 206 getAttributeDefinition(PurapPropertyConstants.ITEM_QUANTITY).getLabel(); 207 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.QUANTITY, KFSKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + item.getItemIdentifierString()); 208 } 209 else if (purItem.getItemType().isAmountBasedGeneralLedgerIndicator() && ObjectUtils.isNotNull(purItem.getItemQuantity())) { 210 valid = false; 211 String attributeLabel = dataDictionaryService. 212 getDataDictionary().getBusinessObjectEntry(item.getClass().getName()). 213 getAttributeDefinition(PurapPropertyConstants.ITEM_QUANTITY).getLabel(); 214 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.QUANTITY, PurapKeyConstants.ERROR_ITEM_QUANTITY_NOT_ALLOWED, attributeLabel + " in " + item.getItemIdentifierString()); 215 } 216 217 return valid; 218 } 219 220 /** 221 * Predicate to do a parameter lookup and tell us whether a commodity code is required. 222 * Override in child classes. 223 * 224 * @return True if a commodity code is required. 225 */ 226 protected boolean commodityCodeIsRequired() { 227 return false; 228 } 229 230 protected boolean validateThatCommodityCodeIsActive(PurApItem item) { 231 if (!((PurchasingItemBase)item).getCommodityCode().isActive()) { 232 //This is the case where the commodity code on the item is not active. 233 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_COMMODITY_CODE, PurapKeyConstants.PUR_COMMODITY_CODE_INACTIVE, " in " + item.getItemIdentifierString()); 234 return false; 235 } 236 return true; 237 } 238 239 public BusinessObjectService getBusinessObjectService() { 240 return businessObjectService; 241 } 242 243 public void setBusinessObjectService(BusinessObjectService businessObjectService) { 244 this.businessObjectService = businessObjectService; 245 } 246 247 public DataDictionaryService getDataDictionaryService() { 248 return dataDictionaryService; 249 } 250 251 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) { 252 this.dataDictionaryService = dataDictionaryService; 253 } 254 255 }