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                     }
760                 } else {
761                     logAndThrowRuntimeException("No status found to set for document being disapproved in node '" + nodeName + "'");
762                 }
763             }
764             // DOCUMENT CANCELED
765             else if (this.getFinancialSystemDocumentHeader().getWorkflowDocument().isCanceled()) {
766                 String currentNodeName = SpringContext.getBean(WorkflowDocumentService.class).getCurrentRouteLevelName(this.getDocumentHeader().getWorkflowDocument());
767                 String cancelledStatus = PurapConstants.PaymentRequestStatuses.getPaymentRequestAppDocDisapproveStatuses().get(currentNodeName);
768 
769                 //**START AZ** KATTS-37 KevinMcO
770                 if (StringUtils.isBlank(cancelledStatus) &&
771                         StringUtils.isBlank(PurapConstants.PaymentRequestStatuses.getPaymentRequestAppDocDisapproveStatuses().get(currentNodeName)) &&
772                         (PaymentRequestStatuses.APPDOC_INITIATE.equals(getStatusCode()) || PaymentRequestStatuses.APPDOC_IN_PROCESS.equals(getStatusCode()))) {
773                     cancelledStatus = PaymentRequestStatuses.APPDOC_CANCELLED_IN_PROCESS;
774                 }
775                 //**END AZ**
776 
777                 if (ObjectUtils.isNotNull(cancelledStatus)) {
778                     SpringContext.getBean(AccountsPayableService.class).cancelAccountsPayableDocument(this, currentNodeName);
779                     updateAndSaveAppDocStatus(cancelledStatus);
780                 } else {
781                     logAndThrowRuntimeException("No status found to set for document being canceled in node '" + currentNodeName + "'");
782                 }
783             }
784         } catch (WorkflowException e) {
785             logAndThrowRuntimeException("Error saving routing data while saving document with id " + getDocumentNumber(), e);
786         }
787     }
788 
789     /**
790      * Generates correcting entries to the GL if accounts are modified.
791      *
792      * @see org.kuali.rice.krad.document.Document#doActionTaken(org.kuali.rice.kew.clientapp.vo.ActionTakenEventDTO)
793      */
794     @Override
795     public void doActionTaken(ActionTakenEvent event) {
796         super.doActionTaken(event);
797         WorkflowDocument workflowDocument = getDocumentHeader().getWorkflowDocument();
798         String currentNode = null;
799         Object[] names = workflowDocument.getCurrentNodeNames().toArray();
800         if (names.length > 0) {
801             currentNode = (String) names[0];
802         }
803 
804         // everything in the below list requires correcting entries to be written to the GL
805         if (PaymentRequestStatuses.getNodesRequiringCorrectingGeneralLedgerEntries().contains(currentNode)) {
806             SpringContext.getBean(PurapGeneralLedgerService.class).generateEntriesModifyPaymentRequest(this);
807         }
808     }
809 
810     /**
811      * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#processNodeChange(java.lang.String, java.lang.String)
812      */
813     @Override
814     public boolean processNodeChange(String newNodeName, String oldNodeName) {
815         if (PaymentRequestStatuses.APPDOC_AUTO_APPROVED.equals(getApplicationDocumentStatus())) {
816             // do nothing for an auto approval
817             return false;
818         }
819         if (PaymentRequestStatuses.NODE_ADHOC_REVIEW.equals(oldNodeName)) {
820             SpringContext.getBean(AccountsPayableService.class).performLogicForFullEntryCompleted(this);
821         }
822         return true;
823     }
824 
825     /**
826      * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#saveDocumentFromPostProcessing()
827      */
828     @Override
829     public void saveDocumentFromPostProcessing() {
830         SpringContext.getBean(PurapService.class).saveDocumentNoValidation(this);
831 
832         // if we've hit full entry completed then close/reopen po
833         if (SpringContext.getBean(PurapService.class).isFullDocumentEntryCompleted(this) && this.isClosePurchaseOrderIndicator()) {
834             SpringContext.getBean(PurapService.class).performLogicForCloseReopenPO(this);
835         }
836     }
837 
838     /**
839      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#getItemClass()
840      */
841     @Override
842     public Class getItemClass() {
843         return PaymentRequestItem.class;
844     }
845 
846     @Override
847     public Class getItemUseTaxClass() {
848         return PaymentRequestItemUseTax.class;
849     }
850 
851     /**
852      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#getPurApSourceDocumentIfPossible()
853      */
854     @Override
855     public PurchaseOrderDocument getPurApSourceDocumentIfPossible() {
856         return getPurchaseOrderDocument();
857     }
858 
859     /**
860      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#getPurApSourceDocumentLabelIfPossible()
861      */
862     @Override
863     public String getPurApSourceDocumentLabelIfPossible() {
864         return SpringContext.getBean(DataDictionaryService.class).getDocumentLabelByTypeName(OLEConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER);
865     }
866 
867     public String getPurchaseOrderNotes() {
868 
869         ArrayList poNotes = (ArrayList) this.getPurchaseOrderDocument().getNotes();
870 
871         if (poNotes.size() > 0) {
872             return "Yes";
873         }
874         return "No";
875     }
876 
877     public void setPurchaseOrderNotes(String purchaseOrderNotes) {
878         this.purchaseOrderNotes = purchaseOrderNotes;
879     }
880 
881     public String getRecurringPaymentTypeCode() {
882         return recurringPaymentTypeCode;
883     }
884 
885     public void setRecurringPaymentTypeCode(String recurringPaymentTypeCode) {
886         this.recurringPaymentTypeCode = recurringPaymentTypeCode;
887     }
888 
889     /**
890      * Returns the total encumbered amount from the purchase order excluding below the line.
891      *
892      * @return Total cost excluding below the line
893      */
894     public KualiDecimal getItemTotalPoEncumbranceAmount() {
895         // get total from po excluding below the line and inactive
896         return this.getPurchaseOrderDocument().getTotalDollarAmount(false, false);
897     }
898 
899     public KualiDecimal getItemTotalPoEncumbranceAmountRelieved() {
900         return getItemTotalPoEncumbranceAmountRelieved(false);
901     }
902 
903     public KualiDecimal getItemTotalPoEncumbranceAmountRelieved(boolean includeBelowTheLine) {
904 
905         KualiDecimal total = KualiDecimal.ZERO;
906 
907         for (PurchaseOrderItem item : (List<PurchaseOrderItem>) getPurchaseOrderDocument().getItems()) {
908             ItemType it = item.getItemType();
909             if (includeBelowTheLine || it.isLineItemIndicator()) {
910                 total = total.add(item.getItemEncumbranceRelievedAmount());
911             }
912         }
913         return total;
914     }
915 
916     public KualiDecimal getLineItemTotal() {
917         return this.getTotalDollarAmountAboveLineItems();
918     }
919 
920     public KualiDecimal getLineItemPreTaxTotal() {
921         return this.getTotalPreTaxDollarAmountAboveLineItems();
922     }
923 
924     public KualiDecimal getLineItemTaxAmount() {
925         return this.getTotalTaxAmountAboveLineItems();
926     }
927 
928     @Override
929     public KualiDecimal getGrandTotal() {
930         return this.getTotalDollarAmount();
931     }
932 
933     public KualiDecimal getGrandTotalExcludingDiscount() {
934         String[] discountCode = new String[]{PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE};
935         return this.getTotalDollarAmountWithExclusions(discountCode, true);
936     }
937 
938     /**
939      * This method is here due to a setter requirement by the htmlControlAttribute
940      *
941      * @param amount - Grand total for document, excluding discount
942      */
943     public void setGrandTotalExcludingDiscount(KualiDecimal amount) {
944         // do nothing
945     }
946 
947     public KualiDecimal getGrandPreTaxTotal() {
948         return this.getTotalPreTaxDollarAmount();
949     }
950 
951     public KualiDecimal getGrandPreTaxTotalExcludingDiscount() {
952         String[] discountCode = new String[]{PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE};
953         return this.getTotalPreTaxDollarAmountWithExclusions(discountCode, true);
954     }
955 
956     public KualiDecimal getGrandTaxAmount() {
957         return this.getTotalTaxAmount();
958     }
959 
960     public KualiDecimal getGrandTaxAmountExcludingDiscount() {
961         String[] discountCode = new String[]{PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE};
962         return this.getTotalTaxAmountWithExclusions(discountCode, true);
963     }
964 
965     public boolean isDiscount() {
966         return SpringContext.getBean(PaymentRequestService.class).hasDiscountItem(this);
967     }
968 
969     /**
970      * The total that was paid on the po excluding below the line
971      *
972      * @return total paid
973      */
974     public KualiDecimal getItemTotalPoPaidAmount() {
975         KualiDecimal total = KualiDecimal.ZERO;
976         for (PurchaseOrderItem item : (List<PurchaseOrderItem>) getPurchaseOrderDocument().getItems()) {
977             ItemType iT = item.getItemType();
978             if (iT.isLineItemIndicator()) {
979                 KualiDecimal itemPaid = item.getItemPaidAmount();
980                 total = total.add(itemPaid);
981             }
982         }
983         return total;
984     }
985 
986     /**
987      * Returns the name of who requested cancel.
988      *
989      * @return - name of who requested cancel.
990      */
991     public String getAccountsPayableRequestCancelPersonName() {
992         String personName = null;
993         Person user = SpringContext.getBean(org.kuali.rice.kim.api.identity.PersonService.class).getPerson(getAccountsPayableRequestCancelIdentifier());
994         if (user != null) {
995             personName = user.getName();
996         } else {
997             personName = "";
998         }
999 
1000         return personName;
1001     }
1002 
1003     /**
1004      * Exists due to a setter requirement by the htmlControlAttribute
1005      *
1006      * @param amount - total po amount paid
1007      */
1008     public void setItemTotalPoPaidAmount(KualiDecimal amount) {
1009         // do nothing
1010     }
1011 
1012     /**
1013      * Exists due to a setter requirement by the htmlControlAttribute
1014      *
1015      * @param amount - total po encumbrance
1016      */
1017     public void setItemTotalPoEncumbranceAmount(KualiDecimal amount) {
1018         // do nothing
1019     }
1020 
1021     /**
1022      * Exists due to a setter requirement by the htmlControlAttribute
1023      *
1024      * @param amount - total po encumbrance amount relieved
1025      */
1026     public void setItemTotalPoEncumbranceAmountRelieved(KualiDecimal amount) {
1027         // do nothing
1028     }
1029 
1030     /**
1031      * Determinines the route levels for a given document.
1032      *
1033      * @param workflowDocument - work flow document
1034      * @return List - list of route levels
1035      */
1036     protected List<String> getCurrentRouteLevels(WorkflowDocument workflowDocument) {
1037         Set<String> names = workflowDocument.getCurrentNodeNames();
1038         return new ArrayList<String>(names);
1039     }
1040 
1041     public RecurringPaymentType getRecurringPaymentType() {
1042         if (ObjectUtils.isNull(recurringPaymentType)) {
1043             refreshReferenceObject(PurapPropertyConstants.RECURRING_PAYMENT_TYPE);
1044         }
1045         return recurringPaymentType;
1046     }
1047 
1048     public void setRecurringPaymentType(RecurringPaymentType recurringPaymentType) {
1049         this.recurringPaymentType = recurringPaymentType;
1050     }
1051 
1052     public PurchaseOrderCostSource getPaymentRequestCostSource() {
1053         return paymentRequestCostSource;
1054     }
1055 
1056     public void setPaymentRequestCostSource(PurchaseOrderCostSource paymentRequestCostSource) {
1057         this.paymentRequestCostSource = paymentRequestCostSource;
1058     }
1059 
1060     /**
1061      * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#getPoDocumentTypeForAccountsPayableDocumentApprove()
1062      */
1063     @Override
1064     public String getPoDocumentTypeForAccountsPayableDocumentCancel() {
1065         return PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_REOPEN_DOCUMENT;
1066     }
1067 
1068     /**
1069      * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#getInitialAmount()
1070      */
1071     @Override
1072     public KualiDecimal getInitialAmount() {
1073         return this.getVendorInvoiceAmount();
1074     }
1075 
1076     /**
1077      * Populates the payment request document, then continues with preparing for save.
1078      *
1079      * @see org.kuali.rice.krad.document.Document#prepareForSave(org.kuali.rice.krad.rule.event.KualiDocumentEvent)
1080      */
1081     @Override
1082     public void prepareForSave(KualiDocumentEvent event) {
1083         WorkflowDocument workflowDocument = this.getDocumentHeader().getWorkflowDocument();
1084         String workflowDocumentTitle = this.buildDocumentTitle(workflowDocument.getTitle());
1085 
1086         this.getFinancialSystemDocumentHeader().getWorkflowDocument().setTitle(workflowDocumentTitle);
1087 
1088         // first populate, then call super
1089         if (event instanceof AttributedContinuePurapEvent) {
1090             SpringContext.getBean(PaymentRequestService.class).populatePaymentRequest(this);
1091         }
1092         super.prepareForSave(event);
1093 
1094     }
1095 
1096     /**
1097      * @see org.kuali.ole.module.purap.document.AccountsPayableDocumentBase#isAttachmentRequired()
1098      */
1099     @Override
1100     protected boolean isAttachmentRequired() {
1101         if (getPaymentRequestElectronicInvoiceIndicator()) {
1102             return false;
1103         }
1104         return StringUtils.equalsIgnoreCase("Y", SpringContext.getBean(ParameterService.class).getParameterValueAsString(PaymentRequestDocument.class, PurapParameterConstants.PURAP_PREQ_REQUIRE_ATTACHMENT));
1105     }
1106 
1107     /**
1108      * @see org.kuali.ole.module.purap.document.AccountsPayableDocument#getDocumentSpecificService()
1109      */
1110     @Override
1111     public AccountsPayableDocumentSpecificService getDocumentSpecificService() {
1112         return SpringContext.getBean(PaymentRequestService.class);
1113     }
1114 
1115     /**
1116      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocumentBase#getItem(int)
1117      */
1118     @Override
1119     public PurApItem getItem(int pos) {
1120         PaymentRequestItem item = (PaymentRequestItem) super.getItem(pos);
1121         if (item.getPaymentRequest() == null) {
1122             item.setPaymentRequest(this);
1123         }
1124         return item;
1125     }
1126 
1127     public String getPrimaryVendorName() {
1128 
1129         if (primaryVendorName == null) {
1130             VendorDetail vd = SpringContext.getBean(VendorService.class).getVendorDetail(this.getOriginalVendorHeaderGeneratedIdentifier(), this.getOriginalVendorDetailAssignedIdentifier());
1131 
1132             if (vd != null) {
1133                 primaryVendorName = vd.getVendorName();
1134             }
1135         }
1136 
1137         return primaryVendorName;
1138     }
1139 
1140     /**
1141      * @deprecated
1142      */
1143     @Deprecated
1144     public void setPrimaryVendorName(String primaryVendorName) {
1145     }
1146 
1147     /**
1148      * Forces general ledger entries to be approved, does not wait for payment request document final approval.
1149      *
1150      * @see org.kuali.module.purap.rules.PurapAccountingDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.ole.sys.document.AccountingDocument,
1151      *      org.kuali.ole.sys.businessobject.AccountingLine, org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry)
1152      */
1153     @Override
1154     public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry) {
1155         super.customizeExplicitGeneralLedgerPendingEntry(postable, explicitEntry);
1156 
1157         SpringContext.getBean(PurapGeneralLedgerService.class).customizeGeneralLedgerPendingEntry(this, (AccountingLine) postable, explicitEntry, getPurchaseOrderIdentifier(), getDebitCreditCodeForGLEntries(), PurapDocTypeCodes.PAYMENT_REQUEST_DOCUMENT, isGenerateEncumbranceEntries());
1158 
1159         // PREQs do not wait for document final approval to post GL entries; here we are forcing them to be APPROVED
1160         explicitEntry.setFinancialDocumentApprovedCode(OLEConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.APPROVED);
1161     }
1162 
1163     /**
1164      * Provides answers to the following splits: PurchaseWasReceived VendorIsEmployeeOrNonResidentAlien
1165      *
1166      * @see org.kuali.ole.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(java.lang.String)
1167      */
1168     @Override
1169     public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
1170         if (nodeName.equals(PurapWorkflowConstants.REQUIRES_IMAGE_ATTACHMENT)) {
1171             return requiresAccountsPayableReviewRouting();
1172         }
1173         if (nodeName.equals(PurapWorkflowConstants.PURCHASE_WAS_RECEIVED)) {
1174             return shouldWaitForReceiving();
1175         }
1176         if (nodeName.equals(PurapWorkflowConstants.VENDOR_IS_EMPLOYEE_OR_NON_RESIDENT_ALIEN)) {
1177             return isVendorEmployeeOrNonResidentAlien();
1178         }
1179         throw new UnsupportedOperationException("Cannot answer split question for this node you call \"" + nodeName + "\"");
1180     }
1181 
1182     protected boolean isVendorEmployeeOrNonResidentAlien() {
1183         String vendorHeaderGeneratedId = this.getVendorHeaderGeneratedIdentifier().toString();
1184         if (StringUtils.isBlank(vendorHeaderGeneratedId)) {
1185             // no vendor header id so can't check for proper tax routing
1186             return false;
1187         }
1188         VendorService vendorService = SpringContext.getBean(VendorService.class);
1189         boolean routeDocumentAsEmployeeVendor = vendorService.isVendorInstitutionEmployee(Integer.valueOf(vendorHeaderGeneratedId));
1190         boolean routeDocumentAsForeignVendor = vendorService.isVendorForeign(Integer.valueOf(vendorHeaderGeneratedId));
1191         if ((!routeDocumentAsEmployeeVendor) && (!routeDocumentAsForeignVendor)) {
1192             // no need to route
1193             return false;
1194         }
1195 
1196         return true;
1197     }
1198 
1199     /**
1200      * Payment Request needs to wait for receiving if the receiving requirements have NOT been met.
1201      *
1202      * @return
1203      */
1204     protected boolean shouldWaitForReceiving() {
1205         // only require if PO was marked to require receiving
1206         if (isReceivingDocumentRequiredIndicator()) {
1207             return !isReceivingRequirementMet();
1208         }
1209 
1210         //receiving is not required or has already been fulfilled, no need to stop for routing
1211         return false;
1212     }
1213 
1214     /**
1215      * Determine if the receiving requirement has been met for all items on the payment request. If any item does not have receiving
1216      * requirements met, return false. Receiving requirement has NOT been met if the quantity invoiced on the Payment Request is
1217      * greater than the quantity of "unpaid and received" items determined by (poQtyReceived - (poQtyInvoiced - preqQtyInvoiced)).
1218      * We have to subtract preqQtyInvoiced from the poQtyInvoiced because this payment request has already updated the totals on the
1219      * po.
1220      *
1221      * @return boolean return true if the receiving requirement has been met for all items on the payment request; false if
1222      *         requirement has not been met
1223      */
1224     public boolean isReceivingRequirementMet() {
1225 
1226         for (Iterator iter = getItems().iterator(); iter.hasNext(); ) {
1227             PaymentRequestItem preqItem = (PaymentRequestItem) iter.next();
1228 
1229             if (preqItem.getItemType().isQuantityBasedGeneralLedgerIndicator()) {
1230                 PurchaseOrderItem poItem = preqItem.getPurchaseOrderItem();
1231                 KualiDecimal preqQuantityInvoiced = preqItem.getItemQuantity() == null ? KualiDecimal.ZERO : preqItem.getItemQuantity();
1232                 KualiDecimal poQuantityReceived = poItem.getItemReceivedTotalQuantity() == null ? KualiDecimal.ZERO : poItem.getItemReceivedTotalQuantity();
1233                 KualiDecimal poQuantityInvoiced = poItem.getItemInvoicedTotalQuantity() == null ? KualiDecimal.ZERO : poItem.getItemInvoicedTotalQuantity();
1234 
1235                 // receiving has NOT been met if preqQtyInvoiced is greater than (poQtyReceived & (poQtyInvoiced & preqQtyInvoiced))
1236                 if (preqQuantityInvoiced.compareTo(poQuantityReceived.subtract(poQuantityInvoiced.subtract(preqQuantityInvoiced))) > 0) {
1237                     return false;
1238                 }
1239             }
1240         }
1241 
1242         return true;
1243     }
1244 
1245     @Override
1246     public Date getTransactionTaxDate() {
1247         return getInvoiceDate();
1248     }
1249 
1250     public String getTaxClassificationCode() {
1251         return taxClassificationCode;
1252     }
1253 
1254     public void setTaxClassificationCode(String taxClassificationCode) {
1255         this.taxClassificationCode = taxClassificationCode;
1256     }
1257 
1258     public KualiDecimal getTaxFederalPercentShort() {
1259         return new KualiDecimal(taxFederalPercent);
1260     }
1261 
1262     public BigDecimal getTaxFederalPercent() {
1263         return taxFederalPercent;
1264     }
1265 
1266     public void setTaxFederalPercent(BigDecimal taxFederalPercent) {
1267         this.taxFederalPercent = taxFederalPercent;
1268     }
1269 
1270     public KualiDecimal getTaxStatePercentShort() {
1271         return new KualiDecimal(taxStatePercent);
1272     }
1273 
1274     public BigDecimal getTaxStatePercent() {
1275         return taxStatePercent;
1276     }
1277 
1278     public void setTaxStatePercent(BigDecimal taxStatePercent) {
1279         this.taxStatePercent = taxStatePercent;
1280     }
1281 
1282     public String getTaxCountryCode() {
1283         return taxCountryCode;
1284     }
1285 
1286     public void setTaxCountryCode(String taxCountryCode) {
1287         this.taxCountryCode = taxCountryCode;
1288     }
1289 
1290     public Boolean getTaxGrossUpIndicator() {
1291         return taxGrossUpIndicator;
1292     }
1293 
1294     public void setTaxGrossUpIndicator(Boolean taxGrossUpIndicator) {
1295         this.taxGrossUpIndicator = taxGrossUpIndicator;
1296     }
1297 
1298     public Boolean getTaxExemptTreatyIndicator() {
1299         return taxExemptTreatyIndicator;
1300     }
1301 
1302     public void setTaxExemptTreatyIndicator(Boolean taxExemptTreatyIndicator) {
1303         this.taxExemptTreatyIndicator = taxExemptTreatyIndicator;
1304     }
1305 
1306     public Boolean getTaxForeignSourceIndicator() {
1307         return taxForeignSourceIndicator;
1308     }
1309 
1310     public void setTaxForeignSourceIndicator(Boolean taxForeignSourceIndicator) {
1311         this.taxForeignSourceIndicator = taxForeignSourceIndicator;
1312     }
1313 
1314     public KualiDecimal getTaxSpecialW4Amount() {
1315         return taxSpecialW4Amount;
1316     }
1317 
1318     public void setTaxSpecialW4Amount(KualiDecimal taxSpecialW4Amount) {
1319         this.taxSpecialW4Amount = taxSpecialW4Amount;
1320     }
1321 
1322     public Boolean getTaxUSAIDPerDiemIndicator() {
1323         return taxUSAIDPerDiemIndicator;
1324     }
1325 
1326     public void setTaxUSAIDPerDiemIndicator(Boolean taxUSAIDPerDiemIndicator) {
1327         this.taxUSAIDPerDiemIndicator = taxUSAIDPerDiemIndicator;
1328     }
1329 
1330     public Boolean getTaxOtherExemptIndicator() {
1331         return taxOtherExemptIndicator;
1332     }
1333 
1334     public void setTaxOtherExemptIndicator(Boolean taxOtherExemptIndicator) {
1335         this.taxOtherExemptIndicator = taxOtherExemptIndicator;
1336     }
1337 
1338     public String getTaxNQIId() {
1339         return taxNQIId;
1340     }
1341 
1342     public void setTaxNQIId(String taxNQIId) {
1343         this.taxNQIId = taxNQIId;
1344     }
1345 
1346     public boolean isPaymentRequestedCancelIndicatorForSearching() {
1347         return paymentRequestedCancelIndicator;
1348     }
1349 
1350     /**
1351      * @return the payment request positive approval indicator
1352      */
1353     public boolean getPaymentRequestPositiveApprovalIndicatorForSearching() {
1354         return paymentRequestPositiveApprovalIndicator;
1355     }
1356 
1357     /**
1358      * @return the receiving document required indicator
1359      */
1360     public boolean getReceivingDocumentRequiredIndicatorForSearching() {
1361         return receivingDocumentRequiredIndicator;
1362     }
1363 
1364 
1365     public String getRequestCancelIndicatorForResult() {
1366         return isPaymentRequestedCancelIndicator() ? "Yes" : "No";
1367     }
1368 
1369     public String getPaidIndicatorForResult() {
1370         return getPaymentPaidTimestamp() != null ? "Yes" : "No";
1371     }
1372 
1373     public Date getAccountsPayableApprovalDateForSearching() {
1374         if (this.getAccountsPayableApprovalTimestamp() == null) {
1375             return null;
1376         }
1377         try {
1378             Date date = SpringContext.getBean(DateTimeService.class).convertToSqlDate(this.getAccountsPayableApprovalTimestamp());
1379             if (LOG.isDebugEnabled()) {
1380                 LOG.debug("getAccountsPayableApprovalDateForSearching() returns " + date);
1381             }
1382             return date;
1383         } catch (Exception e) {
1384             return new Date(this.getAccountsPayableApprovalTimestamp().getTime());
1385         }
1386     }
1387 
1388     /**
1389      * Checks all documents notes for attachments.
1390      *
1391      * @return - true if document does not have an image attached, false otherwise
1392      */
1393     @Override
1394     public boolean documentHasNoImagesAttached() {
1395         List boNotes = this.getNotes();
1396         if (ObjectUtils.isNotNull(boNotes)) {
1397             for (Object obj : boNotes) {
1398                 Note note = (Note) obj;
1399 
1400                 note.refreshReferenceObject("attachment");
1401                 if (ObjectUtils.isNotNull(note.getAttachment()) && PurapConstants.AttachmentTypeCodes.ATTACHMENT_TYPE_INVOICE_IMAGE.equals(note.getAttachment().getAttachmentTypeCode())) {
1402                     return false;
1403                 }
1404             }
1405         }
1406         return true;
1407     }
1408 
1409     protected void closePurchaseOrder() {
1410         //Added for jira OLE-3529 Starts
1411         Integer poIdentifier = purchaseOrderDocument.getPurapDocumentIdentifier();
1412         String docNumber = purchaseOrderDocument.getDocumentNumber();
1413         Map purchaseOrderMap = new HashMap();
1414         purchaseOrderMap.put("documentNumber", docNumber);
1415         purchaseOrderMap.put("itemTypeCode", OLEConstants.ITEM);
1416         KualiDecimal itemQuantity = new KualiDecimal(0);
1417         KualiDecimal itemOrderQuantity = new KualiDecimal(0);
1418         List<OlePurchaseOrderItem> olePurchaseOrderItemList = (List<OlePurchaseOrderItem>) getBusinessObjectService().findMatching(OlePurchaseOrderItem.class, purchaseOrderMap);
1419         for (OlePurchaseOrderItem olePurchaseOrderItem : olePurchaseOrderItemList) {
1420             itemQuantity = itemQuantity.add(olePurchaseOrderItem.getItemQuantity());
1421         }
1422         Map lineItemReceivingMap = new HashMap();
1423         lineItemReceivingMap.put("purchaseOrderIdentifier", poIdentifier);
1424         List<OleLineItemReceivingDocument> oleLineItemReceivingDocumentList = (List<OleLineItemReceivingDocument>) getBusinessObjectService().findMatching(OleLineItemReceivingDocument.class, lineItemReceivingMap);
1425         for (OleLineItemReceivingDocument oleLineItemReceivingDocument : oleLineItemReceivingDocumentList) {
1426             String docId = oleLineItemReceivingDocument.getDocumentNumber();
1427             Map docIdMap = new HashMap();
1428             docIdMap.put("documentNumber", docId);
1429             List<OleLineItemReceivingItem> oleLineItemReceivingItemList = (List<OleLineItemReceivingItem>) getBusinessObjectService().findMatching(OleLineItemReceivingItem.class, docIdMap);
1430             for (OleLineItemReceivingItem oleLineItemReceivingItem : oleLineItemReceivingItemList) {
1431                 itemOrderQuantity = itemOrderQuantity.add(oleLineItemReceivingItem.getItemOrderedQuantity());
1432             }
1433             if (itemQuantity.equals(itemOrderQuantity)) {
1434                 try {
1435                     this.setDocumentHeader(purchaseOrderDocument.getDocumentHeader());
1436                     updateAndSaveAppDocStatus(PurapConstants.PurchaseOrderStatuses.APPDOC_CLOSED);
1437                 } catch (WorkflowException e) {
1438                     logAndThrowRuntimeException("Error while Closing the PO from Payment Request "
1439                             + getDocumentNumber(), e);
1440                 }
1441             }
1442         }
1443         //End
1444     }
1445 }