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