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.rice.core.api.config.property.ConfigurationService;
37 import org.kuali.rice.core.api.util.type.KualiDecimal;
38 import org.kuali.rice.core.api.util.type.KualiInteger;
39 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
40 import org.kuali.rice.kew.api.KewApiServiceLocator;
41 import org.kuali.rice.kew.api.WorkflowDocument;
42 import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
43 import org.kuali.rice.kew.api.document.search.DocumentSearchResult;
44 import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
45 import org.kuali.rice.kew.api.exception.WorkflowException;
46 import org.kuali.rice.krad.bo.AdHocRoutePerson;
47 import org.kuali.rice.krad.bo.Note;
48 import org.kuali.rice.krad.document.Document;
49 import org.kuali.rice.krad.exception.InfrastructureException;
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 InfrastructureException("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 } else if (receivingDocument instanceof CorrectionReceivingDocument) {
492 CorrectionReceivingDocument correctionDocument = (CorrectionReceivingDocument) receivingDocument;
493 poDoc = purchaseOrderService.getCurrentPurchaseOrder(correctionDocument.getLineItemReceivingDocument().getPurchaseOrderIdentifier());
494 }
495
496 updateReceivingTotalsOnPurchaseOrder(receivingDocument, poDoc);
497
498
499
500 purapService.saveDocumentNoValidation(poDoc);
501
502
503
504 spawnPoAmendmentForUnorderedItems(receivingDocument, poDoc);
505
506 purapService.saveDocumentNoValidation(receivingDocument);
507 }
508
509 @Override
510 public void createNoteForReturnedAndDamagedItems(ReceivingDocument recDoc) {
511
512 for (ReceivingItem item : (List<ReceivingItem>) recDoc.getItems()) {
513 if (!StringUtils.equalsIgnoreCase(item.getItemType().getItemTypeCode(), PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE)) {
514 if (item.getItemReturnedTotalQuantity() != null && item.getItemReturnedTotalQuantity().isGreaterThan(KualiDecimal.ZERO)) {
515 try {
516 String noteString = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(PurapKeyConstants.MESSAGE_RECEIVING_LINEITEM_RETURN_NOTE_TEXT);
517 noteString = item.getItemReturnedTotalQuantity().intValue() + " " + noteString + " " + item.getItemLineNumber();
518 addNoteToReceivingDocument(recDoc, noteString);
519 } catch (Exception e) {
520 String errorMsg = "Note Service Exception caught: " + e.getLocalizedMessage();
521 throw new RuntimeException(errorMsg, e);
522 }
523 }
524
525 if (item.getItemDamagedTotalQuantity() != null && item.getItemDamagedTotalQuantity().isGreaterThan(KualiDecimal.ZERO)) {
526 try {
527 String noteString = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(PurapKeyConstants.MESSAGE_RECEIVING_LINEITEM_DAMAGE_NOTE_TEXT);
528 noteString = item.getItemDamagedTotalQuantity().intValue() + " " + noteString + " " + item.getItemLineNumber();
529 addNoteToReceivingDocument(recDoc, noteString);
530 } catch (Exception e) {
531 String errorMsg = "Note Service Exception caught: " + e.getLocalizedMessage();
532 throw new RuntimeException(errorMsg, e);
533 }
534 }
535 }
536 }
537 }
538
539 protected void updateReceivingTotalsOnPurchaseOrder(ReceivingDocument receivingDocument, PurchaseOrderDocument poDoc) {
540 for (OleReceivingItem receivingItem : (List<OleReceivingItem>) receivingDocument.getItems()) {
541 ItemType itemType = receivingItem.getItemType();
542 if (!StringUtils.equalsIgnoreCase(itemType.getItemTypeCode(), PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE)) {
543
544 OlePurchaseOrderItem poItem = (OlePurchaseOrderItem) poDoc.getItemByLineNumber(receivingItem
545 .getItemLineNumber());
546
547 if (ObjectUtils.isNotNull(poItem)) {
548
549 KualiDecimal poItemReceivedTotal = poItem.getItemReceivedTotalQuantity();
550
551 KualiDecimal receivingItemReceivedOriginal = receivingItem.getItemOriginalReceivedTotalQuantity();
552
553
554
555 if (ObjectUtils.isNull(receivingItemReceivedOriginal)) {
556 receivingItemReceivedOriginal = KualiDecimal.ZERO;
557 }
558 KualiDecimal receivingItemReceived = receivingItem.getItemReceivedTotalQuantity();
559 KualiDecimal receivingItemTotalReceivedAdjested = receivingItemReceived.subtract(receivingItemReceivedOriginal);
560
561 if (ObjectUtils.isNull(poItemReceivedTotal)) {
562 poItemReceivedTotal = KualiDecimal.ZERO;
563 }
564 KualiDecimal poItemReceivedTotalAdjusted = poItemReceivedTotal.add(receivingItemTotalReceivedAdjested);
565
566 KualiDecimal receivingItemReturnedOriginal = receivingItem.getItemOriginalReturnedTotalQuantity();
567 if (ObjectUtils.isNull(receivingItemReturnedOriginal)) {
568 receivingItemReturnedOriginal = KualiDecimal.ZERO;
569 }
570
571 KualiDecimal receivingItemReturned = receivingItem.getItemReturnedTotalQuantity();
572 if (ObjectUtils.isNull(receivingItemReturned)) {
573 receivingItemReturned = KualiDecimal.ZERO;
574 }
575
576 KualiDecimal receivingItemTotalReturnedAdjusted = receivingItemReturned.subtract(receivingItemReturnedOriginal);
577
578 poItemReceivedTotalAdjusted = poItemReceivedTotalAdjusted.subtract(receivingItemTotalReturnedAdjusted);
579
580 poItem.setItemReceivedTotalQuantity(poItemReceivedTotalAdjusted);
581
582 KualiDecimal poTotalDamaged = poItem.getItemDamagedTotalQuantity();
583 if (ObjectUtils.isNull(poTotalDamaged)) {
584 poTotalDamaged = KualiDecimal.ZERO;
585 }
586
587 KualiDecimal receivingItemTotalDamagedOriginal = receivingItem.getItemOriginalDamagedTotalQuantity();
588 if (ObjectUtils.isNull(receivingItemTotalDamagedOriginal)) {
589 receivingItemTotalDamagedOriginal = KualiDecimal.ZERO;
590 }
591
592 KualiDecimal receivingItemTotalDamaged = receivingItem.getItemDamagedTotalQuantity();
593 if (ObjectUtils.isNull(receivingItemTotalDamaged)) {
594 receivingItemTotalDamaged = KualiDecimal.ZERO;
595 }
596
597 KualiDecimal receivingItemTotalDamagedAdjusted = receivingItemTotalDamaged.subtract(receivingItemTotalDamagedOriginal);
598
599 poItem.setItemDamagedTotalQuantity(poTotalDamaged.add(receivingItemTotalDamagedAdjusted));
600
601 KualiDecimal poItemPartsReceivedTotal = poItem.getItemReceivedTotalParts();
602
603 KualiDecimal receivingItemPartsReceivedOriginal = receivingItem.getItemOriginalReceivedTotalParts();
604
605 if (ObjectUtils.isNull(receivingItemPartsReceivedOriginal)) {
606 receivingItemPartsReceivedOriginal = KualiDecimal.ZERO;
607 }
608 KualiDecimal receivingItemPartsReceived = receivingItem.getItemReceivedTotalParts();
609 KualiDecimal receivingItemPartsTotalReceivedAdjusted = receivingItemPartsReceived
610 .subtract(receivingItemPartsReceivedOriginal);
611
612 if (ObjectUtils.isNull(poItemPartsReceivedTotal)) {
613 poItemPartsReceivedTotal = KualiDecimal.ZERO;
614 }
615 KualiDecimal poItemPartsReceivedTotalAdjusted = poItemPartsReceivedTotal
616 .add(receivingItemPartsTotalReceivedAdjusted);
617
618 KualiDecimal receivingItemPartsReturnedOriginal = receivingItem.getItemOriginalReturnedTotalParts();
619 if (ObjectUtils.isNull(receivingItemPartsReturnedOriginal)) {
620 receivingItemPartsReturnedOriginal = KualiDecimal.ZERO;
621 }
622
623 KualiDecimal receivingItemPartsReturned = receivingItem.getItemReturnedTotalParts();
624 if (ObjectUtils.isNull(receivingItemPartsReturned)) {
625 receivingItemPartsReturned = KualiDecimal.ZERO;
626 }
627
628 KualiDecimal receivingItemPartsTotalReturnedAdjusted = receivingItemPartsReturned
629 .subtract(receivingItemPartsReturnedOriginal);
630
631 poItemPartsReceivedTotalAdjusted = poItemPartsReceivedTotalAdjusted
632 .subtract(receivingItemPartsTotalReturnedAdjusted);
633
634 poItem.setItemReceivedTotalParts(poItemPartsReceivedTotalAdjusted);
635
636 KualiDecimal poPartsTotalDamaged = poItem.getItemDamagedTotalParts();
637 if (ObjectUtils.isNull(poPartsTotalDamaged)) {
638 poPartsTotalDamaged = KualiDecimal.ZERO;
639 }
640
641 KualiDecimal receivingItemPartsTotalDamagedOriginal = receivingItem
642 .getItemOriginalDamagedTotalParts();
643 if (ObjectUtils.isNull(receivingItemPartsTotalDamagedOriginal)) {
644 receivingItemPartsTotalDamagedOriginal = KualiDecimal.ZERO;
645 }
646
647 KualiDecimal receivingItemPartsTotalDamaged = receivingItem.getItemDamagedTotalParts();
648 if (ObjectUtils.isNull(receivingItemPartsTotalDamaged)) {
649 receivingItemPartsTotalDamaged = KualiDecimal.ZERO;
650 }
651
652 KualiDecimal receivingItemPartsTotalDamagedAdjusted = receivingItemPartsTotalDamaged
653 .subtract(receivingItemPartsTotalDamagedOriginal);
654
655 poItem.setItemDamagedTotalParts(poPartsTotalDamaged.add(receivingItemPartsTotalDamagedAdjusted));
656
657 }
658 }
659 }
660 }
661
662
663
664
665
666
667
668 protected void spawnPoAmendmentForUnorderedItems(ReceivingDocument receivingDocument, PurchaseOrderDocument po) {
669
670
671 if (receivingDocument instanceof LineItemReceivingDocument) {
672 LineItemReceivingDocument rlDoc = (LineItemReceivingDocument) receivingDocument;
673
674
675 if (hasNewUnorderedItem((LineItemReceivingDocument) receivingDocument)) {
676 String newSessionUserId = OLEConstants.SYSTEM_USER;
677 try {
678
679 LogicContainer logicToRun = new LogicContainer() {
680 @Override
681 public Object runLogic(Object[] objects) throws Exception {
682 LineItemReceivingDocument rlDoc = (LineItemReceivingDocument) objects[0];
683 String poDocNumber = (String) objects[1];
684
685
686 PurchaseOrderAmendmentDocument amendmentPo = (PurchaseOrderAmendmentDocument) purchaseOrderService.createAndSavePotentialChangeDocument(poDocNumber, PurchaseOrderDocTypes.PURCHASE_ORDER_AMENDMENT_DOCUMENT, PurchaseOrderStatuses.APPDOC_AMENDMENT);
687
688
689 addUnorderedItemsToAmendment(amendmentPo, rlDoc);
690
691
692
693
694 documentService.saveDocument(amendmentPo);
695
696 String note = "Purchase Order Amendment " + amendmentPo.getPurapDocumentIdentifier() + " (document id " + amendmentPo.getDocumentNumber() + ") created for new unordered line items due to Receiving (document id " + rlDoc.getDocumentNumber() + ")";
697
698 Note noteObj = documentService.createNoteFromDocument(amendmentPo, note);
699 amendmentPo.addNote(noteObj);
700 noteService.save(noteObj);
701
702 return null;
703 }
704 };
705
706 purapService.performLogicWithFakedUserSession(newSessionUserId, logicToRun, new Object[]{rlDoc, po.getDocumentNumber()});
707 } catch (WorkflowException e) {
708 String errorMsg = "Workflow Exception caught: " + e.getLocalizedMessage();
709 throw new RuntimeException(errorMsg, e);
710 } catch (Exception e) {
711 throw new RuntimeException(e);
712 }
713 }
714 }
715 }
716
717
718
719
720
721
722
723 @Override
724 public boolean hasNewUnorderedItem(LineItemReceivingDocument rlDoc) {
725
726 boolean itemAdded = false;
727
728 for (LineItemReceivingItem rlItem : (List<LineItemReceivingItem>) rlDoc.getItems()) {
729 if (PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE.equals(rlItem.getItemTypeCode()) &&
730 !StringUtils.isEmpty(rlItem.getItemReasonAddedCode())) {
731 itemAdded = true;
732 break;
733 }
734 }
735
736 return itemAdded;
737 }
738
739
740
741
742
743
744
745 protected void addUnorderedItemsToAmendment(PurchaseOrderAmendmentDocument amendment, LineItemReceivingDocument rlDoc) {
746
747 PurchaseOrderItem poi = null;
748
749
750
751 for (OleLineItemReceivingItem rlItem : (List<OleLineItemReceivingItem>) rlDoc.getItems()) {
752
753 if (PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE.equals(rlItem.getItemTypeCode()) &&
754 !StringUtils.isEmpty(rlItem.getItemReasonAddedCode())) {
755
756 poi = createPoItemFromReceivingLine(rlItem);
757 poi.setDocumentNumber(amendment.getDocumentNumber());
758
759
760 if (purchaseOrderService.isCommodityCodeRequiredOnPurchaseOrder() && StringUtils.isEmpty(poi.getPurchasingCommodityCode())) {
761 String defaultCommodityCode = SpringContext.getBean(ParameterService.class).getParameterValueAsString(PurchaseOrderAmendmentDocument.class, PurapParameterConstants.UNORDERED_ITEM_DEFAULT_COMMODITY_CODE);
762 poi.setPurchasingCommodityCode(defaultCommodityCode);
763 }
764 poi.refreshNonUpdateableReferences();
765 amendment.addItem(poi);
766 }
767 }
768
769 }
770
771
772
773
774
775
776
777 protected PurchaseOrderItem createPoItemFromReceivingLine(LineItemReceivingItem rlItem) {
778
779 OlePurchaseOrderItem opoi = new OlePurchaseOrderItem();
780 PurchaseOrderItem poi = new OlePurchaseOrderItem();
781
782 poi.setItemActiveIndicator(true);
783 poi.setItemTypeCode(rlItem.getItemTypeCode());
784 poi.setItemLineNumber(rlItem.getItemLineNumber());
785 poi.setItemCatalogNumber(rlItem.getItemCatalogNumber());
786 poi.setItemDescription(rlItem.getItemDescription());
787
788 if (rlItem.getItemReturnedTotalQuantity() == null) {
789 poi.setItemQuantity(rlItem.getItemReceivedTotalQuantity());
790 } else {
791 poi.setItemQuantity(rlItem.getItemReceivedTotalQuantity().subtract(rlItem.getItemReturnedTotalQuantity()));
792 }
793
794 poi.setItemUnitOfMeasureCode(rlItem.getItemUnitOfMeasureCode());
795 poi.setItemUnitPrice(new BigDecimal(0));
796
797 poi.setItemDamagedTotalQuantity(rlItem.getItemDamagedTotalQuantity());
798 poi.setItemReceivedTotalQuantity(rlItem.getItemReceivedTotalQuantity());
799
800 return poi;
801 }
802
803
804
805
806
807
808
809
810 protected OlePurchaseOrderItem createPoItemFromReceivingLine(OleLineItemReceivingItem rlItem) {
811
812
813
814
815 OlePurchaseOrderItem poi = new OlePurchaseOrderItem();
816
817 poi.setItemTitleId(rlItem.getItemTitleId());
818 poi.setItemActiveIndicator(true);
819 poi.setItemTypeCode(rlItem.getItemTypeCode());
820 poi.setItemLineNumber(rlItem.getItemLineNumber());
821 poi.setItemCatalogNumber(rlItem.getItemCatalogNumber());
822 poi.setItemDescription(rlItem.getItemDescription());
823
824 if (rlItem.getItemReturnedTotalQuantity() == null) {
825 poi.setItemQuantity(rlItem.getItemReceivedTotalQuantity());
826 } else {
827 poi.setItemQuantity(rlItem.getItemReceivedTotalQuantity().subtract(rlItem.getItemReturnedTotalQuantity()));
828 }
829
830 poi.setItemUnitOfMeasureCode(rlItem.getItemUnitOfMeasureCode());
831 poi.setItemUnitPrice(new BigDecimal(0));
832
833 poi.setItemDamagedTotalQuantity(rlItem.getItemDamagedTotalQuantity());
834 poi.setItemReceivedTotalQuantity(rlItem.getItemReceivedTotalQuantity());
835 poi.setItemNoOfParts(new KualiInteger(rlItem.getItemReceivedTotalParts().intValue()));
836
837 List<OleCopy> copyList = rlItem.getCopyList() != null ? rlItem.getCopyList() : new ArrayList<OleCopy>();
838 Integer receivedCount = 0;
839 for (OleCopy oleCopy : copyList) {
840 if (oleCopy.getReceiptStatus().equalsIgnoreCase("Received")) {
841 receivedCount++;
842 }
843 }
844 if (receivedCount == 0) {
845 rlItem
846 .setReceiptStatusId(getReceiptStatusDetails(OLEConstants.PO_RECEIPT_STATUS_NOT_RECEIVED));
847 } else if (receivedCount == copyList.size()) {
848 rlItem
849 .setReceiptStatusId(getReceiptStatusDetails(OLEConstants.PO_RECEIPT_STATUS_FULLY_RECEIVED));
850 } else {
851 rlItem
852 .setReceiptStatusId(getReceiptStatusDetails(OLEConstants.PO_RECEIPT_STATUS_PARTIALLY_RECEIVED));
853 }
854 poi.setReceiptStatusId(rlItem.getReceiptStatusId());
855 if (poi.getItemQuantity().equals(new KualiDecimal(1)) && poi.getItemNoOfParts().isGreaterThan(new KualiInteger(1))) {
856 poi.setNoOfCopiesReceived("N/A");
857 poi.setNoOfPartsReceived(receivedCount.toString());
858 } else if (poi.getItemQuantity().isGreaterThan(new KualiDecimal(1)) && poi.getItemNoOfParts().equals(new KualiDecimal(1))) {
859 poi.setNoOfCopiesReceived(receivedCount.toString());
860 poi.setNoOfPartsReceived("N/A");
861 } else if (poi.getItemQuantity().isGreaterThan(new KualiDecimal(1)) && poi.getItemNoOfParts().isGreaterThan(new KualiInteger(1))) {
862 poi.setNoOfCopiesReceived("See Copies Section");
863 poi.setNoOfPartsReceived("See Copies Section");
864 }
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 return poi;
912 }
913
914
915
916
917
918
919
920 protected List<AdHocRoutePerson> createFyiFiscalOfficerList(ReceivingDocument recDoc) {
921
922 PurchaseOrderDocument po = recDoc.getPurchaseOrderDocument();
923 List<AdHocRoutePerson> adHocRoutePersons = new ArrayList<AdHocRoutePerson>();
924 Map fiscalOfficers = new HashMap();
925 AdHocRoutePerson adHocRoutePerson = null;
926
927 for (ReceivingItem recItem : (List<ReceivingItem>) recDoc.getItems()) {
928
929 if (ObjectUtils.isNotNull(recItem.getItemLineNumber())) {
930 PurchaseOrderItem poItem = (PurchaseOrderItem) po.getItemByLineNumber(recItem.getItemLineNumber());
931
932 if (poItem.getItemQuantity().isLessThan(poItem.getItemReceivedTotalQuantity()) ||
933 recItem.getItemDamagedTotalQuantity().isGreaterThan(KualiDecimal.ZERO)) {
934
935
936 for (PurApAccountingLine account : poItem.getSourceAccountingLines()) {
937
938
939 if (fiscalOfficers.containsKey(account.getAccount().getAccountFiscalOfficerUser().getPrincipalName()) == false) {
940
941
942 fiscalOfficers.put(account.getAccount().getAccountFiscalOfficerUser().getPrincipalName(), account.getAccount().getAccountFiscalOfficerUser().getPrincipalName());
943
944
945 adHocRoutePerson = new AdHocRoutePerson();
946 adHocRoutePerson.setId(account.getAccount().getAccountFiscalOfficerUser().getPrincipalName());
947 adHocRoutePerson.setActionRequested(OLEConstants.WORKFLOW_FYI_REQUEST);
948 adHocRoutePersons.add(adHocRoutePerson);
949 }
950 }
951
952 }
953
954 }
955 }
956
957 return adHocRoutePersons;
958 }
959
960
961
962
963
964
965 protected void sendFyiForItems(ReceivingDocument recDoc) {
966
967 List<AdHocRoutePerson> fyiList = createFyiFiscalOfficerList(recDoc);
968 String annotation = "Notification of Item exceeded Quantity or Damaged" + "(document id " + recDoc.getDocumentNumber() + ")";
969 String responsibilityNote = "Please Review";
970
971 for (AdHocRoutePerson adHocPerson : fyiList) {
972 try {
973 recDoc.appSpecificRouteDocumentToUser(
974 recDoc.getDocumentHeader().getWorkflowDocument(),
975 adHocPerson.getPerson().getPrincipalId(),
976 annotation,
977 responsibilityNote);
978 } catch (WorkflowException e) {
979 throw new RuntimeException("Error routing fyi for document with id " + recDoc.getDocumentNumber(), e);
980 }
981
982 }
983 }
984
985 @Override
986 public void addNoteToReceivingDocument(ReceivingDocument receivingDocument, String note) throws Exception {
987 Note noteObj = documentService.createNoteFromDocument(receivingDocument, note);
988 receivingDocument.addNote(noteObj);
989 noteService.save(noteObj);
990 }
991
992 @Override
993 public String getReceivingDeliveryCampusCode(PurchaseOrderDocument po) {
994 String deliveryCampusCode = "";
995 String latestDocumentNumber = "";
996
997 List<LineItemReceivingView> rViews = null;
998 WorkflowDocument workflowDocument = null;
999 DateTime latestCreateDate = null;
1000
1001
1002 if (ObjectUtils.isNotNull(po.getRelatedViews())) {
1003 rViews = po.getRelatedViews().getRelatedLineItemReceivingViews();
1004 }
1005
1006
1007 if (ObjectUtils.isNotNull(rViews) && rViews.isEmpty() == false) {
1008
1009 for (LineItemReceivingView rView : rViews) {
1010 try {
1011 workflowDocument = workflowDocumentService.loadWorkflowDocument(rView.getDocumentNumber(), GlobalVariables.getUserSession().getPerson());
1012
1013
1014 if (ObjectUtils.isNull(latestCreateDate) || latestCreateDate.isBefore(workflowDocument.getDateCreated())) {
1015 latestCreateDate = workflowDocument.getDateCreated();
1016 latestDocumentNumber = workflowDocument.getDocumentId().toString();
1017 }
1018 } catch (WorkflowException we) {
1019 throw new RuntimeException(we);
1020 }
1021 }
1022
1023
1024 if (ObjectUtils.isNotNull(latestCreateDate)) {
1025 try {
1026 LineItemReceivingDocument rlDoc = (LineItemReceivingDocument) documentService.getByDocumentHeaderId(latestDocumentNumber);
1027 deliveryCampusCode = rlDoc.getDeliveryCampusCode();
1028 } catch (WorkflowException we) {
1029 throw new RuntimeException(we);
1030 }
1031 }
1032 }
1033
1034 return deliveryCampusCode;
1035 }
1036
1037
1038
1039
1040 @Override
1041 public boolean isLineItemReceivingDocumentGeneratedForPurchaseOrder(Integer poId) throws RuntimeException {
1042
1043 boolean isGenerated = false;
1044
1045 List<String> docNumbers = receivingDao.getDocumentNumbersByPurchaseOrderId(poId);
1046 WorkflowDocument workflowDocument = null;
1047
1048 for (String docNumber : docNumbers) {
1049
1050 try {
1051 workflowDocument = workflowDocumentService.loadWorkflowDocument(docNumber, GlobalVariables.getUserSession().getPerson());
1052 } catch (WorkflowException we) {
1053 throw new RuntimeException(we);
1054 }
1055
1056 if (workflowDocument.isFinal()) {
1057 isGenerated = true;
1058 break;
1059 }
1060 }
1061
1062 return isGenerated;
1063 }
1064
1065 @Override
1066 public void approveReceivingDocsForPOAmendment() {
1067 List<String> docNumbers = getDocumentsNumbersAwaitingPurchaseOrderOpenStatus();
1068 List<LineItemReceivingDocument> docs = new ArrayList<LineItemReceivingDocument>();
1069 for (String docNumber : docNumbers) {
1070 LineItemReceivingDocument lreq = getLineItemReceivingByDocumentNumber(docNumber);
1071 if (ObjectUtils.isNotNull(lreq)) {
1072 docs.add(lreq);
1073 }
1074 }
1075 if (docs != null) {
1076 for (LineItemReceivingDocument receivingDoc : docs) {
1077 if (receivingDoc.getDocumentHeader().getWorkflowDocument().getCurrentNodeNames().contains(PurapConstants.LineItemReceivingDocumentStrings.AWAITING_PO_OPEN_STATUS)) {
1078 approveReceivingDoc(receivingDoc);
1079 }
1080 }
1081 }
1082
1083 }
1084
1085
1086
1087
1088 public LineItemReceivingDocument getLineItemReceivingByDocumentNumber(String documentNumber) {
1089 LOG.debug("getLineItemReceivingByDocumentNumber() started");
1090
1091 if (ObjectUtils.isNotNull(documentNumber)) {
1092 try {
1093 LineItemReceivingDocument doc = (LineItemReceivingDocument) documentService.getByDocumentHeaderId(documentNumber);
1094 return doc;
1095 } catch (WorkflowException e) {
1096 String errorMessage = "Error getting LineItemReceiving document from document service";
1097 LOG.error("getLineItemReceivingByDocumentNumber() " + errorMessage, e);
1098 throw new RuntimeException(errorMessage, e);
1099 }
1100 }
1101 return null;
1102 }
1103
1104 protected void approveReceivingDoc(LineItemReceivingDocument receivingDoc) {
1105 PurchaseOrderDocument poDoc = receivingDoc.getPurchaseOrderDocument();
1106 if (purchaseOrderService.isPurchaseOrderOpenForProcessing(poDoc)) {
1107 try {
1108 SpringContext.getBean(DocumentService.class).approveDocument(receivingDoc, "Approved by the batch job", null);
1109 } catch (WorkflowException e) {
1110 LOG.error("approveReceivingDoc() Error approving receiving document from awaiting PO open", e);
1111 throw new RuntimeException("Error approving receiving document from awaiting PO open", e);
1112 }
1113 }
1114 }
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125 protected List<String> getDocumentsNumbersAwaitingPurchaseOrderOpenStatus() {
1126 List<String> receivingDocumentNumbers = new ArrayList<String>();
1127
1128 DocumentSearchCriteria.Builder documentSearchCriteriaDTO = DocumentSearchCriteria.Builder.create();
1129 documentSearchCriteriaDTO.setDocumentTypeName(PurapConstants.RECEIVING_LINE_ITEM_DOCUMENT_TYPE);
1130 documentSearchCriteriaDTO.setApplicationDocumentStatus(PurapConstants.LineItemReceivingStatuses.APPDOC_AWAITING_PO_OPEN_STATUS);
1131 documentSearchCriteriaDTO.setSaveName(null);
1132
1133 DocumentSearchResults results = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(null, documentSearchCriteriaDTO.build());
1134
1135 String documentHeaderId = null;
1136
1137 for (DocumentSearchResult result : results.getSearchResults()) {
1138 receivingDocumentNumbers.add(result.getDocument().getDocumentId());
1139 }
1140
1141 return receivingDocumentNumbers;
1142 }
1143
1144 public int getReceiptStatusDetails(String receiptStatusCd) {
1145 int receiptStatusId = 0;
1146 Map<String, String> receiptStatusCdMap = new HashMap<String, String>();
1147 receiptStatusCdMap.put(OLEConstants.RCPT_STATUS_CD, receiptStatusCd);
1148 List<OleReceiptStatus> oleReceiptStatusList = (List) SpringContext.getBean(BusinessObjectService.class)
1149 .findMatching(OleReceiptStatus.class, receiptStatusCdMap);
1150 for (OleReceiptStatus oleReceiptStatus : oleReceiptStatusList) {
1151 receiptStatusId = oleReceiptStatus.getReceiptStatusId().intValue();
1152 }
1153 return receiptStatusId;
1154 }
1155
1156 }
1157