001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.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/ecl2.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 017 package org.kuali.kfs.module.purap.document; 018 019 import java.sql.Date; 020 import java.sql.Timestamp; 021 import java.util.ArrayList; 022 import java.util.List; 023 024 import org.apache.commons.lang.StringUtils; 025 import org.kuali.kfs.module.purap.PurapConstants; 026 import org.kuali.kfs.module.purap.PurapParameterConstants; 027 import org.kuali.kfs.module.purap.PurapPropertyConstants; 028 import org.kuali.kfs.module.purap.PurapWorkflowConstants; 029 import org.kuali.kfs.module.purap.PurapConstants.CREDIT_MEMO_TYPE_LABELS; 030 import org.kuali.kfs.module.purap.PurapConstants.CreditMemoStatuses; 031 import org.kuali.kfs.module.purap.PurapConstants.PurapDocTypeCodes; 032 import org.kuali.kfs.module.purap.PurapWorkflowConstants.NodeDetails; 033 import org.kuali.kfs.module.purap.PurapWorkflowConstants.CreditMemoDocument.NodeDetailEnum; 034 import org.kuali.kfs.module.purap.businessobject.CreditMemoItem; 035 import org.kuali.kfs.module.purap.businessobject.CreditMemoItemUseTax; 036 import org.kuali.kfs.module.purap.document.service.AccountsPayableDocumentSpecificService; 037 import org.kuali.kfs.module.purap.document.service.AccountsPayableService; 038 import org.kuali.kfs.module.purap.document.service.CreditMemoService; 039 import org.kuali.kfs.module.purap.document.service.PaymentRequestService; 040 import org.kuali.kfs.module.purap.document.service.PurapService; 041 import org.kuali.kfs.module.purap.document.validation.event.AttributedContinuePurapEvent; 042 import org.kuali.kfs.module.purap.service.PurapGeneralLedgerService; 043 import org.kuali.kfs.sys.KFSConstants; 044 import org.kuali.kfs.sys.businessobject.AccountingLine; 045 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry; 046 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail; 047 import org.kuali.kfs.sys.context.SpringContext; 048 import org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO; 049 import org.kuali.rice.kew.exception.WorkflowException; 050 import org.kuali.rice.kim.bo.Person; 051 import org.kuali.rice.kns.bo.Note; 052 import org.kuali.rice.kns.rule.event.KualiDocumentEvent; 053 import org.kuali.rice.kns.service.DataDictionaryService; 054 import org.kuali.rice.kns.service.DateTimeService; 055 import org.kuali.rice.kns.service.NoteService; 056 import org.kuali.rice.kns.service.ParameterService; 057 import org.kuali.rice.kns.util.GlobalVariables; 058 import org.kuali.rice.kns.util.KualiDecimal; 059 import org.kuali.rice.kns.util.ObjectUtils; 060 import org.kuali.rice.kns.workflow.service.WorkflowDocumentService; 061 062 /** 063 * Credit Memo Document Business Object. Contains the fields associated with the main document table. 064 */ 065 public class VendorCreditMemoDocument extends AccountsPayableDocumentBase { 066 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(VendorCreditMemoDocument.class); 067 068 protected Integer paymentRequestIdentifier; 069 protected String creditMemoNumber; 070 protected Date creditMemoDate; 071 protected KualiDecimal creditMemoAmount; 072 protected Timestamp creditMemoPaidTimestamp; 073 protected String itemMiscellaneousCreditDescription; 074 protected Date purchaseOrderEndDate; 075 protected String vendorAttentionName; 076 077 protected PaymentRequestDocument paymentRequestDocument; 078 079 /** 080 * Default constructor. 081 */ 082 public VendorCreditMemoDocument() { 083 super(); 084 } 085 086 public boolean isSourceDocumentPaymentRequest() { 087 return getPaymentRequestIdentifier() != null; 088 } 089 090 public boolean isSourceDocumentPurchaseOrder() { 091 return (!isSourceDocumentPaymentRequest()) && (getPurchaseOrderIdentifier() != null); 092 } 093 094 public boolean isSourceVendor() { 095 return (!isSourceDocumentPaymentRequest()) && (!isSourceDocumentPurchaseOrder()); 096 } 097 098 /** 099 * Overrides the method in PurchasingAccountsPayableDocumentBase to add the criteria 100 * specific to Credit Memo Document. 101 * 102 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocumentBase#isInquiryRendered() 103 */ 104 @Override 105 public boolean isInquiryRendered() { 106 if ( isPostingYearPrior() && 107 ( getStatusCode().equals(PurapConstants.CreditMemoStatuses.COMPLETE) || 108 getStatusCode().equals(PurapConstants.PaymentRequestStatuses.CANCELLED_POST_AP_APPROVE) || 109 getStatusCode().equals(PurapConstants.PaymentRequestStatuses.CANCELLED_IN_PROCESS) ) ) { 110 return false; 111 } 112 else { 113 return true; 114 } 115 } 116 117 /** 118 * Initializes the values for a new document. 119 */ 120 public void initiateDocument() { 121 LOG.debug("initiateDocument() started"); 122 setStatusCode(PurapConstants.CreditMemoStatuses.INITIATE); 123 124 Person currentUser = (Person) GlobalVariables.getUserSession().getPerson(); 125 setAccountsPayableProcessorIdentifier(currentUser.getPrincipalId()); 126 setProcessingCampusCode(currentUser.getCampusCode()); 127 } 128 129 /** 130 * Clear out the initially populated fields. 131 */ 132 public void clearInitFields() { 133 LOG.debug("clearDocument() started"); 134 135 // Clearing document overview fields 136 getDocumentHeader().setDocumentDescription(null); 137 getDocumentHeader().setExplanation(null); 138 getDocumentHeader().setFinancialDocumentTotalAmount(null); 139 getDocumentHeader().setOrganizationDocumentNumber(null); 140 141 // Clearing document Init fields 142 setPurchaseOrderIdentifier(null); 143 setCreditMemoNumber(null); 144 setCreditMemoDate(null); 145 setCreditMemoAmount(null); 146 setVendorNumber(null); 147 setPaymentRequestIdentifier(null); 148 } 149 150 /** 151 * Returns the type of the Credit Memo that was selected on the init screen. It is based on them entering the Vendor, PO or PREQ #. 152 * 153 * @return Vendor, PO or PREQ 154 */ 155 public String getCreditMemoType() { 156 String type = CREDIT_MEMO_TYPE_LABELS.TYPE_VENDOR; 157 if (isSourceDocumentPaymentRequest()) { 158 type = CREDIT_MEMO_TYPE_LABELS.TYPE_PREQ; 159 } 160 else if (isSourceDocumentPurchaseOrder()) { 161 type = CREDIT_MEMO_TYPE_LABELS.TYPE_PO; 162 } 163 return type; 164 } 165 166 /** 167 * @see org.kuali.rice.kns.bo.PersistableBusinessObjectBase#isBoNotesSupport() 168 */ 169 @Override 170 public boolean isBoNotesSupport() { 171 return true; 172 } 173 174 /** 175 * Determines if the purchase order has notes, using the note service. 176 * 177 * @return - true if po has notes, false if po does not have notes 178 */ 179 public boolean getPurchaseOrderNotes() { 180 boolean hasNotes = false; 181 182 ArrayList poNotes = SpringContext.getBean(NoteService.class).getByRemoteObjectId((this.getPurchaseOrderIdentifier()).toString()); 183 if (poNotes.size() > 0) { 184 hasNotes = true; 185 } 186 187 return hasNotes; 188 } 189 190 /** 191 * Determines the indicator text that will appear in the workflow document title 192 * 193 * @return - Text of hold 194 */ 195 protected String getTitleIndicator() { 196 if (isHoldIndicator()) { 197 return PurapConstants.PaymentRequestIndicatorText.HOLD; 198 } 199 else return ""; 200 } 201 202 /** 203 * @see org.kuali.rice.kns.document.DocumentBase#doRouteStatusChange() 204 */ 205 @Override 206 public void doRouteStatusChange(DocumentRouteStatusChangeDTO statusChangeEvent) { 207 LOG.debug("doRouteStatusChange() started"); 208 super.doRouteStatusChange(statusChangeEvent); 209 try { 210 // DOCUMENT PROCESSED 211 if (this.getDocumentHeader().getWorkflowDocument().stateIsProcessed()) { 212 SpringContext.getBean(PurapService.class).updateStatus(this, PurapConstants.CreditMemoStatuses.COMPLETE); 213 SpringContext.getBean(PurapService.class).saveDocumentNoValidation(this); 214 215 return; 216 } 217 // DOCUMENT DISAPPROVED 218 else if (this.getDocumentHeader().getWorkflowDocument().stateIsDisapproved()) { 219 String nodeName = SpringContext.getBean(WorkflowDocumentService.class).getCurrentRouteLevelName(getDocumentHeader().getWorkflowDocument()); 220 NodeDetails currentNode = NodeDetailEnum.getNodeDetailEnumByName(nodeName); 221 if (ObjectUtils.isNotNull(currentNode)) { 222 String newStatusCode = currentNode.getDisapprovedStatusCode(); 223 if ((StringUtils.isBlank(newStatusCode)) && ((StringUtils.isBlank(currentNode.getDisapprovedStatusCode())) && ((CreditMemoStatuses.INITIATE.equals(getStatusCode())) || (CreditMemoStatuses.IN_PROCESS.equals(getStatusCode()))))) { 224 newStatusCode = CreditMemoStatuses.CANCELLED_IN_PROCESS; 225 } 226 if (StringUtils.isNotBlank(newStatusCode)) { 227 SpringContext.getBean(AccountsPayableService.class).cancelAccountsPayableDocument(this, nodeName); 228 return; 229 } 230 } 231 logAndThrowRuntimeException("No status found to set for document being disapproved in node '" + nodeName + "'"); 232 } 233 // DOCUMENT CANCELED 234 else if (this.getDocumentHeader().getWorkflowDocument().stateIsCanceled()) { 235 String currentNodeName = SpringContext.getBean(WorkflowDocumentService.class).getCurrentRouteLevelName(getDocumentHeader().getWorkflowDocument()); 236 SpringContext.getBean(AccountsPayableService.class).cancelAccountsPayableDocument(this, currentNodeName); 237 } 238 } 239 catch (WorkflowException e) { 240 logAndThrowRuntimeException("Error saving routing data while saving document with id " + getDocumentNumber(), e); 241 } 242 } 243 244 /** 245 * Hook point for performing actions that occur after a route level change, in this case; Performs logic necessary after full 246 * entry has been completed when past Adhoc Review, or sets the AP approval date when past AP review. 247 * 248 * @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#preProcessNodeChange(java.lang.String, java.lang.String) 249 */ 250 public boolean processNodeChange(String newNodeName, String oldNodeName) { 251 if (NodeDetailEnum.ADHOC_REVIEW.getName().equals(oldNodeName)) { 252 SpringContext.getBean(AccountsPayableService.class).performLogicForFullEntryCompleted(this); 253 } 254 255 // if we've hit Account node then reopen po 256 else if ("Account".equals(newNodeName) && this.isReopenPurchaseOrderIndicator()) { 257 SpringContext.getBean(PurapService.class).performLogicForCloseReopenPO(this); 258 } 259 return true; 260 } 261 262 /** 263 * @see org.kuali.rice.kns.document.DocumentBase#getDocumentTitle() 264 */ 265 @Override 266 public String getDocumentTitle() { 267 if (SpringContext.getBean(ParameterService.class).getIndicatorParameter(VendorCreditMemoDocument.class, PurapParameterConstants.PURAP_OVERRIDE_CM_DOC_TITLE)) { 268 return getCustomDocumentTitle(); 269 } 270 return super.getDocumentTitle(); 271 } 272 273 /** 274 * Returns a custom document title based on the workflow document title. 275 * Depending on the document status, the PO, vendor, amount, etc may be added to the documents title. 276 * 277 * @return - Customized document title text dependent upon route level. 278 */ 279 protected String getCustomDocumentTitle() { 280 String popreq = ""; 281 if (this.isSourceDocumentPurchaseOrder() || this.isSourceDocumentPaymentRequest()) { 282 String poNumber = getPurchaseOrderIdentifier().toString(); 283 popreq = new StringBuffer("PO: ").append(poNumber).toString(); 284 } 285 /* 286 else if (this.isSourceDocumentPaymentRequest()) { 287 String preqNumber = this.getPaymentRequestIdentifier().toString(); 288 popreq = new StringBuffer("PREQ: ").append(preqNumber).toString(); 289 } 290 */ 291 292 String vendorName = StringUtils.trimToEmpty(getVendorName()); 293 String cmAmount = getGrandTotal().toString(); 294 String indicator = getTitleIndicator(); 295 String documentTitle = new StringBuffer(popreq).append(" Vendor: ").append(vendorName).append(" Amount: ").append(cmAmount).append(" ").append(indicator).toString(); 296 return documentTitle; 297 } 298 299 /** 300 * @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#getNodeDetailEnum(java.lang.String) 301 */ 302 public NodeDetails getNodeDetailEnum(String nodeName) { 303 return NodeDetailEnum.getNodeDetailEnumByName(nodeName); 304 } 305 306 /** 307 * @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#saveDocumentFromPostProcessing() 308 */ 309 public void saveDocumentFromPostProcessing() { 310 SpringContext.getBean(PurapService.class).saveDocumentNoValidation(this); 311 } 312 313 /** 314 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocumentBase#getItemClass() 315 */ 316 @Override 317 public Class<CreditMemoItem> getItemClass() { 318 return CreditMemoItem.class; 319 } 320 321 @Override 322 public Class getItemUseTaxClass() { 323 return CreditMemoItemUseTax.class; 324 } 325 326 /** 327 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocumentBase#getPurApSourceDocumentIfPossible() 328 */ 329 @Override 330 public PurchasingAccountsPayableDocument getPurApSourceDocumentIfPossible() { 331 PurchasingAccountsPayableDocument sourceDocument = null; 332 if (isSourceDocumentPaymentRequest()) { 333 sourceDocument = getPaymentRequestDocument(); 334 } 335 else if (isSourceDocumentPurchaseOrder()) { 336 sourceDocument = getPurchaseOrderDocument(); 337 } 338 return sourceDocument; 339 } 340 341 /** 342 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocumentBase#getPurApSourceDocumentLabelIfPossible() 343 */ 344 @Override 345 public String getPurApSourceDocumentLabelIfPossible() { 346 PurchasingAccountsPayableDocument document = getPurApSourceDocumentIfPossible(); 347 if (ObjectUtils.isNotNull(document)) { 348 return SpringContext.getBean(DataDictionaryService.class).getDocumentLabelByClass(document.getClass()); 349 } 350 return null; 351 } 352 353 /** 354 * Calculates the pretax total of the above the line items 355 * 356 * @return KualiDecimal - above the line item pretax total 357 */ 358 public KualiDecimal getLineItemPreTaxTotal() { 359 KualiDecimal lineItemPreTaxTotal = KualiDecimal.ZERO; 360 361 for (CreditMemoItem item : (List<CreditMemoItem>) getItems()) { 362 item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE); 363 if (item.getItemType().isLineItemIndicator() && item.getExtendedPrice() != null) { 364 lineItemPreTaxTotal = lineItemPreTaxTotal.add(item.getExtendedPrice()); 365 } 366 } 367 368 return lineItemPreTaxTotal; 369 } 370 371 /** 372 * Calculates the total of the above the line items 373 * 374 * @return KualiDecimal - above the line item total 375 */ 376 public KualiDecimal getLineItemTotal() { 377 KualiDecimal lineItemTotal = KualiDecimal.ZERO; 378 379 for (CreditMemoItem item : (List<CreditMemoItem>) getItems()) { 380 item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE); 381 if (item.getItemType().isLineItemIndicator() && item.getTotalAmount() != null) { 382 lineItemTotal = lineItemTotal.add(item.getTotalAmount()); 383 } 384 } 385 386 return lineItemTotal; 387 } 388 389 /** 390 * Calculates the credit memo total: Sum of above the line - restocking fees + misc amount 391 * 392 * @return KualiDecimal - credit memo document total 393 */ 394 public KualiDecimal getGrandTotal() { 395 KualiDecimal grandTotal = KualiDecimal.ZERO; 396 397 for (CreditMemoItem item : (List<CreditMemoItem>) getItems()) { 398 item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE); 399 400 if (item.getTotalAmount() != null) { 401 // make sure restocking fee is negative 402 if (StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_RESTCK_FEE_CODE, item.getItemTypeCode())) { 403 if( ObjectUtils.isNotNull(item.getExtendedPrice()) ){ 404 item.setExtendedPrice(item.getExtendedPrice().abs().negated()); 405 }else{ 406 item.setExtendedPrice(KualiDecimal.ZERO); 407 } 408 } 409 grandTotal = grandTotal.add(item.getTotalAmount()); 410 } 411 } 412 413 return grandTotal; 414 } 415 416 /** 417 * Calculates the credit memo pretax total: Sum of above the line - restocking fees + misc amount 418 * 419 * @return KualiDecimal - credit memo document total 420 */ 421 public KualiDecimal getGrandPreTaxTotal() { 422 KualiDecimal grandTotal = KualiDecimal.ZERO; 423 424 for (CreditMemoItem item : (List<CreditMemoItem>) getItems()) { 425 item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE); 426 427 if (item.getExtendedPrice() != null) { 428 // make sure restocking fee is negative 429 if (StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_RESTCK_FEE_CODE, item.getItemTypeCode())) { 430 item.setExtendedPrice(item.getExtendedPrice().abs().negated()); 431 } 432 grandTotal = grandTotal.add(item.getExtendedPrice()); 433 } 434 } 435 436 return grandTotal; 437 } 438 439 /** 440 * Calculates the credit memo tax amount: Sum of above the line - 441 * 442 * @return KualiDecimal - credit memo document total 443 */ 444 public KualiDecimal getGrandTaxAmount() { 445 KualiDecimal grandTotal = KualiDecimal.ZERO; 446 447 for (CreditMemoItem item : (List<CreditMemoItem>) getItems()) { 448 item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE); 449 450 if (item.getItemTaxAmount() != null) { 451 // make sure restocking fee is negative 452 if (StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_RESTCK_FEE_CODE, item.getItemTypeCode())) { 453 item.setExtendedPrice(item.getItemTaxAmount().abs().negated()); 454 } 455 grandTotal = grandTotal.add(item.getItemTaxAmount()); 456 } 457 } 458 459 return grandTotal; 460 } 461 462 public KualiDecimal getGrandPreTaxTotalExcludingRestockingFee() { 463 String[] restockingFeeCode = new String[] { PurapConstants.ItemTypeCodes.ITEM_TYPE_RESTCK_FEE_CODE }; 464 return this.getTotalPreTaxDollarAmountWithExclusions(restockingFeeCode, true); 465 } 466 467 public KualiDecimal getGrandTotalExcludingRestockingFee() { 468 String[] restockingFeeCode = new String[] { PurapConstants.ItemTypeCodes.ITEM_TYPE_RESTCK_FEE_CODE }; 469 return this.getTotalDollarAmountWithExclusions(restockingFeeCode, true); 470 } 471 472 public Integer getPaymentRequestIdentifier() { 473 return paymentRequestIdentifier; 474 } 475 476 public void setPaymentRequestIdentifier(Integer paymentRequestIdentifier) { 477 this.paymentRequestIdentifier = paymentRequestIdentifier; 478 } 479 480 public String getCreditMemoNumber() { 481 return creditMemoNumber; 482 } 483 484 public void setCreditMemoNumber(String creditMemoNumber) { 485 if (creditMemoNumber != null) { 486 creditMemoNumber = creditMemoNumber.toUpperCase(); 487 } 488 489 this.creditMemoNumber = creditMemoNumber; 490 } 491 492 public Date getCreditMemoDate() { 493 return creditMemoDate; 494 } 495 496 public void setCreditMemoDate(Date creditMemoDate) { 497 this.creditMemoDate = creditMemoDate; 498 } 499 500 public KualiDecimal getCreditMemoAmount() { 501 return creditMemoAmount; 502 } 503 504 public void setCreditMemoAmount(KualiDecimal creditMemoAmount) { 505 this.creditMemoAmount = creditMemoAmount; 506 } 507 508 public String getItemMiscellaneousCreditDescription() { 509 return itemMiscellaneousCreditDescription; 510 } 511 512 public void setItemMiscellaneousCreditDescription(String itemMiscellaneousCreditDescription) { 513 this.itemMiscellaneousCreditDescription = itemMiscellaneousCreditDescription; 514 } 515 516 public Timestamp getCreditMemoPaidTimestamp() { 517 return creditMemoPaidTimestamp; 518 } 519 520 public void setCreditMemoPaidTimestamp(Timestamp creditMemoPaidTimestamp) { 521 this.creditMemoPaidTimestamp = creditMemoPaidTimestamp; 522 } 523 524 public PaymentRequestDocument getPaymentRequestDocument() { 525 if ((ObjectUtils.isNull(paymentRequestDocument)) && (ObjectUtils.isNotNull(getPaymentRequestIdentifier()))) { 526 setPaymentRequestDocument(SpringContext.getBean(PaymentRequestService.class).getPaymentRequestById(getPaymentRequestIdentifier())); 527 } 528 return this.paymentRequestDocument; 529 } 530 531 public void setPaymentRequestDocument(PaymentRequestDocument paymentRequestDocument) { 532 if (ObjectUtils.isNull(paymentRequestDocument)) { 533 // do not blank out input, instead throw an error 534 // setPaymentRequestIdentifier(null); 535 this.paymentRequestDocument = null; 536 } 537 else { 538 setPaymentRequestIdentifier(paymentRequestDocument.getPurapDocumentIdentifier()); 539 this.paymentRequestDocument = paymentRequestDocument; 540 } 541 } 542 543 /** 544 * AS A REPLACEMENT USE getPaymentRequestDocument() 545 * 546 * @deprecated 547 */ 548 public PaymentRequestDocument getPaymentRequest() { 549 return getPaymentRequestDocument(); 550 } 551 552 /** 553 * AS A REPLACEMENT USE setPaymentRequestDocument(PaymentRequestDocument) 554 * 555 * @deprecated 556 */ 557 public void setPaymentRequest(PaymentRequestDocument paymentRequest) { 558 setPaymentRequestDocument(paymentRequest); 559 } 560 561 /** 562 * AS A REPLACEMENT USE getPurchaseOrderDocument() 563 * 564 * @deprecated 565 */ 566 public PurchaseOrderDocument getPurchaseOrder() { 567 return getPurchaseOrderDocument(); 568 } 569 570 /** 571 * AS A REPLACEMENT USE setPurchaseOrderDocument(PurchaseOrderDocument) 572 * 573 * @deprecated 574 */ 575 public void setPurchaseOrder(PurchaseOrderDocument purchaseOrder) { 576 setPurchaseOrderDocument(purchaseOrder); 577 } 578 579 public Date getPurchaseOrderEndDate() { 580 return purchaseOrderEndDate; 581 } 582 583 public void setPurchaseOrderEndDate(Date purchaseOrderEndDate) { 584 this.purchaseOrderEndDate = purchaseOrderEndDate; 585 } 586 587 /** 588 * USED FOR ROUTING ONLY 589 * 590 * @deprecated 591 */ 592 public String getStatusDescription() { 593 return ""; 594 } 595 596 /** 597 * USED FOR ROUTING ONLY 598 * 599 * @deprecated 600 */ 601 public void setStatusDescription(String statusDescription) { 602 } 603 604 /** 605 * @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#getPoDocumentTypeForAccountsPayableDocumentApprove() 606 */ 607 public String getPoDocumentTypeForAccountsPayableDocumentCancel() { 608 return PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_CLOSE_DOCUMENT; 609 } 610 611 /** 612 * @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#getInitialAmount() 613 */ 614 public KualiDecimal getInitialAmount() { 615 return this.getCreditMemoAmount(); 616 } 617 618 /** 619 * Credit Memo document is first populated on Continue AP Event, and then prepareForSave continues. 620 * 621 * @see org.kuali.rice.kns.document.Document#prepareForSave(org.kuali.rice.kns.rule.event.KualiDocumentEvent) 622 */ 623 @Override 624 public void prepareForSave(KualiDocumentEvent event) { 625 626 // first populate, then call super 627 if (event instanceof AttributedContinuePurapEvent) { 628 SpringContext.getBean(CreditMemoService.class).populateDocumentAfterInit(this); 629 } 630 631 super.prepareForSave(event); 632 } 633 634 /** 635 * @see org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase#isAttachmentRequired() 636 */ 637 @Override 638 protected boolean isAttachmentRequired() { 639 return StringUtils.equalsIgnoreCase("Y", SpringContext.getBean(ParameterService.class).getParameterValue(VendorCreditMemoDocument.class, PurapParameterConstants.PURAP_CM_REQUIRE_ATTACHMENT)); 640 } 641 642 /** 643 * @see org.kuali.kfs.module.purap.document.AccountsPayableDocument#getDocumentSpecificService() 644 */ 645 @Override 646 public AccountsPayableDocumentSpecificService getDocumentSpecificService() { 647 return SpringContext.getBean(CreditMemoService.class); 648 } 649 650 /** 651 * Forces GL entries to be approved before document final approval. 652 * 653 * @see org.kuali.module.purap.rules.PurapAccountingDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.kfs.sys.document.AccountingDocument, org.kuali.kfs.sys.businessobject.AccountingLine, org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry) 654 */ 655 @Override 656 public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry) { 657 super.customizeExplicitGeneralLedgerPendingEntry(postable, explicitEntry); 658 659 SpringContext.getBean(PurapGeneralLedgerService.class).customizeGeneralLedgerPendingEntry(this, (AccountingLine)postable, explicitEntry, getPurchaseOrderIdentifier(), getDebitCreditCodeForGLEntries(), PurapDocTypeCodes.CREDIT_MEMO_DOCUMENT, isGenerateEncumbranceEntries()); 660 661 // CMs do not wait for document final approval to post GL entries; here we are forcing them to be APPROVED 662 explicitEntry.setFinancialDocumentApprovedCode(KFSConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.APPROVED); 663 } 664 665 public Date getTransactionTaxDate() { 666 return getCreditMemoDate(); 667 } 668 669 public String getVendorAttentionName() { 670 return vendorAttentionName; 671 } 672 673 public void setVendorAttentionName(String vendorAttentionName) { 674 this.vendorAttentionName = vendorAttentionName; 675 } 676 677 /** 678 * Provides answers to the following splits: 679 * RequiresInvoiceAttachment 680 * @see org.kuali.kfs.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(java.lang.String) 681 */ 682 @Override 683 public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException { 684 if (nodeName.equals(PurapWorkflowConstants.REQUIRES_IMAGE_ATTACHMENT)) return requiresAccountsPayableReviewRouting(); 685 throw new UnsupportedOperationException("Cannot answer split question for this node you call \""+nodeName+"\""); 686 } 687 688 public String getPaidIndicatorForResult(){ 689 return getCreditMemoPaidTimestamp() != null ? "Yes" : "No"; 690 } 691 692 /** 693 * Checks all documents notes for attachments. 694 * 695 * @return - true if document does not have an image attached, false otherwise 696 */ 697 public boolean documentHasNoImagesAttached() { 698 List boNotes = this.getDocumentBusinessObject().getBoNotes(); 699 if (ObjectUtils.isNotNull(boNotes)) { 700 for (Object obj : boNotes) { 701 Note note = (Note) obj; 702 703 note.refreshReferenceObject("attachment"); 704 if (ObjectUtils.isNotNull(note.getAttachment()) && PurapConstants.AttachmentTypeCodes.ATTACHMENT_TYPE_CM_IMAGE.equals(note.getAttachment().getAttachmentTypeCode())) { 705 return false; 706 } 707 } 708 } 709 return true; 710 } 711 712 } 713