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.service.impl;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.joda.time.DateTime;
20  import org.kuali.ole.module.purap.PurapConstants;
21  import org.kuali.ole.module.purap.PurapConstants.PurchaseOrderDocTypes;
22  import org.kuali.ole.module.purap.PurapConstants.PurchaseOrderStatuses;
23  import org.kuali.ole.module.purap.PurapKeyConstants;
24  import org.kuali.ole.module.purap.PurapParameterConstants;
25  import org.kuali.ole.module.purap.businessobject.*;
26  import org.kuali.ole.module.purap.document.*;
27  import org.kuali.ole.module.purap.document.dataaccess.ReceivingDao;
28  import org.kuali.ole.module.purap.document.service.LogicContainer;
29  import org.kuali.ole.module.purap.document.service.PurapService;
30  import org.kuali.ole.module.purap.document.service.PurchaseOrderService;
31  import org.kuali.ole.module.purap.document.service.ReceivingService;
32  import org.kuali.ole.module.purap.document.validation.event.AttributedContinuePurapEvent;
33  import org.kuali.ole.select.businessobject.*;
34  import org.kuali.ole.select.document.service.OleSelectDocumentService;
35  import org.kuali.ole.sys.OLEConstants;
36  import org.kuali.ole.sys.context.SpringContext;
37  import org.kuali.ole.sys.service.GeneralLedgerPendingEntryService;
38  import org.kuali.rice.core.api.config.property.ConfigurationService;
39  import org.kuali.rice.core.api.util.type.KualiDecimal;
40  import org.kuali.rice.core.api.util.type.KualiInteger;
41  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
42  import org.kuali.rice.kew.api.KewApiServiceLocator;
43  import org.kuali.rice.kew.api.WorkflowDocument;
44  import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
45  import org.kuali.rice.kew.api.document.search.DocumentSearchResult;
46  import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
47  import org.kuali.rice.kew.api.exception.WorkflowException;
48  import org.kuali.rice.krad.bo.AdHocRoutePerson;
49  import org.kuali.rice.krad.bo.Note;
50  import org.kuali.rice.krad.document.Document;
51  import org.kuali.rice.krad.service.BusinessObjectService;
52  import org.kuali.rice.krad.service.DocumentService;
53  import org.kuali.rice.krad.service.NoteService;
54  import org.kuali.rice.krad.util.GlobalVariables;
55  import org.kuali.rice.krad.util.ObjectUtils;
56  import org.kuali.rice.krad.workflow.service.WorkflowDocumentService;
57  import org.springframework.transaction.annotation.Transactional;
58  
59  import java.math.BigDecimal;
60  import java.text.MessageFormat;
61  import java.util.ArrayList;
62  import java.util.HashMap;
63  import java.util.List;
64  import java.util.Map;
65  
66  @Transactional
67  public class ReceivingServiceImpl implements ReceivingService {
68      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ReceivingServiceImpl.class);
69  
70      protected PurchaseOrderService purchaseOrderService;
71      protected ReceivingDao receivingDao;
72      protected DocumentService documentService;
73      protected WorkflowDocumentService workflowDocumentService;
74      protected ConfigurationService configurationService;
75      protected PurapService purapService;
76      protected NoteService noteService;
77      private OleSelectDocumentService oleSelectDocumentService;
78  
79      public void setPurchaseOrderService(PurchaseOrderService purchaseOrderService) {
80          this.purchaseOrderService = purchaseOrderService;
81      }
82  
83      public void setReceivingDao(ReceivingDao receivingDao) {
84          this.receivingDao = receivingDao;
85      }
86  
87      public void setDocumentService(DocumentService documentService) {
88          this.documentService = documentService;
89      }
90  
91      public void setWorkflowDocumentService(WorkflowDocumentService workflowDocumentService) {
92          this.workflowDocumentService = workflowDocumentService;
93      }
94  
95      public void setConfigurationService(ConfigurationService configurationService) {
96          this.configurationService = configurationService;
97      }
98  
99      public void setPurapService(PurapService purapService) {
100         this.purapService = purapService;
101     }
102 
103     public void setNoteService(NoteService noteService) {
104         this.noteService = noteService;
105     }
106 
107     /**
108      * @see org.kuali.ole.module.purap.document.service.ReceivingService#populateReceivingLineFromPurchaseOrder(org.kuali.ole.module.purap.document.LineItemReceivingDocument)
109      */
110     @Override
111     public void populateReceivingLineFromPurchaseOrder(LineItemReceivingDocument rlDoc) {
112 
113         if (rlDoc == null) {
114             rlDoc = new LineItemReceivingDocument();
115         }
116 
117         //retrieve po by doc id
118         PurchaseOrderDocument poDoc = null;
119         poDoc = purchaseOrderService.getCurrentPurchaseOrder(rlDoc.getPurchaseOrderIdentifier());
120 
121         if (poDoc != null) {
122             rlDoc.populateReceivingLineFromPurchaseOrder(poDoc);
123         }
124 
125     }
126 
127     @Override
128     public void populateCorrectionReceivingFromReceivingLine(CorrectionReceivingDocument rcDoc) {
129 
130         if (rcDoc == null) {
131             rcDoc = new CorrectionReceivingDocument();
132         }
133 
134         //retrieve receiving line by doc id
135         LineItemReceivingDocument rlDoc = rcDoc.getLineItemReceivingDocument();
136 
137         if (rlDoc != null) {
138             rcDoc.populateCorrectionReceivingFromReceivingLine(rlDoc);
139         }
140 
141     }
142 
143     /**
144      * @see org.kuali.ole.module.purap.document.service.ReceivingService#populateAndSaveLineItemReceivingDocument(org.kuali.ole.module.purap.document.LineItemReceivingDocument)
145      */
146     @Override
147     public void populateAndSaveLineItemReceivingDocument(LineItemReceivingDocument rlDoc) throws WorkflowException {
148         try {
149             documentService.saveDocument(rlDoc, AttributedContinuePurapEvent.class);
150         } catch (WorkflowException we) {
151             String errorMsg = "Error saving document # " + rlDoc.getDocumentHeader().getDocumentNumber() + " " + we.getMessage();
152             //LOG.error(errorMsg, we);
153             throw new RuntimeException(errorMsg, we);
154         }
155     }
156 
157     /**
158      * @see org.kuali.ole.module.purap.document.service.ReceivingService#populateCorrectionReceivingDocument(org.kuali.ole.module.purap.document.CorrectionReceivingDocument)
159      */
160     @Override
161     public void populateCorrectionReceivingDocument(CorrectionReceivingDocument rcDoc) {
162         populateCorrectionReceivingFromReceivingLine(rcDoc);
163     }
164 
165     /**
166      * @see org.kuali.ole.module.purap.document.service.ReceivingService#canCreateLineItemReceivingDocument(java.lang.Integer, java.lang.String)
167      */
168     @Override
169     public boolean canCreateLineItemReceivingDocument(Integer poId, String receivingDocumentNumber) throws RuntimeException {
170 
171         PurchaseOrderDocument po = purchaseOrderService.getCurrentPurchaseOrder(poId);
172 
173         return canCreateLineItemReceivingDocument(po, receivingDocumentNumber);
174     }
175 
176     /**
177      * @see org.kuali.ole.module.purap.document.service.ReceivingService#canCreateLineItemReceivingDocument(org.kuali.ole.module.purap.document.PurchaseOrderDocument)
178      */
179     @Override
180     public boolean canCreateLineItemReceivingDocument(PurchaseOrderDocument po) throws RuntimeException {
181         return canCreateLineItemReceivingDocument(po, null);
182     }
183 
184     public boolean canCreateLineItemReceivingDocument(PurchaseOrderDocument po, String receivingDocumentNumber) {
185         boolean canCreate = false;
186 
187         if (isPurchaseOrderValidForLineItemReceivingDocumentCreation(po) &&
188                 !isLineItemReceivingDocumentInProcessForPurchaseOrder(po.getPurapDocumentIdentifier(), receivingDocumentNumber) &&
189                 !isCorrectionReceivingDocumentInProcessForPurchaseOrder(po.getPurapDocumentIdentifier(), null)) {
190             canCreate = true;
191         }
192 
193         return canCreate;
194     }
195 
196     @Override
197     public boolean isPurchaseOrderActiveForLineItemReceivingDocumentCreation(Integer poId) {
198         PurchaseOrderDocument po = purchaseOrderService.getCurrentPurchaseOrder(poId);
199         return isPurchaseOrderValidForLineItemReceivingDocumentCreation(po);
200     }
201 
202     protected boolean isPurchaseOrderValidForLineItemReceivingDocumentCreation(PurchaseOrderDocument po) {
203         return po != null &&
204                 ObjectUtils.isNotNull(po.getPurapDocumentIdentifier()) &&
205                 po.isPurchaseOrderCurrentIndicator() &&
206                 (PurchaseOrderStatuses.APPDOC_OPEN.equals(po.getApplicationDocumentStatus()) ||
207                         PurchaseOrderStatuses.APPDOC_CLOSED.equals(po.getApplicationDocumentStatus()) ||
208                         PurchaseOrderStatuses.APPDOC_PAYMENT_HOLD.equals(po.getApplicationDocumentStatus()));
209     }
210 
211     @Override
212     public boolean canCreateCorrectionReceivingDocument(LineItemReceivingDocument rl) throws RuntimeException {
213         return canCreateCorrectionReceivingDocument(rl, null);
214     }
215 
216     @Override
217     public boolean canCreateCorrectionReceivingDocument(LineItemReceivingDocument rl, String receivingCorrectionDocNumber) throws RuntimeException {
218 
219         boolean canCreate = false;
220         WorkflowDocument workflowDocument = null;
221 
222         try {
223             workflowDocument = workflowDocumentService.loadWorkflowDocument(rl.getDocumentNumber(), GlobalVariables.getUserSession().getPerson());
224         } catch (WorkflowException we) {
225             throw new RuntimeException(we);
226         }
227 
228         if (workflowDocument.isFinal() &&
229                 !isCorrectionReceivingDocumentInProcessForReceivingLine(rl.getDocumentNumber(), receivingCorrectionDocNumber)) {
230             canCreate = true;
231         }
232 
233         return canCreate;
234     }
235 
236     protected boolean isLineItemReceivingDocumentInProcessForPurchaseOrder(Integer poId, String receivingDocumentNumber) throws RuntimeException {
237         return !getLineItemReceivingDocumentNumbersInProcessForPurchaseOrder(poId, receivingDocumentNumber).isEmpty();
238     }
239 
240     @Override
241     public List<String> getLineItemReceivingDocumentNumbersInProcessForPurchaseOrder(Integer poId,
242                                                                                      String receivingDocumentNumber) {
243 
244         List<String> inProcessDocNumbers = new ArrayList<String>();
245         List<String> docNumbers = receivingDao.getDocumentNumbersByPurchaseOrderId(poId);
246         WorkflowDocument workflowDocument = null;
247 
248         for (String docNumber : docNumbers) {
249 
250             try {
251                 workflowDocument = workflowDocumentService.loadWorkflowDocument(docNumber, GlobalVariables.getUserSession().getPerson());
252             } catch (WorkflowException we) {
253                 throw new RuntimeException(we);
254             }
255 
256             if (!(workflowDocument.isCanceled() ||
257                     workflowDocument.isException() ||
258                     workflowDocument.isFinal()) &&
259                     docNumber.equals(receivingDocumentNumber) == false) {
260                 inProcessDocNumbers.add(docNumber);
261             }
262         }
263 
264         return inProcessDocNumbers;
265     }
266 
267     @Override
268     public List<LineItemReceivingDocument> getLineItemReceivingDocumentsInFinalForPurchaseOrder(Integer poId) {
269 
270         List<String> finalDocNumbers = new ArrayList<String>();
271         List<String> docNumbers = receivingDao.getDocumentNumbersByPurchaseOrderId(poId);
272         WorkflowDocument workflowDocument = null;
273 
274         for (String docNumber : docNumbers) {
275 
276             try {
277                 workflowDocument = workflowDocumentService.loadWorkflowDocument(docNumber, GlobalVariables.getUserSession().getPerson());
278             } catch (WorkflowException we) {
279                 throw new RuntimeException(we);
280             }
281 
282             if (workflowDocument.isFinal()) {
283                 finalDocNumbers.add(docNumber);
284             }
285         }
286 
287         if (finalDocNumbers.size() > 0) {
288             try {
289                 List<LineItemReceivingDocument> docs = new ArrayList<LineItemReceivingDocument>();
290                 for (Document doc : documentService.getDocumentsByListOfDocumentHeaderIds(LineItemReceivingDocument.class, finalDocNumbers)) {
291                     docs.add((LineItemReceivingDocument) doc);
292                 }
293                 return docs;
294             } catch (WorkflowException e) {
295                 throw new IllegalArgumentException("unable to retrieve LineItemReceivingDocuments", e);
296             }
297         } else {
298             return null;
299         }
300 
301     }
302 
303     protected boolean isCorrectionReceivingDocumentInProcessForPurchaseOrder(Integer poId, String receivingDocumentNumber) throws RuntimeException {
304         return !getCorrectionReceivingDocumentNumbersInProcessForPurchaseOrder(poId, receivingDocumentNumber).isEmpty();
305     }
306 
307     @Override
308     public List<String> getCorrectionReceivingDocumentNumbersInProcessForPurchaseOrder(Integer poId,
309                                                                                        String receivingDocumentNumber) {
310 
311         boolean isInProcess = false;
312 
313         List<String> inProcessDocNumbers = new ArrayList<String>();
314         List<String> docNumbers = receivingDao.getCorrectionReceivingDocumentNumbersByPurchaseOrderId(poId);
315         WorkflowDocument workflowDocument = null;
316 
317         for (String docNumber : docNumbers) {
318 
319             try {
320                 workflowDocument = workflowDocumentService.loadWorkflowDocument(docNumber, GlobalVariables.getUserSession().getPerson());
321             } catch (WorkflowException we) {
322                 throw new RuntimeException(we);
323             }
324 
325             if (!(workflowDocument.isCanceled() ||
326                     workflowDocument.isException() ||
327                     workflowDocument.isFinal()) &&
328                     docNumber.equals(receivingDocumentNumber) == false) {
329                 inProcessDocNumbers.add(docNumber);
330             }
331         }
332 
333         return inProcessDocNumbers;
334     }
335 
336 
337     protected boolean isCorrectionReceivingDocumentInProcessForReceivingLine(String receivingDocumentNumber, String receivingCorrectionDocNumber) throws RuntimeException {
338 
339         boolean isInProcess = false;
340 
341         List<String> docNumbers = receivingDao.getCorrectionReceivingDocumentNumbersByReceivingLineNumber(receivingDocumentNumber);
342         WorkflowDocument workflowDocument = null;
343 
344         for (String docNumber : docNumbers) {
345 
346             try {
347                 workflowDocument = workflowDocumentService.loadWorkflowDocument(docNumber, GlobalVariables.getUserSession().getPerson());
348             } catch (WorkflowException we) {
349                 throw new RuntimeException(we);
350             }
351 
352             if (!(workflowDocument.isCanceled() ||
353                     workflowDocument.isException() ||
354                     workflowDocument.isFinal()) &&
355                     docNumber.equals(receivingCorrectionDocNumber) == false) {
356 
357                 isInProcess = true;
358                 break;
359             }
360         }
361 
362         return isInProcess;
363     }
364 
365     /**
366      * @see org.kuali.ole.module.purap.document.service.ReceivingService#receivingLineDuplicateMessages(org.kuali.ole.module.purap.document.LineItemReceivingDocument)
367      */
368     @Override
369     public HashMap<String, String> receivingLineDuplicateMessages(LineItemReceivingDocument rlDoc) {
370         HashMap<String, String> msgs;
371         msgs = new HashMap<String, String>();
372         Integer poId = rlDoc.getPurchaseOrderIdentifier();
373         StringBuffer currentMessage = new StringBuffer("");
374         List<String> docNumbers = null;
375 
376         //check vendor date for duplicates
377         if (rlDoc.getShipmentReceivedDate() != null) {
378             docNumbers = receivingDao.duplicateVendorDate(poId, rlDoc.getShipmentReceivedDate());
379             if (hasDuplicateEntry(docNumbers)) {
380                 appendDuplicateMessage(currentMessage, PurapKeyConstants.MESSAGE_DUPLICATE_RECEIVING_LINE_VENDOR_DATE, rlDoc.getPurchaseOrderIdentifier());
381             }
382         }
383 
384         //check packing slip number for duplicates
385         if (!StringUtils.isEmpty(rlDoc.getShipmentPackingSlipNumber())) {
386             docNumbers = receivingDao.duplicatePackingSlipNumber(poId, rlDoc.getShipmentPackingSlipNumber());
387             if (hasDuplicateEntry(docNumbers)) {
388                 appendDuplicateMessage(currentMessage, PurapKeyConstants.MESSAGE_DUPLICATE_RECEIVING_LINE_PACKING_SLIP_NUMBER, rlDoc.getPurchaseOrderIdentifier());
389             }
390         }
391 
392         //check bill of lading number for duplicates
393         if (!StringUtils.isEmpty(rlDoc.getShipmentBillOfLadingNumber())) {
394             docNumbers = receivingDao.duplicateBillOfLadingNumber(poId, rlDoc.getShipmentBillOfLadingNumber());
395             if (hasDuplicateEntry(docNumbers)) {
396                 appendDuplicateMessage(currentMessage, PurapKeyConstants.MESSAGE_DUPLICATE_RECEIVING_LINE_BILL_OF_LADING_NUMBER, rlDoc.getPurchaseOrderIdentifier());
397             }
398         }
399 
400         //add message if one exists
401         if (currentMessage.length() > 0) {
402             //add suffix
403             appendDuplicateMessage(currentMessage, PurapKeyConstants.MESSAGE_DUPLICATE_RECEIVING_LINE_SUFFIX, rlDoc.getPurchaseOrderIdentifier());
404 
405             //add msg to map
406             msgs.put(PurapConstants.LineItemReceivingDocumentStrings.DUPLICATE_RECEIVING_LINE_QUESTION, currentMessage.toString());
407         }
408 
409         return msgs;
410     }
411 
412     /**
413      * Looks at a list of doc numbers, but only considers an entry duplicate
414      * if the document is in a Final status.
415      *
416      * @param docNumbers
417      * @return
418      */
419     protected boolean hasDuplicateEntry(List<String> docNumbers) {
420 
421         boolean isDuplicate = false;
422         WorkflowDocument workflowDocument = null;
423 
424         for (String docNumber : docNumbers) {
425 
426             try {
427                 workflowDocument = workflowDocumentService.loadWorkflowDocument(docNumber, GlobalVariables.getUserSession().getPerson());
428             } catch (WorkflowException we) {
429                 throw new RuntimeException(we);
430             }
431 
432             //if the doc number exists, and is in final status, consider this a dupe and return
433             if (workflowDocument.isFinal()) {
434                 isDuplicate = true;
435                 break;
436             }
437         }
438 
439         return isDuplicate;
440 
441     }
442 
443     protected void appendDuplicateMessage(StringBuffer currentMessage, String duplicateMessageKey, Integer poId) {
444 
445         //append prefix if this is first call
446         if (currentMessage.length() == 0) {
447             String messageText = configurationService.getPropertyValueAsString(PurapKeyConstants.MESSAGE_DUPLICATE_RECEIVING_LINE_PREFIX);
448             String prefix = MessageFormat.format(messageText, poId.toString());
449 
450             currentMessage.append(prefix);
451         }
452 
453         //append message
454         currentMessage.append(configurationService.getPropertyValueAsString(duplicateMessageKey));
455     }
456 
457     @Override
458     public void completeCorrectionReceivingDocument(ReceivingDocument correctionDocument) {
459 
460         ReceivingDocument receivingDoc = ((CorrectionReceivingDocument) correctionDocument).getLineItemReceivingDocument();
461 
462         for (CorrectionReceivingItem correctionItem : (List<CorrectionReceivingItem>) correctionDocument.getItems()) {
463             if (!StringUtils.equalsIgnoreCase(correctionItem.getItemType().getItemTypeCode(), PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE)) {
464 
465                 LineItemReceivingItem recItem = (LineItemReceivingItem) receivingDoc.getItem(correctionItem.getItemLineNumber().intValue() - 1);
466                 List<PurchaseOrderItem> purchaseOrderItems = receivingDoc.getPurchaseOrderDocument().getItems();
467                 PurchaseOrderItem poItem = purchaseOrderItems.get(correctionItem.getItemLineNumber().intValue() - 1);
468 
469                 if (ObjectUtils.isNotNull(recItem)) {
470                     recItem.setItemReceivedTotalQuantity(correctionItem.getItemReceivedTotalQuantity());
471                     recItem.setItemReturnedTotalQuantity(correctionItem.getItemReturnedTotalQuantity());
472                     recItem.setItemDamagedTotalQuantity(correctionItem.getItemDamagedTotalQuantity());
473                 }
474             }
475         }
476 
477     }
478 
479     /**
480      * This method deletes unneeded items and updates the totals on the po and does any additional processing based on items i.e. FYI etc
481      *
482      * @param receivingDocument receiving document
483      */
484     @Override
485     public void completeReceivingDocument(ReceivingDocument receivingDocument) {
486 
487         PurchaseOrderDocument poDoc = null;
488 
489         if (receivingDocument instanceof LineItemReceivingDocument) {
490             // delete unentered items
491             purapService.deleteUnenteredItems(receivingDocument);
492             poDoc = receivingDocument.getPurchaseOrderDocument();
493        //     SpringContext.getBean(GeneralLedgerPendingEntryService.class).generateGeneralLedgerPendingEntries(poDoc);
494         } else if (receivingDocument instanceof CorrectionReceivingDocument) {
495             CorrectionReceivingDocument correctionDocument = (CorrectionReceivingDocument) receivingDocument;
496             poDoc = purchaseOrderService.getCurrentPurchaseOrder(correctionDocument.getLineItemReceivingDocument().getPurchaseOrderIdentifier());
497         }
498 
499         updateReceivingTotalsOnPurchaseOrder(receivingDocument, poDoc);
500 
501         //TODO: custom doc specific service hook here for correction to do it's receiving doc update
502 
503      //   purapService.saveDocumentNoValidation(poDoc);
504 
505         // sendFyiForItems(receivingDocument);
506 
507         spawnPoAmendmentForUnorderedItems(receivingDocument, poDoc);
508 
509         purapService.saveDocumentNoValidation(receivingDocument);
510     }
511 
512     @Override
513     public void createNoteForReturnedAndDamagedItems(ReceivingDocument recDoc) {
514 
515         for (ReceivingItem item : (List<ReceivingItem>) recDoc.getItems()) {
516             if (!StringUtils.equalsIgnoreCase(item.getItemType().getItemTypeCode(), PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE)) {
517                 if (item.getItemReturnedTotalQuantity() != null && item.getItemReturnedTotalQuantity().isGreaterThan(KualiDecimal.ZERO)) {
518                     try {
519                         String noteString = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(PurapKeyConstants.MESSAGE_RECEIVING_LINEITEM_RETURN_NOTE_TEXT);
520                         noteString = item.getItemReturnedTotalQuantity().intValue() + " " + noteString + " " + item.getItemLineNumber();
521                         addNoteToReceivingDocument(recDoc, noteString);
522                     } catch (Exception e) {
523                         String errorMsg = "Note Service Exception caught: " + e.getLocalizedMessage();
524                         throw new RuntimeException(errorMsg, e);
525                     }
526                 }
527 
528                 if (item.getItemDamagedTotalQuantity() != null && item.getItemDamagedTotalQuantity().isGreaterThan(KualiDecimal.ZERO)) {
529                     try {
530                         String noteString = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(PurapKeyConstants.MESSAGE_RECEIVING_LINEITEM_DAMAGE_NOTE_TEXT);
531                         noteString = item.getItemDamagedTotalQuantity().intValue() + " " + noteString + " " + item.getItemLineNumber();
532                         addNoteToReceivingDocument(recDoc, noteString);
533                     } catch (Exception e) {
534                         String errorMsg = "Note Service Exception caught: " + e.getLocalizedMessage();
535                         throw new RuntimeException(errorMsg, e);
536                     }
537                 }
538             }
539         }
540     }
541 
542     protected void updateReceivingTotalsOnPurchaseOrder(ReceivingDocument receivingDocument, PurchaseOrderDocument poDoc) {
543         for (OleReceivingItem receivingItem : (List<OleReceivingItem>) receivingDocument.getItems()) {
544             ItemType itemType = receivingItem.getItemType();
545             if (!StringUtils.equalsIgnoreCase(itemType.getItemTypeCode(), PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE)) {
546                 //TODO: Chris - this method of getting the line out of po should be turned into a method that can get an item based on a combo or itemType and line
547                 OlePurchaseOrderItem poItem = (OlePurchaseOrderItem) poDoc.getItemByLineNumber(receivingItem
548                         .getItemLineNumber());
549 
550                 if (ObjectUtils.isNotNull(poItem)) {
551 
552                     KualiDecimal poItemReceivedTotal = poItem.getItemReceivedTotalQuantity();
553 
554                     KualiDecimal receivingItemReceivedOriginal = receivingItem.getItemOriginalReceivedTotalQuantity();
555                     /**
556                      * FIXME: It's coming as null although we set the default value in the LineItemReceivingItem constructor - mpv
557                      */
558                     if (ObjectUtils.isNull(receivingItemReceivedOriginal)) {
559                         receivingItemReceivedOriginal = KualiDecimal.ZERO;
560                     }
561                     KualiDecimal receivingItemReceived = receivingItem.getItemReceivedTotalQuantity();
562                     KualiDecimal receivingItemTotalReceivedAdjested = receivingItemReceived.subtract(receivingItemReceivedOriginal);
563 
564                     if (ObjectUtils.isNull(poItemReceivedTotal)) {
565                         poItemReceivedTotal = KualiDecimal.ZERO;
566                     }
567                     KualiDecimal poItemReceivedTotalAdjusted = poItemReceivedTotal.add(receivingItemTotalReceivedAdjested);
568 
569                     KualiDecimal receivingItemReturnedOriginal = receivingItem.getItemOriginalReturnedTotalQuantity();
570                     if (ObjectUtils.isNull(receivingItemReturnedOriginal)) {
571                         receivingItemReturnedOriginal = KualiDecimal.ZERO;
572                     }
573 
574                     KualiDecimal receivingItemReturned = receivingItem.getItemReturnedTotalQuantity();
575                     if (ObjectUtils.isNull(receivingItemReturned)) {
576                         receivingItemReturned = KualiDecimal.ZERO;
577                     }
578 
579                     KualiDecimal receivingItemTotalReturnedAdjusted = receivingItemReturned.subtract(receivingItemReturnedOriginal);
580 
581                     poItemReceivedTotalAdjusted = poItemReceivedTotalAdjusted.subtract(receivingItemTotalReturnedAdjusted);
582 
583                     poItem.setItemReceivedTotalQuantity(poItemReceivedTotalAdjusted);
584 
585                     KualiDecimal poTotalDamaged = poItem.getItemDamagedTotalQuantity();
586                     if (ObjectUtils.isNull(poTotalDamaged)) {
587                         poTotalDamaged = KualiDecimal.ZERO;
588                     }
589 
590                     KualiDecimal receivingItemTotalDamagedOriginal = receivingItem.getItemOriginalDamagedTotalQuantity();
591                     if (ObjectUtils.isNull(receivingItemTotalDamagedOriginal)) {
592                         receivingItemTotalDamagedOriginal = KualiDecimal.ZERO;
593                     }
594 
595                     KualiDecimal receivingItemTotalDamaged = receivingItem.getItemDamagedTotalQuantity();
596                     if (ObjectUtils.isNull(receivingItemTotalDamaged)) {
597                         receivingItemTotalDamaged = KualiDecimal.ZERO;
598                     }
599 
600                     KualiDecimal receivingItemTotalDamagedAdjusted = receivingItemTotalDamaged.subtract(receivingItemTotalDamagedOriginal);
601 
602                     poItem.setItemDamagedTotalQuantity(poTotalDamaged.add(receivingItemTotalDamagedAdjusted));
603                     // Updating the Total Parts
604                     KualiDecimal poItemPartsReceivedTotal = poItem.getItemReceivedTotalParts();
605 
606                     KualiDecimal receivingItemPartsReceivedOriginal = receivingItem.getItemOriginalReceivedTotalParts();
607 
608                     if (ObjectUtils.isNull(receivingItemPartsReceivedOriginal)) {
609                         receivingItemPartsReceivedOriginal = KualiDecimal.ZERO;
610                     }
611                     KualiDecimal receivingItemPartsReceived = receivingItem.getItemReceivedTotalParts();
612                     KualiDecimal receivingItemPartsTotalReceivedAdjusted = receivingItemPartsReceived
613                             .subtract(receivingItemPartsReceivedOriginal);
614 
615                     if (ObjectUtils.isNull(poItemPartsReceivedTotal)) {
616                         poItemPartsReceivedTotal = KualiDecimal.ZERO;
617                     }
618                     KualiDecimal poItemPartsReceivedTotalAdjusted = poItemPartsReceivedTotal
619                             .add(receivingItemPartsTotalReceivedAdjusted);
620 
621                     KualiDecimal receivingItemPartsReturnedOriginal = receivingItem.getItemOriginalReturnedTotalParts();
622                     if (ObjectUtils.isNull(receivingItemPartsReturnedOriginal)) {
623                         receivingItemPartsReturnedOriginal = KualiDecimal.ZERO;
624                     }
625 
626                     KualiDecimal receivingItemPartsReturned = receivingItem.getItemReturnedTotalParts();
627                     if (ObjectUtils.isNull(receivingItemPartsReturned)) {
628                         receivingItemPartsReturned = KualiDecimal.ZERO;
629                     }
630 
631                     KualiDecimal receivingItemPartsTotalReturnedAdjusted = receivingItemPartsReturned
632                             .subtract(receivingItemPartsReturnedOriginal);
633 
634                     poItemPartsReceivedTotalAdjusted = poItemPartsReceivedTotalAdjusted
635                             .subtract(receivingItemPartsTotalReturnedAdjusted);
636 
637                     poItem.setItemReceivedTotalParts(poItemPartsReceivedTotalAdjusted);
638 
639                     KualiDecimal poPartsTotalDamaged = poItem.getItemDamagedTotalParts();
640                     if (ObjectUtils.isNull(poPartsTotalDamaged)) {
641                         poPartsTotalDamaged = KualiDecimal.ZERO;
642                     }
643 
644                     KualiDecimal receivingItemPartsTotalDamagedOriginal = receivingItem
645                             .getItemOriginalDamagedTotalParts();
646                     if (ObjectUtils.isNull(receivingItemPartsTotalDamagedOriginal)) {
647                         receivingItemPartsTotalDamagedOriginal = KualiDecimal.ZERO;
648                     }
649 
650                     KualiDecimal receivingItemPartsTotalDamaged = receivingItem.getItemDamagedTotalParts();
651                     if (ObjectUtils.isNull(receivingItemPartsTotalDamaged)) {
652                         receivingItemPartsTotalDamaged = KualiDecimal.ZERO;
653                     }
654 
655                     KualiDecimal receivingItemPartsTotalDamagedAdjusted = receivingItemPartsTotalDamaged
656                             .subtract(receivingItemPartsTotalDamagedOriginal);
657 
658                     poItem.setItemDamagedTotalParts(poPartsTotalDamaged.add(receivingItemPartsTotalDamagedAdjusted));
659 
660                 }
661             }
662         }
663     }
664 
665     /**
666      * Spawns PO amendments for new unordered items on a receiving document.
667      *
668      * @param receivingDocument
669      * @param po
670      */
671     protected void spawnPoAmendmentForUnorderedItems(ReceivingDocument receivingDocument, PurchaseOrderDocument po) {
672 
673         //if receiving line document
674         if (receivingDocument instanceof LineItemReceivingDocument) {
675             LineItemReceivingDocument rlDoc = (LineItemReceivingDocument) receivingDocument;
676 
677             //if a new item has been added spawn a purchase order amendment
678             if (hasNewUnorderedItem((LineItemReceivingDocument) receivingDocument)) {
679                 String newSessionUserId = getOleSelectDocumentService().getSelectParameterValue(OLEConstants.SYSTEM_USER);
680                 try {
681 
682                     LogicContainer logicToRun = new LogicContainer() {
683                         @Override
684                         public Object runLogic(Object[] objects) throws Exception {
685                             LineItemReceivingDocument rlDoc = (LineItemReceivingDocument) objects[0];
686                             String poDocNumber = (String) objects[1];
687 
688                             //create a PO amendment
689                             PurchaseOrderAmendmentDocument amendmentPo = (PurchaseOrderAmendmentDocument) purchaseOrderService.createAndSavePotentialChangeDocument(poDocNumber, PurchaseOrderDocTypes.PURCHASE_ORDER_AMENDMENT_DOCUMENT, PurchaseOrderStatuses.APPDOC_AMENDMENT);
690 
691                             //add new lines to amendement
692                             addUnorderedItemsToAmendment(amendmentPo, rlDoc);
693 
694                             //route amendment
695                             //documentService.routeDocument(amendmentPo, null, null);
696                             //save document
697                             documentService.saveDocument(amendmentPo);
698                             //add note to amendment po document
699                             String note = "Purchase Order Amendment " + amendmentPo.getPurapDocumentIdentifier() + " (document id " + amendmentPo.getDocumentNumber() + ") created for new unordered line items due to Receiving (document id " + rlDoc.getDocumentNumber() + ")";
700 
701                             Note noteObj = documentService.createNoteFromDocument(amendmentPo, note);
702                             amendmentPo.addNote(noteObj);
703                             noteService.save(noteObj);
704 
705                             return null;
706                         }
707                     };
708 
709                     purapService.performLogicWithFakedUserSession(newSessionUserId, logicToRun, new Object[]{rlDoc, po.getDocumentNumber()});
710                 } catch (WorkflowException e) {
711                     String errorMsg = "Workflow Exception caught: " + e.getLocalizedMessage();
712                     throw new RuntimeException(errorMsg, e);
713                 } catch (Exception e) {
714                     throw new RuntimeException(e);
715                 }
716             }
717         }
718     }
719 
720     /**
721      * Checks the item list for newly added items.
722      *
723      * @param rlDoc
724      * @return
725      */
726     @Override
727     public boolean hasNewUnorderedItem(LineItemReceivingDocument rlDoc) {
728 
729         boolean itemAdded = false;
730 
731         for (LineItemReceivingItem rlItem : (List<LineItemReceivingItem>) rlDoc.getItems()) {
732             if (PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE.equals(rlItem.getItemTypeCode()) &&
733                     !StringUtils.isEmpty(rlItem.getItemReasonAddedCode())) {
734                 itemAdded = true;
735                 break;
736             }
737         }
738 
739         return itemAdded;
740     }
741 
742     /**
743      * Adds an unordered item to a po amendment document.
744      *
745      * @param amendment
746      * @param rlDoc
747      */
748     protected void addUnorderedItemsToAmendment(PurchaseOrderAmendmentDocument amendment, LineItemReceivingDocument rlDoc) {
749 
750         PurchaseOrderItem poi = null;
751         // Added for jira OLE-2515
752 //        OlePurchaseOrderItem  opoi = null;
753 
754         for (OleLineItemReceivingItem rlItem : (List<OleLineItemReceivingItem>) rlDoc.getItems()) {
755 
756             if (PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE.equals(rlItem.getItemTypeCode()) &&
757                     !StringUtils.isEmpty(rlItem.getItemReasonAddedCode())) {
758 
759                 poi = createPoItemFromReceivingLine(rlItem);
760                 poi.setDocumentNumber(amendment.getDocumentNumber());
761                 // add default commodity code from parameter, if commodity code is required on PO and not specified in the unordered item
762                 // Note: if we don't add logic to populate commodity code in LineItemReceivingItem, then at this point this field is always empty for unordered item
763                 if (purchaseOrderService.isCommodityCodeRequiredOnPurchaseOrder() && StringUtils.isEmpty(poi.getPurchasingCommodityCode())) {
764                     String defaultCommodityCode = SpringContext.getBean(ParameterService.class).getParameterValueAsString(PurchaseOrderAmendmentDocument.class, PurapParameterConstants.UNORDERED_ITEM_DEFAULT_COMMODITY_CODE);
765                     poi.setPurchasingCommodityCode(defaultCommodityCode);
766                 }
767                 poi.refreshNonUpdateableReferences();
768                 amendment.addItem(poi);
769             }
770         }
771 
772     }
773 
774     /**
775      * Creates a PO item from a receiving line item.
776      *
777      * @param rlItem
778      * @return
779      */
780     protected PurchaseOrderItem createPoItemFromReceivingLine(LineItemReceivingItem rlItem) {
781 
782         OlePurchaseOrderItem opoi = new OlePurchaseOrderItem();
783         PurchaseOrderItem poi = new OlePurchaseOrderItem();
784 
785         poi.setItemActiveIndicator(true);
786         poi.setItemTypeCode(rlItem.getItemTypeCode());
787         poi.setItemLineNumber(rlItem.getItemLineNumber());
788         poi.setItemCatalogNumber(rlItem.getItemCatalogNumber());
789         poi.setItemDescription(rlItem.getItemDescription());
790 
791         if (rlItem.getItemReturnedTotalQuantity() == null) {
792             poi.setItemQuantity(rlItem.getItemReceivedTotalQuantity());
793         } else {
794             poi.setItemQuantity(rlItem.getItemReceivedTotalQuantity().subtract(rlItem.getItemReturnedTotalQuantity()));
795         }
796 
797         poi.setItemUnitOfMeasureCode(rlItem.getItemUnitOfMeasureCode());
798         poi.setItemUnitPrice(new BigDecimal(0));
799 
800         poi.setItemDamagedTotalQuantity(rlItem.getItemDamagedTotalQuantity());
801         poi.setItemReceivedTotalQuantity(rlItem.getItemReceivedTotalQuantity());
802 
803         return poi;
804     }
805 
806 
807     /**
808      * Creates a PO item from a receiving line item.
809      *
810      * @param rlItem
811      * @return
812      */
813     protected OlePurchaseOrderItem createPoItemFromReceivingLine(OleLineItemReceivingItem rlItem) {
814 
815         //  OlePurchaseOrderItem opoi = new OlePurchaseOrderItem();
816         //  (OleLineItemReceivingItem) rlItem.getItemT
817         //opoi.setItemTitleId(rlItem.getitem);
818         OlePurchaseOrderItem poi = new OlePurchaseOrderItem();
819 
820         poi.setItemTitleId(rlItem.getItemTitleId());
821         poi.setItemActiveIndicator(true);
822         poi.setItemTypeCode(rlItem.getItemTypeCode());
823         poi.setItemLineNumber(rlItem.getItemLineNumber());
824         poi.setItemCatalogNumber(rlItem.getItemCatalogNumber());
825         poi.setItemDescription(rlItem.getItemDescription());
826 
827         if (rlItem.getItemReturnedTotalQuantity() == null) {
828             poi.setItemQuantity(rlItem.getItemReceivedTotalQuantity());
829         } else {
830             poi.setItemQuantity(rlItem.getItemReceivedTotalQuantity().subtract(rlItem.getItemReturnedTotalQuantity()));
831         }
832 
833         poi.setItemUnitOfMeasureCode(rlItem.getItemUnitOfMeasureCode());
834         poi.setItemUnitPrice(new BigDecimal(0));
835 
836         poi.setItemDamagedTotalQuantity(rlItem.getItemDamagedTotalQuantity());
837         poi.setItemReceivedTotalQuantity(rlItem.getItemReceivedTotalQuantity());
838         poi.setItemNoOfParts(new KualiInteger(rlItem.getItemReceivedTotalParts().intValue()));
839 
840         List<OleCopy> copyList = rlItem.getCopyList() != null ? rlItem.getCopyList() : new ArrayList<OleCopy>();
841         Integer receivedCount = 0;
842         for (OleCopy oleCopy : copyList) {
843             if (oleCopy.getReceiptStatus().equalsIgnoreCase("Received")) {
844                 receivedCount++;
845             }
846         }
847         if (receivedCount == 0) {
848             rlItem
849                     .setReceiptStatusId(getReceiptStatusDetails(OLEConstants.PO_RECEIPT_STATUS_NOT_RECEIVED));
850         } else if (receivedCount == copyList.size()) {
851             rlItem
852                     .setReceiptStatusId(getReceiptStatusDetails(OLEConstants.PO_RECEIPT_STATUS_FULLY_RECEIVED));
853         } else {
854             rlItem
855                     .setReceiptStatusId(getReceiptStatusDetails(OLEConstants.PO_RECEIPT_STATUS_PARTIALLY_RECEIVED));
856         }
857         poi.setReceiptStatusId(rlItem.getReceiptStatusId());
858         if (poi.getItemQuantity().equals(new KualiDecimal(1)) && poi.getItemNoOfParts().isGreaterThan(new KualiInteger(1))) {
859             poi.setNoOfCopiesReceived("N/A");
860             poi.setNoOfPartsReceived(receivedCount.toString());
861         } else if (poi.getItemQuantity().isGreaterThan(new KualiDecimal(1)) && poi.getItemNoOfParts().equals(new KualiDecimal(1))) {
862             poi.setNoOfCopiesReceived(receivedCount.toString());
863             poi.setNoOfPartsReceived("N/A");
864         } else if (poi.getItemQuantity().isGreaterThan(new KualiDecimal(1)) && poi.getItemNoOfParts().isGreaterThan(new KualiInteger(1))) {
865             poi.setNoOfCopiesReceived("See Copies Section");
866             poi.setNoOfPartsReceived("See Copies Section");
867         }
868        /* poi.setNoOfCopiesReceived((poi.getNoOfCopiesReceived().add(new KualiInteger(rlItem
869                 .getItemReceivedTotalQuantity().bigDecimalValue()))).subtract(new KualiInteger(rlItem
870                 .getItemReturnedTotalQuantity().bigDecimalValue())));
871         poi.setNoOfPartsReceived((poi.getNoOfPartsReceived().add(new KualiInteger(rlItem.getItemReceivedTotalParts()
872                 .bigDecimalValue()))).subtract(new KualiInteger(rlItem.getItemReturnedTotalParts().bigDecimalValue())));
873         if (poi.getItemQuantity().intValue() == poi.getNoOfCopiesReceived().intValue()
874                 && poi.getItemNoOfParts().intValue() == poi.getNoOfPartsReceived().intValue()) {
875             poi.setReceiptStatusId(getReceiptStatusDetails(OLEConstants.PO_RECEIPT_STATUS_FULLY_RECEIVED));
876         }
877         else {
878             if (poi.getNoOfPartsReceived().isZero() && poi.getNoOfCopiesReceived().isZero()) {
879                 poi.setReceiptStatusId(getReceiptStatusDetails(OLEConstants.PO_RECEIPT_STATUS_NOT_RECEIVED));
880             }
881             else {
882                 poi.setReceiptStatusId(getReceiptStatusDetails(OLEConstants.PO_RECEIPT_STATUS_PARTIALLY_RECEIVED));
883             }
884         }
885         List<OleLineItemReceivingDoc> oleLineItemReceivingItemDocList = new ArrayList<OleLineItemReceivingDoc>();
886         oleLineItemReceivingItemDocList = rlItem.getOleLineItemReceivingItemDocList();
887         Iterator iterator = oleLineItemReceivingItemDocList.iterator();
888         while (iterator.hasNext()) {
889             Object object = iterator.next();
890             if (object instanceof OleLineItemReceivingDoc) {
891                 OleLineItemReceivingDoc oleLineItemReceivingDoc = (OleLineItemReceivingDoc) object;
892                 if (rlItem.getReceivingItemIdentifier().intValue() == oleLineItemReceivingDoc.getReceivingLineItem()
893                         .getReceivingItemIdentifier()) {
894                     if (null != oleLineItemReceivingDoc.getItemTitleId()) {
895                         poi.setItemTitleId(oleLineItemReceivingDoc.getItemTitleId());
896                         List<String> itemTitleIdsList = new ArrayList<String>();
897 
898                         itemTitleIdsList.add(rlItem.getItemTitleId());
899 
900                     }
901                     if (null != oleLineItemReceivingDoc.getItemTitleId()) {
902                         if (rlItem.getItemReceivedTotalQuantity().isGreaterThan(new KualiDecimal(1))
903                                 || rlItem.getItemReceivedTotalParts().isGreaterThan(new KualiDecimal(1))) {
904                             List<OleCopies> copies = rlItem.getCopies();
905                                 poi.setCopies(copies);
906 
907                         }
908 
909                     }
910                 }
911             }
912         }    */
913 
914         return poi;
915     }
916 
917     /**
918      * Creates a list of fiscal officers for new unordered items added to a purchase order.
919      *
920      * @param po
921      * @return
922      */
923     protected List<AdHocRoutePerson> createFyiFiscalOfficerList(ReceivingDocument recDoc) {
924 
925         PurchaseOrderDocument po = recDoc.getPurchaseOrderDocument();
926         List<AdHocRoutePerson> adHocRoutePersons = new ArrayList<AdHocRoutePerson>();
927         Map fiscalOfficers = new HashMap();
928         AdHocRoutePerson adHocRoutePerson = null;
929 
930         for (ReceivingItem recItem : (List<ReceivingItem>) recDoc.getItems()) {
931             //if this item has an item line number then it is coming from the po
932             if (ObjectUtils.isNotNull(recItem.getItemLineNumber())) {
933                 PurchaseOrderItem poItem = (PurchaseOrderItem) po.getItemByLineNumber(recItem.getItemLineNumber());
934 
935                 if (poItem.getItemQuantity().isLessThan(poItem.getItemReceivedTotalQuantity()) ||
936                         recItem.getItemDamagedTotalQuantity().isGreaterThan(KualiDecimal.ZERO)) {
937 
938                     // loop through accounts and pull off fiscal officer
939                     for (PurApAccountingLine account : poItem.getSourceAccountingLines()) {
940 
941                         //check for dupes of fiscal officer
942                         if (fiscalOfficers.containsKey(account.getAccount().getAccountFiscalOfficerUser().getPrincipalName()) == false) {
943 
944                             //add fiscal officer to list
945                             fiscalOfficers.put(account.getAccount().getAccountFiscalOfficerUser().getPrincipalName(), account.getAccount().getAccountFiscalOfficerUser().getPrincipalName());
946 
947                             //create AdHocRoutePerson object and add to list
948                             adHocRoutePerson = new AdHocRoutePerson();
949                             adHocRoutePerson.setId(account.getAccount().getAccountFiscalOfficerUser().getPrincipalName());
950                             adHocRoutePerson.setActionRequested(OLEConstants.WORKFLOW_FYI_REQUEST);
951                             adHocRoutePersons.add(adHocRoutePerson);
952                         }
953                     }
954 
955                 }
956 
957             }
958         }
959 
960         return adHocRoutePersons;
961     }
962 
963     /**
964      * Sends an FYI to fiscal officers for new unordered items.
965      *
966      * @param po
967      */
968     protected void sendFyiForItems(ReceivingDocument recDoc) {
969 
970         List<AdHocRoutePerson> fyiList = createFyiFiscalOfficerList(recDoc);
971         String annotation = "Notification of Item exceeded Quantity or Damaged" + "(document id " + recDoc.getDocumentNumber() + ")";
972         String responsibilityNote = "Please Review";
973 
974         for (AdHocRoutePerson adHocPerson : fyiList) {
975             try {
976                 recDoc.appSpecificRouteDocumentToUser(
977                         recDoc.getDocumentHeader().getWorkflowDocument(),
978                         adHocPerson.getPerson().getPrincipalId(),
979                         annotation,
980                         responsibilityNote);
981             } catch (WorkflowException e) {
982                 throw new RuntimeException("Error routing fyi for document with id " + recDoc.getDocumentNumber(), e);
983             }
984 
985         }
986     }
987 
988     @Override
989     public void addNoteToReceivingDocument(ReceivingDocument receivingDocument, String note) throws Exception {
990         Note noteObj = documentService.createNoteFromDocument(receivingDocument, note);
991         receivingDocument.addNote(noteObj);
992         noteService.save(noteObj);
993     }
994 
995     @Override
996     public String getReceivingDeliveryCampusCode(PurchaseOrderDocument po) {
997         String deliveryCampusCode = "";
998         String latestDocumentNumber = "";
999 
1000         List<LineItemReceivingView> rViews = null;
1001         WorkflowDocument workflowDocument = null;
1002         DateTime latestCreateDate = null;
1003 
1004         //get related views
1005         if (ObjectUtils.isNotNull(po.getRelatedViews())) {
1006             rViews = po.getRelatedViews().getRelatedLineItemReceivingViews();
1007         }
1008 
1009         //if not empty, then grab the latest receiving view
1010         if (ObjectUtils.isNotNull(rViews) && rViews.isEmpty() == false) {
1011 
1012             for (LineItemReceivingView rView : rViews) {
1013                 try {
1014                     workflowDocument = workflowDocumentService.loadWorkflowDocument(rView.getDocumentNumber(), GlobalVariables.getUserSession().getPerson());
1015 
1016                     //if latest create date is null or the latest is before the current, current is newer
1017                     if (ObjectUtils.isNull(latestCreateDate) || latestCreateDate.isBefore(workflowDocument.getDateCreated())) {
1018                         latestCreateDate = workflowDocument.getDateCreated();
1019                         latestDocumentNumber = workflowDocument.getDocumentId().toString();
1020                     }
1021                 } catch (WorkflowException we) {
1022                     throw new RuntimeException(we);
1023                 }
1024             }
1025 
1026             //if there is a create date, a latest workflow doc was found
1027             if (ObjectUtils.isNotNull(latestCreateDate)) {
1028                 try {
1029                     LineItemReceivingDocument rlDoc = (LineItemReceivingDocument) documentService.getByDocumentHeaderId(latestDocumentNumber);
1030                     deliveryCampusCode = rlDoc.getDeliveryCampusCode();
1031                 } catch (WorkflowException we) {
1032                     throw new RuntimeException(we);
1033                 }
1034             }
1035         }
1036 
1037         return deliveryCampusCode;
1038     }
1039 
1040     /**
1041      * @see org.kuali.ole.module.purap.document.service.ReceivingService#isLineItemReceivingDocumentGeneratedForPurchaseOrder(java.lang.Integer)
1042      */
1043     @Override
1044     public boolean isLineItemReceivingDocumentGeneratedForPurchaseOrder(Integer poId) throws RuntimeException {
1045 
1046         boolean isGenerated = false;
1047 
1048         List<String> docNumbers = receivingDao.getDocumentNumbersByPurchaseOrderId(poId);
1049         WorkflowDocument workflowDocument = null;
1050 
1051         for (String docNumber : docNumbers) {
1052 
1053             try {
1054                 workflowDocument = workflowDocumentService.loadWorkflowDocument(docNumber, GlobalVariables.getUserSession().getPerson());
1055             } catch (WorkflowException we) {
1056                 throw new RuntimeException(we);
1057             }
1058 
1059             if (workflowDocument.isFinal()) {
1060                 isGenerated = true;
1061                 break;
1062             }
1063         }
1064 
1065         return isGenerated;
1066     }
1067 
1068     @Override
1069     public void approveReceivingDocsForPOAmendment() {
1070         List<String> docNumbers = getDocumentsNumbersAwaitingPurchaseOrderOpenStatus();
1071         List<LineItemReceivingDocument> docs = new ArrayList<LineItemReceivingDocument>();
1072         for (String docNumber : docNumbers) {
1073             LineItemReceivingDocument lreq = getLineItemReceivingByDocumentNumber(docNumber);
1074             if (ObjectUtils.isNotNull(lreq)) {
1075                 docs.add(lreq);
1076             }
1077         }
1078         if (docs != null) {
1079             for (LineItemReceivingDocument receivingDoc : docs) {
1080                 if (receivingDoc.getDocumentHeader().getWorkflowDocument().getCurrentNodeNames().contains(PurapConstants.LineItemReceivingDocumentStrings.AWAITING_PO_OPEN_STATUS)) {
1081                     approveReceivingDoc(receivingDoc);
1082                 }
1083             }
1084         }
1085 
1086     }
1087 
1088     /**
1089      * @see org.kuali.ole.module.purap.document.service.PaymentRequestService#getPaymentRequestByDocumentNumber(java.lang.String)
1090      */
1091     public LineItemReceivingDocument getLineItemReceivingByDocumentNumber(String documentNumber) {
1092         LOG.debug("getLineItemReceivingByDocumentNumber() started");
1093 
1094         if (ObjectUtils.isNotNull(documentNumber)) {
1095             try {
1096                 LineItemReceivingDocument doc = (LineItemReceivingDocument) documentService.getByDocumentHeaderId(documentNumber);
1097                 return doc;
1098             } catch (WorkflowException e) {
1099                 String errorMessage = "Error getting LineItemReceiving document from document service";
1100                 LOG.error("getLineItemReceivingByDocumentNumber() " + errorMessage, e);
1101                 throw new RuntimeException(errorMessage, e);
1102             }
1103         }
1104         return null;
1105     }
1106 
1107     protected void approveReceivingDoc(LineItemReceivingDocument receivingDoc) {
1108         PurchaseOrderDocument poDoc = receivingDoc.getPurchaseOrderDocument();
1109         if (purchaseOrderService.isPurchaseOrderOpenForProcessing(poDoc)) {
1110             try {
1111                 SpringContext.getBean(DocumentService.class).approveDocument(receivingDoc, "Approved by the batch job", null);
1112             } catch (WorkflowException e) {
1113                 LOG.error("approveReceivingDoc() Error approving receiving document from awaiting PO open", e);
1114                 throw new RuntimeException("Error approving receiving document from awaiting PO open", e);
1115             }
1116         }
1117     }
1118 
1119     /**
1120      * Gets a list of strings of receiving line item document numbers from
1121      * workflow documents where  applicationdocumentstatus = 'Awaiting Purchase Order Open Status'
1122      * If there are documents then the document number is added to the list
1123      * <p/>
1124      * NOTE: simplify using DocSearch lookup with AppDocStatus
1125      *
1126      * @return list of documentNumbers to retrieve line item receiving documents.
1127      */
1128     protected List<String> getDocumentsNumbersAwaitingPurchaseOrderOpenStatus() {
1129         List<String> receivingDocumentNumbers = new ArrayList<String>();
1130 
1131         DocumentSearchCriteria.Builder documentSearchCriteriaDTO = DocumentSearchCriteria.Builder.create();
1132         documentSearchCriteriaDTO.setDocumentTypeName(PurapConstants.RECEIVING_LINE_ITEM_DOCUMENT_TYPE);
1133         documentSearchCriteriaDTO.setApplicationDocumentStatus(PurapConstants.LineItemReceivingStatuses.APPDOC_AWAITING_PO_OPEN_STATUS);
1134         documentSearchCriteriaDTO.setSaveName(null);
1135 
1136         DocumentSearchResults results = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(null, documentSearchCriteriaDTO.build());
1137 
1138         String documentHeaderId = null;
1139 
1140         for (DocumentSearchResult result : results.getSearchResults()) {
1141             receivingDocumentNumbers.add(result.getDocument().getDocumentId());
1142         }
1143 
1144         return receivingDocumentNumbers;
1145     }
1146 
1147     public int getReceiptStatusDetails(String receiptStatusCd) {
1148         int receiptStatusId = 0;
1149         Map<String, String> receiptStatusCdMap = new HashMap<String, String>();
1150         receiptStatusCdMap.put(OLEConstants.RCPT_STATUS_CD, receiptStatusCd);
1151         List<OleReceiptStatus> oleReceiptStatusList = (List) SpringContext.getBean(BusinessObjectService.class)
1152                 .findMatching(OleReceiptStatus.class, receiptStatusCdMap);
1153         for (OleReceiptStatus oleReceiptStatus : oleReceiptStatusList) {
1154             receiptStatusId = oleReceiptStatus.getReceiptStatusId().intValue();
1155         }
1156         return receiptStatusId;
1157     }
1158 
1159     public OleSelectDocumentService getOleSelectDocumentService() {
1160         if(oleSelectDocumentService == null){
1161             oleSelectDocumentService = SpringContext.getBean(OleSelectDocumentService.class);
1162         }
1163         return oleSelectDocumentService;
1164     }
1165 
1166     public void setOleSelectDocumentService(OleSelectDocumentService oleSelectDocumentService) {
1167         this.oleSelectDocumentService = oleSelectDocumentService;
1168     }
1169 }
1170