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.collections.CollectionUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.apache.commons.lang.text.StrBuilder;
21  import org.kuali.ole.module.purap.PurapConstants;
22  import org.kuali.ole.module.purap.PurapConstants.CreditMemoStatuses;
23  import org.kuali.ole.module.purap.PurapKeyConstants;
24  import org.kuali.ole.module.purap.PurapParameterConstants;
25  import org.kuali.ole.module.purap.PurapPropertyConstants;
26  import org.kuali.ole.module.purap.businessobject.*;
27  import org.kuali.ole.module.purap.document.*;
28  import org.kuali.ole.module.purap.document.dataaccess.CreditMemoDao;
29  import org.kuali.ole.module.purap.document.service.*;
30  import org.kuali.ole.module.purap.document.validation.event.AttributedContinuePurapEvent;
31  import org.kuali.ole.module.purap.service.PurapAccountingService;
32  import org.kuali.ole.module.purap.service.PurapGeneralLedgerService;
33  import org.kuali.ole.module.purap.util.ExpiredOrClosedAccountEntry;
34  import org.kuali.ole.module.purap.util.VendorGroupingHelper;
35  import org.kuali.ole.select.document.OleVendorCreditMemoDocument;
36  import org.kuali.ole.sys.businessobject.Bank;
37  import org.kuali.ole.sys.businessobject.SourceAccountingLine;
38  import org.kuali.ole.sys.context.SpringContext;
39  import org.kuali.ole.sys.service.BankService;
40  import org.kuali.ole.vnd.VendorConstants;
41  import org.kuali.ole.vnd.VendorUtils;
42  import org.kuali.ole.vnd.businessobject.VendorAddress;
43  import org.kuali.ole.vnd.businessobject.VendorDetail;
44  import org.kuali.ole.vnd.document.service.VendorService;
45  import org.kuali.rice.core.api.config.property.ConfigurationService;
46  import org.kuali.rice.core.api.util.type.KualiDecimal;
47  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
48  import org.kuali.rice.kew.api.KewApiServiceLocator;
49  import org.kuali.rice.kew.api.WorkflowDocument;
50  import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
51  import org.kuali.rice.kew.api.document.search.DocumentSearchResult;
52  import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
53  import org.kuali.rice.kew.api.exception.WorkflowException;
54  import org.kuali.rice.kim.api.identity.Person;
55  import org.kuali.rice.kns.service.DataDictionaryService;
56  import org.kuali.rice.krad.bo.DocumentHeader;
57  import org.kuali.rice.krad.bo.Note;
58  import org.kuali.rice.krad.exception.ValidationException;
59  import org.kuali.rice.krad.service.DocumentService;
60  import org.kuali.rice.krad.service.NoteService;
61  import org.kuali.rice.krad.util.GlobalVariables;
62  import org.kuali.rice.krad.util.KRADPropertyConstants;
63  import org.kuali.rice.krad.util.ObjectUtils;
64  import org.kuali.rice.krad.workflow.service.WorkflowDocumentService;
65  import org.springframework.transaction.annotation.Transactional;
66  
67  import java.math.BigDecimal;
68  import java.sql.Date;
69  import java.sql.Timestamp;
70  import java.util.*;
71  
72  
73  
74  
75  @Transactional
76  public class CreditMemoServiceImpl implements CreditMemoService {
77      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CreditMemoServiceImpl.class);
78  
79      private AccountsPayableService accountsPayableService;
80      private CreditMemoDao creditMemoDao;
81      private DataDictionaryService dataDictionaryService;
82      private DocumentService documentService;
83      private ConfigurationService kualiConfigurationService;
84      private NoteService noteService;
85      private PaymentRequestService paymentRequestService;
86      private PurapAccountingService purapAccountingService;
87      private PurapGeneralLedgerService purapGeneralLedgerService;
88      private PurapService purapService;
89      private PurchaseOrderService purchaseOrderService;
90      private VendorService vendorService;
91      private WorkflowDocumentService workflowDocumentService;
92  
93  
94      public void setAccountsPayableService(AccountsPayableService accountsPayableService) {
95          this.accountsPayableService = accountsPayableService;
96      }
97  
98      public void setCreditMemoDao(CreditMemoDao creditMemoDao) {
99          this.creditMemoDao = creditMemoDao;
100     }
101 
102     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
103         this.dataDictionaryService = dataDictionaryService;
104     }
105 
106     public void setDocumentService(DocumentService documentService) {
107         this.documentService = documentService;
108     }
109 
110     public void setConfigurationService(ConfigurationService kualiConfigurationService) {
111         this.kualiConfigurationService = kualiConfigurationService;
112     }
113 
114     public void setNoteService(NoteService noteService) {
115         this.noteService = noteService;
116     }
117 
118     public void setPaymentRequestService(PaymentRequestService paymentRequestService) {
119         this.paymentRequestService = paymentRequestService;
120     }
121 
122     public void setPurapAccountingService(PurapAccountingService purapAccountingService) {
123         this.purapAccountingService = purapAccountingService;
124     }
125 
126     public void setPurapGeneralLedgerService(PurapGeneralLedgerService purapGeneralLedgerService) {
127         this.purapGeneralLedgerService = purapGeneralLedgerService;
128     }
129 
130     public void setPurapService(PurapService purapService) {
131         this.purapService = purapService;
132     }
133 
134     public void setPurchaseOrderService(PurchaseOrderService purchaseOrderService) {
135         this.purchaseOrderService = purchaseOrderService;
136     }
137 
138     public void setVendorService(VendorService vendorService) {
139         this.vendorService = vendorService;
140     }
141 
142     public void setWorkflowDocumentService(WorkflowDocumentService workflowDocumentService) {
143         this.workflowDocumentService = workflowDocumentService;
144     }
145 
146 
147     
148 
149 
150     @Override
151     public List<VendorCreditMemoDocument> getCreditMemosToExtract(String chartCode) {
152         LOG.debug("getCreditMemosToExtract() started");
153 
154         List<VendorCreditMemoDocument> docs = creditMemoDao.getCreditMemosToExtract(chartCode);
155         docs = (List<VendorCreditMemoDocument>) filterCreditMemoByAppDocStatus(docs, CreditMemoStatuses.STATUSES_ALLOWED_FOR_EXTRACTION);
156 
157         return docs;
158 
159     }
160 
161     @Override
162     public Collection<VendorCreditMemoDocument> getCreditMemosToExtractByVendor(String chartCode, VendorGroupingHelper vendor) {
163         LOG.debug("getCreditMemosToExtractByVendor() started");
164 
165         Collection<VendorCreditMemoDocument> docs = creditMemoDao.getCreditMemosToExtractByVendor(chartCode, vendor);
166         docs = filterCreditMemoByAppDocStatus(docs, CreditMemoStatuses.STATUSES_ALLOWED_FOR_EXTRACTION);
167         return docs;
168 
169     }
170 
171     @Override
172     public Set<VendorGroupingHelper> getVendorsOnCreditMemosToExtract(String chartCode) {
173         LOG.debug("getVendorsOnCreditMemosToExtract() started");
174         HashSet<VendorGroupingHelper> vendors = new HashSet<VendorGroupingHelper>();
175 
176         List<VendorCreditMemoDocument> docs = this.getCreditMemosToExtract(chartCode);
177 
178         for(VendorCreditMemoDocument vendorCreditMemoDocument : docs) {
179             vendors.add(new VendorGroupingHelper(vendorCreditMemoDocument));
180         }
181 
182 
183         
184         
185         
186         return vendors;
187     }
188 
189     
190 
191 
192 
193 
194 
195 
196 
197 
198 
199 
200     private List<String> filterCreditMemoByAppDocStatus(List<String> lookupDocNumbers, String... appDocStatus) {
201         boolean valid = false;
202 
203         final String DOC_NUM_DELIM = "|";
204         StrBuilder routerHeaderIdBuilder = new StrBuilder().appendWithSeparators(lookupDocNumbers, DOC_NUM_DELIM);
205 
206         List<String> creditMemoDocNumbers = new ArrayList<String>();
207 
208         DocumentSearchCriteria.Builder documentSearchCriteriaDTO = DocumentSearchCriteria.Builder.create();
209         documentSearchCriteriaDTO.setDocumentId(routerHeaderIdBuilder.toString());
210         documentSearchCriteriaDTO.setDocumentTypeName(PurapConstants.PurapDocTypeCodes.CREDIT_MEMO_DOCUMENT);
211 
212         DocumentSearchResults creditMemoDocumentsList = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(
213                 GlobalVariables.getUserSession().getPrincipalId(), documentSearchCriteriaDTO.build());
214 
215         for (DocumentSearchResult creditMemoDocument : creditMemoDocumentsList.getSearchResults()) {
216             
217             if (Arrays.asList(appDocStatus).contains(creditMemoDocument.getDocument().getApplicationDocumentStatus())) {
218                 
219                 creditMemoDocNumbers.add(creditMemoDocument.getDocument().getDocumentId());
220             }
221         }
222 
223         return creditMemoDocNumbers;
224     }
225 
226     
227 
228 
229 
230 
231 
232 
233 
234 
235 
236 
237     private Collection<VendorCreditMemoDocument> filterCreditMemoByAppDocStatus(Collection<VendorCreditMemoDocument> creditMemoDocuments, String... appDocStatus) {
238         List<String> creditMemoDocNumbers = new ArrayList<String>();
239         for (VendorCreditMemoDocument creditMemo : creditMemoDocuments) {
240             creditMemoDocNumbers.add(creditMemo.getDocumentNumber());
241         }
242 
243         List<String> filteredCreditMemoDocNumbers = filterCreditMemoByAppDocStatus(creditMemoDocNumbers, appDocStatus);
244 
245         Collection<VendorCreditMemoDocument> filteredCreditMemoDocuments = new ArrayList<VendorCreditMemoDocument>();
246         
247         for (VendorCreditMemoDocument creditMemo : creditMemoDocuments) {
248             if (filteredCreditMemoDocNumbers.contains(creditMemo.getDocumentNumber())) {
249                 filteredCreditMemoDocuments.add(creditMemo);
250             }
251         }
252         return filteredCreditMemoDocuments;
253     }
254 
255 
256     
257 
258 
259 
260 
261 
262 
263 
264 
265 
266     private Iterator<VendorCreditMemoDocument> filterCreditMemoByAppDocStatus(Iterator<VendorCreditMemoDocument> creditMemoIterator, String... appDocStatus) {
267         Collection<VendorCreditMemoDocument> creditMemoDocuments = new ArrayList<VendorCreditMemoDocument>();
268         for (; creditMemoIterator.hasNext(); ) {
269             creditMemoDocuments.add(creditMemoIterator.next());
270         }
271 
272         return filterCreditMemoByAppDocStatus(creditMemoDocuments, appDocStatus).iterator();
273     }
274 
275     
276 
277 
278     @Override
279     public String creditMemoDuplicateMessages(VendorCreditMemoDocument cmDocument) {
280         String duplicateMessage = null;
281 
282         String vendorNumber = cmDocument.getVendorNumber();
283         if (StringUtils.isEmpty(vendorNumber)) {
284             PurchasingAccountsPayableDocument sourceDocument = cmDocument.getPurApSourceDocumentIfPossible();
285             if (ObjectUtils.isNotNull(sourceDocument)) {
286                 vendorNumber = sourceDocument.getVendorNumber();
287             }
288         }
289 
290         if (StringUtils.isNotEmpty(vendorNumber)) {
291             
292             if (creditMemoDao.duplicateExists(VendorUtils.getVendorHeaderId(vendorNumber), VendorUtils.getVendorDetailId(vendorNumber), cmDocument.getCreditMemoNumber())) {
293                 duplicateMessage = kualiConfigurationService.getPropertyValueAsString(PurapKeyConstants.MESSAGE_DUPLICATE_CREDIT_MEMO_VENDOR_NUMBER);
294             }
295 
296             
297             if (creditMemoDao.duplicateExists(VendorUtils.getVendorHeaderId(vendorNumber), VendorUtils.getVendorDetailId(vendorNumber), cmDocument.getCreditMemoDate(), cmDocument.getCreditMemoAmount())) {
298                 duplicateMessage = kualiConfigurationService.getPropertyValueAsString(PurapKeyConstants.MESSAGE_DUPLICATE_CREDIT_MEMO_VENDOR_NUMBER_DATE_AMOUNT);
299             }
300         }
301 
302         return duplicateMessage;
303     }
304 
305     
306 
307 
308     @Override
309     public List<PurchaseOrderItem> getPOInvoicedItems(PurchaseOrderDocument poDocument) {
310         List<PurchaseOrderItem> invoicedItems = new ArrayList<PurchaseOrderItem>();
311 
312         for (Iterator iter = poDocument.getItems().iterator(); iter.hasNext(); ) {
313             PurchaseOrderItem poItem = (PurchaseOrderItem) iter.next();
314 
315             
316             if (poItem.getItemType().isAdditionalChargeIndicator()) {
317                 continue;
318             }
319 
320             if (poItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && poItem.getItemInvoicedTotalQuantity().isGreaterThan(KualiDecimal.ZERO)) {
321                 invoicedItems.add(poItem);
322             } else {
323                 BigDecimal unitPrice = (poItem.getItemUnitPrice() == null ? new BigDecimal(0) : poItem.getItemUnitPrice());
324                 if (unitPrice.doubleValue() > poItem.getItemOutstandingEncumberedAmount().doubleValue()) {
325                     invoicedItems.add(poItem);
326                 }
327             }
328         }
329 
330         return invoicedItems;
331     }
332 
333 
334     
335 
336 
337     @Override
338     public void calculateCreditMemo(VendorCreditMemoDocument cmDocument) {
339 
340         cmDocument.updateExtendedPriceOnItems();
341 
342         for (CreditMemoItem item : (List<CreditMemoItem>) cmDocument.getItems()) {
343             
344             if (StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_RESTCK_FEE_CODE, item.getItemTypeCode())) {
345                 if (item.getItemUnitPrice() != null) {
346                     item.setExtendedPrice(item.getExtendedPrice().abs().negated());
347                     item.setItemUnitPrice(item.getItemUnitPrice().abs().negate());
348                 }
349             }
350         }
351 
352         
353         if (cmDocument.isSourceVendor() == false) {
354             purapService.calculateTax(cmDocument);
355         }
356 
357         
358         if (cmDocument.isSourceVendor()) {
359             
360             return;
361         }
362 
363         for (CreditMemoItem item : (List<CreditMemoItem>) cmDocument.getItems()) {
364 
365             
366             if (item.getItemType().isLineItemIndicator()) {
367                 continue;
368             }
369 
370             if ((item.getSourceAccountingLines().isEmpty()) && (ObjectUtils.isNotNull(item.getExtendedPrice())) && (KualiDecimal.ZERO.compareTo(item.getExtendedPrice()) != 0)) {
371 
372                 KualiDecimal totalAmount = KualiDecimal.ZERO;
373                 List<PurApAccountingLine> distributedAccounts = null;
374                 List<SourceAccountingLine> summaryAccounts = null;
375 
376                 totalAmount = cmDocument.getPurApSourceDocumentIfPossible().getTotalDollarAmount();
377                 
378                 purapAccountingService.updateAccountAmounts(cmDocument.getPurApSourceDocumentIfPossible());
379                 summaryAccounts = purapAccountingService.generateSummary(cmDocument.getPurApSourceDocumentIfPossible().getItems());
380                 distributedAccounts = purapAccountingService.generateAccountDistributionForProration(summaryAccounts, totalAmount, PurapConstants.PRORATION_SCALE, CreditMemoAccount.class);
381 
382                 if (CollectionUtils.isNotEmpty(distributedAccounts) && CollectionUtils.isEmpty(item.getSourceAccountingLines())) {
383                     item.setSourceAccountingLines(distributedAccounts);
384                 }
385             }
386         }
387         
388     }
389 
390     
391 
392 
393     @Override
394     public VendorCreditMemoDocument getCreditMemoByDocumentNumber(String documentNumber) {
395         LOG.debug("getCreditMemoByDocumentNumber() started");
396 
397         if (ObjectUtils.isNotNull(documentNumber)) {
398             try {
399                 VendorCreditMemoDocument doc = (VendorCreditMemoDocument) documentService.getByDocumentHeaderId(documentNumber);
400                 return doc;
401             } catch (WorkflowException e) {
402                 String errorMessage = "Error getting credit memo document from document service";
403                 LOG.error("getCreditMemoByDocumentNumber() " + errorMessage, e);
404                 throw new RuntimeException(errorMessage, e);
405             }
406         }
407         return null;
408     }
409 
410     
411 
412 
413     @Override
414     public VendorCreditMemoDocument getCreditMemoDocumentById(Integer purchasingDocumentIdentifier) {
415         return getCreditMemoByDocumentNumber(creditMemoDao.getDocumentNumberByCreditMemoId(purchasingDocumentIdentifier));
416     }
417 
418     
419 
420 
421     @Override
422     public void populateAndSaveCreditMemo(VendorCreditMemoDocument document) {
423         try {
424             
425             
426             document.updateAndSaveAppDocStatus(PurapConstants.CreditMemoStatuses.APPDOC_IN_PROCESS);
427 
428             if (document.isSourceDocumentPaymentRequest()) {
429                 document.setBankCode(document.getPaymentRequestDocument().getBankCode());
430                 document.setBank(document.getPaymentRequestDocument().getBank());
431             } else {
432                 
433                 Bank defaultBank = SpringContext.getBean(BankService.class).getDefaultBankByDocType(document.getClass());
434                 if (defaultBank != null) {
435                     document.setBankCode(defaultBank.getBankCode());
436                     document.setBank(defaultBank);
437                 }
438             }
439 
440             documentService.saveDocument(document, AttributedContinuePurapEvent.class);
441         } catch (ValidationException ve) {
442             
443             try {
444                 document.updateAndSaveAppDocStatus(PurapConstants.CreditMemoStatuses.APPDOC_INITIATE);
445             } catch (WorkflowException workflowException) {
446 
447             }
448         } catch (WorkflowException we) {
449             
450             try {
451                 document.updateAndSaveAppDocStatus(PurapConstants.CreditMemoStatuses.APPDOC_INITIATE);
452             } catch (WorkflowException workflowException) {
453 
454             }
455             String errorMsg = "Error saving document # " + document.getDocumentNumber() + " " + we.getMessage();
456             LOG.error(errorMsg, we);
457             throw new RuntimeException(errorMsg, we);
458         }
459     }
460 
461     
462 
463 
464     @Override
465     public void reopenClosedPO(VendorCreditMemoDocument cmDocument) {
466         
467         Integer purchaseOrderDocumentId = cmDocument.getPurchaseOrderIdentifier();
468         if (cmDocument.isSourceDocumentPaymentRequest() && ObjectUtils.isNull(purchaseOrderDocumentId)) {
469             PaymentRequestDocument paymentRequestDocument = paymentRequestService.getPaymentRequestById(cmDocument.getPaymentRequestIdentifier());
470             purchaseOrderDocumentId = paymentRequestDocument.getPurchaseOrderIdentifier();
471         }
472         
473         if (ObjectUtils.isNotNull(purchaseOrderDocumentId)) {
474             PurchaseOrderDocument purchaseOrderDocument = purchaseOrderService.getCurrentPurchaseOrder(purchaseOrderDocumentId);
475             
476             if (ObjectUtils.isNotNull(purchaseOrderDocument) && (!purchaseOrderDocument.isPendingActionIndicator()) && PurapConstants.PurchaseOrderStatuses.APPDOC_CLOSED.equals(purchaseOrderDocument.getApplicationDocumentStatus())) {
477 
478             }
479         }
480     }
481 
482     
483 
484 
485 
486     @Override
487     public VendorCreditMemoDocument addHoldOnCreditMemo(VendorCreditMemoDocument cmDocument, String note) throws Exception {
488         
489         Note noteObj = documentService.createNoteFromDocument(cmDocument, note);
490         cmDocument.addNote(noteObj);
491         noteService.save(noteObj);
492 
493         
494         VendorCreditMemoDocument cmDoc = getCreditMemoDocumentById(cmDocument.getPurapDocumentIdentifier());
495         cmDoc.setHoldIndicator(true);
496         cmDoc.setLastActionPerformedByPersonId(GlobalVariables.getUserSession().getPerson().getPrincipalId());
497         purapService.saveDocumentNoValidation(cmDoc);
498 
499         
500         cmDocument.setHoldIndicator(true);
501         cmDocument.setLastActionPerformedByPersonId(GlobalVariables.getUserSession().getPerson().getPrincipalId());
502 
503         return cmDoc;
504     }
505 
506     
507 
508 
509 
510     @Override
511     public VendorCreditMemoDocument removeHoldOnCreditMemo(VendorCreditMemoDocument cmDocument, String note) throws Exception {
512         
513         Note noteObj = documentService.createNoteFromDocument(cmDocument, note);
514         cmDocument.addNote(noteObj);
515         noteService.save(noteObj);
516 
517         
518         VendorCreditMemoDocument cmDoc = getCreditMemoDocumentById(cmDocument.getPurapDocumentIdentifier());
519         cmDoc.setHoldIndicator(false);
520         cmDoc.setLastActionPerformedByPersonId(null);
521         purapService.saveDocumentNoValidation(cmDoc);
522 
523         
524         cmDocument.setHoldIndicator(false);
525         cmDocument.setLastActionPerformedByPersonId(null);
526 
527         return cmDoc;
528     }
529 
530     
531 
532 
533     @Override
534     public String updateStatusByNode(String currentNodeName, AccountsPayableDocument apDoc) {
535         return updateStatusByNode(currentNodeName, (VendorCreditMemoDocument) apDoc);
536     }
537 
538     
539 
540 
541 
542 
543 
544 
545     protected String updateStatusByNode(String currentNodeName, VendorCreditMemoDocument cmDoc) {
546         
547 
548         String cancelledStatusCode = "";
549         if (StringUtils.isEmpty(currentNodeName)) {
550             cancelledStatusCode = PurapConstants.CreditMemoStatuses.APPDOC_CANCELLED_POST_AP_APPROVE;
551         } else {
552             cancelledStatusCode = CreditMemoStatuses.getCreditMemoAppDocDisapproveStatuses().get(currentNodeName);
553         }
554 
555         if (StringUtils.isNotBlank(cancelledStatusCode)) {
556             try {
557                 cmDoc.updateAndSaveAppDocStatus(cancelledStatusCode);
558             } catch (WorkflowException we) {
559                 throw new RuntimeException("Unable to save the workflow document with document id: " + cmDoc.getDocumentNumber());
560             }
561             purapService.saveDocumentNoValidation(cmDoc);
562             return cancelledStatusCode;
563         } else {
564             logAndThrowRuntimeException("No status found to set for document being disapproved in node '" + currentNodeName + "'");
565         }
566         return cancelledStatusCode;
567     }
568 
569     
570 
571 
572 
573     @Override
574     public void cancelExtractedCreditMemo(VendorCreditMemoDocument cmDocument, String note) {
575         LOG.debug("cancelExtractedCreditMemo() started");
576         if (CreditMemoStatuses.CANCELLED_STATUSES.contains(cmDocument.getApplicationDocumentStatus())) {
577             LOG.debug("cancelExtractedCreditMemo() ended");
578             return;
579         }
580 
581         try {
582             Note noteObj = documentService.createNoteFromDocument(cmDocument, note);
583             cmDocument.addNote(noteObj);
584         } catch (Exception e) {
585             throw new RuntimeException(e.getMessage());
586         }
587 
588         accountsPayableService.cancelAccountsPayableDocument(cmDocument, "");
589         if (LOG.isDebugEnabled()) {
590             LOG.debug("cancelExtractedCreditMemo() CM " + cmDocument.getPurapDocumentIdentifier() + " Cancelled Without Workflow");
591         }
592         LOG.debug("cancelExtractedCreditMemo() ended");
593 
594     }
595 
596     
597 
598 
599 
600     @Override
601     public void resetExtractedCreditMemo(VendorCreditMemoDocument cmDocument, String note) {
602         LOG.debug("resetExtractedCreditMemo() started");
603         if (CreditMemoStatuses.CANCELLED_STATUSES.contains(cmDocument.getApplicationDocumentStatus())) {
604             LOG.debug("resetExtractedCreditMemo() ended");
605             return;
606         }
607         cmDocument.setExtractedTimestamp(null);
608         cmDocument.setCreditMemoPaidTimestamp(null);
609 
610         Note noteObj;
611         try {
612             noteObj = documentService.createNoteFromDocument(cmDocument, note);
613             cmDocument.addNote(noteObj);
614         } catch (Exception e) {
615             throw new RuntimeException(e.getMessage());
616         }
617         purapService.saveDocumentNoValidation(cmDocument);
618 
619         if (LOG.isDebugEnabled()) {
620             LOG.debug("resetExtractedCreditMemo() CM " + cmDocument.getPurapDocumentIdentifier() + " Cancelled Without Workflow");
621         }
622         LOG.debug("resetExtractedCreditMemo() ended");
623     }
624 
625     
626 
627 
628     @Override
629     public boolean shouldPurchaseOrderBeReversed(AccountsPayableDocument apDoc) {
630         
631         return false;
632     }
633 
634     
635 
636 
637     @Override
638     public Person getPersonForCancel(AccountsPayableDocument apDoc) {
639         
640         return null;
641     }
642 
643     
644 
645 
646     @Override
647     public void takePurchaseOrderCancelAction(AccountsPayableDocument apDoc) {
648         VendorCreditMemoDocument cmDocument = (VendorCreditMemoDocument) apDoc;
649         if (cmDocument.isReopenPurchaseOrderIndicator()) {
650             String docType = PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_CLOSE_DOCUMENT;
651             purchaseOrderService.createAndRoutePotentialChangeDocument(cmDocument.getPurchaseOrderDocument().getDocumentNumber(), docType, "reopened by Payment Request " + apDoc.getPurapDocumentIdentifier() + "cancel", new ArrayList(), PurapConstants.PurchaseOrderStatuses.APPDOC_PENDING_CLOSE);
652         }
653     }
654 
655     
656 
657 
658 
659     @Override
660     public void markPaid(VendorCreditMemoDocument cm, Date processDate) {
661         LOG.debug("markPaid() started");
662 
663         cm.setCreditMemoPaidTimestamp(new Timestamp(processDate.getTime()));
664         purapService.saveDocumentNoValidation(cm);
665     }
666 
667     
668 
669 
670     @Override
671     public boolean poItemEligibleForAp(AccountsPayableDocument apDoc, PurchaseOrderItem poItem) {
672         
673         if (!poItem.isItemActiveIndicator()) {
674             return false;
675         }
676 
677         if (poItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && poItem.getItemInvoicedTotalQuantity().isGreaterThan(KualiDecimal.ZERO)) {
678             return true;
679         } else {
680             BigDecimal unitPrice = (poItem.getItemUnitPrice() == null ? new BigDecimal(0) : poItem.getItemUnitPrice());
681             if (unitPrice.doubleValue() > poItem.getItemOutstandingEncumberedAmount().doubleValue()) {
682                 return true;
683             }
684         }
685         return false;
686     }
687 
688     
689 
690 
691 
692 
693     @Override
694     public void generateGLEntriesCreateAccountsPayableDocument(AccountsPayableDocument apDocument) {
695         VendorCreditMemoDocument creditMemo = (VendorCreditMemoDocument) apDocument;
696         purapGeneralLedgerService.generateEntriesCreateCreditMemo(creditMemo);
697     }
698 
699     
700 
701 
702 
703 
704     protected void logAndThrowRuntimeException(String errorMessage) {
705         this.logAndThrowRuntimeException(errorMessage, null);
706     }
707 
708     
709 
710 
711 
712 
713 
714     protected void logAndThrowRuntimeException(String errorMessage, Exception e) {
715         if (ObjectUtils.isNotNull(e)) {
716             LOG.error(errorMessage, e);
717             throw new RuntimeException(errorMessage, e);
718         } else {
719             LOG.error(errorMessage);
720             throw new RuntimeException(errorMessage);
721         }
722     }
723 
724     
725 
726 
727     @Override
728     public boolean hasActiveCreditMemosForPurchaseOrder(Integer purchaseOrderIdentifier) {
729 
730         boolean hasActiveCreditMemos = false;
731         List<String> docNumbers = null;
732         WorkflowDocument workflowDocument = null;
733 
734         docNumbers = creditMemoDao.getActiveCreditMemoDocumentNumbersForPurchaseOrder(purchaseOrderIdentifier);
735         docNumbers = filterCreditMemoByAppDocStatus(docNumbers, CreditMemoStatuses.STATUSES_POTENTIALLY_ACTIVE);
736 
737         for (String docNumber : docNumbers) {
738             try {
739                 workflowDocument = workflowDocumentService.loadWorkflowDocument(docNumber, GlobalVariables.getUserSession().getPerson());
740             } catch (WorkflowException we) {
741                 throw new RuntimeException(we);
742             }
743 
744             
745             if (!(workflowDocument.isCanceled() ||
746                     workflowDocument.isException() ||
747                     workflowDocument.isFinal())) {
748                 hasActiveCreditMemos = true;
749                 break;
750             }
751 
752         }
753 
754         return hasActiveCreditMemos;
755     }
756 
757     
758 
759 
760     @Override
761     public void populateDocumentAfterInit(VendorCreditMemoDocument cmDocument) {
762 
763         OleVendorCreditMemoDocument vendorCreditMemoDocument = (OleVendorCreditMemoDocument) cmDocument;
764         
765         HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList = accountsPayableService.getExpiredOrClosedAccountList(cmDocument);
766 
767         if (vendorCreditMemoDocument.isSourceDocumentPaymentRequest() && vendorCreditMemoDocument.getInvoiceIdentifier() == null) {
768             populateDocumentFromPreq(vendorCreditMemoDocument, expiredOrClosedAccountList);
769         } else if (vendorCreditMemoDocument.isSourceDocumentPurchaseOrder() && vendorCreditMemoDocument.getInvoiceIdentifier() == null) {
770             populateDocumentFromPO(vendorCreditMemoDocument, expiredOrClosedAccountList);
771         } else if (vendorCreditMemoDocument.getInvoiceIdentifier() != null) {
772             populateDocumentFromVendor(vendorCreditMemoDocument);
773         }
774 
775         populateDocumentDescription(vendorCreditMemoDocument);
776 
777         
778         
779         accountsPayableService.generateExpiredOrClosedAccountNote(cmDocument, expiredOrClosedAccountList);
780 
781         
782         if (ObjectUtils.isNotNull(expiredOrClosedAccountList) && !expiredOrClosedAccountList.isEmpty()) {
783             cmDocument.setContinuationAccountIndicator(true);
784         }
785 
786     }
787 
788     
789 
790 
791 
792 
793     protected void populateDocumentFromPreq(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
794         PaymentRequestDocument paymentRequestDocument = paymentRequestService.getPaymentRequestById(cmDocument.getPaymentRequestIdentifier());
795         cmDocument.getDocumentHeader().setOrganizationDocumentNumber(paymentRequestDocument.getDocumentHeader().getOrganizationDocumentNumber());
796         cmDocument.setPaymentRequestDocument(paymentRequestDocument);
797         cmDocument.setPurchaseOrderDocument(paymentRequestDocument.getPurchaseOrderDocument());
798         cmDocument.setUseTaxIndicator(paymentRequestDocument.isUseTaxIndicator());
799 
800         
801         cmDocument.setVendorHeaderGeneratedIdentifier(paymentRequestDocument.getVendorHeaderGeneratedIdentifier());
802         cmDocument.setVendorDetailAssignedIdentifier(paymentRequestDocument.getVendorDetailAssignedIdentifier());
803         cmDocument.setVendorAddressGeneratedIdentifier(paymentRequestDocument.getVendorAddressGeneratedIdentifier());
804         cmDocument.setVendorCustomerNumber(paymentRequestDocument.getVendorCustomerNumber());
805         cmDocument.setVendorName(paymentRequestDocument.getVendorName());
806         cmDocument.setVendorLine1Address(paymentRequestDocument.getVendorLine1Address());
807         cmDocument.setVendorLine2Address(paymentRequestDocument.getVendorLine2Address());
808         cmDocument.setVendorCityName(paymentRequestDocument.getVendorCityName());
809         cmDocument.setVendorStateCode(paymentRequestDocument.getVendorStateCode());
810         cmDocument.setVendorPostalCode(paymentRequestDocument.getVendorPostalCode());
811         cmDocument.setVendorCountryCode(paymentRequestDocument.getVendorCountryCode());
812         cmDocument.setVendorAttentionName(paymentRequestDocument.getVendorAttentionName());
813         cmDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(paymentRequestDocument.getAccountsPayablePurchasingDocumentLinkIdentifier());
814         cmDocument.setPaymentMethodId(paymentRequestDocument.getVendorDetail().getPaymentMethodId());
815         
816         purapAccountingService.convertMoneyToPercent(paymentRequestDocument);
817         populateItemLinesFromPreq(cmDocument, expiredOrClosedAccountList);
818     }
819 
820     
821 
822 
823 
824 
825     protected void populateItemLinesFromPreq(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
826         PaymentRequestDocument preqDocument = cmDocument.getPaymentRequestDocument();
827 
828         for (PaymentRequestItem preqItemToTemplate : (List<PaymentRequestItem>) preqDocument.getItems()) {
829             preqItemToTemplate.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE);
830 
831             if (preqItemToTemplate.getItemType().isLineItemIndicator() && ((preqItemToTemplate.getItemType().isQuantityBasedGeneralLedgerIndicator() && preqItemToTemplate.getItemQuantity().isNonZero())
832                     || (preqItemToTemplate.getItemType().isAmountBasedGeneralLedgerIndicator() && preqItemToTemplate.getTotalAmount().isNonZero()))) {
833                 cmDocument.getItems().add(new CreditMemoItem(cmDocument, preqItemToTemplate, preqItemToTemplate.getPurchaseOrderItem(), expiredOrClosedAccountList));
834             }
835         }
836 
837         
838         purapService.addBelowLineItems(cmDocument);
839 
840         cmDocument.fixItemReferences();
841     }
842 
843     
844 
845 
846 
847 
848     protected void populateDocumentFromPO(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
849         PurchaseOrderDocument purchaseOrderDocument = purchaseOrderService.getCurrentPurchaseOrder(cmDocument.getPurchaseOrderIdentifier());
850         cmDocument.setPurchaseOrderDocument(purchaseOrderDocument);
851         cmDocument.getDocumentHeader().setOrganizationDocumentNumber(purchaseOrderDocument.getDocumentHeader().getOrganizationDocumentNumber());
852         cmDocument.setUseTaxIndicator(cmDocument.isUseTaxIndicator());
853 
854         cmDocument.setVendorHeaderGeneratedIdentifier(purchaseOrderDocument.getVendorHeaderGeneratedIdentifier());
855         cmDocument.setVendorDetailAssignedIdentifier(purchaseOrderDocument.getVendorDetailAssignedIdentifier());
856         cmDocument.setVendorCustomerNumber(purchaseOrderDocument.getVendorCustomerNumber());
857         cmDocument.setVendorName(purchaseOrderDocument.getVendorName());
858         cmDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(purchaseOrderDocument.getAccountsPayablePurchasingDocumentLinkIdentifier());
859         cmDocument.setPaymentMethodId(purchaseOrderDocument.getVendorDetail().getPaymentMethodId());
860         
861         String userCampus = GlobalVariables.getUserSession().getPerson().getCampusCode();
862         VendorAddress vendorAddress = vendorService.getVendorDefaultAddress(purchaseOrderDocument.getVendorHeaderGeneratedIdentifier(), purchaseOrderDocument.getVendorDetailAssignedIdentifier(), VendorConstants.AddressTypes.REMIT, userCampus);
863         if (vendorAddress != null) {
864             cmDocument.templateVendorAddress(vendorAddress);
865             cmDocument.setVendorAddressGeneratedIdentifier(vendorAddress.getVendorAddressGeneratedIdentifier());
866             cmDocument.setVendorAttentionName(StringUtils.defaultString(vendorAddress.getVendorAttentionName()));
867         } else {
868             
869             cmDocument.setVendorAddressGeneratedIdentifier(purchaseOrderDocument.getVendorAddressGeneratedIdentifier());
870             cmDocument.setVendorLine1Address(purchaseOrderDocument.getVendorLine1Address());
871             cmDocument.setVendorLine2Address(purchaseOrderDocument.getVendorLine2Address());
872             cmDocument.setVendorCityName(purchaseOrderDocument.getVendorCityName());
873             cmDocument.setVendorStateCode(purchaseOrderDocument.getVendorStateCode());
874             cmDocument.setVendorPostalCode(purchaseOrderDocument.getVendorPostalCode());
875             cmDocument.setVendorCountryCode(purchaseOrderDocument.getVendorCountryCode());
876 
877             boolean blankAttentionLine = StringUtils.equalsIgnoreCase("Y", SpringContext.getBean(ParameterService.class).getParameterValueAsString(PurapConstants.PURAP_NAMESPACE, "Document", PurapParameterConstants.BLANK_ATTENTION_LINE_FOR_PO_TYPE_ADDRESS));
878             if (blankAttentionLine) {
879                 cmDocument.setVendorAttentionName(StringUtils.EMPTY);
880             } else {
881                 cmDocument.setVendorAttentionName(StringUtils.defaultString(purchaseOrderDocument.getVendorAttentionName()));
882             }
883         }
884 
885         populateItemLinesFromPO(cmDocument, expiredOrClosedAccountList);
886     }
887 
888     
889 
890 
891 
892 
893     protected void populateItemLinesFromPO(VendorCreditMemoDocument cmDocument, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
894         List<PurchaseOrderItem> invoicedItems = getPOInvoicedItems(cmDocument.getPurchaseOrderDocument());
895         for (PurchaseOrderItem poItem : invoicedItems) {
896             if ((poItem.getItemType().isQuantityBasedGeneralLedgerIndicator() && poItem.getItemInvoicedTotalQuantity().isNonZero())
897                     || (poItem.getItemType().isAmountBasedGeneralLedgerIndicator() && poItem.getItemInvoicedTotalAmount().isNonZero())) {
898                 CreditMemoItem creditMemoItem = new CreditMemoItem(cmDocument, poItem, expiredOrClosedAccountList);
899                 cmDocument.getItems().add(creditMemoItem);
900                 PurchasingCapitalAssetItem purchasingCAMSItem = cmDocument.getPurchaseOrderDocument().getPurchasingCapitalAssetItemByItemIdentifier(poItem.getItemIdentifier());
901                 if (purchasingCAMSItem != null) {
902                     creditMemoItem.setCapitalAssetTransactionTypeCode(purchasingCAMSItem.getCapitalAssetTransactionTypeCode());
903                 }
904             }
905         }
906 
907         
908         purapService.addBelowLineItems(cmDocument);
909 
910         cmDocument.fixItemReferences();
911     }
912 
913     
914 
915 
916 
917 
918     protected void populateDocumentFromVendor(VendorCreditMemoDocument cmDocument) {
919         Integer vendorHeaderId = VendorUtils.getVendorHeaderId(cmDocument.getVendorNumber());
920         Integer vendorDetailId = VendorUtils.getVendorDetailId(cmDocument.getVendorNumber());
921 
922         VendorDetail vendorDetail = vendorService.getVendorDetail(vendorHeaderId, vendorDetailId);
923         cmDocument.setVendorDetail(vendorDetail);
924 
925         cmDocument.setVendorHeaderGeneratedIdentifier(vendorDetail.getVendorHeaderGeneratedIdentifier());
926         cmDocument.setVendorDetailAssignedIdentifier(vendorDetail.getVendorDetailAssignedIdentifier());
927         cmDocument.setVendorCustomerNumber(vendorDetail.getVendorNumber());
928         cmDocument.setVendorName(vendorDetail.getVendorName());
929         cmDocument.setPaymentMethodId(vendorDetail.getPaymentMethodId());
930 
931         
932         String userCampus = GlobalVariables.getUserSession().getPerson().getCampusCode();
933         VendorAddress vendorAddress = vendorService.getVendorDefaultAddress(vendorHeaderId, vendorDetailId, VendorConstants.AddressTypes.REMIT, userCampus);
934         if (vendorAddress == null) {
935             
936             vendorAddress = vendorService.getVendorDefaultAddress(vendorHeaderId, vendorDetailId, VendorConstants.AddressTypes.PURCHASE_ORDER, userCampus);
937         }
938 
939         cmDocument.setVendorAddressGeneratedIdentifier(vendorAddress.getVendorAddressGeneratedIdentifier());
940         cmDocument.templateVendorAddress(vendorAddress);
941 
942         
943         purapService.addBelowLineItems(cmDocument);
944     }
945 
946     
947 
948 
949 
950 
951     protected void populateDocumentDescription(VendorCreditMemoDocument cmDocument) {
952         String description = "";
953         if (cmDocument.isSourceVendor()) {
954             description = "Vendor: " + cmDocument.getVendorName();
955         } else {
956             description = "PO: " + cmDocument.getPurchaseOrderDocument().getPurapDocumentIdentifier() + " Vendor: " + cmDocument.getVendorName();
957         }
958 
959         
960         int noteTextMaxLength = dataDictionaryService.getAttributeMaxLength(DocumentHeader.class, KRADPropertyConstants.DOCUMENT_DESCRIPTION).intValue();
961         if (noteTextMaxLength < description.length()) {
962             description = description.substring(0, noteTextMaxLength);
963         }
964 
965         cmDocument.getDocumentHeader().setDocumentDescription(description);
966     }
967 
968 }
969