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