001/* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.ole.select.document.validation.impl; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.ole.module.purap.PurapConstants; 020import org.kuali.ole.module.purap.businessobject.LineItemReceivingItem; 021import org.kuali.ole.module.purap.businessobject.PurapEnterableItem; 022import org.kuali.ole.module.purap.businessobject.ReceivingItem; 023import org.kuali.ole.module.purap.document.LineItemReceivingDocument; 024import org.kuali.ole.module.purap.document.ReceivingDocument; 025import org.kuali.ole.module.purap.document.validation.impl.LineItemReceivingDocumentRule; 026import org.kuali.ole.select.OleSelectConstant; 027import org.kuali.ole.select.businessobject.OleCopies; 028import org.kuali.ole.select.businessobject.OleLineItemReceivingItem; 029import org.kuali.ole.select.businessobject.OleLineItemReceivingReceiptNotes; 030import org.kuali.ole.select.businessobject.OleReceivingItem; 031import org.kuali.ole.select.document.OleLineItemReceivingDocument; 032import org.kuali.ole.sys.OLEKeyConstants; 033import org.kuali.rice.core.api.util.type.KualiDecimal; 034import org.kuali.rice.krad.document.Document; 035import org.kuali.rice.krad.util.GlobalVariables; 036import org.kuali.rice.krad.util.ObjectUtils; 037 038import java.util.List; 039 040/** 041 * This class handles validation rules for OLE Line Item Receiving Document. 042 */ 043 044public class OleLineItemReceivingDocumentRule extends LineItemReceivingDocumentRule { 045 046 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OleLineItemReceivingDocumentRule.class); 047 048 /** 049 * Overridden method to include validation for parts along with the existing validation 050 * for OLE Line Item Receiving Document. 051 * 052 * @param document 053 * @return If the document passed all validations 054 */ 055 @Override 056 protected boolean processCustomRouteDocumentBusinessRules(Document document) { 057 LOG.debug("Inside processCustomRouteDocumentBusinessRules of OleLineItemReceivingDocumentRule"); 058 boolean valid = true; 059 060 LineItemReceivingDocument lineItemReceivingDocument = (LineItemReceivingDocument) document; 061 valid &= canCreateLineItemReceivingDocument(lineItemReceivingDocument); 062 valid &= isAtLeastOneItemEntered(lineItemReceivingDocument); 063 valid &= validateItemUnitOfMeasure(lineItemReceivingDocument); 064 // makes sure all of the lines adhere to the rule that quantityDamaged and 065 // quantityReturned cannot (each) equal more than the quantityReceived 066 valid &= validateAllReceivingLinesHaveSaneQuantities(lineItemReceivingDocument); 067 068 valid &= validateAllReceivingLinesHaveSaneParts(lineItemReceivingDocument); 069 //valid &= validateReceivedQuantityAndParts(lineItemReceivingDocument); 070 valid &= isExceptionNotesMandatory(lineItemReceivingDocument); 071 valid &= isAcknowledged(lineItemReceivingDocument); 072 valid &= validateItemDescriptionRequired(lineItemReceivingDocument); 073 /* 074 * valid &= checkForValidCopiesAndPartsForSubmit((OleLineItemReceivingDocument) lineItemReceivingDocument); valid &= 075 * validateCopies((OleLineItemReceivingDocument) lineItemReceivingDocument); 076 */ 077 LOG.debug("Leaving processCustomRouteDocumentBusinessRules of OleLineItemReceivingDocumentRule"); 078 return valid; 079 } 080 081 /** 082 * Overridden method to include validation for parts along with the existing validation 083 * when adding a new line item in OLE Line Item Receiving Document. 084 * 085 * @param document 086 * @param item 087 * @param errorPathPrefix 088 * @return If the newly added item passed all validations 089 */ 090 @Override 091 public boolean processAddReceivingItemRules(ReceivingDocument document, LineItemReceivingItem item, String errorPathPrefix) { 092 LOG.debug("Inside processAddReceivingItemRules of OleLineItemReceivingDocumentRule"); 093 boolean valid = super.processAddReceivingItemRules(document, item, errorPathPrefix); 094 095 valid &= validatePartsReturnedNotMoreThanReceived(document, item, errorPathPrefix, new Integer(0)); 096 valid &= validatePartsDamagedNotMoreThanReceived(document, item, errorPathPrefix, new Integer(0)); 097 LOG.debug("Leaving processAddReceivingItemRules of OleLineItemReceivingDocumentRule"); 098 return valid; 099 } 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}