View Javadoc
1   /*
2    * Copyright 2007 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.kuali.ole.module.purap.document;
18  
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.ole.module.purap.PurapConstants;
21  import org.kuali.ole.module.purap.PurapConstants.PaymentRequestStatuses;
22  import org.kuali.ole.module.purap.PurapConstants.PurapDocTypeCodes;
23  import org.kuali.ole.module.purap.PurapParameterConstants;
24  import org.kuali.ole.module.purap.PurapPropertyConstants;
25  import org.kuali.ole.module.purap.PurapWorkflowConstants;
26  import org.kuali.ole.module.purap.businessobject.*;
27  import org.kuali.ole.module.purap.document.service.AccountsPayableDocumentSpecificService;
28  import org.kuali.ole.module.purap.document.service.AccountsPayableService;
29  import org.kuali.ole.module.purap.document.service.PaymentRequestService;
30  import org.kuali.ole.module.purap.document.service.PurapService;
31  import org.kuali.ole.module.purap.document.validation.event.AttributedContinuePurapEvent;
32  import org.kuali.ole.module.purap.service.PurapGeneralLedgerService;
33  import org.kuali.ole.module.purap.util.ExpiredOrClosedAccountEntry;
34  import org.kuali.ole.select.businessobject.OleLineItemReceivingItem;
35  import org.kuali.ole.select.businessobject.OlePurchaseOrderItem;
36  import org.kuali.ole.select.document.OleLineItemReceivingDocument;
37  import org.kuali.ole.select.document.OlePaymentRequestDocument;
38  import org.kuali.ole.select.document.service.OlePaymentRequestService;
39  import org.kuali.ole.sys.OLEConstants;
40  import org.kuali.ole.sys.businessobject.AccountingLine;
41  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry;
42  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
43  import org.kuali.ole.sys.context.SpringContext;
44  import org.kuali.ole.sys.service.UniversityDateService;
45  import org.kuali.ole.sys.service.impl.OleParameterConstants;
46  import org.kuali.ole.vnd.VendorConstants;
47  import org.kuali.ole.vnd.VendorPropertyConstants;
48  import org.kuali.ole.vnd.businessobject.*;
49  import org.kuali.ole.vnd.document.service.VendorService;
50  import org.kuali.rice.core.api.datetime.DateTimeService;
51  import org.kuali.rice.core.api.util.type.KualiDecimal;
52  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
53  import org.kuali.rice.kew.api.WorkflowDocument;
54  import org.kuali.rice.kew.api.exception.WorkflowException;
55  import org.kuali.rice.kew.framework.postprocessor.ActionTakenEvent;
56  import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
57  import org.kuali.rice.kim.api.identity.Person;
58  import org.kuali.rice.kns.service.DataDictionaryService;
59  import org.kuali.rice.krad.bo.DocumentHeader;
60  import org.kuali.rice.krad.bo.Note;
61  import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent;
62  import org.kuali.rice.krad.service.KRADServiceLocator;
63  import org.kuali.rice.krad.util.GlobalVariables;
64  import org.kuali.rice.krad.util.ObjectUtils;
65  import org.kuali.rice.krad.workflow.service.WorkflowDocumentService;
66  
67  import java.math.BigDecimal;
68  import java.sql.Date;
69  import java.sql.Timestamp;
70  import java.text.SimpleDateFormat;
71  import java.util.*;
72  
73  /**
74   * Payment Request Document Business Object. Contains the fields associated with the main document table.
75   */
76  public class PaymentRequestDocument extends AccountsPayableDocumentBase {
77      protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PaymentRequestDocument.class);
78  
79      protected Date invoiceDate;
80      protected String invoiceNumber;
81      protected KualiDecimal vendorInvoiceAmount;
82      protected String vendorPaymentTermsCode;
83      protected String vendorShippingPaymentTermsCode;
84      protected Date paymentRequestPayDate;
85      protected String paymentRequestCostSourceCode;
86      protected boolean paymentRequestedCancelIndicator;
87      protected boolean paymentAttachmentIndicator;
88      protected boolean immediatePaymentIndicator;
89      protected String specialHandlingInstructionLine1Text;
90      protected String specialHandlingInstructionLine2Text;
91      protected String specialHandlingInstructionLine3Text;
92      protected Timestamp paymentPaidTimestamp;
93      protected boolean paymentRequestElectronicInvoiceIndicator;
94      protected String accountsPayableRequestCancelIdentifier;
95      protected Integer originalVendorHeaderGeneratedIdentifier;
96      protected Integer originalVendorDetailAssignedIdentifier;
97      protected Integer alternateVendorHeaderGeneratedIdentifier;
98      protected Integer alternateVendorDetailAssignedIdentifier;
99      protected String purchaseOrderNotes;
100     protected String recurringPaymentTypeCode;
101     protected boolean receivingDocumentRequiredIndicator;
102     protected boolean paymentRequestPositiveApprovalIndicator;
103     protected Integer invoiceIdentifier;
104 
105 
106     public Integer getInvoiceIdentifier() {
107         return invoiceIdentifier;
108     }
109 
110 
111     public void setInvoiceIdentifier(Integer invoiceIdentifier) {
112         this.invoiceIdentifier = invoiceIdentifier;
113     }
114 
115 
116     // TAX EDIT AREA FIELDS
117     protected String taxClassificationCode;
118     protected String taxCountryCode;
119     protected String taxNQIId;
120     protected BigDecimal taxFederalPercent; // number is in whole form so 5% is 5.00
121     protected BigDecimal taxStatePercent; // number is in whole form so 5% is 5.00
122     protected KualiDecimal taxSpecialW4Amount;
123     protected Boolean taxGrossUpIndicator;
124     protected Boolean taxExemptTreatyIndicator;
125     protected Boolean taxForeignSourceIndicator;
126     protected Boolean taxUSAIDPerDiemIndicator;
127     protected Boolean taxOtherExemptIndicator;
128 
129     // NOT PERSISTED IN DB
130     protected String vendorShippingTitleCode;
131     protected Date purchaseOrderEndDate;
132     protected String primaryVendorName;
133 
134     // BELOW USED BY ROUTING
135     protected Integer requisitionIdentifier;
136 
137     // REFERENCE OBJECTS
138     protected PaymentTermType vendorPaymentTerms;
139     protected ShippingPaymentTerms vendorShippingPaymentTerms;
140     protected PurchaseOrderCostSource paymentRequestCostSource;
141     protected RecurringPaymentType recurringPaymentType;
142 
143     /**
144      * Default constructor.
145      */
146     public PaymentRequestDocument() {
147         super();
148     }
149 
150     /**
151      * @see org.kuali.rice.krad.bo.PersistableBusinessObjectBase#isBoNotesSupport()
152      */
153     public boolean isBoNotesSupport() {
154         return true;
155     }
156 
157     public Integer getPostingYearPriorOrCurrent() {
158         if (SpringContext.getBean(PaymentRequestService.class).allowBackpost(this)) {
159             // allow prior; use it
160             return SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear() - 1;
161         }
162         // don't allow prior; use CURRENT
163         return SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear();
164     }
165 
166 
167     /**
168      * Overrides the method in PurchasingAccountsPayableDocumentBase to add the criteria specific to Payment Request Document.
169      *
170      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#isInquiryRendered()
171      */
172     @Override
173     public boolean isInquiryRendered() {
174         if (isPostingYearPrior() && (getApplicationDocumentStatus().equals(PurapConstants.PaymentRequestStatuses.APPDOC_DEPARTMENT_APPROVED) || getApplicationDocumentStatus().equals(PurapConstants.PaymentRequestStatuses.APPDOC_AUTO_APPROVED) || getApplicationDocumentStatus().equals(PaymentRequestStatuses.APPDOC_EXTRACTED) || getApplicationDocumentStatus().equals(PaymentRequestStatuses.APPDOC_DO_NOT_EXTRACT) || getApplicationDocumentStatus().equals(PurapConstants.PaymentRequestStatuses.APPDOC_CANCELLED_POST_AP_APPROVE) || getApplicationDocumentStatus().equals(PurapConstants.PaymentRequestStatuses.APPDOC_CANCELLED_IN_PROCESS))) {
175             return false;
176         } else {
177             return true;
178         }
179     }
180 
181     public Integer getRequisitionIdentifier() {
182         return getPurchaseOrderDocument().getRequisitionIdentifier();
183     }
184 
185     public void setRequisitionIdentifier(Integer requisitionIdentifier) {
186         this.requisitionIdentifier = requisitionIdentifier;
187     }
188 
189     /**
190      * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#populateDocumentForRouting()
191      */
192     @Override
193     public void populateDocumentForRouting() {
194         this.setRequisitionIdentifier(getPurchaseOrderDocument().getRequisitionIdentifier());
195         super.populateDocumentForRouting();
196     }
197 
198     /**
199      * Decides whether receivingDocumentRequiredIndicator functionality shall be enabled according to the controlling parameter.
200      */
201     public boolean isEnableReceivingDocumentRequiredIndicator() {
202         return SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(OleParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.RECEIVING_DOCUMENT_REQUIRED_IND);
203     }
204 
205     /**
206      * Decides whether paymentRequestPositiveApprovalIndicator functionality shall be enabled according to the controlling parameter.
207      */
208     public boolean isEnablePaymentRequestPositiveApprovalIndicator() {
209         return SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(OleParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.PAYMENT_REQUEST_POSITIVE_APPROVAL_IND);
210     }
211 
212     public Date getInvoiceDate() {
213         return invoiceDate;
214     }
215 
216     public void setInvoiceDate(Date invoiceDate) {
217         this.invoiceDate = invoiceDate;
218     }
219 
220     public String getInvoiceNumber() {
221         return invoiceNumber;
222     }
223 
224     public void setInvoiceNumber(String invoiceNumber) {
225         if (!StringUtils.isEmpty(invoiceNumber)) {
226             this.invoiceNumber = invoiceNumber.toUpperCase();
227         } else {
228             this.invoiceNumber = invoiceNumber;
229         }
230     }
231 
232     public KualiDecimal getVendorInvoiceAmount() {
233         return vendorInvoiceAmount;
234     }
235 
236     public void setVendorInvoiceAmount(KualiDecimal vendorInvoiceAmount) {
237         this.vendorInvoiceAmount = vendorInvoiceAmount;
238     }
239 
240     public String getVendorPaymentTermsCode() {
241         return vendorPaymentTermsCode;
242     }
243 
244     public void setVendorPaymentTermsCode(String vendorPaymentTermsCode) {
245         this.vendorPaymentTermsCode = vendorPaymentTermsCode;
246         refreshReferenceObject("vendorPaymentTerms");
247     }
248 
249     public PaymentTermType getVendorPaymentTerms() {
250         if (ObjectUtils.isNull(vendorPaymentTerms) || !StringUtils.equalsIgnoreCase(getVendorPaymentTermsCode(), vendorPaymentTerms.getVendorPaymentTermsCode())) {
251             refreshReferenceObject(VendorPropertyConstants.VENDOR_PAYMENT_TERMS);
252         }
253         return vendorPaymentTerms;
254     }
255 
256     public void setVendorPaymentTerms(PaymentTermType vendorPaymentTerms) {
257         this.vendorPaymentTerms = vendorPaymentTerms;
258     }
259 
260     public String getVendorShippingPaymentTermsCode() {
261         if (ObjectUtils.isNull(vendorPaymentTerms)) {
262             refreshReferenceObject(VendorPropertyConstants.VENDOR_SHIPPING_PAYMENT_TERMS);
263         }
264         return vendorShippingPaymentTermsCode;
265     }
266 
267     public void setVendorShippingPaymentTermsCode(String vendorShippingPaymentTermsCode) {
268         this.vendorShippingPaymentTermsCode = vendorShippingPaymentTermsCode;
269     }
270 
271     public Date getPaymentRequestPayDate() {
272         return paymentRequestPayDate;
273     }
274 
275     public void setPaymentRequestPayDate(Date paymentRequestPayDate) {
276         this.paymentRequestPayDate = paymentRequestPayDate;
277     }
278 
279     public String getPaymentRequestCostSourceCode() {
280         return paymentRequestCostSourceCode;
281     }
282 
283     public void setPaymentRequestCostSourceCode(String paymentRequestCostSourceCode) {
284         this.paymentRequestCostSourceCode = paymentRequestCostSourceCode;
285     }
286 
287     public boolean getPaymentRequestedCancelIndicator() {
288         return paymentRequestedCancelIndicator;
289     }
290 
291     public boolean isPaymentRequestedCancelIndicator() {
292         return paymentRequestedCancelIndicator;
293     }
294 
295     public void setPaymentRequestedCancelIndicator(boolean paymentRequestedCancelIndicator) {
296         this.paymentRequestedCancelIndicator = paymentRequestedCancelIndicator;
297     }
298 
299     public boolean getPaymentAttachmentIndicator() {
300         return paymentAttachmentIndicator;
301     }
302 
303     public void setPaymentAttachmentIndicator(boolean paymentAttachmentIndicator) {
304         this.paymentAttachmentIndicator = paymentAttachmentIndicator;
305     }
306 
307     public boolean getImmediatePaymentIndicator() {
308         return immediatePaymentIndicator;
309     }
310 
311     public void setImmediatePaymentIndicator(boolean immediatePaymentIndicator) {
312         this.immediatePaymentIndicator = immediatePaymentIndicator;
313     }
314 
315     public String getSpecialHandlingInstructionLine1Text() {
316         return specialHandlingInstructionLine1Text;
317     }
318 
319     public void setSpecialHandlingInstructionLine1Text(String specialHandlingInstructionLine1Text) {
320         this.specialHandlingInstructionLine1Text = specialHandlingInstructionLine1Text;
321     }
322 
323     public String getSpecialHandlingInstructionLine2Text() {
324         return specialHandlingInstructionLine2Text;
325     }
326 
327     public void setSpecialHandlingInstructionLine2Text(String specialHandlingInstructionLine2Text) {
328         this.specialHandlingInstructionLine2Text = specialHandlingInstructionLine2Text;
329     }
330 
331     public String getSpecialHandlingInstructionLine3Text() {
332         return specialHandlingInstructionLine3Text;
333     }
334 
335     public void setSpecialHandlingInstructionLine3Text(String specialHandlingInstructionLine3Text) {
336         this.specialHandlingInstructionLine3Text = specialHandlingInstructionLine3Text;
337     }
338 
339     public Timestamp getPaymentPaidTimestamp() {
340         return paymentPaidTimestamp;
341     }
342 
343     public void setPaymentPaidTimestamp(Timestamp paymentPaidTimestamp) {
344         this.paymentPaidTimestamp = paymentPaidTimestamp;
345     }
346 
347     public boolean getPaymentRequestElectronicInvoiceIndicator() {
348         return paymentRequestElectronicInvoiceIndicator;
349     }
350 
351     public void setPaymentRequestElectronicInvoiceIndicator(boolean paymentRequestElectronicInvoiceIndicator) {
352         this.paymentRequestElectronicInvoiceIndicator = paymentRequestElectronicInvoiceIndicator;
353     }
354 
355     public String getAccountsPayableRequestCancelIdentifier() {
356         return accountsPayableRequestCancelIdentifier;
357     }
358 
359     public void setAccountsPayableRequestCancelIdentifier(String accountsPayableRequestCancelIdentifier) {
360         this.accountsPayableRequestCancelIdentifier = accountsPayableRequestCancelIdentifier;
361     }
362 
363     public Integer getOriginalVendorHeaderGeneratedIdentifier() {
364         return originalVendorHeaderGeneratedIdentifier;
365     }
366 
367     public void setOriginalVendorHeaderGeneratedIdentifier(Integer originalVendorHeaderGeneratedIdentifier) {
368         this.originalVendorHeaderGeneratedIdentifier = originalVendorHeaderGeneratedIdentifier;
369     }
370 
371     public Integer getOriginalVendorDetailAssignedIdentifier() {
372         return originalVendorDetailAssignedIdentifier;
373     }
374 
375     public void setOriginalVendorDetailAssignedIdentifier(Integer originalVendorDetailAssignedIdentifier) {
376         this.originalVendorDetailAssignedIdentifier = originalVendorDetailAssignedIdentifier;
377     }
378 
379     public Integer getAlternateVendorHeaderGeneratedIdentifier() {
380         return alternateVendorHeaderGeneratedIdentifier;
381     }
382 
383     public void setAlternateVendorHeaderGeneratedIdentifier(Integer alternateVendorHeaderGeneratedIdentifier) {
384         this.alternateVendorHeaderGeneratedIdentifier = alternateVendorHeaderGeneratedIdentifier;
385     }
386 
387     public Integer getAlternateVendorDetailAssignedIdentifier() {
388         return alternateVendorDetailAssignedIdentifier;
389     }
390 
391     public void setAlternateVendorDetailAssignedIdentifier(Integer alternateVendorDetailAssignedIdentifier) {
392         this.alternateVendorDetailAssignedIdentifier = alternateVendorDetailAssignedIdentifier;
393     }
394 
395     public ShippingPaymentTerms getVendorShippingPaymentTerms() {
396         return vendorShippingPaymentTerms;
397     }
398 
399     public void setVendorShippingPaymentTerms(ShippingPaymentTerms vendorShippingPaymentTerms) {
400         this.vendorShippingPaymentTerms = vendorShippingPaymentTerms;
401     }
402 
403     public String getVendorShippingTitleCode() {
404         if (ObjectUtils.isNotNull(this.getPurchaseOrderDocument())) {
405             return this.getPurchaseOrderDocument().getVendorShippingTitleCode();
406         }
407         return vendorShippingTitleCode;
408     }
409 
410     public void setVendorShippingTitleCode(String vendorShippingTitleCode) {
411         this.vendorShippingTitleCode = vendorShippingTitleCode;
412     }
413 
414     public Date getPurchaseOrderEndDate() {
415         return purchaseOrderEndDate;
416     }
417 
418     public void setPurchaseOrderEndDate(Date purchaseOrderEndDate) {
419         this.purchaseOrderEndDate = purchaseOrderEndDate;
420     }
421 
422     /**
423      * Gets the paymentRequestPositiveApprovalIndicator attribute.
424      *
425      * @return Returns the paymentRequestPositiveApprovalIndicator.
426      */
427     public boolean isPaymentRequestPositiveApprovalIndicator() {
428         return paymentRequestPositiveApprovalIndicator;
429     }
430 
431     /**
432      * Sets the paymentRequestPositiveApprovalIndicator attribute value.
433      *
434      * @param paymentRequestPositiveApprovalIndicator
435      *         The paymentRequestPositiveApprovalIndicator to set.
436      */
437     public void setPaymentRequestPositiveApprovalIndicator(boolean paymentRequestPositiveApprovalIndicator) {
438         // if paymentRequestPositiveApprovalIndicator functionality is disabled, always set it to false, overriding the passed-in value
439         if (!isEnablePaymentRequestPositiveApprovalIndicator()) {
440             paymentRequestPositiveApprovalIndicator = false;
441         } else {
442             this.paymentRequestPositiveApprovalIndicator = paymentRequestPositiveApprovalIndicator;
443         }
444     }
445 
446     /**
447      * Gets the receivingDocumentRequiredIndicator attribute.
448      *
449      * @return Returns the receivingDocumentRequiredIndicator.
450      */
451     public boolean isReceivingDocumentRequiredIndicator() {
452         return receivingDocumentRequiredIndicator;
453     }
454 
455     /**
456      * Sets the receivingDocumentRequiredIndicator attribute value.
457      *
458      * @param receivingDocumentRequiredIndicator
459      *         The receivingDocumentRequiredIndicator to set.
460      */
461     public void setReceivingDocumentRequiredIndicator(boolean receivingDocumentRequiredIndicator) {
462         // if receivingDocumentRequiredIndicator functionality is disabled, always set it to false, overriding the passed-in value
463         if (!isEnableReceivingDocumentRequiredIndicator()) {
464             receivingDocumentRequiredIndicator = false;
465         } else {
466             this.receivingDocumentRequiredIndicator = receivingDocumentRequiredIndicator;
467         }
468     }
469 
470     /**
471      * Perform logic needed to initiate PREQ Document
472      */
473     public void initiateDocument() throws WorkflowException {
474         LOG.debug("initiateDocument() started");
475         Person currentUser = GlobalVariables.getUserSession().getPerson();
476         updateAndSaveAppDocStatus(PurapConstants.PaymentRequestStatuses.APPDOC_INITIATE);
477         this.setAccountsPayableProcessorIdentifier(currentUser.getPrincipalId());
478         this.setProcessingCampusCode(currentUser.getCampusCode());
479         this.refreshNonUpdateableReferences();
480     }
481 
482     /**
483      * Perform logic needed to clear the initial fields on a PREQ Document
484      */
485     public void clearInitFields() {
486         LOG.debug("clearDocument() started");
487         // Clearing document overview fields
488         this.getDocumentHeader().setDocumentDescription(null);
489         this.getDocumentHeader().setExplanation(null);
490         this.getFinancialSystemDocumentHeader().setFinancialDocumentTotalAmount(null);
491         this.getDocumentHeader().setOrganizationDocumentNumber(null);
492 
493         // Clearing document Init fields
494         this.setPurchaseOrderIdentifier(null);
495         this.setInvoiceNumber(null);
496         this.setInvoiceDate(null);
497         this.setVendorInvoiceAmount(null);
498         this.setSpecialHandlingInstructionLine1Text(null);
499         this.setSpecialHandlingInstructionLine2Text(null);
500         this.setSpecialHandlingInstructionLine3Text(null);
501     }
502 
503     /**
504      * Populates a preq from a PO - delegate method
505      *
506      * @param po -
507      */
508     public void populatePaymentRequestFromPurchaseOrder(PurchaseOrderDocument po) {
509         populatePaymentRequestFromPurchaseOrder(po, new HashMap<String, ExpiredOrClosedAccountEntry>());
510     }
511 
512 
513     /**
514      * Populates a preq from a PO
515      *
516      * @param po                         Purchase Order Document used for populating the PREQ
517      * @param expiredOrClosedAccountList a list of closed or expired accounts
518      */
519     public void populatePaymentRequestFromPurchaseOrder(PurchaseOrderDocument po, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
520         this.setPurchaseOrderIdentifier(po.getPurapDocumentIdentifier());
521         this.getDocumentHeader().setOrganizationDocumentNumber(po.getDocumentHeader().getOrganizationDocumentNumber());
522         this.setPostingYear(po.getPostingYear());
523         this.setReceivingDocumentRequiredIndicator(po.isReceivingDocumentRequiredIndicator());
524         this.setUseTaxIndicator(po.isUseTaxIndicator());
525         this.setPaymentRequestPositiveApprovalIndicator(po.isPaymentRequestPositiveApprovalIndicator());
526         this.setVendorCustomerNumber(po.getVendorCustomerNumber());
527         this.setAccountDistributionMethod(po.getAccountDistributionMethod());
528 
529         if (po.getPurchaseOrderCostSource() != null) {
530             this.setPaymentRequestCostSource(po.getPurchaseOrderCostSource());
531             this.setPaymentRequestCostSourceCode(po.getPurchaseOrderCostSourceCode());
532         }
533 
534         if (po.getVendorShippingPaymentTerms() != null) {
535             this.setVendorShippingPaymentTerms(po.getVendorShippingPaymentTerms());
536             this.setVendorShippingPaymentTermsCode(po.getVendorShippingPaymentTermsCode());
537         }
538 
539         if (po.getVendorPaymentTerms() != null) {
540             this.setVendorPaymentTermsCode(po.getVendorPaymentTermsCode());
541             this.setVendorPaymentTerms(po.getVendorPaymentTerms());
542         }
543 
544         if (po.getRecurringPaymentType() != null) {
545             this.setRecurringPaymentType(po.getRecurringPaymentType());
546             this.setRecurringPaymentTypeCode(po.getRecurringPaymentTypeCode());
547         }
548 
549         this.setVendorHeaderGeneratedIdentifier(po.getVendorHeaderGeneratedIdentifier());
550         this.setVendorDetailAssignedIdentifier(po.getVendorDetailAssignedIdentifier());
551         this.setVendorCustomerNumber(po.getVendorCustomerNumber());
552         this.setVendorName(po.getVendorName());
553 
554         // set original vendor
555         this.setOriginalVendorHeaderGeneratedIdentifier(po.getVendorHeaderGeneratedIdentifier());
556         this.setOriginalVendorDetailAssignedIdentifier(po.getVendorDetailAssignedIdentifier());
557 
558         // set alternate vendor info as well
559         this.setAlternateVendorHeaderGeneratedIdentifier(po.getAlternateVendorHeaderGeneratedIdentifier());
560         this.setAlternateVendorDetailAssignedIdentifier(po.getAlternateVendorDetailAssignedIdentifier());
561 
562         // populate preq vendor address with the default remit address type for the vendor if found
563         String userCampus = GlobalVariables.getUserSession().getPerson().getCampusCode();
564         VendorAddress vendorAddress = SpringContext.getBean(VendorService.class).getVendorDefaultAddress(po.getVendorHeaderGeneratedIdentifier(), po.getVendorDetailAssignedIdentifier(), VendorConstants.AddressTypes.REMIT, userCampus);
565         if (vendorAddress != null) {
566             this.templateVendorAddress(vendorAddress);
567             this.setVendorAddressGeneratedIdentifier(vendorAddress.getVendorAddressGeneratedIdentifier());
568             setVendorAttentionName(StringUtils.defaultString(vendorAddress.getVendorAttentionName()));
569         } else {
570             // set address from PO
571             this.setVendorAddressGeneratedIdentifier(po.getVendorAddressGeneratedIdentifier());
572             this.setVendorLine1Address(po.getVendorLine1Address());
573             this.setVendorLine2Address(po.getVendorLine2Address());
574             this.setVendorCityName(po.getVendorCityName());
575             this.setVendorAddressInternationalProvinceName(po.getVendorAddressInternationalProvinceName());
576             this.setVendorStateCode(po.getVendorStateCode());
577             this.setVendorPostalCode(po.getVendorPostalCode());
578             this.setVendorCountryCode(po.getVendorCountryCode());
579 
580             boolean blankAttentionLine = StringUtils.equalsIgnoreCase("Y", SpringContext.getBean(ParameterService.class).getParameterValueAsString(PurapConstants.PURAP_NAMESPACE, "Document", PurapParameterConstants.BLANK_ATTENTION_LINE_FOR_PO_TYPE_ADDRESS));
581 
582             if (blankAttentionLine) {
583                 setVendorAttentionName(StringUtils.EMPTY);
584             } else {
585                 setVendorAttentionName(StringUtils.defaultString(po.getVendorAttentionName()));
586             }
587         }
588 
589         this.setPaymentRequestPayDate(SpringContext.getBean(PaymentRequestService.class).calculatePayDate(this.getInvoiceDate(), this.getVendorPaymentTerms()));
590 
591         AccountsPayableService accountsPayableService = SpringContext.getBean(AccountsPayableService.class);
592 
593         if (SpringContext.getBean(PaymentRequestService.class).encumberedItemExistsForInvoicing(po)) {
594             for (PurchaseOrderItem poi : (List<PurchaseOrderItem>) po.getItems()) {
595                 // check to make sure it's eligible for payment (i.e. active and has encumbrance available
596                 if (getDocumentSpecificService().poItemEligibleForAp(this, poi)) {
597                     PaymentRequestItem paymentRequestItem = new PaymentRequestItem(poi, this, expiredOrClosedAccountList);
598                     this.getItems().add(paymentRequestItem);
599                     PurchasingCapitalAssetItem purchasingCAMSItem = po.getPurchasingCapitalAssetItemByItemIdentifier(poi.getItemIdentifier());
600                     if (purchasingCAMSItem != null) {
601                         paymentRequestItem.setCapitalAssetTransactionTypeCode(purchasingCAMSItem.getCapitalAssetTransactionTypeCode());
602                     }
603 
604                     /*
605                     // copy usetaxitems over
606                     paymentRequestItem.getUseTaxItems().clear();
607                     for (PurApItemUseTax useTax : poi.getUseTaxItems()) {
608                         paymentRequestItem.getUseTaxItems().add(useTax);
609                     }
610                     */
611                 }
612             }
613         }
614 
615         // add missing below the line
616         SpringContext.getBean(PurapService.class).addBelowLineItems(this);
617         this.setAccountsPayablePurchasingDocumentLinkIdentifier(po.getAccountsPayablePurchasingDocumentLinkIdentifier());
618 
619         //fix up below the line items
620         SpringContext.getBean(PaymentRequestService.class).removeIneligibleAdditionalCharges(this);
621 
622         this.fixItemReferences();
623         this.refreshNonUpdateableReferences();
624     }
625 
626     /**
627      * @see org.kuali.rice.krad.document.DocumentBase#getDocumentTitle()
628      */
629     @Override
630     public String getDocumentTitle() {
631         if (SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(PaymentRequestDocument.class, PurapParameterConstants.PURAP_OVERRIDE_PREQ_DOC_TITLE)) {
632             return getCustomDocumentTitle();
633         }
634         return this.buildDocumentTitle(super.getDocumentTitle());
635     }
636 
637     /**
638      * Returns a custom document title based on the workflow document title. Depending on what route level the document is currently
639      * in, the PO, vendor, amount, account number, dept, campus may be added to the documents title.
640      *
641      * @return - Customized document title text dependent upon route level.
642      */
643     protected String getCustomDocumentTitle() {
644 
645         // set the workflow document title
646         String poNumber = getPurchaseOrderIdentifier().toString();
647         String vendorName = StringUtils.trimToEmpty(getVendorName());
648         String preqAmount = getGrandTotal().toString();
649 
650         String documentTitle = "";
651         Set<String> nodeNames = this.getFinancialSystemDocumentHeader().getWorkflowDocument().getCurrentNodeNames();
652 
653         // if this doc is final or will be final
654         if (nodeNames.size() == 0 || this.getFinancialSystemDocumentHeader().getWorkflowDocument().isFinal()) {
655             documentTitle = (new StringBuffer("PO: ")).append(poNumber).append(" Vendor: ").append(vendorName).append(" Amount: ").append(preqAmount).toString();
656         } else {
657             PurApAccountingLine theAccount = getFirstAccount();
658             String accountNumber = (theAccount != null ? StringUtils.trimToEmpty(theAccount.getAccountNumber()) : "n/a");
659             String accountChart = (theAccount != null ? theAccount.getChartOfAccountsCode() : "");
660             String payDate = (new SimpleDateFormat("MM/dd/yyyy")).format(getPaymentRequestPayDate());
661             String indicator = getTitleIndicator();
662 
663             // set title to: PO# - VendorName - Chart/Account - total amt - Pay Date - Indicator (ie Hold, Request Cancel)
664             documentTitle = (new StringBuffer("PO: ")).append(poNumber).append(" Vendor: ").append(vendorName).append(" Account: ").append(accountChart).append(" ").append(accountNumber).append(" Amount: ").append(preqAmount).append(" Pay Date: ").append(payDate).append(" ").append(indicator).toString();
665         }
666         return documentTitle;
667     }
668 
669     /**
670      * Returns the first payment item's first account (assuming the item list is sequentially ordered).
671      *
672      * @return - Accounting Line object for first account of first payment item.
673      */
674     public PurApAccountingLine getFirstAccount() {
675         // loop through items, and pick the first item
676         if ((getItems() != null) && (!getItems().isEmpty())) {
677             PaymentRequestItem itemToUse = null;
678             for (Iterator iter = getItems().iterator(); iter.hasNext(); ) {
679                 PaymentRequestItem item = (PaymentRequestItem) iter.next();
680                 if ((item.isConsideredEntered()) && ((item.getSourceAccountingLines() != null) && (!item.getSourceAccountingLines().isEmpty()))) {
681                     // accounting lines are not empty so pick the first account
682                     PurApAccountingLine accountLine = item.getSourceAccountingLine(0);
683                     accountLine.refreshNonUpdateableReferences();
684                     return accountLine;
685                 }
686                 /*
687                 if (((item.getExtendedPrice() != null) && item.getExtendedPrice().compareTo(BigDecimal.ZERO) > 0) && ((item.getAccounts() != null) && (!item.getAccounts().isEmpty()))) {
688                     // accounting lines are not empty so pick the first account
689                List accts = (List)item.getAccounts();
690                PaymentRequestAccount accountLine = (PaymentRequestAccount)accts.get(0);
691                     return accountLine.getFinancialChartOfAccountsCode() + "-" + accountLine.getAccountNumber();
692                 }
693                 */
694             }
695         }
696         return null;
697     }
698 
699     /**
700      * Determines the indicator text that will appear in the workflow document title
701      *
702      * @return - Text of hold or request cancel
703      */
704     protected String getTitleIndicator() {
705         if (isHoldIndicator()) {
706             return PurapConstants.PaymentRequestIndicatorText.HOLD;
707         } else if (isPaymentRequestedCancelIndicator()) {
708             return PurapConstants.PaymentRequestIndicatorText.REQUEST_CANCEL;
709         }
710         return "";
711     }
712 
713 
714     /**
715      * @see org.kuali.rice.krad.document.DocumentBase#doRouteStatusChange(org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange)
716      */
717     @Override
718     public void doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) {
719         LOG.debug("doRouteStatusChange() started");
720 
721         super.doRouteStatusChange(statusChangeEvent);
722         try {
723             // DOCUMENT PROCESSED
724             if (this.getFinancialSystemDocumentHeader().getWorkflowDocument().isProcessed()) {
725                 if (!PaymentRequestStatuses.APPDOC_AUTO_APPROVED.equals(getApplicationDocumentStatus())) {
726                     populateDocumentForRouting();
727                   //  updateAndSaveAppDocStatus(PurapConstants.PaymentRequestStatuses.APPDOC_DEPARTMENT_APPROVED);
728 
729                     Map payMap = new HashMap();
730                     payMap.put("purchaseOrderIdentifier",this.getPurchaseOrderIdentifier());
731                     List<OlePaymentRequestDocument> olePaymentRequestDocument = (List<OlePaymentRequestDocument>) KRADServiceLocator.getBusinessObjectService().findMatching(OlePaymentRequestDocument.class,payMap);
732 
733                     if(!(SpringContext.getBean(OlePaymentRequestService.class).getPaymentMethod(olePaymentRequestDocument.get(0).getPaymentMethodId()).equals(OLEConstants.DEPOSIT)))   {
734                         updateAndSaveAppDocStatus(PurapConstants.PaymentRequestStatuses.APPDOC_DEPARTMENT_APPROVED);
735                     }
736                     else {
737                         updateAndSaveAppDocStatus(PaymentRequestStatuses.APPDOC_DO_NOT_EXTRACT);
738                     }
739 
740                     PurchaseOrderDocument purchaseOrderDocument = this.getPurchaseOrderDocument();
741                     if (purchaseOrderDocument.getOrderType().getPurchaseOrderType().equals(OLEConstants.ORD_TYPE_FIRM_FIX) || purchaseOrderDocument.getOrderType().getPurchaseOrderType().equals(OLEConstants.APPROVAL) || purchaseOrderDocument.getOrderType().getPurchaseOrderType().equals(OLEConstants.FIRM_MUL_PART)) {
742                         DocumentHeader paymentRequestDocumentHeader = this.getDocumentHeader();
743                         closePurchaseOrder();
744                         this.setDocumentHeader(paymentRequestDocumentHeader);
745                     }
746                 }
747             }
748             // DOCUMENT DISAPPROVED
749             else if (this.getFinancialSystemDocumentHeader().getWorkflowDocument().isDisapproved()) {
750                 String nodeName = SpringContext.getBean(WorkflowDocumentService.class).getCurrentRouteLevelName(getDocumentHeader().getWorkflowDocument());
751                 String disapprovalStatus = PurapConstants.PaymentRequestStatuses.getPaymentRequestAppDocDisapproveStatuses().get(nodeName);
752 
753                 if (ObjectUtils.isNotNull(nodeName)) {
754                     if (((StringUtils.isBlank(disapprovalStatus)) && ((PaymentRequestStatuses.APPDOC_INITIATE.equals(getApplicationDocumentStatus())) || (PaymentRequestStatuses.APPDOC_IN_PROCESS.equals(getApplicationDocumentStatus()))))) {
755                         disapprovalStatus = PaymentRequestStatuses.APPDOC_CANCELLED_IN_PROCESS;
756                     }
757                     if (StringUtils.isNotBlank(disapprovalStatus)) {
758                         SpringContext.getBean(AccountsPayableService.class).cancelAccountsPayableDocument(this, nodeName);
759                         updateAndSaveAppDocStatus(disapprovalStatus);
760                     }
761                 } else {
762                     logAndThrowRuntimeException("No status found to set for document being disapproved in node '" + nodeName + "'");
763                 }
764             }
765             // DOCUMENT CANCELED
766             else if (this.getFinancialSystemDocumentHeader().getWorkflowDocument().isCanceled()) {
767                 String currentNodeName = SpringContext.getBean(WorkflowDocumentService.class).getCurrentRouteLevelName(this.getDocumentHeader().getWorkflowDocument());
768                 String cancelledStatus = PurapConstants.PaymentRequestStatuses.getPaymentRequestAppDocDisapproveStatuses().get(currentNodeName);
769 
770                 //**START AZ** KATTS-37 KevinMcO
771                 if (StringUtils.isBlank(cancelledStatus) &&
772                         StringUtils.isBlank(PurapConstants.PaymentRequestStatuses.getPaymentRequestAppDocDisapproveStatuses().get(currentNodeName)) &&
773                         (PaymentRequestStatuses.APPDOC_INITIATE.equals(getStatusCode()) || PaymentRequestStatuses.APPDOC_IN_PROCESS.equals(getStatusCode()))) {
774                     cancelledStatus = PaymentRequestStatuses.APPDOC_CANCELLED_IN_PROCESS;
775                 }
776                 //**END AZ**
777 
778                 if (ObjectUtils.isNotNull(cancelledStatus)) {
779                     SpringContext.getBean(AccountsPayableService.class).cancelAccountsPayableDocument(this, currentNodeName);
780                     updateAndSaveAppDocStatus(cancelledStatus);
781                 } else {
782                     logAndThrowRuntimeException("No status found to set for document being canceled in node '" + currentNodeName + "'");
783                 }
784             }
785         } catch (WorkflowException e) {
786             logAndThrowRuntimeException("Error saving routing data while saving document with id " + getDocumentNumber(), e);
787         }
788     }
789 
790     /**
791      * Generates correcting entries to the GL if accounts are modified.
792      *
793      * @see org.kuali.rice.krad.document.Document#doActionTaken(org.kuali.rice.kew.clientapp.vo.ActionTakenEventDTO)
794      */
795     @Override
796     public void doActionTaken(ActionTakenEvent event) {
797         super.doActionTaken(event);
798         WorkflowDocument workflowDocument = getDocumentHeader().getWorkflowDocument();
799         String currentNode = null;
800         Object[] names = workflowDocument.getCurrentNodeNames().toArray();
801         if (names.length > 0) {
802             currentNode = (String) names[0];
803         }
804 
805         // everything in the below list requires correcting entries to be written to the GL
806         if (PaymentRequestStatuses.getNodesRequiringCorrectingGeneralLedgerEntries().contains(currentNode)) {
807             SpringContext.getBean(PurapGeneralLedgerService.class).generateEntriesModifyPaymentRequest(this);
808         }
809     }
810 
811     /**
812      * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#processNodeChange(java.lang.String, java.lang.String)
813      */
814     @Override
815     public boolean processNodeChange(String newNodeName, String oldNodeName) {
816         if (PaymentRequestStatuses.APPDOC_AUTO_APPROVED.equals(getApplicationDocumentStatus())) {
817             // do nothing for an auto approval
818             return false;
819         }
820         if (PaymentRequestStatuses.NODE_ADHOC_REVIEW.equals(oldNodeName)) {
821             SpringContext.getBean(AccountsPayableService.class).performLogicForFullEntryCompleted(this);
822         }
823         return true;
824     }
825 
826     /**
827      * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#saveDocumentFromPostProcessing()
828      */
829     @Override
830     public void saveDocumentFromPostProcessing() {
831         SpringContext.getBean(PurapService.class).saveDocumentNoValidation(this);
832 
833         // if we've hit full entry completed then close/reopen po
834         if (SpringContext.getBean(PurapService.class).isFullDocumentEntryCompleted(this) && this.isClosePurchaseOrderIndicator()) {
835             SpringContext.getBean(PurapService.class).performLogicForCloseReopenPO(this);
836         }
837     }
838 
839     /**
840      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#getItemClass()
841      */
842     @Override
843     public Class getItemClass() {
844         return PaymentRequestItem.class;
845     }
846 
847     @Override
848     public Class getItemUseTaxClass() {
849         return PaymentRequestItemUseTax.class;
850     }
851 
852     /**
853      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#getPurApSourceDocumentIfPossible()
854      */
855     @Override
856     public PurchaseOrderDocument getPurApSourceDocumentIfPossible() {
857         return getPurchaseOrderDocument();
858     }
859 
860     /**
861      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#getPurApSourceDocumentLabelIfPossible()
862      */
863     @Override
864     public String getPurApSourceDocumentLabelIfPossible() {
865         return SpringContext.getBean(DataDictionaryService.class).getDocumentLabelByTypeName(OLEConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER);
866     }
867 
868     public String getPurchaseOrderNotes() {
869 
870         ArrayList poNotes = (ArrayList) this.getPurchaseOrderDocument().getNotes();
871 
872         if (poNotes.size() > 0) {
873             return "Yes";
874         }
875         return "No";
876     }
877 
878     public void setPurchaseOrderNotes(String purchaseOrderNotes) {
879         this.purchaseOrderNotes = purchaseOrderNotes;
880     }
881 
882     public String getRecurringPaymentTypeCode() {
883         return recurringPaymentTypeCode;
884     }
885 
886     public void setRecurringPaymentTypeCode(String recurringPaymentTypeCode) {
887         this.recurringPaymentTypeCode = recurringPaymentTypeCode;
888     }
889 
890     /**
891      * Returns the total encumbered amount from the purchase order excluding below the line.
892      *
893      * @return Total cost excluding below the line
894      */
895     public KualiDecimal getItemTotalPoEncumbranceAmount() {
896         // get total from po excluding below the line and inactive
897         return this.getPurchaseOrderDocument().getTotalDollarAmount(false, false);
898     }
899 
900     public KualiDecimal getItemTotalPoEncumbranceAmountRelieved() {
901         return getItemTotalPoEncumbranceAmountRelieved(false);
902     }
903 
904     public KualiDecimal getItemTotalPoEncumbranceAmountRelieved(boolean includeBelowTheLine) {
905 
906         KualiDecimal total = KualiDecimal.ZERO;
907 
908         for (PurchaseOrderItem item : (List<PurchaseOrderItem>) getPurchaseOrderDocument().getItems()) {
909             ItemType it = item.getItemType();
910             if (includeBelowTheLine || it.isLineItemIndicator()) {
911                 total = total.add(item.getItemEncumbranceRelievedAmount());
912             }
913         }
914         return total;
915     }
916 
917     public KualiDecimal getLineItemTotal() {
918         return this.getTotalDollarAmountAboveLineItems();
919     }
920 
921     public KualiDecimal getLineItemPreTaxTotal() {
922         return this.getTotalPreTaxDollarAmountAboveLineItems();
923     }
924 
925     public KualiDecimal getLineItemTaxAmount() {
926         return this.getTotalTaxAmountAboveLineItems();
927     }
928 
929     @Override
930     public KualiDecimal getGrandTotal() {
931         return this.getTotalDollarAmount();
932     }
933 
934     public KualiDecimal getGrandTotalExcludingDiscount() {
935         String[] discountCode = new String[]{PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE};
936         return this.getTotalDollarAmountWithExclusions(discountCode, true);
937     }
938 
939     /**
940      * This method is here due to a setter requirement by the htmlControlAttribute
941      *
942      * @param amount - Grand total for document, excluding discount
943      */
944     public void setGrandTotalExcludingDiscount(KualiDecimal amount) {
945         // do nothing
946     }
947 
948     public KualiDecimal getGrandPreTaxTotal() {
949         return this.getTotalPreTaxDollarAmount();
950     }
951 
952     public KualiDecimal getGrandPreTaxTotalExcludingDiscount() {
953         String[] discountCode = new String[]{PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE};
954         return this.getTotalPreTaxDollarAmountWithExclusions(discountCode, true);
955     }
956 
957     public KualiDecimal getGrandTaxAmount() {
958         return this.getTotalTaxAmount();
959     }
960 
961     public KualiDecimal getGrandTaxAmountExcludingDiscount() {
962         String[] discountCode = new String[]{PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE};
963         return this.getTotalTaxAmountWithExclusions(discountCode, true);
964     }
965 
966     public boolean isDiscount() {
967         return SpringContext.getBean(PaymentRequestService.class).hasDiscountItem(this);
968     }
969 
970     /**
971      * The total that was paid on the po excluding below the line
972      *
973      * @return total paid
974      */
975     public KualiDecimal getItemTotalPoPaidAmount() {
976         KualiDecimal total = KualiDecimal.ZERO;
977         for (PurchaseOrderItem item : (List<PurchaseOrderItem>) getPurchaseOrderDocument().getItems()) {
978             ItemType iT = item.getItemType();
979             if (iT.isLineItemIndicator()) {
980                 KualiDecimal itemPaid = item.getItemPaidAmount();
981                 total = total.add(itemPaid);
982             }
983         }
984         return total;
985     }
986 
987     /**
988      * Returns the name of who requested cancel.
989      *
990      * @return - name of who requested cancel.
991      */
992     public String getAccountsPayableRequestCancelPersonName() {
993         String personName = null;
994         Person user = SpringContext.getBean(org.kuali.rice.kim.api.identity.PersonService.class).getPerson(getAccountsPayableRequestCancelIdentifier());
995         if (user != null) {
996             personName = user.getName();
997         } else {
998             personName = "";
999         }
1000 
1001         return personName;
1002     }
1003 
1004     /**
1005      * Exists due to a setter requirement by the htmlControlAttribute
1006      *
1007      * @param amount - total po amount paid
1008      */
1009     public void setItemTotalPoPaidAmount(KualiDecimal amount) {
1010         // do nothing
1011     }
1012 
1013     /**
1014      * Exists due to a setter requirement by the htmlControlAttribute
1015      *
1016      * @param amount - total po encumbrance
1017      */
1018     public void setItemTotalPoEncumbranceAmount(KualiDecimal amount) {
1019         // do nothing
1020     }
1021 
1022     /**
1023      * Exists due to a setter requirement by the htmlControlAttribute
1024      *
1025      * @param amount - total po encumbrance amount relieved
1026      */
1027     public void setItemTotalPoEncumbranceAmountRelieved(KualiDecimal amount) {
1028         // do nothing
1029     }
1030 
1031     /**
1032      * Determinines the route levels for a given document.
1033      *
1034      * @param workflowDocument - work flow document
1035      * @return List - list of route levels
1036      */
1037     protected List<String> getCurrentRouteLevels(WorkflowDocument workflowDocument) {
1038         Set<String> names = workflowDocument.getCurrentNodeNames();
1039         return new ArrayList<String>(names);
1040     }
1041 
1042     public RecurringPaymentType getRecurringPaymentType() {
1043         if (ObjectUtils.isNull(recurringPaymentType)) {
1044             refreshReferenceObject(PurapPropertyConstants.RECURRING_PAYMENT_TYPE);
1045         }
1046         return recurringPaymentType;
1047     }
1048 
1049     public void setRecurringPaymentType(RecurringPaymentType recurringPaymentType) {
1050         this.recurringPaymentType = recurringPaymentType;
1051     }
1052 
1053     public PurchaseOrderCostSource getPaymentRequestCostSource() {
1054         return paymentRequestCostSource;
1055     }
1056 
1057     public void setPaymentRequestCostSource(PurchaseOrderCostSource paymentRequestCostSource) {
1058         this.paymentRequestCostSource = paymentRequestCostSource;
1059     }
1060 
1061     /**
1062      * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#getPoDocumentTypeForAccountsPayableDocumentApprove()
1063      */
1064     @Override
1065     public String getPoDocumentTypeForAccountsPayableDocumentCancel() {
1066         return PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_REOPEN_DOCUMENT;
1067     }
1068 
1069     /**
1070      * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#getInitialAmount()
1071      */
1072     @Override
1073     public KualiDecimal getInitialAmount() {
1074         return this.getVendorInvoiceAmount();
1075     }
1076 
1077     /**
1078      * Populates the payment request document, then continues with preparing for save.
1079      *
1080      * @see org.kuali.rice.krad.document.Document#prepareForSave(org.kuali.rice.krad.rule.event.KualiDocumentEvent)
1081      */
1082     @Override
1083     public void prepareForSave(KualiDocumentEvent event) {
1084         WorkflowDocument workflowDocument = this.getDocumentHeader().getWorkflowDocument();
1085         String workflowDocumentTitle = this.buildDocumentTitle(workflowDocument.getTitle());
1086 
1087         this.getFinancialSystemDocumentHeader().getWorkflowDocument().setTitle(workflowDocumentTitle);
1088 
1089         // first populate, then call super
1090         if (event instanceof AttributedContinuePurapEvent) {
1091             SpringContext.getBean(PaymentRequestService.class).populatePaymentRequest(this);
1092         }
1093         super.prepareForSave(event);
1094 
1095     }
1096 
1097     /**
1098      * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#isAttachmentRequired()
1099      */
1100     @Override
1101     protected boolean isAttachmentRequired() {
1102         if (getPaymentRequestElectronicInvoiceIndicator()) {
1103             return false;
1104         }
1105         return StringUtils.equalsIgnoreCase("Y", SpringContext.getBean(ParameterService.class).getParameterValueAsString(PaymentRequestDocument.class, PurapParameterConstants.PURAP_PREQ_REQUIRE_ATTACHMENT));
1106     }
1107 
1108     /**
1109      * @see org.kuali.ole.module.purap.document.AccountsPayableDocument#getDocumentSpecificService()
1110      */
1111     @Override
1112     public AccountsPayableDocumentSpecificService getDocumentSpecificService() {
1113         return SpringContext.getBean(PaymentRequestService.class);
1114     }
1115 
1116     /**
1117      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#getItem(int)
1118      */
1119     @Override
1120     public PurApItem getItem(int pos) {
1121         PaymentRequestItem item = (PaymentRequestItem) super.getItem(pos);
1122         if (item.getPaymentRequest() == null) {
1123             item.setPaymentRequest(this);
1124         }
1125         return item;
1126     }
1127 
1128     public String getPrimaryVendorName() {
1129 
1130         if (primaryVendorName == null) {
1131             VendorDetail vd = SpringContext.getBean(VendorService.class).getVendorDetail(this.getOriginalVendorHeaderGeneratedIdentifier(), this.getOriginalVendorDetailAssignedIdentifier());
1132 
1133             if (vd != null) {
1134                 primaryVendorName = vd.getVendorName();
1135             }
1136         }
1137 
1138         return primaryVendorName;
1139     }
1140 
1141     /**
1142      * @deprecated
1143      */
1144     @Deprecated
1145     public void setPrimaryVendorName(String primaryVendorName) {
1146     }
1147 
1148     /**
1149      * Forces general ledger entries to be approved, does not wait for payment request document final approval.
1150      *
1151      * @see org.kuali.module.purap.rules.PurapAccountingDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.ole.sys.document.AccountingDocument,
1152      *      org.kuali.ole.sys.businessobject.AccountingLine, org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry)
1153      */
1154     @Override
1155     public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry) {
1156         super.customizeExplicitGeneralLedgerPendingEntry(postable, explicitEntry);
1157 
1158         SpringContext.getBean(PurapGeneralLedgerService.class).customizeGeneralLedgerPendingEntry(this, (AccountingLine) postable, explicitEntry, getPurchaseOrderIdentifier(), getDebitCreditCodeForGLEntries(), PurapDocTypeCodes.PAYMENT_REQUEST_DOCUMENT, isGenerateEncumbranceEntries());
1159 
1160         // PREQs do not wait for document final approval to post GL entries; here we are forcing them to be APPROVED
1161         explicitEntry.setFinancialDocumentApprovedCode(OLEConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.APPROVED);
1162     }
1163 
1164     /**
1165      * Provides answers to the following splits: PurchaseWasReceived VendorIsEmployeeOrNonResidentAlien
1166      *
1167      * @see org.kuali.ole.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(java.lang.String)
1168      */
1169     @Override
1170     public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
1171         if (nodeName.equals(PurapWorkflowConstants.REQUIRES_IMAGE_ATTACHMENT)) {
1172             return requiresAccountsPayableReviewRouting();
1173         }
1174         if (nodeName.equals(PurapWorkflowConstants.PURCHASE_WAS_RECEIVED)) {
1175             return shouldWaitForReceiving();
1176         }
1177         if (nodeName.equals(PurapWorkflowConstants.VENDOR_IS_EMPLOYEE_OR_NON_RESIDENT_ALIEN)) {
1178             return isVendorEmployeeOrNonResidentAlien();
1179         }
1180         throw new UnsupportedOperationException("Cannot answer split question for this node you call \"" + nodeName + "\"");
1181     }
1182 
1183     protected boolean isVendorEmployeeOrNonResidentAlien() {
1184         String vendorHeaderGeneratedId = this.getVendorHeaderGeneratedIdentifier().toString();
1185         if (StringUtils.isBlank(vendorHeaderGeneratedId)) {
1186             // no vendor header id so can't check for proper tax routing
1187             return false;
1188         }
1189         VendorService vendorService = SpringContext.getBean(VendorService.class);
1190         boolean routeDocumentAsEmployeeVendor = vendorService.isVendorInstitutionEmployee(Integer.valueOf(vendorHeaderGeneratedId));
1191         boolean routeDocumentAsForeignVendor = vendorService.isVendorForeign(Integer.valueOf(vendorHeaderGeneratedId));
1192         if ((!routeDocumentAsEmployeeVendor) && (!routeDocumentAsForeignVendor)) {
1193             // no need to route
1194             return false;
1195         }
1196 
1197         return true;
1198     }
1199 
1200     /**
1201      * Payment Request needs to wait for receiving if the receiving requirements have NOT been met.
1202      *
1203      * @return
1204      */
1205     protected boolean shouldWaitForReceiving() {
1206         // only require if PO was marked to require receiving
1207         if (isReceivingDocumentRequiredIndicator()) {
1208             return !isReceivingRequirementMet();
1209         }
1210 
1211         //receiving is not required or has already been fulfilled, no need to stop for routing
1212         return false;
1213     }
1214 
1215     /**
1216      * Determine if the receiving requirement has been met for all items on the payment request. If any item does not have receiving
1217      * requirements met, return false. Receiving requirement has NOT been met if the quantity invoiced on the Payment Request is
1218      * greater than the quantity of "unpaid and received" items determined by (poQtyReceived - (poQtyInvoiced - preqQtyInvoiced)).
1219      * We have to subtract preqQtyInvoiced from the poQtyInvoiced because this payment request has already updated the totals on the
1220      * po.
1221      *
1222      * @return boolean return true if the receiving requirement has been met for all items on the payment request; false if
1223      *         requirement has not been met
1224      */
1225     public boolean isReceivingRequirementMet() {
1226 
1227         for (Iterator iter = getItems().iterator(); iter.hasNext(); ) {
1228             PaymentRequestItem preqItem = (PaymentRequestItem) iter.next();
1229 
1230             if (preqItem.getItemType().isQuantityBasedGeneralLedgerIndicator()) {
1231                 PurchaseOrderItem poItem = preqItem.getPurchaseOrderItem();
1232                 KualiDecimal preqQuantityInvoiced = preqItem.getItemQuantity() == null ? KualiDecimal.ZERO : preqItem.getItemQuantity();
1233                 KualiDecimal poQuantityReceived = poItem.getItemReceivedTotalQuantity() == null ? KualiDecimal.ZERO : poItem.getItemReceivedTotalQuantity();
1234                 KualiDecimal poQuantityInvoiced = poItem.getItemInvoicedTotalQuantity() == null ? KualiDecimal.ZERO : poItem.getItemInvoicedTotalQuantity();
1235 
1236                 // receiving has NOT been met if preqQtyInvoiced is greater than (poQtyReceived & (poQtyInvoiced & preqQtyInvoiced))
1237                 if (preqQuantityInvoiced.compareTo(poQuantityReceived.subtract(poQuantityInvoiced.subtract(preqQuantityInvoiced))) > 0) {
1238                     return false;
1239                 }
1240             }
1241         }
1242 
1243         return true;
1244     }
1245 
1246     @Override
1247     public Date getTransactionTaxDate() {
1248         return getInvoiceDate();
1249     }
1250 
1251     public String getTaxClassificationCode() {
1252         return taxClassificationCode;
1253     }
1254 
1255     public void setTaxClassificationCode(String taxClassificationCode) {
1256         this.taxClassificationCode = taxClassificationCode;
1257     }
1258 
1259     public KualiDecimal getTaxFederalPercentShort() {
1260         return new KualiDecimal(taxFederalPercent);
1261     }
1262 
1263     public BigDecimal getTaxFederalPercent() {
1264         return taxFederalPercent;
1265     }
1266 
1267     public void setTaxFederalPercent(BigDecimal taxFederalPercent) {
1268         this.taxFederalPercent = taxFederalPercent;
1269     }
1270 
1271     public KualiDecimal getTaxStatePercentShort() {
1272         return new KualiDecimal(taxStatePercent);
1273     }
1274 
1275     public BigDecimal getTaxStatePercent() {
1276         return taxStatePercent;
1277     }
1278 
1279     public void setTaxStatePercent(BigDecimal taxStatePercent) {
1280         this.taxStatePercent = taxStatePercent;
1281     }
1282 
1283     public String getTaxCountryCode() {
1284         return taxCountryCode;
1285     }
1286 
1287     public void setTaxCountryCode(String taxCountryCode) {
1288         this.taxCountryCode = taxCountryCode;
1289     }
1290 
1291     public Boolean getTaxGrossUpIndicator() {
1292         return taxGrossUpIndicator;
1293     }
1294 
1295     public void setTaxGrossUpIndicator(Boolean taxGrossUpIndicator) {
1296         this.taxGrossUpIndicator = taxGrossUpIndicator;
1297     }
1298 
1299     public Boolean getTaxExemptTreatyIndicator() {
1300         return taxExemptTreatyIndicator;
1301     }
1302 
1303     public void setTaxExemptTreatyIndicator(Boolean taxExemptTreatyIndicator) {
1304         this.taxExemptTreatyIndicator = taxExemptTreatyIndicator;
1305     }
1306 
1307     public Boolean getTaxForeignSourceIndicator() {
1308         return taxForeignSourceIndicator;
1309     }
1310 
1311     public void setTaxForeignSourceIndicator(Boolean taxForeignSourceIndicator) {
1312         this.taxForeignSourceIndicator = taxForeignSourceIndicator;
1313     }
1314 
1315     public KualiDecimal getTaxSpecialW4Amount() {
1316         return taxSpecialW4Amount;
1317     }
1318 
1319     public void setTaxSpecialW4Amount(KualiDecimal taxSpecialW4Amount) {
1320         this.taxSpecialW4Amount = taxSpecialW4Amount;
1321     }
1322 
1323     public Boolean getTaxUSAIDPerDiemIndicator() {
1324         return taxUSAIDPerDiemIndicator;
1325     }
1326 
1327     public void setTaxUSAIDPerDiemIndicator(Boolean taxUSAIDPerDiemIndicator) {
1328         this.taxUSAIDPerDiemIndicator = taxUSAIDPerDiemIndicator;
1329     }
1330 
1331     public Boolean getTaxOtherExemptIndicator() {
1332         return taxOtherExemptIndicator;
1333     }
1334 
1335     public void setTaxOtherExemptIndicator(Boolean taxOtherExemptIndicator) {
1336         this.taxOtherExemptIndicator = taxOtherExemptIndicator;
1337     }
1338 
1339     public String getTaxNQIId() {
1340         return taxNQIId;
1341     }
1342 
1343     public void setTaxNQIId(String taxNQIId) {
1344         this.taxNQIId = taxNQIId;
1345     }
1346 
1347     public boolean isPaymentRequestedCancelIndicatorForSearching() {
1348         return paymentRequestedCancelIndicator;
1349     }
1350 
1351     /**
1352      * @return the payment request positive approval indicator
1353      */
1354     public boolean getPaymentRequestPositiveApprovalIndicatorForSearching() {
1355         return paymentRequestPositiveApprovalIndicator;
1356     }
1357 
1358     /**
1359      * @return the receiving document required indicator
1360      */
1361     public boolean getReceivingDocumentRequiredIndicatorForSearching() {
1362         return receivingDocumentRequiredIndicator;
1363     }
1364 
1365 
1366     public String getRequestCancelIndicatorForResult() {
1367         return isPaymentRequestedCancelIndicator() ? "Yes" : "No";
1368     }
1369 
1370     public String getPaidIndicatorForResult() {
1371         return getPaymentPaidTimestamp() != null ? "Yes" : "No";
1372     }
1373 
1374     public Date getAccountsPayableApprovalDateForSearching() {
1375         if (this.getAccountsPayableApprovalTimestamp() == null) {
1376             return null;
1377         }
1378         try {
1379             Date date = SpringContext.getBean(DateTimeService.class).convertToSqlDate(this.getAccountsPayableApprovalTimestamp());
1380             if (LOG.isDebugEnabled()) {
1381                 LOG.debug("getAccountsPayableApprovalDateForSearching() returns " + date);
1382             }
1383             return date;
1384         } catch (Exception e) {
1385             return new Date(this.getAccountsPayableApprovalTimestamp().getTime());
1386         }
1387     }
1388 
1389     /**
1390      * Checks all documents notes for attachments.
1391      *
1392      * @return - true if document does not have an image attached, false otherwise
1393      */
1394     @Override
1395     public boolean documentHasNoImagesAttached() {
1396         List boNotes = this.getNotes();
1397         if (ObjectUtils.isNotNull(boNotes)) {
1398             for (Object obj : boNotes) {
1399                 Note note = (Note) obj;
1400 
1401                 note.refreshReferenceObject("attachment");
1402                 if (ObjectUtils.isNotNull(note.getAttachment()) && PurapConstants.AttachmentTypeCodes.ATTACHMENT_TYPE_INVOICE_IMAGE.equals(note.getAttachment().getAttachmentTypeCode())) {
1403                     return false;
1404                 }
1405             }
1406         }
1407         return true;
1408     }
1409 
1410     protected void closePurchaseOrder() {
1411         //Added for jira OLE-3529 Starts
1412         Integer poIdentifier = purchaseOrderDocument.getPurapDocumentIdentifier();
1413         String docNumber = purchaseOrderDocument.getDocumentNumber();
1414         Map purchaseOrderMap = new HashMap();
1415         purchaseOrderMap.put("documentNumber", docNumber);
1416         purchaseOrderMap.put("itemTypeCode", OLEConstants.ITEM);
1417         KualiDecimal itemQuantity = new KualiDecimal(0);
1418         KualiDecimal itemOrderQuantity = new KualiDecimal(0);
1419         List<OlePurchaseOrderItem> olePurchaseOrderItemList = (List<OlePurchaseOrderItem>) getBusinessObjectService().findMatching(OlePurchaseOrderItem.class, purchaseOrderMap);
1420         for (OlePurchaseOrderItem olePurchaseOrderItem : olePurchaseOrderItemList) {
1421             itemQuantity = itemQuantity.add(olePurchaseOrderItem.getItemQuantity());
1422         }
1423         Map lineItemReceivingMap = new HashMap();
1424         lineItemReceivingMap.put("purchaseOrderIdentifier", poIdentifier);
1425         List<OleLineItemReceivingDocument> oleLineItemReceivingDocumentList = (List<OleLineItemReceivingDocument>) getBusinessObjectService().findMatching(OleLineItemReceivingDocument.class, lineItemReceivingMap);
1426         for (OleLineItemReceivingDocument oleLineItemReceivingDocument : oleLineItemReceivingDocumentList) {
1427             String docId = oleLineItemReceivingDocument.getDocumentNumber();
1428             Map docIdMap = new HashMap();
1429             docIdMap.put("documentNumber", docId);
1430             List<OleLineItemReceivingItem> oleLineItemReceivingItemList = (List<OleLineItemReceivingItem>) getBusinessObjectService().findMatching(OleLineItemReceivingItem.class, docIdMap);
1431             for (OleLineItemReceivingItem oleLineItemReceivingItem : oleLineItemReceivingItemList) {
1432                 itemOrderQuantity = itemOrderQuantity.add(oleLineItemReceivingItem.getItemOrderedQuantity());
1433             }
1434             if (itemQuantity.equals(itemOrderQuantity)) {
1435                 try {
1436                     this.setDocumentHeader(purchaseOrderDocument.getDocumentHeader());
1437                     updateAndSaveAppDocStatus(PurapConstants.PurchaseOrderStatuses.APPDOC_CLOSED);
1438                 } catch (WorkflowException e) {
1439                     logAndThrowRuntimeException("Error while Closing the PO from Payment Request "
1440                             + getDocumentNumber(), e);
1441                 }
1442             }
1443         }
1444         //End
1445     }
1446 }