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