View Javadoc
1   /*
2    * Copyright 2009 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.module.purap.document.validation.impl;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.ole.module.purap.PurapConstants.ItemFields;
20  import org.kuali.ole.module.purap.PurapConstants.ItemTypeCodes;
21  import org.kuali.ole.module.purap.PurapKeyConstants;
22  import org.kuali.ole.module.purap.PurapPropertyConstants;
23  import org.kuali.ole.module.purap.businessobject.PurApItem;
24  import org.kuali.ole.module.purap.businessobject.PurchasingItemBase;
25  import org.kuali.ole.sys.OLEKeyConstants;
26  import org.kuali.ole.sys.OLEPropertyConstants;
27  import org.kuali.ole.sys.businessobject.UnitOfMeasure;
28  import org.kuali.ole.sys.document.validation.event.AttributedDocumentEvent;
29  import org.kuali.ole.vnd.businessobject.CommodityCode;
30  import org.kuali.rice.kns.service.DataDictionaryService;
31  import org.kuali.rice.krad.service.BusinessObjectService;
32  import org.kuali.rice.krad.util.GlobalVariables;
33  import org.kuali.rice.krad.util.ObjectUtils;
34  
35  import java.math.BigDecimal;
36  import java.util.HashMap;
37  import java.util.Map;
38  
39  public class PurchasingAddItemValidation extends PurchasingAccountsPayableAddItemValidation {
40  
41      private BusinessObjectService businessObjectService;
42      private DataDictionaryService dataDictionaryService;
43  
44      @Override
45      public boolean validate(AttributedDocumentEvent event) {
46          boolean valid = true;
47          GlobalVariables.getMessageMap().addToErrorPath(PurapPropertyConstants.NEW_PURCHASING_ITEM_LINE);
48          //refresh itemType
49          PurApItem refreshedItem = getItemForValidation();
50          refreshedItem.refreshReferenceObject("itemType");
51          super.setItemForValidation(refreshedItem);
52  
53          valid &= super.validate(event);
54          valid &= validateItemUnitPrice(getItemForValidation());
55          valid &= validateUnitOfMeasure(getItemForValidation());
56          if (getItemForValidation().getItemType().isLineItemIndicator()) {
57              //valid &= validateItemDescription(getItemForValidation());
58              valid &= validateItemQuantity(getItemForValidation());
59              valid &= validateCommodityCodes(getItemForValidation(), commodityCodeIsRequired());
60          }
61          GlobalVariables.getMessageMap().removeFromErrorPath(PurapPropertyConstants.NEW_PURCHASING_ITEM_LINE);
62  
63          return valid;
64      }
65  
66      /**
67       * Validates whether the commodity code existed on the item, and if existed, whether the
68       * commodity code on the item existed in the database, and if so, whether the commodity
69       * code is active. Display error if any of these 3 conditions are not met.
70       *
71       * @param item The PurApItem containing the commodity code to be validated.
72       * @return boolean false if the validation fails and true otherwise.
73       */
74      protected boolean validateCommodityCodes(PurApItem item, boolean commodityCodeRequired) {
75          boolean valid = true;
76          String identifierString = item.getItemIdentifierString();
77          PurchasingItemBase purItem = (PurchasingItemBase) item;
78  
79          //This validation is only needed if the commodityCodeRequired system parameter is true
80          if (commodityCodeRequired && StringUtils.isBlank(purItem.getPurchasingCommodityCode())) {
81              //This is the case where the commodity code is required but the item does not currently contain the commodity code.
82              valid = false;
83              String attributeLabel = dataDictionaryService.
84                      getDataDictionary().getBusinessObjectEntry(CommodityCode.class.getName()).
85                      getAttributeDefinition(PurapPropertyConstants.ITEM_COMMODITY_CODE).getLabel();
86              GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_COMMODITY_CODE, OLEKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + identifierString);
87          } else if (StringUtils.isNotBlank(purItem.getPurchasingCommodityCode())) {
88              //Find out whether the commodity code has existed in the database
89              Map<String, String> fieldValues = new HashMap<String, String>();
90              fieldValues.put(PurapPropertyConstants.ITEM_COMMODITY_CODE, purItem.getPurchasingCommodityCode());
91              if (businessObjectService.countMatching(CommodityCode.class, fieldValues) != 1) {
92                  //This is the case where the commodity code on the item does not exist in the database.
93                  valid = false;
94                  GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_COMMODITY_CODE, PurapKeyConstants.PUR_COMMODITY_CODE_INVALID, " in " + identifierString);
95              } else {
96                  valid &= validateThatCommodityCodeIsActive(item);
97              }
98          }
99  
100         return valid;
101     }
102 
103     /**
104      * Validates the unit price for all applicable item types. It validates that the unit price field was
105      * entered on the item, and that the price is in the right range for the item type.
106      *
107      * @param purDocument the purchasing document to be validated
108      * @return boolean false if there is any validation that fails.
109      */
110     public boolean validateItemUnitPrice(PurApItem item) {
111         boolean valid = true;
112         if (item.getItemType().isLineItemIndicator()) {
113             if (ObjectUtils.isNull(item.getItemUnitPrice())) {
114                 valid = false;
115                 String attributeLabel = dataDictionaryService.
116                         getDataDictionary().getBusinessObjectEntry(item.getClass().getName()).
117                         getAttributeDefinition(PurapPropertyConstants.ITEM_UNIT_PRICE).getLabel();
118                 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_UNIT_PRICE, OLEKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + item.getItemIdentifierString());
119             }
120         }
121 
122         if (ObjectUtils.isNotNull(item.getItemUnitPrice())) {
123             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)))) {
124                 // If the item type is not full order discount or trade in items, don't allow negative unit price.
125                 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_UNIT_PRICE, PurapKeyConstants.ERROR_ITEM_AMOUNT_BELOW_ZERO, ItemFields.UNIT_COST, item.getItemIdentifierString());
126                 valid = false;
127             } 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)))) {
128                 // If the item type is full order discount or trade in items, its unit price must be negative.
129                 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_UNIT_PRICE, PurapKeyConstants.ERROR_ITEM_AMOUNT_NOT_BELOW_ZERO, ItemFields.UNIT_COST, item.getItemIdentifierString());
130                 valid = false;
131             }
132         }
133 
134         return valid;
135     }
136 
137     /**
138      * Validates that if the item type is quantity based, the unit of measure is required.
139      *
140      * @param item the item to be validated
141      * @return boolean false if the item type is quantity based and the unit of measure is empty.
142      */
143     public boolean validateUnitOfMeasure(PurApItem item) {
144         boolean valid = true;
145         PurchasingItemBase purItem = (PurchasingItemBase) item;
146         // Validations for quantity based item type
147         if (purItem.getItemType().isQuantityBasedGeneralLedgerIndicator()) {
148             String uomCode = purItem.getItemUnitOfMeasureCode();
149             if (StringUtils.isEmpty(uomCode)) {
150                 valid = false;
151                 String attributeLabel = dataDictionaryService.
152                         getDataDictionary().getBusinessObjectEntry(item.getClass().getName()).
153                         getAttributeDefinition(OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE).
154                         getLabel();
155                 GlobalVariables.getMessageMap().putError(OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, OLEKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + item.getItemIdentifierString());
156             } else {
157                 //Find out whether the unit of measure code has existed in the database
158                 Map<String, String> fieldValues = new HashMap<String, String>();
159                 fieldValues.put(OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, purItem.getItemUnitOfMeasureCode());
160                 if (businessObjectService.countMatching(UnitOfMeasure.class, fieldValues) != 1) {
161                     //This is the case where the unit of measure code on the item does not exist in the database.
162                     valid = false;
163                     GlobalVariables.getMessageMap().putError(OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, PurapKeyConstants.PUR_ITEM_UNIT_OF_MEASURE_CODE_INVALID, " in " + item.getItemIdentifierString());
164                 }
165             }
166         }
167 
168         // MSU Contribution OLEMI-5041 DTT-3371 OLECNTRB-955
169         // Validations for non-quantity based item type
170         if (purItem.getItemType().isAmountBasedGeneralLedgerIndicator()
171                 && StringUtils.isNotBlank(purItem.getItemUnitOfMeasureCode())) {
172             valid = false;
173             String attributeLabel = dataDictionaryService.getDataDictionary()
174                     .getBusinessObjectEntry(item.getClass().getName())
175                     .getAttributeDefinition(PurapPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE).getLabel();
176             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE,
177                     PurapKeyConstants.ERROR_ITEM_UOM_NOT_ALLOWED,
178                     attributeLabel + " in " + item.getItemIdentifierString());
179         }
180 
181         return valid;
182     }
183 
184     /**
185      * Checks that a description was entered for the item.
186      *
187      * @param item
188      * @return
189      */
190     public boolean validateItemDescription(PurApItem item) {
191         boolean valid = true;
192         if (StringUtils.isEmpty(item.getItemDescription())) {
193             valid = false;
194             String attributeLabel = dataDictionaryService.
195                     getDataDictionary().getBusinessObjectEntry(item.getClass().getName()).
196                     getAttributeDefinition(PurapPropertyConstants.ITEM_DESCRIPTION).getLabel();
197             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_DESCRIPTION, OLEKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + item.getItemIdentifierString());
198         }
199         return valid;
200     }
201 
202     /**
203      * Validates that if the item type is quantity based, the item quantity is required and if the item type is amount based, the
204      * quantity is not allowed.
205      *
206      * @param item the item to be validated
207      * @return boolean false if there's any validation that fails.
208      */
209     public boolean validateItemQuantity(PurApItem item) {
210         boolean valid = true;
211         PurchasingItemBase purItem = (PurchasingItemBase) item;
212         if (purItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && (ObjectUtils.isNull(purItem.getItemQuantity()))) {
213             valid = false;
214             String attributeLabel = dataDictionaryService.
215                     getDataDictionary().getBusinessObjectEntry(item.getClass().getName()).
216                     getAttributeDefinition(PurapPropertyConstants.ITEM_QUANTITY).getLabel();
217             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.QUANTITY, OLEKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + item.getItemIdentifierString());
218         } else if (purItem.getItemType().isAmountBasedGeneralLedgerIndicator() && ObjectUtils.isNotNull(purItem.getItemQuantity())) {
219             valid = false;
220             String attributeLabel = dataDictionaryService.
221                     getDataDictionary().getBusinessObjectEntry(item.getClass().getName()).
222                     getAttributeDefinition(PurapPropertyConstants.ITEM_QUANTITY).getLabel();
223             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.QUANTITY, PurapKeyConstants.ERROR_ITEM_QUANTITY_NOT_ALLOWED, attributeLabel + " in " + item.getItemIdentifierString());
224         }
225 
226         return valid;
227     }
228 
229     /**
230      * Predicate to do a parameter lookup and tell us whether a commodity code is required.
231      * Override in child classes.
232      *
233      * @return True if a commodity code is required.
234      */
235     protected boolean commodityCodeIsRequired() {
236         return false;
237     }
238 
239     protected boolean validateThatCommodityCodeIsActive(PurApItem item) {
240         if (!((PurchasingItemBase) item).getCommodityCode().isActive()) {
241             //This is the case where the commodity code on the item is not active.
242             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_COMMODITY_CODE, PurapKeyConstants.PUR_COMMODITY_CODE_INACTIVE, " in " + item.getItemIdentifierString());
243             return false;
244         }
245         return true;
246     }
247 
248     public BusinessObjectService getBusinessObjectService() {
249         return businessObjectService;
250     }
251 
252     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
253         this.businessObjectService = businessObjectService;
254     }
255 
256     public DataDictionaryService getDataDictionaryService() {
257         return dataDictionaryService;
258     }
259 
260     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
261         this.dataDictionaryService = dataDictionaryService;
262     }
263 
264 }