View Javadoc
1   /*
2    * Copyright 2008 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.PREQDocumentsStrings;
21  import org.kuali.ole.module.purap.PurapKeyConstants;
22  import org.kuali.ole.module.purap.PurapPropertyConstants;
23  import org.kuali.ole.module.purap.businessobject.LineItemReceivingItem;
24  import org.kuali.ole.module.purap.businessobject.PurapEnterableItem;
25  import org.kuali.ole.module.purap.businessobject.ReceivingItem;
26  import org.kuali.ole.module.purap.document.LineItemReceivingDocument;
27  import org.kuali.ole.module.purap.document.ReceivingDocument;
28  import org.kuali.ole.module.purap.document.service.ReceivingService;
29  import org.kuali.ole.module.purap.document.validation.AddReceivingItemRule;
30  import org.kuali.ole.module.purap.document.validation.ContinuePurapRule;
31  import org.kuali.ole.sys.OLEKeyConstants;
32  import org.kuali.ole.sys.OLEPropertyConstants;
33  import org.kuali.ole.sys.businessobject.UnitOfMeasure;
34  import org.kuali.ole.sys.context.SpringContext;
35  import org.kuali.rice.krad.document.Document;
36  import org.kuali.rice.krad.document.TransactionalDocument;
37  import org.kuali.rice.krad.rules.DocumentRuleBase;
38  import org.kuali.rice.krad.service.BusinessObjectService;
39  import org.kuali.rice.krad.service.DataDictionaryService;
40  import org.kuali.rice.krad.service.DictionaryValidationService;
41  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
42  import org.kuali.rice.krad.util.GlobalVariables;
43  import org.kuali.rice.krad.util.ObjectUtils;
44  
45  import java.util.HashMap;
46  import java.util.List;
47  import java.util.Map;
48  
49  public class LineItemReceivingDocumentRule extends DocumentRuleBase implements ContinuePurapRule, AddReceivingItemRule {
50  
51      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LineItemReceivingDocumentRule.class);
52  
53      @Override
54      protected boolean processCustomRouteDocumentBusinessRules(Document document) {
55          LOG.debug("Inside processCustomRouteDocumentBusinessRules of LineItemReceivingDocumentRule");
56          boolean valid = true;
57          LineItemReceivingDocument lineItemReceivingDocument = (LineItemReceivingDocument) document;
58          if (LOG.isDebugEnabled())
59              LOG.debug("LineItemReceivingDocument :" + lineItemReceivingDocument);
60  
61          GlobalVariables.getMessageMap().clearErrorPath();
62          GlobalVariables.getMessageMap().addToErrorPath(OLEPropertyConstants.DOCUMENT);
63  
64          valid &= super.processCustomRouteDocumentBusinessRules(document);
65          valid &= canCreateLineItemReceivingDocument(lineItemReceivingDocument);
66          valid &= isAtLeastOneItemEntered(lineItemReceivingDocument);
67          valid &= validateItemUnitOfMeasure(lineItemReceivingDocument);
68  
69          //  makes sure all of the lines adhere to the rule that quantityDamaged and 
70          // quantityReturned cannot (each) equal more than the quantityReceived
71          valid &= validateAllReceivingLinesHaveSaneQuantities(lineItemReceivingDocument);
72          if (LOG.isDebugEnabled())
73              LOG.debug("isValid from LineItemReceivingDocumentRule :" + valid);
74  
75          return valid;
76      }
77  
78      /**
79       * TODO: move this up
80       * This method...
81       *
82       * @param receivingDocument
83       * @return
84       */
85      protected boolean isAtLeastOneItemEntered(ReceivingDocument receivingDocument) {
86          if (LOG.isDebugEnabled()) {
87              LOG.debug("Inside isAtLeastOneItemEntered of LineItemReceivingDocumentRule");
88              LOG.debug("Number of Items :" + receivingDocument.getItems().size());
89          }
90          for (ReceivingItem item : (List<ReceivingItem>) receivingDocument.getItems()) {
91              if (((PurapEnterableItem) item).isConsideredEntered()) {
92                  //if any item is entered return true
93                  return true;
94              }
95          }
96          //if no items are entered return false
97          GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_RECEIVING_LINEITEM_REQUIRED);
98          return false;
99  
100     }
101 
102     public boolean processContinuePurapBusinessRules(TransactionalDocument document) {
103 
104         boolean valid = true;
105         LineItemReceivingDocument lineItemReceivingDocument = (LineItemReceivingDocument) document;
106 
107         GlobalVariables.getMessageMap().clearErrorPath();
108         GlobalVariables.getMessageMap().addToErrorPath(OLEPropertyConstants.DOCUMENT);
109 
110         valid &= hasRequiredFieldsForContinue(lineItemReceivingDocument);
111         //only do this if valid
112         if (valid) {
113             valid &= canCreateLineItemReceivingDocument(lineItemReceivingDocument);
114         }
115 
116         return valid;
117     }
118 
119     /**
120      * Make sure the required fields on the init screen are filled in.
121      *
122      * @param lineItemReceivingDocument
123      * @return
124      */
125     protected boolean hasRequiredFieldsForContinue(LineItemReceivingDocument lineItemReceivingDocument) {
126 
127         boolean valid = true;
128 
129         if (ObjectUtils.isNull(lineItemReceivingDocument.getPurchaseOrderIdentifier())) {
130             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.PURCHASE_ORDER_IDENTIFIER, OLEKeyConstants.ERROR_REQUIRED, PREQDocumentsStrings.PURCHASE_ORDER_ID);
131             valid &= false;
132         }
133 
134         if (ObjectUtils.isNull(lineItemReceivingDocument.getShipmentReceivedDate())) {
135             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.SHIPMENT_RECEIVED_DATE, OLEKeyConstants.ERROR_REQUIRED, PurapConstants.LineItemReceivingDocumentStrings.VENDOR_DATE);
136             valid &= false;
137         }
138 
139         return valid;
140     }
141 
142     /**
143      * Determines if it is valid to create a receiving line document.  Only one
144      * receiving line document can be active at any time per purchase order document.
145      *
146      * @param lineItemReceivingDocument
147      * @return
148      */
149     protected boolean canCreateLineItemReceivingDocument(LineItemReceivingDocument lineItemReceivingDocument) {
150 
151         boolean valid = true;
152 
153         if (SpringContext.getBean(ReceivingService.class).canCreateLineItemReceivingDocument(lineItemReceivingDocument.getPurchaseOrderIdentifier(), lineItemReceivingDocument.getDocumentNumber()) == false) {
154             valid &= false;
155             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.PURCHASE_ORDER_IDENTIFIER, PurapKeyConstants.ERROR_RECEIVING_LINE_DOCUMENT_ACTIVE_FOR_PO, lineItemReceivingDocument.getDocumentNumber(), lineItemReceivingDocument.getPurchaseOrderIdentifier().toString());
156         }
157 
158         return valid;
159     }
160 
161     /**
162      * Validates that if the item type is quantity based, the unit of measure is required.
163      */
164     protected boolean validateItemUnitOfMeasure(ReceivingDocument receivingDocument) {
165         boolean valid = true;
166         for (ReceivingItem item : (List<ReceivingItem>) receivingDocument.getItems()) {
167             // Validations for quantity based item type
168             if (item.getItemType().isQuantityBasedGeneralLedgerIndicator()) {
169                 String uomCode = item.getItemUnitOfMeasureCode();
170                 if (StringUtils.isEmpty(uomCode)) {
171                     valid = false;
172                     String attributeLabel = SpringContext.getBean(DataDictionaryService.class).getDataDictionary().getBusinessObjectEntry(item.getClass().getName()).getAttributeDefinition(OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE).getLabel();
173                     GlobalVariables.getMessageMap().putError(OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, OLEKeyConstants.ERROR_REQUIRED, attributeLabel + item.getItemUnitOfMeasureCode());
174                 } else {
175                     // Find out whether the unit of measure code has existed in the database
176                     Map<String, String> fieldValues = new HashMap<String, String>();
177                     fieldValues.put(OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, item.getItemUnitOfMeasureCode());
178                     if ((KRADServiceLocatorWeb.getLegacyDataAdapter().findMatching(UnitOfMeasure.class, fieldValues)).size() != 1) {
179                         // This is the case where the unit of measure code on the item does not exist in the database.
180                         valid = false;
181                         GlobalVariables.getMessageMap().putError(OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, PurapKeyConstants.PUR_ITEM_UNIT_OF_MEASURE_CODE_INVALID, item.getItemUnitOfMeasureCode());
182                     }
183                 }
184             }
185         }
186         return valid;
187     }
188 
189     /**
190      * @see org.kuali.ole.module.purap.document.validation.AddReceivingItemRule#processAddReceivingItemRules(org.kuali.ole.module.purap.document.ReceivingDocument, org.kuali.ole.module.purap.businessobject.ReceivingItem)
191      */
192     public boolean processAddReceivingItemRules(ReceivingDocument document, LineItemReceivingItem item, String errorPathPrefix) {
193         boolean valid = true;
194 
195         valid &= SpringContext.getBean(DictionaryValidationService.class).isBusinessObjectValid(item, errorPathPrefix);
196 
197         //  test that the amount entered in the QuantityReturned and/or QuantityDamaged fields dont 
198         // either equal more than the QuantityReceived.  In other words, you can only return or mark as 
199         // damaged those that are received.  It doesnt make sense to receive 2 but return 3.  
200         valid &= validateQuantityReturnedNotMoreThanReceived(document, item, errorPathPrefix, new Integer(0));
201         valid &= validateQuantityDamagedNotMoreThanReceived(document, item, errorPathPrefix, new Integer(0));
202 
203         return valid;
204     }
205 
206     protected boolean validateQuantityReturnedNotMoreThanReceived(ReceivingDocument document, LineItemReceivingItem item, String errorPathPrefix, Integer lineNumber) {
207         if (item.getItemReturnedTotalQuantity() != null && item.getItemReceivedTotalQuantity() != null) {
208             if (item.getItemReturnedTotalQuantity().isGreaterThan(item.getItemReceivedTotalQuantity())) {
209                 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_RECEIVING_LINE_QTYRETURNED_GT_QTYRECEIVED, (lineNumber.intValue() == 0 ? "Add Line" : lineNumber.toString()));
210                 return false;
211             }
212         }
213         return true;
214     }
215 
216     protected boolean validateQuantityDamagedNotMoreThanReceived(ReceivingDocument document, LineItemReceivingItem item, String errorPathPrefix, Integer lineNumber) {
217         if (item.getItemDamagedTotalQuantity() != null && item.getItemReceivedTotalQuantity() != null) {
218             if (item.getItemDamagedTotalQuantity().isGreaterThan(item.getItemReceivedTotalQuantity())) {
219                 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_RECEIVING_LINE_QTYDAMAGED_GT_QTYRECEIVED, (lineNumber.intValue() == 0 ? "Add Line" : lineNumber.toString()));
220                 return false;
221             }
222         }
223         return true;
224     }
225 
226     protected boolean validateAllReceivingLinesHaveSaneQuantities(ReceivingDocument document) {
227         GlobalVariables.getMessageMap().clearErrorPath();
228         boolean valid = true;
229         for (int i = 0; i < document.getItems().size(); i++) {
230             LineItemReceivingItem item = (LineItemReceivingItem) document.getItems().get(i);
231 
232             valid &= validateQuantityReturnedNotMoreThanReceived(document, item, "", new Integer(i + 1));
233             valid &= validateQuantityDamagedNotMoreThanReceived(document, item, "", new Integer(i + 1));
234         }
235         return valid;
236     }
237 
238 }