1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.kuali.ole.module.purap.document.validation.impl;
17  
18  import org.kuali.ole.module.purap.PurapConstants;
19  import org.kuali.ole.module.purap.PurapConstants.ItemFields;
20  import org.kuali.ole.module.purap.PurapKeyConstants;
21  import org.kuali.ole.module.purap.PurapParameterConstants;
22  import org.kuali.ole.module.purap.businessobject.InvoiceItem;
23  import org.kuali.ole.module.purap.businessobject.PurApAccountingLine;
24  import org.kuali.ole.module.purap.businessobject.PurApItem;
25  import org.kuali.ole.module.purap.document.InvoiceDocument;
26  import org.kuali.ole.module.purap.document.service.PurapService;
27  import org.kuali.ole.select.OleSelectConstant;
28  import org.kuali.ole.select.businessobject.OleInvoiceItem;
29  import org.kuali.ole.select.document.OleInvoiceDocument;
30  import org.kuali.ole.sys.OLEConstants;
31  import org.kuali.ole.sys.OLEKeyConstants;
32  import org.kuali.ole.sys.context.SpringContext;
33  import org.kuali.ole.sys.document.validation.GenericValidation;
34  import org.kuali.ole.sys.document.validation.Validation;
35  import org.kuali.ole.sys.document.validation.event.AttributedDocumentEvent;
36  import org.kuali.ole.sys.document.validation.impl.*;
37  import org.kuali.ole.sys.service.impl.OleParameterConstants;
38  import org.kuali.ole.vnd.businessobject.VendorCustomerNumber;
39  import org.kuali.rice.core.api.util.type.KualiDecimal;
40  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
41  import org.kuali.rice.krad.service.KRADServiceLocator;
42  import org.kuali.rice.krad.util.GlobalVariables;
43  import org.kuali.rice.krad.util.KRADConstants;
44  import org.kuali.rice.krad.util.ObjectUtils;
45  
46  import java.math.BigDecimal;
47  import java.util.ArrayList;
48  import java.util.HashMap;
49  import java.util.List;
50  import java.util.Map;
51  
52  public class InvoiceProcessItemValidation extends GenericValidation {
53  
54      private PurapService purapService;
55      private PurApItem itemForValidation;
56      private AttributedDocumentEvent event;
57      private CompositeValidation reviewAccountingLineValidation;
58      private InvoiceDocument invoiceDocument;
59      private PurApAccountingLine invoiceAccountingLine;
60  
61      @Override
62      public boolean validate(AttributedDocumentEvent event) {
63          boolean valid = true;
64          this.event = event;
65  
66          InvoiceDocument invoiceDocument = (InvoiceDocument) event.getDocument();
67          InvoiceItem invoiceItem = (InvoiceItem) itemForValidation;
68  
69          valid &= validateEachItem(invoiceDocument, invoiceItem);
70  
71          return valid;
72  
73      }
74  
75      
76  
77  
78  
79  
80  
81  
82      protected boolean validateEachItem(InvoiceDocument invoiceDocument, InvoiceItem item) {
83          boolean valid = true;
84          String identifierString = item.getItemIdentifierString();
85          valid &= validateItem(invoiceDocument, item, identifierString);
86          return valid;
87      }
88  
89      
90  
91  
92  
93  
94  
95  
96  
97  
98      public boolean validateItem(InvoiceDocument invoiceDocument, InvoiceItem item, String identifierString) {
99          boolean valid = true;
100         
101         if (!purapService.isFullDocumentEntryCompleted(invoiceDocument)) {
102             if (item.getItemType().isLineItemIndicator()) {
103                 valid &= validateAboveTheLineItems(item, identifierString, invoiceDocument.isReceivingDocumentRequiredIndicator());
104                 valid &= validatePOItem((OleInvoiceItem)item);
105             }
106             valid &= validateItemWithoutAccounts(item, identifierString);
107         }
108         
109         valid &= validateProrationType(invoiceDocument);
110         valid &= validateItemAccounts(invoiceDocument, item, identifierString);
111         return valid;
112     }
113 
114     private boolean validatePOItem (OleInvoiceItem invoiceItem) {
115         if (invoiceItem.getItemType().isQuantityBasedGeneralLedgerIndicator()) {
116             if(invoiceItem.getPoItemIdentifier() == null ||
117                     invoiceItem.getPoItemIdentifier().compareTo(new Integer(0)) == 0) {
118                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, OLEConstants.ITEM_WITHOUT_PO);
119                 return false;
120             }
121         }
122         return true;
123 
124     }
125 
126     protected boolean validateProrationType(InvoiceDocument invoiceDocument) {
127         boolean isValid = true;
128         OleInvoiceDocument document = (OleInvoiceDocument) invoiceDocument;
129         List<OleInvoiceItem> items = document.getItems();
130         boolean additionalItemPresent = false;
131         boolean canProrate = false;
132         KualiDecimal additionalCharge = KualiDecimal.ZERO;
133         KualiDecimal totalAmt = document.getInvoicedItemTotal() != null ?
134                 new KualiDecimal(document.getInvoicedItemTotal()) : KualiDecimal.ZERO;
135         for (OleInvoiceItem invoiceItem : items) {
136             if (invoiceItem.getItemType().isAdditionalChargeIndicator() && invoiceItem.getExtendedPrice() != null &&
137                     !invoiceItem.getExtendedPrice().isZero()) {
138                 additionalCharge = additionalCharge.add(invoiceItem.getExtendedPrice());
139                 additionalItemPresent  = true;
140             }
141             if (invoiceItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && invoiceItem.getItemUnitPrice().compareTo(BigDecimal.ZERO) != 0 ) {
142                 canProrate = true;
143             }
144         }
145         if (additionalItemPresent && ((document.getProrateBy() == null) ||
146                 (!document.isProrateDollar() && !document.isProrateManual() && !document.isProrateQty() && !document.isNoProrate()))) {
147             GlobalVariables.getMessageMap().putErrorForSectionId(OleSelectConstant.INVOICE_ADDITIONAL_ITEM_SECTION_ID,
148                     OLEKeyConstants.ERROR_REQUIRED, PurapConstants.PRQSDocumentsStrings.PRORATION_TYPE);
149             isValid &= false;
150 
151         }
152         if ((totalAmt.isZero() || !canProrate) && document.isProrateDollar() ) {
153             GlobalVariables.getMessageMap().putError(OleSelectConstant.INVOICE_ADDITIONAL_CHARGE_SECTION_ID,
154                     OLEKeyConstants.ERROR_PRORATE_DOLLAR_ZERO_ITEM_TOTAL);
155         }
156         if (document.getVendorCustomerNumber() != null && !document.getVendorCustomerNumber().equalsIgnoreCase("")) {
157             Map<String, String> map = new HashMap<String, String>();
158             if (document.getVendorCustomerNumber() != null && !document.getVendorCustomerNumber().equalsIgnoreCase("")) {
159                 map.put(OLEConstants.VENDOR_CUSTOMER_NUMBER, document.getVendorCustomerNumber());
160             }
161             if (document.getVendorHeaderGeneratedIdentifier() != null && !document.getVendorHeaderGeneratedIdentifier().toString().equalsIgnoreCase("")) {
162                 map.put(OLEConstants.VENDOR_HEADER_IDENTIFIER, document.getVendorHeaderGeneratedIdentifier().toString());
163             }
164             if (document.getVendorDetailAssignedIdentifier() != null && !document.getVendorDetailAssignedIdentifier().toString().equalsIgnoreCase("")) {
165                 map.put(OLEConstants.VENDOR_DETAIL_IDENTIFIER, document.getVendorDetailAssignedIdentifier().toString());
166             }
167             List<VendorCustomerNumber> vendorCustomerNumbers = (List<VendorCustomerNumber>) KRADServiceLocator.getBusinessObjectService().findMatching(VendorCustomerNumber.class, map);
168             if (!(vendorCustomerNumbers != null && vendorCustomerNumbers.size() > 0)) {
169                 isValid &= false;
170                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, OLEConstants.INVALID_ACQUISITION_NUMBER);
171             }
172         }
173        
174 
175 
176 
177 
178         return isValid;
179     }
180     
181 
182 
183 
184 
185 
186 
187     protected boolean validateAboveTheLineItems(InvoiceItem item, String identifierString, boolean isReceivingDocumentRequiredIndicator) {
188         boolean valid = true;
189         
190         
191         if (ObjectUtils.isNotNull(item.getItemQuantity())) {
192             
193 
194 
195 
196 
197             if (!isReceivingDocumentRequiredIndicator) {
198                 
199 
200 
201 
202             }
203         }
204         
205         if (ObjectUtils.isNotNull(item.getExtendedPrice()) && item.getExtendedPrice().isPositive()) {
206 
207             
208             if (ObjectUtils.isNull(item.getItemQuantity()) || item.getItemQuantity().isZero()) {
209                 
210                 
211                 valid = false;
212                 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_ITEM_QUANTITY_REQUIRED, ItemFields.INVOICE_QUANTITY, identifierString, ItemFields.OPEN_QUANTITY);
213             }
214         }
215 
216         
217         if ((ObjectUtils.isNull(item.getInvoice().getPurapDocumentIdentifier())) || (PurapConstants.InvoiceStatuses.APPDOC_IN_PROCESS.equals(item.getInvoice().getApplicationDocumentStatus()))) {
218 
219             if ((item.getItemType().isAmountBasedGeneralLedgerIndicator()) && ((item.getExtendedPrice() != null) && item.getExtendedPrice().isNonZero())) {
220                 if (item.getPoOutstandingAmount() == null || item.getPoOutstandingAmount().isZero()) {
221                     valid = false;
222                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_ITEM_AMOUNT_ALREADY_PAID, identifierString);
223                 }
224             }
225         }
226 
227         return valid;
228     }
229 
230     
231 
232 
233 
234 
235 
236     public boolean validateItemWithoutAccounts(InvoiceItem item, String identifierString) {
237         boolean valid = true;
238         if (ObjectUtils.isNotNull(item.getItemUnitPrice()) && (new KualiDecimal(item.getItemUnitPrice())).isNonZero() && item.isAccountListEmpty()) {
239             valid = false;
240             GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_ITEM_ACCOUNTING_INCOMPLETE, identifierString);
241         }
242         return valid;
243     }
244 
245     
246 
247 
248 
249 
250 
251 
252 
253 
254     public boolean validateItemAccounts(InvoiceDocument invoiceDocument, InvoiceItem item, String identifierString) {
255         boolean valid = true;
256         List<PurApAccountingLine> accountingLines = item.getSourceAccountingLines();
257         KualiDecimal itemTotal = item.getTotalAmount();
258         KualiDecimal accountTotal = KualiDecimal.ZERO;
259         KualiDecimal prorateSurcharge = KualiDecimal.ZERO;
260         OleInvoiceItem invoiceItem = (OleInvoiceItem) item;
261         if (invoiceItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && invoiceItem.getExtendedPrice() != null && invoiceItem.getExtendedPrice().compareTo(KualiDecimal.ZERO) != 0) {
262             if (invoiceItem.getItemSurcharge() != null && invoiceItem.getItemTypeCode().equals("ITEM")) {
263                 prorateSurcharge = new KualiDecimal(invoiceItem.getItemSurcharge()).multiply(invoiceItem.getItemQuantity());
264             }
265             itemTotal = itemTotal.subtract(prorateSurcharge);
266         }
267         for (PurApAccountingLine accountingLine : accountingLines) {
268             if (accountingLine.getAmount().isZero()) {
269                 if (!canApproveAccountingLinesWithZeroAmount()) {
270                     GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_ITEM_ACCOUNTING_AMOUNT_INVALID, itemForValidation.getItemIdentifierString());
271                     valid &= false;
272                 }
273             }
274             valid &= reviewAccountingLineValidation(invoiceDocument, accountingLine);
275             accountTotal = accountTotal.add(accountingLine.getAmount());
276         }
277         if (purapService.isFullDocumentEntryCompleted(invoiceDocument)) {
278             
279             if (accountTotal.compareTo(itemTotal) != 0) {
280                 valid = false;
281                 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_ITEM_ACCOUNTING_AMOUNT_TOTAL, identifierString);
282             }
283         }
284         return valid;
285     }
286 
287     public CompositeValidation getReviewAccountingLineValidation() {
288         return reviewAccountingLineValidation;
289     }
290 
291     public void setReviewAccountingLineValidation(CompositeValidation reviewAccountingLineValidation) {
292         this.reviewAccountingLineValidation = reviewAccountingLineValidation;
293     }
294 
295     public PurapService getPurapService() {
296         return purapService;
297     }
298 
299     public void setPurapService(PurapService purapService) {
300         this.purapService = purapService;
301     }
302 
303     public PurApItem getItemForValidation() {
304         return itemForValidation;
305     }
306 
307     public void setItemForValidation(PurApItem itemForValidation) {
308         this.itemForValidation = itemForValidation;
309     }
310 
311     protected boolean reviewAccountingLineValidation(InvoiceDocument document, PurApAccountingLine accountingLine) {
312         boolean valid = true;
313         List<Validation> gauntlet = new ArrayList<Validation>();
314         this.invoiceDocument = document;
315         this.invoiceAccountingLine = accountingLine;
316 
317         createGauntlet(reviewAccountingLineValidation);
318 
319         for (Validation validation : gauntlet) {
320             valid &= validation.validate(event);
321         }
322 
323         return valid;
324     }
325 
326     protected void createGauntlet(CompositeValidation validation) {
327         for (Validation val : validation.getValidations()) {
328             if (val instanceof CompositeValidation) {
329                 createGauntlet((CompositeValidation) val);
330             } else if (val instanceof BusinessObjectDataDictionaryValidation) {
331                 addParametersToValidation((BusinessObjectDataDictionaryValidation) val);
332             } else if (val instanceof AccountingLineAmountPositiveValidation) {
333                 
334             } else if (val instanceof AccountingLineDataDictionaryValidation) {
335                 addParametersToValidation((AccountingLineDataDictionaryValidation) val);
336             } else if (val instanceof AccountingLineValuesAllowedValidationHutch) {
337                 addParametersToValidation((AccountingLineValuesAllowedValidationHutch) val);
338             } else {
339                 throw new IllegalStateException("Validations in the InvoiceProcessItemValidation must contain specific instances of validation");
340             }
341         }
342     }
343 
344     
345 
346 
347 
348 
349 
350 
351     public boolean canApproveAccountingLinesWithZeroAmount() {
352         boolean canApproveLine = false;
353 
354         
355         String approveZeroAmountLine = SpringContext.getBean(ParameterService.class).getParameterValueAsString(OleParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.APPROVE_ACCOUNTING_LINES_WITH_ZERO_DOLLAR_AMOUNT_IND);
356 
357         if ("Y".equalsIgnoreCase(approveZeroAmountLine)) {
358             return true;
359         }
360 
361         return canApproveLine;
362     }
363 
364     protected void addParametersToValidation(BusinessObjectDataDictionaryValidation validation) {
365         validation.setBusinessObjectForValidation(this.invoiceAccountingLine);
366     }
367 
368     protected void addParametersToValidation(AccountingLineAmountPositiveValidation validation) {
369         validation.setAccountingDocumentForValidation(this.invoiceDocument);
370         validation.setAccountingLineForValidation(this.invoiceAccountingLine);
371     }
372 
373     protected void addParametersToValidation(AccountingLineDataDictionaryValidation validation) {
374         validation.setAccountingLineForValidation(this.invoiceAccountingLine);
375     }
376 
377     protected void addParametersToValidation(AccountingLineValuesAllowedValidationHutch validation) {
378         validation.setAccountingDocumentForValidation(this.invoiceDocument);
379         validation.setAccountingLineForValidation(this.invoiceAccountingLine);
380     }
381 
382     
383 
384 
385 
386 
387     protected AttributedDocumentEvent getEvent() {
388         return event;
389     }
390 
391     
392 
393 
394 
395 
396     protected void setEvent(AttributedDocumentEvent event) {
397         this.event = event;
398     }
399 
400     
401 
402 
403 
404 
405     protected InvoiceDocument getPreqDocument() {
406         return invoiceDocument;
407     }
408 
409     
410 
411 
412 
413 
414     protected void setPreqDocument(InvoiceDocument invoiceDocument) {
415         this.invoiceDocument = invoiceDocument;
416     }
417 
418     
419 
420 
421 
422 
423     protected PurApAccountingLine getPreqAccountingLine() {
424         return invoiceAccountingLine;
425     }
426 
427     
428 
429 
430 
431 
432     protected void setPreqAccountingLine(PurApAccountingLine invoiceAccountingLine) {
433         this.invoiceAccountingLine = invoiceAccountingLine;
434     }
435 
436 }