001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.opensource.org/licenses/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.module.purap.service.impl;
017:
018: import java.math.BigDecimal;
019: import java.sql.Date;
020: import java.sql.Timestamp;
021: import java.util.ArrayList;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Set;
026:
027: import org.apache.commons.collections.CollectionUtils;
028: import org.apache.commons.lang.StringUtils;
029: import org.kuali.core.bo.Note;
030: import org.kuali.core.bo.user.UniversalUser;
031: import org.kuali.core.exceptions.ValidationException;
032: import org.kuali.core.service.BusinessObjectService;
033: import org.kuali.core.service.DocumentService;
034: import org.kuali.core.service.KualiConfigurationService;
035: import org.kuali.core.service.NoteService;
036: import org.kuali.core.util.GlobalVariables;
037: import org.kuali.core.util.KualiDecimal;
038: import org.kuali.core.util.ObjectUtils;
039: import org.kuali.kfs.bo.SourceAccountingLine;
040: import org.kuali.kfs.context.SpringContext;
041: import org.kuali.kfs.rule.event.DocumentSystemSaveEvent;
042: import org.kuali.kfs.service.ParameterService;
043: import org.kuali.kfs.service.impl.ParameterConstants;
044: import org.kuali.module.purap.PurapConstants;
045: import org.kuali.module.purap.PurapKeyConstants;
046: import org.kuali.module.purap.PurapParameterConstants;
047: import org.kuali.module.purap.PurapConstants.CreditMemoStatuses;
048: import org.kuali.module.purap.PurapWorkflowConstants.NodeDetails;
049: import org.kuali.module.purap.PurapWorkflowConstants.CreditMemoDocument.NodeDetailEnum;
050: import org.kuali.module.purap.bo.CreditMemoAccount;
051: import org.kuali.module.purap.bo.CreditMemoItem;
052: import org.kuali.module.purap.bo.PurApAccountingLine;
053: import org.kuali.module.purap.bo.PurchaseOrderItem;
054: import org.kuali.module.purap.dao.CreditMemoDao;
055: import org.kuali.module.purap.document.AccountsPayableDocument;
056: import org.kuali.module.purap.document.CreditMemoDocument;
057: import org.kuali.module.purap.document.PaymentRequestDocument;
058: import org.kuali.module.purap.document.PurchaseOrderDocument;
059: import org.kuali.module.purap.document.PurchasingAccountsPayableDocument;
060: import org.kuali.module.purap.rule.event.ContinueAccountsPayableEvent;
061: import org.kuali.module.purap.service.AccountsPayableService;
062: import org.kuali.module.purap.service.CreditMemoService;
063: import org.kuali.module.purap.service.PaymentRequestService;
064: import org.kuali.module.purap.service.PurapAccountingService;
065: import org.kuali.module.purap.service.PurapGeneralLedgerService;
066: import org.kuali.module.purap.service.PurapService;
067: import org.kuali.module.purap.service.PurchaseOrderService;
068: import org.kuali.module.purap.util.VendorGroupingHelper;
069: import org.kuali.module.vendor.util.VendorUtils;
070: import org.springframework.transaction.annotation.Transactional;
071:
072: import edu.iu.uis.eden.exception.WorkflowException;
073:
074: /**
075: * Provides services to support the creation of a Credit Memo Document.
076: */
077: @Transactional
078: public class CreditMemoServiceImpl implements CreditMemoService {
079: private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
080: .getLogger(CreditMemoServiceImpl.class);
081:
082: private CreditMemoDao creditMemoDao;
083: private KualiConfigurationService kualiConfigurationService;
084: private ParameterService parameterService;
085: private BusinessObjectService businessObjectService;
086: private DocumentService documentService;
087: private NoteService noteService;
088: private PurapService purapService;
089: private PurapGeneralLedgerService purapGeneralLedgerService;
090: private PaymentRequestService paymentRequestService;
091: private PurchaseOrderService purchaseOrderService;
092:
093: /**
094: * @see org.kuali.module.purap.service.CreditMemoService#getCreditMemosToExtract(java.lang.String)
095: */
096: public Iterator<CreditMemoDocument> getCreditMemosToExtract(
097: String chartCode) {
098: LOG.debug("getCreditMemosToExtract() started");
099:
100: return creditMemoDao.getCreditMemosToExtract(chartCode);
101: }
102:
103: public Iterator<CreditMemoDocument> getCreditMemosToExtractByVendor(
104: String chartCode, VendorGroupingHelper vendor) {
105: LOG.debug("getCreditMemosToExtractByVendor() started");
106:
107: return creditMemoDao.getCreditMemosToExtractByVendor(chartCode,
108: vendor);
109: }
110:
111: public Set<VendorGroupingHelper> getVendorsOnCreditMemosToExtract(
112: String chartCode) {
113: LOG.debug("getVendorsOnCreditMemosToExtract() started");
114: HashSet<VendorGroupingHelper> vendors = new HashSet<VendorGroupingHelper>();
115:
116: Iterator<CreditMemoDocument> docs = getCreditMemosToExtract(chartCode);
117: while (docs.hasNext()) {
118: CreditMemoDocument doc = docs.next();
119: vendors.add(new VendorGroupingHelper(doc));
120: }
121: return vendors;
122: }
123:
124: /**
125: * @see org.kuali.module.purap.service.CreditMemoService#creditMemoDuplicateMessages(org.kuali.module.purap.document.CreditMemoDocument)
126: */
127: public String creditMemoDuplicateMessages(
128: CreditMemoDocument cmDocument) {
129: String duplicateMessage = null;
130:
131: String vendorNumber = cmDocument.getVendorNumber();
132: if (StringUtils.isEmpty(vendorNumber)) {
133: PurchasingAccountsPayableDocument sourceDocument = cmDocument
134: .getPurApSourceDocumentIfPossible();
135: if (ObjectUtils.isNotNull(sourceDocument)) {
136: vendorNumber = sourceDocument.getVendorNumber();
137: }
138: }
139:
140: if (StringUtils.isNotEmpty(vendorNumber)) {
141: // check for existence of another credit memo with the same vendor and vendor credit memo number
142: if (creditMemoDao.duplicateExists(VendorUtils
143: .getVendorHeaderId(vendorNumber), VendorUtils
144: .getVendorDetailId(vendorNumber), cmDocument
145: .getCreditMemoNumber())) {
146: duplicateMessage = kualiConfigurationService
147: .getPropertyString(PurapKeyConstants.MESSAGE_DUPLICATE_CREDIT_MEMO_VENDOR_NUMBER);
148: }
149:
150: // check for existence of another credit memo with the same vendor and credit memo date
151: if (creditMemoDao.duplicateExists(VendorUtils
152: .getVendorHeaderId(vendorNumber), VendorUtils
153: .getVendorDetailId(vendorNumber), cmDocument
154: .getCreditMemoDate(), cmDocument
155: .getCreditMemoAmount())) {
156: duplicateMessage = kualiConfigurationService
157: .getPropertyString(PurapKeyConstants.MESSAGE_DUPLICATE_CREDIT_MEMO_VENDOR_NUMBER_DATE_AMOUNT);
158: }
159: }
160:
161: return duplicateMessage;
162: }
163:
164: /**
165: * @see org.kuali.module.purap.service.CreditMemoService#getPOInvoicedItems(org.kuali.module.purap.document.PurchaseOrderDocument)
166: */
167: public List<PurchaseOrderItem> getPOInvoicedItems(
168: PurchaseOrderDocument poDocument) {
169: List<PurchaseOrderItem> invoicedItems = new ArrayList<PurchaseOrderItem>();
170:
171: for (Iterator iter = poDocument.getItems().iterator(); iter
172: .hasNext();) {
173: PurchaseOrderItem poItem = (PurchaseOrderItem) iter.next();
174:
175: // only items of type above the line can be considered for being invoiced
176: if (!poItem.getItemType().isItemTypeAboveTheLineIndicator()) {
177: continue;
178: }
179:
180: if (poItem.getItemType()
181: .isQuantityBasedGeneralLedgerIndicator()
182: && poItem.getItemInvoicedTotalQuantity()
183: .isGreaterThan(KualiDecimal.ZERO)) {
184: invoicedItems.add(poItem);
185: } else {
186: BigDecimal unitPrice = (poItem.getItemUnitPrice() == null ? new BigDecimal(
187: 0)
188: : poItem.getItemUnitPrice());
189: if (unitPrice.doubleValue() > poItem
190: .getItemOutstandingEncumberedAmount()
191: .doubleValue()) {
192: invoicedItems.add(poItem);
193: }
194: }
195: }
196:
197: return invoicedItems;
198: }
199:
200: /**
201: * @see org.kuali.module.purap.service.CreditMemoService#calculateCreditMemo(org.kuali.module.purap.document.CreditMemoDocument)
202: */
203: public void calculateCreditMemo(CreditMemoDocument cmDocument) {
204:
205: cmDocument.updateExtendedPriceOnItems();
206:
207: for (CreditMemoItem item : (List<CreditMemoItem>) cmDocument
208: .getItems()) {
209: // update unit price for service items
210: if (item.getItemType().isItemTypeAboveTheLineIndicator()
211: && !item.getItemType()
212: .isQuantityBasedGeneralLedgerIndicator()) {
213: item.setItemUnitPrice(new BigDecimal(item
214: .getExtendedPrice().toString()));
215: }
216: // make sure restocking fee is negative
217: else if (StringUtils
218: .equals(
219: PurapConstants.ItemTypeCodes.ITEM_TYPE_RESTCK_FEE_CODE,
220: item.getItemTypeCode())) {
221: item.setExtendedPrice(item.getExtendedPrice().abs()
222: .negated());
223: if (item.getItemUnitPrice() != null) {
224: item.setItemUnitPrice(item.getItemUnitPrice().abs()
225: .negate());
226: }
227: }
228: }
229:
230: // proration
231: if (cmDocument.isSourceVendor()) {
232: // no proration on vendor
233: return;
234: }
235:
236: for (CreditMemoItem item : (List<CreditMemoItem>) cmDocument
237: .getItems()) {
238:
239: // skip above the line
240: if (item.getItemType().isItemTypeAboveTheLineIndicator()) {
241: continue;
242: }
243:
244: if ((item.getSourceAccountingLines().isEmpty())
245: && (ObjectUtils.isNotNull(item.getExtendedPrice()))
246: && (KualiDecimal.ZERO.compareTo(item
247: .getExtendedPrice()) != 0)) {
248:
249: KualiDecimal totalAmount = KualiDecimal.ZERO;
250: List<PurApAccountingLine> distributedAccounts = null;
251: List<SourceAccountingLine> summaryAccounts = null;
252:
253: totalAmount = cmDocument
254: .getPurApSourceDocumentIfPossible()
255: .getTotalDollarAmount();
256: // this should do nothing on preq which is fine
257: SpringContext
258: .getBean(PurapAccountingService.class)
259: .updateAccountAmounts(
260: cmDocument
261: .getPurApSourceDocumentIfPossible());
262: summaryAccounts = SpringContext.getBean(
263: PurapAccountingService.class).generateSummary(
264: cmDocument.getPurApSourceDocumentIfPossible()
265: .getItems());
266: distributedAccounts = SpringContext.getBean(
267: PurapAccountingService.class)
268: .generateAccountDistributionForProration(
269: summaryAccounts, totalAmount,
270: PurapConstants.PRORATION_SCALE,
271: CreditMemoAccount.class);
272:
273: if (CollectionUtils.isNotEmpty(distributedAccounts)
274: && CollectionUtils.isEmpty(item
275: .getSourceAccountingLines())) {
276: item.setSourceAccountingLines(distributedAccounts);
277: }
278: }
279: }
280: // end proration
281: }
282:
283: /**
284: * @see org.kuali.module.purap.service.CreditMemoService#getCreditMemoByDocumentNumber(java.lang.String)
285: */
286: public CreditMemoDocument getCreditMemoByDocumentNumber(
287: String documentNumber) {
288: LOG.debug("getCreditMemoByDocumentNumber() started");
289:
290: if (ObjectUtils.isNotNull(documentNumber)) {
291: try {
292: CreditMemoDocument doc = (CreditMemoDocument) documentService
293: .getByDocumentHeaderId(documentNumber);
294: return doc;
295: } catch (WorkflowException e) {
296: String errorMessage = "Error getting credit memo document from document service";
297: LOG.error("getCreditMemoByDocumentNumber() "
298: + errorMessage, e);
299: throw new RuntimeException(errorMessage, e);
300: }
301: }
302: return null;
303: }
304:
305: /**
306: * @see org.kuali.module.purap.service.CreditMemoService#getCreditMemoDocumentById(java.lang.Integer)
307: */
308: public CreditMemoDocument getCreditMemoDocumentById(
309: Integer purchasingDocumentIdentifier) {
310: return getCreditMemoByDocumentNumber(creditMemoDao
311: .getDocumentNumberByCreditMemoId(purchasingDocumentIdentifier));
312: }
313:
314: /**
315: * Not used
316: *
317: * @see org.kuali.module.purap.service.CreditMemoService#saveDocumentWithoutValidation(org.kuali.module.purap.document.CreditMemoDocument)
318: */
319: public void saveDocumentWithoutValidation(
320: CreditMemoDocument document) {
321: try {
322: documentService.saveDocument(document,
323: DocumentSystemSaveEvent.class);
324:
325: } catch (WorkflowException we) {
326: String errorMsg = "Error saving document # "
327: + document.getDocumentHeader().getDocumentNumber()
328: + " " + we.getMessage();
329: LOG.error(errorMsg, we);
330: throw new RuntimeException(errorMsg, we);
331: } catch (RuntimeException re) {
332: String errorMsg = "Error saving document # "
333: + document.getDocumentHeader().getDocumentNumber()
334: + " " + re.getMessage();
335: LOG.error(errorMsg, re);
336: throw new RuntimeException(errorMsg, re);
337: }
338: }
339:
340: /**
341: * @see org.kuali.module.purap.service.CreditMemoService#saveDocument(org.kuali.module.purap.document.CreditMemoDocument)
342: */
343: public void populateAndSaveCreditMemo(CreditMemoDocument document) {
344: try {
345: document
346: .setStatusCode(PurapConstants.CreditMemoStatuses.IN_PROCESS);
347: documentService.saveDocument(document,
348: ContinueAccountsPayableEvent.class);
349: } catch (ValidationException ve) {
350: document
351: .setStatusCode(PurapConstants.CreditMemoStatuses.INITIATE);
352: } catch (WorkflowException we) {
353: // set the status back to initiate
354: document
355: .setStatusCode(PurapConstants.CreditMemoStatuses.INITIATE);
356: String errorMsg = "Error saving document # "
357: + document.getDocumentHeader().getDocumentNumber()
358: + " " + we.getMessage();
359: LOG.error(errorMsg, we);
360: throw new RuntimeException(errorMsg, we);
361: }
362: }
363:
364: /**
365: * @see org.kuali.module.purap.service.CreditMemoService#reopenClosedPO(org.kuali.module.purap.document.CreditMemoDocument)
366: */
367: public void reopenClosedPO(CreditMemoDocument cmDocument) {
368: // reopen PO if closed
369: Integer purchaseOrderDocumentId = cmDocument
370: .getPurchaseOrderIdentifier();
371: if (cmDocument.isSourceDocumentPaymentRequest()
372: && ObjectUtils.isNull(purchaseOrderDocumentId)) {
373: PaymentRequestDocument paymentRequestDocument = paymentRequestService
374: .getPaymentRequestById(cmDocument
375: .getPaymentRequestIdentifier());
376: purchaseOrderDocumentId = paymentRequestDocument
377: .getPurchaseOrderIdentifier();
378: }
379: // if we found a valid po id number then check it for reopening
380: if (ObjectUtils.isNotNull(purchaseOrderDocumentId)) {
381: PurchaseOrderDocument purchaseOrderDocument = purchaseOrderService
382: .getCurrentPurchaseOrder(purchaseOrderDocumentId);
383: // only reopen if the po is not null, it does not have a pending change already scheduled, and it is in closed status
384: if (ObjectUtils.isNotNull(purchaseOrderDocument)
385: && (!purchaseOrderDocument
386: .isPendingActionIndicator())
387: && PurapConstants.PurchaseOrderStatuses.CLOSED
388: .equals(purchaseOrderDocument
389: .getStatusCode())) {
390:
391: }
392: }
393: }
394:
395: /**
396: * @see org.kuali.module.purap.service.CreditMemoService#canHoldPaymentRequest(org.kuali.module.purap.document.CreditMemoDocument,
397: * org.kuali.core.bo.user.UniversalUser)
398: */
399: public boolean canHoldCreditMemo(CreditMemoDocument cmDocument,
400: UniversalUser user) {
401: boolean canHold = false;
402:
403: String accountsPayableGroup = parameterService
404: .getParameterValue(
405: ParameterConstants.PURCHASING_DOCUMENT.class,
406: PurapParameterConstants.Workgroups.WORKGROUP_ACCOUNTS_PAYABLE);
407: if ((!cmDocument.isHoldIndicator())
408: && user.isMember(accountsPayableGroup)
409: && ObjectUtils.isNull(cmDocument.getExtractedDate())
410: && (!PurapConstants.CreditMemoStatuses.STATUSES_DISALLOWING_HOLD
411: .contains(cmDocument.getStatusCode()))) {
412: canHold = true;
413: }
414:
415: return canHold;
416: }
417:
418: /**
419: * @see org.kuali.module.purap.service.CreditMemoService#addHoldOnPaymentRequest(org.kuali.module.purap.document.CreditMemoDocument,
420: * java.lang.String)
421: */
422: public void addHoldOnCreditMemo(CreditMemoDocument cmDocument,
423: String note) throws Exception {
424: // save the note
425: Note noteObj = documentService.createNoteFromDocument(
426: cmDocument, note);
427: documentService.addNoteToDocument(cmDocument, noteObj);
428: noteService.save(noteObj);
429:
430: // retrieve and save with hold indicator set to true
431: CreditMemoDocument cmDoc = getCreditMemoDocumentById(cmDocument
432: .getPurapDocumentIdentifier());
433: cmDoc.setHoldIndicator(true);
434: cmDoc.setLastActionPerformedByUniversalUserId(GlobalVariables
435: .getUserSession().getUniversalUser()
436: .getPersonUniversalIdentifier());
437: saveDocumentWithoutValidation(cmDoc);
438:
439: // must also save it on the incoming document
440: cmDocument.setHoldIndicator(true);
441: cmDocument
442: .setLastActionPerformedByUniversalUserId(GlobalVariables
443: .getUserSession().getUniversalUser()
444: .getPersonUniversalIdentifier());
445: }
446:
447: /**
448: * @see org.kuali.module.purap.service.CreditMemoService#canRemoveHoldPaymentRequest(org.kuali.module.purap.document.CreditMemoDocument,
449: * org.kuali.core.bo.user.UniversalUser)
450: */
451: public boolean canRemoveHoldCreditMemo(
452: CreditMemoDocument cmDocument, UniversalUser user) {
453: boolean canRemoveHold = false;
454:
455: String accountsPayableSupervisorGroup = parameterService
456: .getParameterValue(
457: ParameterConstants.PURCHASING_DOCUMENT.class,
458: PurapParameterConstants.Workgroups.WORKGROUP_ACCOUNTS_PAYABLE_SUPERVISOR);
459: if (cmDocument.isHoldIndicator()
460: && (user
461: .getPersonUniversalIdentifier()
462: .equals(
463: cmDocument
464: .getLastActionPerformedByUniversalUserId()) || user
465: .isMember(accountsPayableSupervisorGroup))) {
466: canRemoveHold = true;
467: }
468:
469: return canRemoveHold;
470: }
471:
472: /**
473: * @see org.kuali.module.purap.service.CreditMemoService#removeHoldOnCreditMemo(org.kuali.module.purap.document.CreditMemoDocument,
474: * java.lang.String)
475: */
476: public void removeHoldOnCreditMemo(CreditMemoDocument cmDocument,
477: String note) throws Exception {
478: // save the note
479: Note noteObj = documentService.createNoteFromDocument(
480: cmDocument, note);
481: documentService.addNoteToDocument(cmDocument, noteObj);
482: noteService.save(noteObj);
483:
484: // retrieve and save with hold indicator set to false
485: CreditMemoDocument cmDoc = getCreditMemoDocumentById(cmDocument
486: .getPurapDocumentIdentifier());
487: cmDoc.setHoldIndicator(false);
488: cmDoc.setLastActionPerformedByUniversalUserId(null);
489: saveDocumentWithoutValidation(cmDoc);
490:
491: // must also save it on the incoming document
492: cmDocument.setHoldIndicator(false);
493: cmDocument.setLastActionPerformedByUniversalUserId(null);
494: }
495:
496: /**
497: * @see org.kuali.module.purap.service.CreditMemoService#canCancelCreditMemo(org.kuali.module.purap.document.CreditMemoDocument,
498: * org.kuali.core.bo.user.UniversalUser)
499: */
500: public boolean canCancelCreditMemo(CreditMemoDocument cmDocument,
501: UniversalUser user) {
502: boolean canCancel = false;
503:
504: String accountsPayableGroup = parameterService
505: .getParameterValue(
506: ParameterConstants.PURCHASING_DOCUMENT.class,
507: PurapParameterConstants.Workgroups.WORKGROUP_ACCOUNTS_PAYABLE);
508: if ((!CreditMemoStatuses.CANCELLED_STATUSES.contains(cmDocument
509: .getStatusCode()))
510: && cmDocument.getExtractedDate() == null
511: && !cmDocument.isHoldIndicator()
512: && user.isMember(accountsPayableGroup)) {
513: canCancel = true;
514: }
515:
516: return canCancel;
517: }
518:
519: /**
520: * @see org.kuali.module.purap.service.AccountsPayableDocumentSpecificService#updateStatusByNode(java.lang.String, org.kuali.module.purap.document.AccountsPayableDocument)
521: */
522: public String updateStatusByNode(String currentNodeName,
523: AccountsPayableDocument apDoc) {
524: return updateStatusByNode(currentNodeName,
525: (CreditMemoDocument) apDoc);
526: }
527:
528: /**
529: * Updates the status of a credit memo document, currently this is used by the cancel action
530: *
531: * @param currentNodeName The string representing the current node to be used to obtain the canceled status code.
532: * @param cmDoc The credit memo document to be updated.
533: * @return The string representing the canceledStatusCode, if empty it is assumed to be not from workflow.
534: */
535: private String updateStatusByNode(String currentNodeName,
536: CreditMemoDocument cmDoc) {
537: // update the status on the document
538:
539: String cancelledStatusCode = "";
540: if (StringUtils.isEmpty(currentNodeName)) {
541: cancelledStatusCode = PurapConstants.CreditMemoStatuses.CANCELLED_POST_AP_APPROVE;
542: } else {
543: NodeDetails currentNode = NodeDetailEnum
544: .getNodeDetailEnumByName(currentNodeName);
545: if (ObjectUtils.isNotNull(currentNode)) {
546: cancelledStatusCode = currentNode
547: .getDisapprovedStatusCode();
548: }
549: }
550:
551: if (StringUtils.isNotBlank(cancelledStatusCode)) {
552: purapService.updateStatus(cmDoc, cancelledStatusCode);
553: saveDocumentWithoutValidation(cmDoc);
554: return cancelledStatusCode;
555: } else {
556: logAndThrowRuntimeException("No status found to set for document being disapproved in node '"
557: + currentNodeName + "'");
558: }
559: return cancelledStatusCode;
560: }
561:
562: /**
563: * @see org.kuali.module.purap.service.CreditMemoService#cancelExtractedCreditMemo(org.kuali.module.purap.document.CreditMemoDocument,
564: * java.lang.String)
565: */
566: public void cancelExtractedCreditMemo(
567: CreditMemoDocument cmDocument, String note) {
568: LOG.debug("cancelExtractedCreditMemo() started");
569: if (CreditMemoStatuses.CANCELLED_STATUSES.contains(cmDocument
570: .getStatusCode())) {
571: LOG.debug("cancelExtractedCreditMemo() ended");
572: return;
573: }
574:
575: try {
576: Note noteObj = documentService.createNoteFromDocument(
577: cmDocument, note);
578: documentService.addNoteToDocument(cmDocument, noteObj);
579: } catch (Exception e) {
580: throw new RuntimeException(e.getMessage());
581: }
582:
583: SpringContext.getBean(AccountsPayableService.class)
584: .cancelAccountsPayableDocument(cmDocument, "");
585: LOG.debug("cancelExtractedCreditMemo() CM "
586: + cmDocument.getPurapDocumentIdentifier()
587: + " Cancelled Without Workflow");
588: LOG.debug("cancelExtractedCreditMemo() ended");
589:
590: }
591:
592: /**
593: * @see org.kuali.module.purap.service.CreditMemoService#resetExtractedCreditMemo(org.kuali.module.purap.document.CreditMemoDocument,
594: * java.lang.String)
595: */
596: public void resetExtractedCreditMemo(CreditMemoDocument cmDocument,
597: String note) {
598: LOG.debug("resetExtractedCreditMemo() started");
599: if (CreditMemoStatuses.CANCELLED_STATUSES.contains(cmDocument
600: .getStatusCode())) {
601: LOG.debug("resetExtractedCreditMemo() ended");
602: return;
603: }
604: cmDocument.setExtractedDate(null);
605: cmDocument.setCreditMemoPaidTimestamp(null);
606:
607: Note noteObj;
608: try {
609: noteObj = documentService.createNoteFromDocument(
610: cmDocument, note);
611: documentService.addNoteToDocument(cmDocument, noteObj);
612: } catch (Exception e) {
613: throw new RuntimeException(e.getMessage());
614: }
615: saveDocumentWithoutValidation(cmDocument);
616:
617: LOG.debug("resetExtractedCreditMemo() CM "
618: + cmDocument.getPurapDocumentIdentifier()
619: + " Cancelled Without Workflow");
620: LOG.debug("resetExtractedCreditMemo() ended");
621: }
622:
623: public void setCreditMemoDao(CreditMemoDao creditMemoDao) {
624: this .creditMemoDao = creditMemoDao;
625: }
626:
627: public void setKualiConfigurationService(
628: KualiConfigurationService kualiConfigurationService) {
629: this .kualiConfigurationService = kualiConfigurationService;
630: }
631:
632: public void setBusinessObjectService(
633: BusinessObjectService businessObjectService) {
634: this .businessObjectService = businessObjectService;
635: }
636:
637: public void setDocumentService(DocumentService documentService) {
638: this .documentService = documentService;
639: }
640:
641: public void setNoteService(NoteService noteService) {
642: this .noteService = noteService;
643: }
644:
645: public void setPurapService(PurapService purapService) {
646: this .purapService = purapService;
647: }
648:
649: public void setPurapGeneralLedgerService(
650: PurapGeneralLedgerService purapGeneralLedgerService) {
651: this .purapGeneralLedgerService = purapGeneralLedgerService;
652: }
653:
654: public void setPaymentRequestService(
655: PaymentRequestService paymentRequestService) {
656: this .paymentRequestService = paymentRequestService;
657: }
658:
659: public void setPurchaseOrderService(
660: PurchaseOrderService purchaseOrderService) {
661: this .purchaseOrderService = purchaseOrderService;
662: }
663:
664: /**
665: * @see org.kuali.module.purap.service.AccountsPayableDocumentSpecificService#shouldPurchaseOrderBeReversed(org.kuali.module.purap.document.AccountsPayableDocument)
666: */
667: public boolean shouldPurchaseOrderBeReversed(
668: AccountsPayableDocument apDoc) {
669: // always return false, never reverse
670: return false;
671: }
672:
673: /**
674: * @see org.kuali.module.purap.service.AccountsPayableDocumentSpecificService#getUniversalUserForCancel(org.kuali.module.purap.document.AccountsPayableDocument)
675: */
676: public UniversalUser getUniversalUserForCancel(
677: AccountsPayableDocument apDoc) {
678: // return null, since superuser is fine for CM
679: return null;
680: }
681:
682: /**
683: * @see org.kuali.module.purap.service.AccountsPayableDocumentSpecificService#takePurchaseOrderCancelAction(org.kuali.module.purap.document.AccountsPayableDocument)
684: */
685: public void takePurchaseOrderCancelAction(
686: AccountsPayableDocument apDoc) {
687: CreditMemoDocument cmDocument = (CreditMemoDocument) apDoc;
688: if (cmDocument.isReopenPurchaseOrderIndicator()) {
689: String docType = PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_CLOSE_DOCUMENT;
690: SpringContext
691: .getBean(PurchaseOrderService.class)
692: .createAndRoutePotentialChangeDocument(
693: cmDocument.getPurchaseOrderDocument()
694: .getDocumentNumber(),
695: docType,
696: "reopened by Payment Request "
697: + apDoc
698: .getPurapDocumentIdentifier()
699: + "cancel",
700: new ArrayList(),
701: PurapConstants.PurchaseOrderStatuses.PENDING_CLOSE);
702: }
703: }
704:
705: /**
706: * @see org.kuali.module.purap.service.CreditMemoService#markPaid(org.kuali.module.purap.document.CreditMemoDocument,
707: * java.sql.Date)
708: */
709: public void markPaid(CreditMemoDocument cm, Date processDate) {
710: LOG.debug("markPaid() started");
711:
712: cm.setCreditMemoPaidTimestamp(new Timestamp(processDate
713: .getTime()));
714: saveDocumentWithoutValidation(cm);
715: }
716:
717: public void setParameterService(ParameterService parameterService) {
718: this .parameterService = parameterService;
719: }
720:
721: /**
722: * @see org.kuali.module.purap.service.AccountsPayableDocumentSpecificService#poItemEligibleForAp(org.kuali.module.purap.document.AccountsPayableDocument, org.kuali.module.purap.bo.PurchaseOrderItem)
723: */
724: public boolean poItemEligibleForAp(AccountsPayableDocument apDoc,
725: PurchaseOrderItem poItem) {
726: // if the po item is not active... skip it
727: if (!poItem.isItemActiveIndicator()) {
728: return false;
729: }
730:
731: if (poItem.getItemType()
732: .isQuantityBasedGeneralLedgerIndicator()
733: && poItem.getItemInvoicedTotalQuantity().isGreaterThan(
734: KualiDecimal.ZERO)) {
735: return true;
736: } else {
737: BigDecimal unitPrice = (poItem.getItemUnitPrice() == null ? new BigDecimal(
738: 0)
739: : poItem.getItemUnitPrice());
740: if (unitPrice.doubleValue() > poItem
741: .getItemOutstandingEncumberedAmount().doubleValue()) {
742: return true;
743: }
744: }
745: return false;
746: }
747:
748: /**
749: * Records the specified error message into the Log file and throws a runtime exception.
750: *
751: * @param errorMessage the error message to be logged.
752: */
753: protected void logAndThrowRuntimeException(String errorMessage) {
754: this .logAndThrowRuntimeException(errorMessage, null);
755: }
756:
757: /**
758: * Records the specified error message into the Log file and throws the specified runtime exception.
759: *
760: * @param errorMessage the specified error message.
761: * @param e the specified runtime exception.
762: */
763: protected void logAndThrowRuntimeException(String errorMessage,
764: Exception e) {
765: if (ObjectUtils.isNotNull(e)) {
766: LOG.error(errorMessage, e);
767: throw new RuntimeException(errorMessage, e);
768: } else {
769: LOG.error(errorMessage);
770: throw new RuntimeException(errorMessage);
771: }
772: }
773: }
|