View Javadoc
1   /*
2    * Copyright 2011 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.select.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.businessobject.LineItemReceivingItem;
21  import org.kuali.ole.module.purap.businessobject.PurapEnterableItem;
22  import org.kuali.ole.module.purap.businessobject.ReceivingItem;
23  import org.kuali.ole.module.purap.document.LineItemReceivingDocument;
24  import org.kuali.ole.module.purap.document.ReceivingDocument;
25  import org.kuali.ole.module.purap.document.validation.impl.LineItemReceivingDocumentRule;
26  import org.kuali.ole.select.OleSelectConstant;
27  import org.kuali.ole.select.businessobject.OleCopies;
28  import org.kuali.ole.select.businessobject.OleLineItemReceivingItem;
29  import org.kuali.ole.select.businessobject.OleLineItemReceivingReceiptNotes;
30  import org.kuali.ole.select.businessobject.OleReceivingItem;
31  import org.kuali.ole.select.document.OleLineItemReceivingDocument;
32  import org.kuali.ole.sys.OLEKeyConstants;
33  import org.kuali.rice.core.api.util.type.KualiDecimal;
34  import org.kuali.rice.krad.document.Document;
35  import org.kuali.rice.krad.util.GlobalVariables;
36  import org.kuali.rice.krad.util.ObjectUtils;
37  
38  import java.util.List;
39  
40  /**
41   * This class handles validation rules for OLE Line Item Receiving Document.
42   */
43  
44  public class OleLineItemReceivingDocumentRule extends LineItemReceivingDocumentRule {
45  
46      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OleLineItemReceivingDocumentRule.class);
47  
48      /**
49       * Overridden method to include validation for parts along with the existing validation
50       * for OLE Line Item Receiving Document.
51       *
52       * @param document
53       * @return If the document passed all validations
54       */
55      @Override
56      protected boolean processCustomRouteDocumentBusinessRules(Document document) {
57          LOG.debug("Inside processCustomRouteDocumentBusinessRules of OleLineItemReceivingDocumentRule");
58          boolean valid = true;
59  
60          LineItemReceivingDocument lineItemReceivingDocument = (LineItemReceivingDocument) document;
61          valid &= canCreateLineItemReceivingDocument(lineItemReceivingDocument);
62          valid &= isAtLeastOneItemEntered(lineItemReceivingDocument);
63          valid &= validateItemUnitOfMeasure(lineItemReceivingDocument);
64          //  makes sure all of the lines adhere to the rule that quantityDamaged and
65          // quantityReturned cannot (each) equal more than the quantityReceived
66          valid &= validateAllReceivingLinesHaveSaneQuantities(lineItemReceivingDocument);
67  
68          valid &= validateAllReceivingLinesHaveSaneParts(lineItemReceivingDocument);
69          //valid &= validateReceivedQuantityAndParts(lineItemReceivingDocument);
70          valid &= isExceptionNotesMandatory(lineItemReceivingDocument);
71          valid &= isAcknowledged(lineItemReceivingDocument);
72          valid &= validateItemDescriptionRequired(lineItemReceivingDocument);
73          /*
74           * valid &= checkForValidCopiesAndPartsForSubmit((OleLineItemReceivingDocument) lineItemReceivingDocument); valid &=
75           * validateCopies((OleLineItemReceivingDocument) lineItemReceivingDocument);
76           */
77          LOG.debug("Leaving processCustomRouteDocumentBusinessRules of OleLineItemReceivingDocumentRule");
78          return valid;
79      }
80  
81      /**
82       * Overridden method to include validation for parts along with the existing validation
83       * when adding a new line item in OLE Line Item Receiving Document.
84       *
85       * @param document
86       * @param item
87       * @param errorPathPrefix
88       * @return If the newly added item passed all validations
89       */
90      @Override
91      public boolean processAddReceivingItemRules(ReceivingDocument document, LineItemReceivingItem item, String errorPathPrefix) {
92          LOG.debug("Inside processAddReceivingItemRules of OleLineItemReceivingDocumentRule");
93          boolean valid = super.processAddReceivingItemRules(document, item, errorPathPrefix);
94  
95          valid &= validatePartsReturnedNotMoreThanReceived(document, item, errorPathPrefix, new Integer(0));
96          valid &= validatePartsDamagedNotMoreThanReceived(document, item, errorPathPrefix, new Integer(0));
97          LOG.debug("Leaving processAddReceivingItemRules of OleLineItemReceivingDocumentRule");
98          return valid;
99      }
100 
101     /**
102      * This method validates if parts returned is greater than parts received for a line item
103      * in OLE Line Item Receiving document and sets error accordingly.
104      *
105      * @param document
106      * @param item
107      * @param errorPathPrefix
108      * @param lineNumber
109      * @return boolean value (If the line item is valid or not)
110      */
111     protected boolean validatePartsReturnedNotMoreThanReceived(ReceivingDocument document, LineItemReceivingItem item, String errorPathPrefix, Integer lineNumber) {
112         LOG.debug("Inside validatePartsReturnedNotMoreThanReceived of OleLineItemReceivingDocumentRule");
113         OleLineItemReceivingItem oleItem = (OleLineItemReceivingItem) item;
114         if (oleItem.getItemReturnedTotalParts() != null && oleItem.getItemReceivedTotalParts() != null) {
115             if (oleItem.getItemReturnedTotalParts().isGreaterThan(oleItem.getItemReceivedTotalParts())) {
116                 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_PRTRETURNED_GT_PRTRECEIVED, (lineNumber.intValue() == 0 ? "Add Line" : lineNumber.toString()));
117                 return false;
118             }
119         }
120         LOG.debug("Leaving validatePartsReturnedNotMoreThanReceived of OleLineItemReceivingDocumentRule");
121         return true;
122     }
123 
124     /**
125      * This method validates if parts damaged is greater than parts received for a line item
126      * in OLE Line Item Receiving document and sets error accordingly.
127      *
128      * @param document
129      * @param item
130      * @param errorPathPrefix
131      * @param lineNumber
132      * @return boolean value (If the line item is valid or not)
133      */
134     protected boolean validatePartsDamagedNotMoreThanReceived(ReceivingDocument document, LineItemReceivingItem item, String errorPathPrefix, Integer lineNumber) {
135         LOG.debug("Inside validatePartsDamagedNotMoreThanReceived of OleLineItemReceivingDocumentRule");
136         OleLineItemReceivingItem oleItem = (OleLineItemReceivingItem) item;
137         if (oleItem.getItemDamagedTotalParts() != null && oleItem.getItemReceivedTotalParts() != null) {
138             if (oleItem.getItemDamagedTotalParts().isGreaterThan(oleItem.getItemReceivedTotalParts())) {
139                 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_PRTDAMAGED_GT_PRTRECEIVED, (lineNumber.intValue() == 0 ? "Add Line" : lineNumber.toString()));
140                 return false;
141             }
142         }
143         LOG.debug("Leaving validatePartsDamagedNotMoreThanReceived of OleLineItemReceivingDocumentRule");
144         return true;
145     }
146 
147     /**
148      * This method validates if parts returned/damaged is greater than parts received for a line item
149      * in OLE Line Item Receiving document
150      *
151      * @param document
152      * @return boolean value (If the line item is valid or not)
153      */
154     protected boolean validateAllReceivingLinesHaveSaneParts(ReceivingDocument document) {
155         LOG.debug("Inside validateAllReceivingLinesHaveSaneParts of OleLineItemReceivingDocumentRule");
156         GlobalVariables.getMessageMap().clearErrorPath();
157         boolean valid = true;
158         for (int i = 0; i < document.getItems().size(); i++) {
159             LineItemReceivingItem item = (LineItemReceivingItem) document.getItems().get(i);
160 
161             valid &= validatePartsReturnedNotMoreThanReceived(document, item, "", new Integer(i + 1));
162             valid &= validatePartsDamagedNotMoreThanReceived(document, item, "", new Integer(i + 1));
163         }
164         LOG.debug("Leaving validateAllReceivingLinesHaveSaneParts of OleLineItemReceivingDocumentRule");
165         return valid;
166     }
167 
168     /**
169      * This method validates if exception note is mandatory for the line item entered.
170      * Sets an error message accordingly.
171      *
172      * @param receivingDocument
173      * @return boolean
174      */
175     private boolean isExceptionNotesMandatory(LineItemReceivingDocument receivingDocument) {
176         LOG.debug("Inside isExceptionNotesMandatory of OleLineItemReceivingDocumentRule");
177         boolean isMandatory = false;
178         boolean isMandatoryAll = true;
179         for (OleLineItemReceivingItem item : (List<OleLineItemReceivingItem>) receivingDocument.getItems()) {
180             if (ObjectUtils.isNotNull(item.getItemDamagedTotalParts()) && ObjectUtils.isNotNull(item.getItemDamagedTotalQuantity()) && ObjectUtils.isNotNull(item.getItemReturnedTotalParts()) && ObjectUtils.isNotNull(item.getItemReturnedTotalQuantity())) {
181                 if ((item.getItemDamagedTotalParts().isNonZero() || item.getItemDamagedTotalQuantity().isNonZero() || item.getItemReturnedTotalParts().isNonZero() || item.getItemReturnedTotalQuantity().isNonZero()) && !item.getExceptionNoteList().isEmpty()) {
182                     isMandatory = true;
183                 } else if (item.getItemDamagedTotalParts().isZero() && item.getItemDamagedTotalQuantity().isZero() && item.getItemReturnedTotalParts().isZero() && item.getItemReturnedTotalQuantity().isZero()) {
184                     isMandatory = true;
185                 } else {
186                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_EXCEPTION_NOTE_MANDATORY);
187                     isMandatory = false;
188                 }
189                 isMandatoryAll &= isMandatory;
190             }
191         }
192 
193         return isMandatoryAll;
194     }
195 
196     /**
197      * This method validates if all Special Handling notes are acknowledged
198      * for the line item entered.
199      *
200      * @param receivingDocument
201      * @return boolean
202      */
203     protected boolean isAcknowledged(LineItemReceivingDocument receivingDocument) {
204         LOG.debug("Inside isAcknowledged of OleLineItemReceivingDocumentRule");
205         boolean isNotesAck = true;
206         for (OleLineItemReceivingItem item : (List<OleLineItemReceivingItem>) receivingDocument.getItems()) {
207             boolean ack = item.isConsideredEntered();
208             boolean isAck = false;
209             for (OleLineItemReceivingReceiptNotes notes : item.getSpecialHandlingNoteList()) {
210                 isAck = notes.isNotesAck();
211                 isNotesAck &= isAck;
212             }
213             if (ack & isNotesAck) {
214                 return true;
215             } else if (!ack) {
216                 return true;
217             }
218         }
219         GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_NOTACKNOWLEDGED);
220         return false;
221     }
222 
223     /**
224      * This method validates if exception note is mandatory for the line item entered.
225      * Sets an error message accordingly.
226      *
227      * @param receivingDocument
228      * @return boolean
229      */
230     private boolean validateReceivedQuantityAndParts(LineItemReceivingDocument receivingDocument) {
231         LOG.debug("Inside isExceptionNotesMandatory of OleLineItemReceivingDocumentRule");
232         boolean isNonZero = false;
233         boolean isNonZeroAll = true;
234         int index = 0;
235         for (OleLineItemReceivingItem item : (List<OleLineItemReceivingItem>) receivingDocument.getItems()) {
236             index += 1;
237             if (StringUtils.equalsIgnoreCase(item.getItemTypeCode(), PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE)) {
238                 if ((ObjectUtils.isNull(item.getItemReceivedTotalQuantity()) || item.getItemReceivedTotalQuantity().isZero()) && (ObjectUtils.isNull(item.getItemReceivedTotalParts()) || item.getItemReceivedTotalParts().isZero())) {
239                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_RECEIVED_TOTAL_QUANTITY_NON_ZERO_UNORDERED, String.valueOf(index));
240                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_RECEIVED_TOTAL_PARTS_NON_ZERO_UNORDERED, String.valueOf(index));
241                     isNonZero = false;
242                 } else if ((ObjectUtils.isNull(item.getItemReceivedTotalParts()) || item.getItemReceivedTotalParts().isZero()) && (ObjectUtils.isNotNull(item.getItemReceivedTotalQuantity()) && item.getItemReceivedTotalQuantity().isGreaterThan(KualiDecimal.ZERO))) {
243                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_RECEIVED_TOTAL_PARTS_NON_ZERO_UNORDERED, String.valueOf(index));
244                     isNonZero = false;
245                 } else if ((ObjectUtils.isNull(item.getItemReceivedTotalQuantity()) || item.getItemReceivedTotalQuantity().isZero()) && (ObjectUtils.isNotNull(item.getItemReceivedTotalParts()) && item.getItemReceivedTotalParts().isGreaterThan(KualiDecimal.ZERO))) {
246                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_RECEIVED_TOTAL_QUANTITY_NON_ZERO_UNORDERED, String.valueOf(index));
247                     isNonZero = false;
248                 } else {
249                     isNonZero = true;
250                 }
251                 isNonZeroAll &= isNonZero;
252             }
253         }
254         return isNonZeroAll;
255     }
256 
257     /**
258      * This method overrided to Add the Error Message separatly for Total Quantity Received and Total Parts Received
259      *
260      * @param receivingDocument
261      * @return
262      */
263     @Override
264     protected boolean isAtLeastOneItemEntered(ReceivingDocument receivingDocument) {
265 
266         if (LOG.isDebugEnabled()) {
267             LOG.debug("Inside isAtLeastOneItemEntered of LineItemReceivingDocumentRule");
268             LOG.debug("Number of Items :" + receivingDocument.getItems().size());
269         }
270 
271         LineItemReceivingDocument lineItemReceivingDocument = (LineItemReceivingDocument) receivingDocument;
272         boolean valid = false;
273         for (ReceivingItem items : (List<ReceivingItem>) receivingDocument.getItems()) {
274             if (StringUtils.equalsIgnoreCase(items.getItemTypeCode(), PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE)) {
275                 valid = true;
276                 break;
277             }
278         }
279         if (valid) {
280             validateReceivedQuantityAndParts(lineItemReceivingDocument);
281         } else {
282             for (ReceivingItem item : (List<ReceivingItem>) receivingDocument.getItems()) {
283                 if (((PurapEnterableItem) item).isConsideredEntered()) {
284                     // if any item is entered return true
285                     return true;
286                 }
287             }
288             boolean quantity = true;
289             boolean parts = true;
290             boolean noOfQuantity=true;
291             if (!valid) {
292                 valid = true;
293                 for (OleReceivingItem oleItem : (List<OleReceivingItem>) receivingDocument.getItems()) {
294 
295                     if ((ObjectUtils.isNull(oleItem.getItemReceivedTotalQuantity()) || oleItem.getItemReceivedTotalQuantity().isZero()) && (ObjectUtils.isNotNull(oleItem.getItemReceivedTotalParts()) && oleItem.getItemReceivedTotalParts().isGreaterThan(KualiDecimal.ZERO))) {
296                         quantity = false;
297                     } else if ((ObjectUtils.isNull(oleItem.getItemReceivedTotalParts()) || oleItem.getItemReceivedTotalParts().isZero()) && (ObjectUtils.isNotNull(oleItem.getItemReceivedTotalQuantity()) && oleItem.getItemReceivedTotalQuantity().isGreaterThan(KualiDecimal.ZERO))) {
298                         parts = false;
299                     }
300                     if((ObjectUtils.isNull(oleItem.getItemReceivedTotalQuantity()) || oleItem.getItemReceivedTotalQuantity().isZero())&&(ObjectUtils.isNull(oleItem.getItemReceivedTotalParts()) || oleItem.getItemReceivedTotalParts().isZero()))  {
301                         noOfQuantity=false;
302                     }
303                 }
304                 // if no items are entered return false
305                 if (!quantity) {
306                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_RECEIVED_TOTAL_QUANTITY_NON_ZERO_ORDERED);
307                     quantity = true;
308                 } else if (!parts) {
309                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_RECEIVED_TOTAL_PARTS_NON_ZERO_ORDERED);
310                     parts = true;
311                 }
312                 else if(!noOfQuantity){
313                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_ITEM_RECEIVED_TOTAL_QUANTITY);
314                 }
315                 /* else {
316                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_RECEIVED_TOTAL_QUANTITY_NON_ZERO_ORDERED);
317                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OLEKeyConstants.ERROR_RECEIVING_LINE_RECEIVED_TOTAL_PARTS_NON_ZERO_ORDERED)
318                 }*/
319 
320             }
321         }
322         return valid;
323     }
324 
325     private boolean validateItemDescriptionRequired(LineItemReceivingDocument receivingDocument) {
326         LOG.debug("Inside isExceptionNotesMandatory of OleLineItemReceivingDocumentRule");
327         boolean isNotNull = true;
328         int index = 0;
329         for (LineItemReceivingItem item : (List<LineItemReceivingItem>) receivingDocument.getItems()) {
330             index += 1;
331             if (StringUtils.equalsIgnoreCase(item.getItemTypeCode(), PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE) || StringUtils.equalsIgnoreCase(item.getItemTypeCode(), PurapConstants.ItemTypeCodes.ITEM_TYPE_ITEM_CODE)) {
332                 if (item.getItemDescription() == null || item.getItemDescription().trim().length() <= 0) {
333                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OleSelectConstant.ERROR_REQUIRED, new String("Item Line " + index));
334                     isNotNull = false;
335                 }
336             }
337         }
338         return isNotNull;
339     }
340 
341     public boolean processCustomLineItemReceivingDescriptionBusinessRules(Document document, OleLineItemReceivingItem lineItem) {
342         boolean validate = true;
343         if (lineItem.getItemDescription() == null || lineItem.getItemDescription().isEmpty()) {
344             GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, OleSelectConstant.ERROR_REQUIRED, new String[]{"Line Item"});
345             validate = false;
346         }
347         return validate;
348     }
349 
350     /**
351      * This method validates the copies entered for the line item
352      */
353     private boolean validateCopies(OleLineItemReceivingDocument receivingDocument) {
354         LOG.debug("Inside validateCopies of OleLineItemReceivingDocumentRule");
355         boolean isValid = true;
356         for (OleLineItemReceivingItem item : (List<OleLineItemReceivingItem>) receivingDocument.getItems()) {
357             KualiDecimal itemQuantity = item.getItemReceivedTotalQuantity();
358             KualiDecimal itemCopies = KualiDecimal.ZERO;
359             if (item.getCopies().size() > 0) {
360                 for (OleCopies copies : item.getCopies()) {
361                     itemCopies = itemCopies.add(copies.getItemCopies());
362                 }
363                 if (item.getItemReceivedTotalQuantity().isGreaterThan(new KualiDecimal(1))
364                         || item.getItemReceivedTotalParts().isGreaterThan(new KualiDecimal(1))) {
365                     if (!itemQuantity.equals(itemCopies)) {
366                         GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY,
367                                 OLEKeyConstants.ERROR_RECEIVING_LINE_TOTAL_COPIES_NOT_EQUAL_QUANITY);
368                         return false;
369                     }
370                 }
371             } else {
372                 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY,
373                         OLEKeyConstants.ERROR_ATLEAST_ONE_COPY_SHOULD_ADD_WHEN_TOTAL_RECEIVED_COPY_IS_GREATERTHAN_ZERO);
374                 return false;
375             }
376         }
377         return isValid;
378     }
379 
380     /**
381      * This method validates whether total copies and total parts are lessThan or equal to quantity to be received and parts to be
382      * received
383      *
384      * @param receivingDocument
385      * @return boolean
386      */
387     private boolean checkForValidCopiesAndPartsForSubmit(OleLineItemReceivingDocument receivingDocument) {
388         LOG.debug("Inside checkForValidCopiesAndPartsForSubmit of OleLineItemReceivingDocumentRule");
389         boolean isValid = true;
390         for (OleLineItemReceivingItem item : (List<OleLineItemReceivingItem>) receivingDocument.getItems()) {
391             if (null != item.getPurchaseOrderIdentifier()) {
392                 KualiDecimal itemTotalQuantity = item.getItemReceivedTotalQuantity();
393                 KualiDecimal itemTotalParts = item.getItemReceivedTotalParts();
394                 KualiDecimal itemQuantityToBeReceived = item.getItemReceivedToBeQuantity();
395                 KualiDecimal itemPartsToBeReceived = item.getItemReceivedToBeParts();
396                 if (!(itemTotalQuantity.isLessEqual(itemQuantityToBeReceived))
397                         && !(itemTotalParts.isLessEqual(itemPartsToBeReceived))) {
398                     GlobalVariables
399                             .getMessageMap()
400                             .putError(
401                                     PurapConstants.ITEM_TAB_ERROR_PROPERTY,
402                                     OLEKeyConstants.ERROR_TOTAL_COPIES_TOTAL_PARTS_SHOULDBE_LESSTHAN_OR_EQUALTO_QUANTITY_TOBE_RECEIVED_AND_PARTS_TOBE_RECEIVED);
403                     return false;
404                 }
405             }
406         }
407         return isValid;
408     }
409 }