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