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