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.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
109
110 @Override
111 public void populateReceivingLineFromPurchaseOrder(LineItemReceivingDocument rlDoc) {
112
113 if (rlDoc == null) {
114 rlDoc = new LineItemReceivingDocument();
115 }
116
117
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
135 LineItemReceivingDocument rlDoc = rcDoc.getLineItemReceivingDocument();
136
137 if (rlDoc != null) {
138 rcDoc.populateCorrectionReceivingFromReceivingLine(rlDoc);
139 }
140
141 }
142
143
144
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
153 throw new RuntimeException(errorMsg, we);
154 }
155 }
156
157
158
159
160 @Override
161 public void populateCorrectionReceivingDocument(CorrectionReceivingDocument rcDoc) {
162 populateCorrectionReceivingFromReceivingLine(rcDoc);
163 }
164
165
166
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
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
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
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
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
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
401 if (currentMessage.length() > 0) {
402
403 appendDuplicateMessage(currentMessage, PurapKeyConstants.MESSAGE_DUPLICATE_RECEIVING_LINE_SUFFIX, rlDoc.getPurchaseOrderIdentifier());
404
405
406 msgs.put(PurapConstants.LineItemReceivingDocumentStrings.DUPLICATE_RECEIVING_LINE_QUESTION, currentMessage.toString());
407 }
408
409 return msgs;
410 }
411
412
413
414
415
416
417
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
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
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
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
481
482
483
484 @Override
485 public void completeReceivingDocument(ReceivingDocument receivingDocument) {
486
487 PurchaseOrderDocument poDoc = null;
488
489 if (receivingDocument instanceof LineItemReceivingDocument) {
490
491 purapService.deleteUnenteredItems(receivingDocument);
492 poDoc = receivingDocument.getPurchaseOrderDocument();
493
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
502
503
504
505
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
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
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
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
667
668
669
670
671 protected void spawnPoAmendmentForUnorderedItems(ReceivingDocument receivingDocument, PurchaseOrderDocument po) {
672
673
674 if (receivingDocument instanceof LineItemReceivingDocument) {
675 LineItemReceivingDocument rlDoc = (LineItemReceivingDocument) receivingDocument;
676
677
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
689 PurchaseOrderAmendmentDocument amendmentPo = (PurchaseOrderAmendmentDocument) purchaseOrderService.createAndSavePotentialChangeDocument(poDocNumber, PurchaseOrderDocTypes.PURCHASE_ORDER_AMENDMENT_DOCUMENT, PurchaseOrderStatuses.APPDOC_AMENDMENT);
690
691
692 addUnorderedItemsToAmendment(amendmentPo, rlDoc);
693
694
695
696
697 documentService.saveDocument(amendmentPo);
698
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
722
723
724
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
744
745
746
747
748 protected void addUnorderedItemsToAmendment(PurchaseOrderAmendmentDocument amendment, LineItemReceivingDocument rlDoc) {
749
750 PurchaseOrderItem poi = null;
751
752
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
762
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
776
777
778
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
809
810
811
812
813 protected OlePurchaseOrderItem createPoItemFromReceivingLine(OleLineItemReceivingItem rlItem) {
814
815
816
817
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
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
913
914 return poi;
915 }
916
917
918
919
920
921
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
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
939 for (PurApAccountingLine account : poItem.getSourceAccountingLines()) {
940
941
942 if (fiscalOfficers.containsKey(account.getAccount().getAccountFiscalOfficerUser().getPrincipalName()) == false) {
943
944
945 fiscalOfficers.put(account.getAccount().getAccountFiscalOfficerUser().getPrincipalName(), account.getAccount().getAccountFiscalOfficerUser().getPrincipalName());
946
947
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
965
966
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
1005 if (ObjectUtils.isNotNull(po.getRelatedViews())) {
1006 rViews = po.getRelatedViews().getRelatedLineItemReceivingViews();
1007 }
1008
1009
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
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
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
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
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
1121
1122
1123
1124
1125
1126
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