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;
20  import org.kuali.ole.module.purap.PurapConstants.ItemFields;
21  import org.kuali.ole.module.purap.PurapConstants.ItemTypeCodes;
22  import org.kuali.ole.module.purap.PurapKeyConstants;
23  import org.kuali.ole.module.purap.PurapPropertyConstants;
24  import org.kuali.ole.module.purap.businessobject.PurApItem;
25  import org.kuali.ole.module.purap.businessobject.PurchasingItemBase;
26  import org.kuali.ole.sys.OLEKeyConstants;
27  import org.kuali.ole.sys.OLEPropertyConstants;
28  import org.kuali.ole.sys.businessobject.UnitOfMeasure;
29  import org.kuali.ole.sys.document.validation.event.AttributedDocumentEvent;
30  import org.kuali.ole.vnd.businessobject.CommodityCode;
31  import org.kuali.rice.kns.service.DataDictionaryService;
32  import org.kuali.rice.krad.service.BusinessObjectService;
33  import org.kuali.rice.krad.util.GlobalVariables;
34  import org.kuali.rice.krad.util.ObjectUtils;
35  
36  import java.math.BigDecimal;
37  import java.util.HashMap;
38  import java.util.Map;
39  
40  public class PurchasingImportItemValidation extends PurchasingAccountsPayableImportItemValidation {
41  
42      private BusinessObjectService businessObjectService;
43      private DataDictionaryService dataDictionaryService;
44  
45      public boolean validate(AttributedDocumentEvent event) {
46          boolean valid = true;
47          valid &= super.validate(event);
48          GlobalVariables.getMessageMap().addToErrorPath(PurapConstants.ITEM_TAB_ERROR_PROPERTY);
49  
50          if (getItemForValidation().getItemType().isLineItemIndicator()) {
51              valid &= validateItemDescription(getItemForValidation());
52          }
53          valid &= validateItemUnitPrice(getItemForValidation());
54          valid &= validateUnitOfMeasureCodeExists(getItemForValidation());
55          valid &= validateCommodityCodes(getItemForValidation(), commodityCodeIsRequired());
56  
57          GlobalVariables.getMessageMap().removeFromErrorPath(PurapConstants.ITEM_TAB_ERROR_PROPERTY);
58          return valid;
59      }
60  
61      /**
62       * Validates whether the commodity code existed on the item, and if existed, whether the
63       * commodity code on the item existed in the database, and if so, whether the commodity
64       * code is active. Display error if any of these 3 conditions are not met.
65       *
66       * @param item The PurApItem containing the commodity code to be validated.
67       * @return boolean false if the validation fails and true otherwise.
68       */
69      protected boolean validateCommodityCodes(PurApItem item, boolean commodityCodeRequired) {
70          boolean valid = true;
71          String identifierString = item.getItemIdentifierString();
72          PurchasingItemBase purItem = (PurchasingItemBase) item;
73  
74          //This validation is only needed if the commodityCodeRequired system parameter is true
75          if (commodityCodeRequired && StringUtils.isBlank(purItem.getPurchasingCommodityCode())) {
76              //This is the case where the commodity code is required but the item does not currently contain the commodity code.
77              valid = false;
78              String attributeLabel = dataDictionaryService.
79                      getDataDictionary().getBusinessObjectEntry(CommodityCode.class.getName()).
80                      getAttributeDefinition(PurapPropertyConstants.ITEM_COMMODITY_CODE).getLabel();
81              GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_COMMODITY_CODE, OLEKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + identifierString);
82          } else if (StringUtils.isNotBlank(purItem.getPurchasingCommodityCode())) {
83              //Find out whether the commodity code has existed in the database
84              Map<String, String> fieldValues = new HashMap<String, String>();
85              fieldValues.put(PurapPropertyConstants.ITEM_COMMODITY_CODE, purItem.getPurchasingCommodityCode());
86              if (businessObjectService.countMatching(CommodityCode.class, fieldValues) != 1) {
87                  //This is the case where the commodity code on the item does not exist in the database.
88                  valid = false;
89                  GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_COMMODITY_CODE, PurapKeyConstants.PUR_COMMODITY_CODE_INVALID, " in " + identifierString);
90              } else {
91                  valid &= validateThatCommodityCodeIsActive(item);
92              }
93          }
94  
95          return valid;
96      }
97  
98      /**
99       * Checks that a description was entered for the item.
100      *
101      * @param item
102      * @return
103      */
104     public boolean validateItemDescription(PurApItem item) {
105         boolean valid = true;
106         if (StringUtils.isEmpty(item.getItemDescription())) {
107             valid = false;
108             String attributeLabel = dataDictionaryService.
109                     getDataDictionary().getBusinessObjectEntry(item.getClass().getName()).
110                     getAttributeDefinition(PurapPropertyConstants.ITEM_DESCRIPTION).getLabel();
111             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_DESCRIPTION, OLEKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + item.getItemIdentifierString());
112         }
113         return valid;
114     }
115 
116     /**
117      * Validates the unit price for all applicable item types. It validates that the unit price field was
118      * entered on the item, and that the price is in the right range for the item type.
119      *
120      * @param purDocument the purchasing document to be validated
121      * @return boolean false if there is any validation that fails.
122      */
123     public boolean validateItemUnitPrice(PurApItem item) {
124         boolean valid = true;
125         if (item.getItemType().isLineItemIndicator()) {
126             if (ObjectUtils.isNull(item.getItemUnitPrice())) {
127                 valid = false;
128                 String attributeLabel = dataDictionaryService.
129                         getDataDictionary().getBusinessObjectEntry(item.getClass().getName()).
130                         getAttributeDefinition(PurapPropertyConstants.ITEM_UNIT_PRICE).getLabel();
131                 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_UNIT_PRICE, OLEKeyConstants.ERROR_REQUIRED, attributeLabel + " in " + item.getItemIdentifierString());
132             }
133         }
134 
135         if (ObjectUtils.isNotNull(item.getItemUnitPrice())) {
136             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)))) {
137                 // If the item type is not full order discount or trade in items, don't allow negative unit price.
138                 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_UNIT_PRICE, PurapKeyConstants.ERROR_ITEM_AMOUNT_BELOW_ZERO, ItemFields.UNIT_COST, item.getItemIdentifierString());
139                 valid = false;
140             } 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)))) {
141                 // If the item type is full order discount or trade in items, its unit price must be negative.
142                 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_UNIT_PRICE, PurapKeyConstants.ERROR_ITEM_AMOUNT_NOT_BELOW_ZERO, ItemFields.UNIT_COST, item.getItemIdentifierString());
143                 valid = false;
144             }
145         }
146 
147         return valid;
148     }
149 
150     /**
151      * Validates that if the item type is quantity based, that the unit of measure code is valid.
152      * Looks for the UOM Code in the table. If it is not there, the code is invalid.
153      * This checking is needed only for imported items, since items added from new line could only
154      * choose an existing UOM from the drop-down list.
155      *
156      * @param item the item to be validated
157      * @return boolean false if the item type is quantity based and the unit of measure code is invalid.
158      */
159     protected boolean validateUnitOfMeasureCodeExists(PurApItem item) {
160         boolean valid = true;
161 
162         if (item.getItemType().isQuantityBasedGeneralLedgerIndicator()) {
163             String uomCode = item.getItemUnitOfMeasureCode();
164             Map<String, String> fieldValues = new HashMap<String, String>();
165             fieldValues.put(OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, uomCode);
166             if (businessObjectService.countMatching(UnitOfMeasure.class, fieldValues) != 1) {
167                 String[] errorParams = {uomCode, "" + item.getItemLineNumber()};
168                 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERRORS, PurapKeyConstants.ERROR_ITEMPARSER_INVALID_UOM_CODE, errorParams);
169                 valid = false;
170             }
171         }
172 
173         return valid;
174     }
175 
176     /**
177      * Predicate to do a parameter lookup and tell us whether a commodity code is required.
178      * Override in child classes.
179      *
180      * @return True if a commodity code is required.
181      */
182     protected boolean commodityCodeIsRequired() {
183         return false;
184     }
185 
186     protected boolean validateThatCommodityCodeIsActive(PurApItem item) {
187         if (!((PurchasingItemBase) item).getCommodityCode().isActive()) {
188             //This is the case where the commodity code on the item is not active.
189             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.ITEM_COMMODITY_CODE, PurapKeyConstants.PUR_COMMODITY_CODE_INACTIVE, " in " + item.getItemIdentifierString());
190             return false;
191         }
192         return true;
193     }
194 
195     public BusinessObjectService getBusinessObjectService() {
196         return businessObjectService;
197     }
198 
199     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
200         this.businessObjectService = businessObjectService;
201     }
202 
203     public DataDictionaryService getDataDictionaryService() {
204         return dataDictionaryService;
205     }
206 
207     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
208         this.dataDictionaryService = dataDictionaryService;
209     }
210 
211 }