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