View Javadoc
1   /*
2    * Copyright 2005-2006 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.fp.document;
18  
19  import static org.kuali.ole.sys.OLEConstants.GL_CREDIT_CODE;
20  import static org.kuali.ole.sys.OLEConstants.GL_DEBIT_CODE;
21  
22  import java.sql.Date;
23  import java.sql.Timestamp;
24  import java.text.MessageFormat;
25  import java.util.ArrayList;
26  import java.util.Calendar;
27  import java.util.HashSet;
28  import java.util.List;
29  import java.util.Set;
30  
31  import org.apache.commons.lang.StringUtils;
32  import org.apache.log4j.Logger;
33  import org.kuali.ole.coa.businessobject.ObjectCode;
34  import org.kuali.ole.coa.service.ObjectTypeService;
35  import org.kuali.ole.fp.batch.service.DisbursementVoucherExtractService;
36  import org.kuali.ole.fp.businessobject.DisbursementVoucherDocumentationLocation;
37  import org.kuali.ole.fp.businessobject.DisbursementVoucherNonEmployeeTravel;
38  import org.kuali.ole.fp.businessobject.DisbursementVoucherNonResidentAlienTax;
39  import org.kuali.ole.fp.businessobject.DisbursementVoucherPayeeDetail;
40  import org.kuali.ole.fp.businessobject.DisbursementVoucherPreConferenceDetail;
41  import org.kuali.ole.fp.businessobject.DisbursementVoucherPreConferenceRegistrant;
42  import org.kuali.ole.fp.businessobject.DisbursementVoucherWireTransfer;
43  import org.kuali.ole.fp.businessobject.WireCharge;
44  import org.kuali.ole.fp.businessobject.options.DisbursementVoucherDocumentationLocationValuesFinder;
45  import org.kuali.ole.fp.businessobject.options.PaymentMethodValuesFinder;
46  import org.kuali.ole.fp.document.service.DisbursementVoucherPaymentReasonService;
47  import org.kuali.ole.fp.document.service.DisbursementVoucherTaxService;
48  import org.kuali.ole.select.businessobject.OlePaymentMethod;
49  import org.kuali.ole.sys.OLEConstants;
50  import org.kuali.ole.sys.OLEKeyConstants;
51  import org.kuali.ole.sys.OLEPropertyConstants;
52  import org.kuali.ole.sys.OLEConstants.AdHocPaymentIndicator;
53  import org.kuali.ole.sys.businessobject.AccountingLine;
54  import org.kuali.ole.sys.businessobject.Bank;
55  import org.kuali.ole.sys.businessobject.ChartOrgHolder;
56  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry;
57  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper;
58  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
59  import org.kuali.ole.sys.context.SpringContext;
60  import org.kuali.ole.sys.document.AccountingDocumentBase;
61  import org.kuali.ole.sys.document.AmountTotaling;
62  import org.kuali.ole.sys.document.service.AccountingDocumentRuleHelperService;
63  import org.kuali.ole.sys.document.service.DebitDeterminerService;
64  import org.kuali.ole.sys.document.validation.impl.AccountingDocumentRuleBaseConstants.GENERAL_LEDGER_PENDING_ENTRY_CODE;
65  import org.kuali.ole.sys.service.BankService;
66  import org.kuali.ole.sys.service.FlexibleOffsetAccountService;
67  import org.kuali.ole.sys.service.GeneralLedgerPendingEntryService;
68  import org.kuali.ole.sys.service.HomeOriginationService;
69  import org.kuali.ole.sys.service.OptionsService;
70  import org.kuali.ole.sys.service.UniversityDateService;
71  import org.kuali.ole.sys.service.impl.OleParameterConstants;
72  import org.kuali.ole.vnd.VendorConstants;
73  import org.kuali.ole.vnd.businessobject.VendorAddress;
74  import org.kuali.ole.vnd.businessobject.VendorDetail;
75  import org.kuali.ole.vnd.document.service.VendorService;
76  import org.kuali.ole.vnd.service.PhoneNumberService;
77  import org.kuali.rice.core.api.config.property.ConfigurationService;
78  import org.kuali.rice.core.api.datetime.DateTimeService;
79  import org.kuali.rice.core.api.util.type.KualiDecimal;
80  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
81  import org.kuali.rice.kew.api.KewApiConstants;
82  import org.kuali.rice.kew.api.action.ActionTaken;
83  import org.kuali.rice.kew.api.document.node.RouteNodeInstance;
84  import org.kuali.rice.kew.api.exception.WorkflowException;
85  import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
86  import org.kuali.rice.kim.api.KimConstants;
87  import org.kuali.rice.kim.api.identity.Person;
88  import org.kuali.rice.kim.api.identity.PersonService;
89  import org.kuali.rice.kim.api.identity.address.EntityAddress;
90  import org.kuali.rice.kim.api.identity.entity.Entity;
91  import org.kuali.rice.kim.api.identity.type.EntityTypeContactInfo;
92  import org.kuali.rice.kim.api.services.IdentityManagementService;
93  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
94  import org.kuali.rice.kns.util.KNSGlobalVariables;
95  import org.kuali.rice.krad.bo.DocumentHeader;
96  import org.kuali.rice.krad.document.Copyable;
97  import org.kuali.rice.krad.service.BusinessObjectService;
98  import org.kuali.rice.krad.util.GlobalVariables;
99  import org.kuali.rice.krad.util.KRADConstants;
100 import org.kuali.rice.krad.util.ObjectUtils;
101 
102 /**
103  * This is the business object that represents the DisbursementVoucher document in Kuali.
104  */
105 public class DisbursementVoucherDocument extends AccountingDocumentBase implements Copyable, AmountTotaling {
106     protected static Logger LOG = Logger.getLogger(DisbursementVoucherDocument.class);
107 
108     protected static final String PAYEE_IS_PURCHASE_ORDER_VENDOR_SPLIT = "PayeeIsPurchaseOrderVendor";
109     protected static final String PURCHASE_ORDER_VENDOR_TYPE = "PO";
110     protected static final String DOCUMENT_REQUIRES_TAX_REVIEW_SPLIT = "RequiresTaxReview";
111     protected static final String DOCUMENT_REQUIRES_TRAVEL_REVIEW_SPLIT = "RequiresTravelReview";
112     protected static final String DOCUMENT_REQUIRES_SEPARATION_OF_DUTIES = "RequiresSeparationOfDutiesReview";
113     protected static final String DISBURSEMENT_VOUCHER_TYPE = "DisbursementVoucher";
114 
115     protected static final String PAYMENT_REASONS_REQUIRING_TAX_REVIEW_PARAMETER_NAME = "PAYMENT_REASONS_REQUIRING_TAX_REVIEW";
116     protected static final String USE_DEFAULT_EMPLOYEE_ADDRESS_PARAMETER_NAME = "USE_DEFAULT_EMPLOYEE_ADDRESS_IND";
117     protected static final String DEFAULT_EMPLOYEE_ADDRESS_TYPE_PARAMETER_NAME = "DEFAULT_EMPLOYEE_ADDRESS_TYPE";
118     protected static final String SEPARATION_OF_DUTIES_PARAMETER_NAME = "ENABLE_SEPARATION_OF_DUTIES_IND";
119 
120     protected static final String TAX_CONTROL_BACKUP_HOLDING = "B";
121     protected static final String TAX_CONTROL_HOLD_PAYMENTS = "H";
122 
123     protected static transient PersonService personService;
124     protected static transient ParameterService parameterService;
125     protected static transient VendorService vendorService;
126     protected static transient BusinessObjectService businessObjectService;
127     protected static transient DateTimeService dateTimeService;
128     protected static transient DisbursementVoucherPaymentReasonService dvPymentReasonService;
129     protected static transient IdentityManagementService identityManagementService;
130     protected static transient DisbursementVoucherExtractService disbursementVoucherExtractService;
131 
132     protected Integer finDocNextRegistrantLineNbr;
133     protected String disbVchrContactPersonName;
134     protected String disbVchrContactPhoneNumber;
135     protected String disbVchrContactEmailId;
136     protected Date disbursementVoucherDueDate;
137     protected boolean disbVchrAttachmentCode;
138     protected boolean disbVchrSpecialHandlingCode;
139     protected KualiDecimal disbVchrCheckTotalAmount;
140     protected boolean disbVchrForeignCurrencyInd;
141     protected String disbursementVoucherDocumentationLocationCode;
142     protected String disbVchrCheckStubText;
143     protected boolean dvCheckStubOverflowCode;
144     protected String campusCode;
145     protected String disbVchrPayeeTaxControlCode;
146     protected boolean disbVchrPayeeChangedInd;
147     protected String disbursementVoucherCheckNbr;
148     protected Timestamp disbursementVoucherCheckDate;
149     protected boolean disbVchrPayeeW9CompleteCode;
150     protected String disbVchrPaymentMethodCode;
151     protected boolean exceptionIndicator;
152     protected boolean disbExcptAttachedIndicator;
153     protected Date extractDate;
154     protected Date paidDate;
155     protected Date cancelDate;
156     protected String disbVchrBankCode;
157     protected String disbVchrPdpBankCode;
158 
159     protected boolean payeeAssigned = false;
160     protected boolean editW9W8BENbox = false;
161     protected boolean immediatePaymentIndicator = false;
162 
163     protected DocumentHeader financialDocument;
164     protected DisbursementVoucherDocumentationLocation disbVchrDocumentationLoc;
165     protected DisbursementVoucherNonEmployeeTravel dvNonEmployeeTravel;
166     protected DisbursementVoucherNonResidentAlienTax dvNonResidentAlienTax;
167     protected DisbursementVoucherPayeeDetail dvPayeeDetail;
168     protected DisbursementVoucherPreConferenceDetail dvPreConferenceDetail;
169     protected DisbursementVoucherWireTransfer dvWireTransfer;
170 
171     protected Bank bank;
172     private OlePaymentMethod paymentMethod;
173     protected Integer paymentMethodId;
174     /**
175      * Default no-arg constructor.
176      */
177     public DisbursementVoucherDocument() {
178         super();
179         exceptionIndicator = false;
180         finDocNextRegistrantLineNbr = new Integer(1);
181         dvNonEmployeeTravel = new DisbursementVoucherNonEmployeeTravel();
182         dvNonResidentAlienTax = new DisbursementVoucherNonResidentAlienTax();
183         dvPayeeDetail = new DisbursementVoucherPayeeDetail();
184         dvPreConferenceDetail = new DisbursementVoucherPreConferenceDetail();
185         dvWireTransfer = new DisbursementVoucherWireTransfer();
186         disbVchrCheckTotalAmount = KualiDecimal.ZERO;
187         bank = new Bank();
188     }
189 
190 
191     /**
192      * @see org.kuali.ole.sys.document.AccountingDocumentBase#getPendingLedgerEntriesForSufficientFundsChecking()
193      */
194     @Override
195     public List<GeneralLedgerPendingEntry> getPendingLedgerEntriesForSufficientFundsChecking() {
196         List<GeneralLedgerPendingEntry> ples = new ArrayList<GeneralLedgerPendingEntry>();
197 
198         ConfigurationService kualiConfigurationService = SpringContext.getBean(ConfigurationService.class);
199         FlexibleOffsetAccountService flexibleOffsetAccountService = SpringContext.getBean(FlexibleOffsetAccountService.class);
200 
201         ObjectTypeService objectTypeService = SpringContext.getBean(ObjectTypeService.class);
202 
203         for (GeneralLedgerPendingEntry ple : this.getGeneralLedgerPendingEntries()) {
204             List<String> expenseObjectTypes = objectTypeService.getExpenseObjectTypes(ple.getUniversityFiscalYear());
205             if (expenseObjectTypes.contains(ple.getFinancialObjectTypeCode())) {
206                 // is an expense object type, keep checking
207                 ple.refreshNonUpdateableReferences();
208                 if (ple.getAccount().isPendingAcctSufficientFundsIndicator() && ple.getAccount().getAccountSufficientFundsCode().equals(OLEConstants.SF_TYPE_CASH_AT_ACCOUNT)) {
209                     // is a cash account
210                     if (flexibleOffsetAccountService.getByPrimaryIdIfEnabled(ple.getChartOfAccountsCode(), ple.getAccountNumber(), ple.getChart().getFinancialCashObjectCode()) == null && flexibleOffsetAccountService.getByPrimaryIdIfEnabled(ple.getChartOfAccountsCode(), ple.getAccountNumber(), ple.getChart().getFinAccountsPayableObjectCode()) == null) {
211                         // does not have a flexible offset for cash or liability, set the object code to cash and add to list of
212                         // PLEs to check for SF
213 
214                         ple = new GeneralLedgerPendingEntry(ple);
215                         ple.setFinancialObjectCode(ple.getChart().getFinancialCashObjectCode());
216                         ple.setTransactionDebitCreditCode(ple.getTransactionDebitCreditCode().equals(OLEConstants.GL_DEBIT_CODE) ? OLEConstants.GL_CREDIT_CODE : OLEConstants.GL_DEBIT_CODE);
217                         ples.add(ple);
218                     }
219 
220                 }
221                 else {
222                     // is not a cash account, process as normal
223                     ples.add(ple);
224                 }
225             }
226         }
227 
228         return ples;
229     }
230 
231 
232     /**
233      * Gets the finDocNextRegistrantLineNbr attribute.
234      *
235      * @return Returns the finDocNextRegistrantLineNbr
236      */
237     public Integer getFinDocNextRegistrantLineNbr() {
238         return finDocNextRegistrantLineNbr;
239     }
240 
241 
242     /**
243      * Sets the finDocNextRegistrantLineNbr attribute.
244      *
245      * @param finDocNextRegistrantLineNbr The finDocNextRegistrantLineNbr to set.
246      */
247     public void setFinDocNextRegistrantLineNbr(Integer finDocNextRegistrantLineNbr) {
248         this.finDocNextRegistrantLineNbr = finDocNextRegistrantLineNbr;
249     }
250 
251     /**
252      * Gets the disbVchrContactPersonName attribute.
253      *
254      * @return Returns the disbVchrContactPersonName
255      */
256     public String getDisbVchrContactPersonName() {
257         return disbVchrContactPersonName;
258     }
259 
260 
261     /**
262      * Sets the disbVchrContactPersonName attribute.
263      *
264      * @param disbVchrContactPersonName The disbVchrContactPersonName to set.
265      */
266     public void setDisbVchrContactPersonName(String disbVchrContactPersonName) {
267         this.disbVchrContactPersonName = disbVchrContactPersonName;
268     }
269 
270     /**
271      * Gets the disbVchrContactPhoneNumber attribute.
272      *
273      * @return Returns the disbVchrContactPhoneNumber
274      */
275     public String getDisbVchrContactPhoneNumber() {
276         return disbVchrContactPhoneNumber;
277     }
278 
279 
280     /**
281      * Sets the disbVchrContactPhoneNumber attribute.
282      *
283      * @param disbVchrContactPhoneNumber The disbVchrContactPhoneNumber to set.
284      */
285     public void setDisbVchrContactPhoneNumber(String disbVchrContactPhoneNumber) {
286         this.disbVchrContactPhoneNumber = disbVchrContactPhoneNumber;
287     }
288 
289     /**
290      * Gets the disbVchrContactEmailId attribute.
291      *
292      * @return Returns the disbVchrContactEmailId
293      */
294     public String getDisbVchrContactEmailId() {
295         return disbVchrContactEmailId;
296     }
297 
298 
299     /**
300      * Sets the disbVchrContactEmailId attribute.
301      *
302      * @param disbVchrContactEmailId The disbVchrContactEmailId to set.
303      */
304     public void setDisbVchrContactEmailId(String disbVchrContactEmailId) {
305         this.disbVchrContactEmailId = disbVchrContactEmailId;
306     }
307 
308     /**
309      * Gets the disbursementVoucherDueDate attribute.
310      *
311      * @return Returns the disbursementVoucherDueDate
312      */
313     public Date getDisbursementVoucherDueDate() {
314         return disbursementVoucherDueDate;
315     }
316 
317 
318     /**
319      * Sets the disbursementVoucherDueDate attribute.
320      *
321      * @param disbursementVoucherDueDate The disbursementVoucherDueDate to set.
322      */
323     public void setDisbursementVoucherDueDate(Date disbursementVoucherDueDate) {
324         this.disbursementVoucherDueDate = disbursementVoucherDueDate;
325     }
326 
327     /**
328      * Gets the disbVchrAttachmentCode attribute.
329      *
330      * @return Returns the disbVchrAttachmentCode
331      */
332     public boolean isDisbVchrAttachmentCode() {
333         return disbVchrAttachmentCode;
334     }
335 
336 
337     /**
338      * Sets the disbVchrAttachmentCode attribute.
339      *
340      * @param disbVchrAttachmentCode The disbVchrAttachmentCode to set.
341      */
342     public void setDisbVchrAttachmentCode(boolean disbVchrAttachmentCode) {
343         this.disbVchrAttachmentCode = disbVchrAttachmentCode;
344     }
345 
346     /**
347      * Gets the disbVchrSpecialHandlingCode attribute.
348      *
349      * @return Returns the disbVchrSpecialHandlingCode
350      */
351     public boolean isDisbVchrSpecialHandlingCode() {
352         return disbVchrSpecialHandlingCode;
353     }
354 
355 
356     /**
357      * Sets the disbVchrSpecialHandlingCode attribute.
358      *
359      * @param disbVchrSpecialHandlingCode The disbVchrSpecialHandlingCode to set.
360      */
361     public void setDisbVchrSpecialHandlingCode(boolean disbVchrSpecialHandlingCode) {
362         this.disbVchrSpecialHandlingCode = disbVchrSpecialHandlingCode;
363     }
364 
365     /**
366      * Gets the disbVchrCheckTotalAmount attribute.
367      *
368      * @return Returns the disbVchrCheckTotalAmount
369      */
370     public KualiDecimal getDisbVchrCheckTotalAmount() {
371         return disbVchrCheckTotalAmount;
372     }
373 
374 
375     /**
376      * Sets the disbVchrCheckTotalAmount attribute.
377      *
378      * @param disbVchrCheckTotalAmount The disbVchrCheckTotalAmount to set.
379      */
380     public void setDisbVchrCheckTotalAmount(KualiDecimal disbVchrCheckTotalAmount) {
381         if (disbVchrCheckTotalAmount != null) {
382             this.disbVchrCheckTotalAmount = disbVchrCheckTotalAmount;
383         }
384     }
385 
386     /**
387      * Gets the disbVchrForeignCurrencyInd attribute.
388      *
389      * @return Returns the disbVchrForeignCurrencyInd
390      */
391     public boolean isDisbVchrForeignCurrencyInd() {
392         return disbVchrForeignCurrencyInd;
393     }
394 
395 
396     /**
397      * Sets the disbVchrForeignCurrencyInd attribute.
398      *
399      * @param disbVchrForeignCurrencyInd The disbVchrForeignCurrencyInd to set.
400      */
401     public void setDisbVchrForeignCurrencyInd(boolean disbVchrForeignCurrencyInd) {
402         this.disbVchrForeignCurrencyInd = disbVchrForeignCurrencyInd;
403     }
404 
405     /**
406      * Gets the disbursementVoucherDocumentationLocationCode attribute.
407      *
408      * @return Returns the disbursementVoucherDocumentationLocationCode
409      */
410     public String getDisbursementVoucherDocumentationLocationCode() {
411         return disbursementVoucherDocumentationLocationCode;
412     }
413 
414 
415     /**
416      * Sets the disbursementVoucherDocumentationLocationCode attribute.
417      *
418      * @param disbursementVoucherDocumentationLocationCode The disbursementVoucherDocumentationLocationCode to set.
419      */
420     public void setDisbursementVoucherDocumentationLocationCode(String disbursementVoucherDocumentationLocationCode) {
421         this.disbursementVoucherDocumentationLocationCode = disbursementVoucherDocumentationLocationCode;
422     }
423 
424     /**
425      * Gets the disbVchrCheckStubText attribute.
426      *
427      * @return Returns the disbVchrCheckStubText
428      */
429     public String getDisbVchrCheckStubText() {
430         return disbVchrCheckStubText;
431     }
432 
433 
434     /**
435      * Sets the disbVchrCheckStubText attribute.
436      *
437      * @param disbVchrCheckStubText The disbVchrCheckStubText to set.
438      */
439     public void setDisbVchrCheckStubText(String disbVchrCheckStubText) {
440         this.disbVchrCheckStubText = disbVchrCheckStubText;
441     }
442 
443     /**
444      * Gets the dvCheckStubOverflowCode attribute.
445      *
446      * @return Returns the dvCheckStubOverflowCode
447      */
448     public boolean getDvCheckStubOverflowCode() {
449         return dvCheckStubOverflowCode;
450     }
451 
452 
453     /**
454      * Sets the dvCheckStubOverflowCode attribute.
455      *
456      * @param dvCheckStubOverflowCode The dvCheckStubOverflowCode to set.
457      */
458     public void setDvCheckStubOverflowCode(boolean dvCheckStubOverflowCode) {
459         this.dvCheckStubOverflowCode = dvCheckStubOverflowCode;
460     }
461 
462     /**
463      * Gets the campusCode attribute.
464      *
465      * @return Returns the campusCode
466      */
467     public String getCampusCode() {
468         return campusCode;
469     }
470 
471 
472     /**
473      * Sets the campusCode attribute.
474      *
475      * @param campusCode The campusCode to set.
476      */
477     public void setCampusCode(String campusCode) {
478         this.campusCode = campusCode;
479     }
480 
481     /**
482      * Gets the disbVchrPayeeTaxControlCode attribute.
483      *
484      * @return Returns the disbVchrPayeeTaxControlCode
485      */
486     public String getDisbVchrPayeeTaxControlCode() {
487         return disbVchrPayeeTaxControlCode;
488     }
489 
490 
491     /**
492      * Sets the disbVchrPayeeTaxControlCode attribute.
493      *
494      * @param disbVchrPayeeTaxControlCode The disbVchrPayeeTaxControlCode to set.
495      */
496     public void setDisbVchrPayeeTaxControlCode(String disbVchrPayeeTaxControlCode) {
497         this.disbVchrPayeeTaxControlCode = disbVchrPayeeTaxControlCode;
498     }
499 
500     /**
501      * Gets the disbVchrPayeeChangedInd attribute.
502      *
503      * @return Returns the disbVchrPayeeChangedInd
504      */
505     public boolean isDisbVchrPayeeChangedInd() {
506         return disbVchrPayeeChangedInd;
507     }
508 
509 
510     /**
511      * Sets the disbVchrPayeeChangedInd attribute.
512      *
513      * @param disbVchrPayeeChangedInd The disbVchrPayeeChangedInd to set.
514      */
515     public void setDisbVchrPayeeChangedInd(boolean disbVchrPayeeChangedInd) {
516         this.disbVchrPayeeChangedInd = disbVchrPayeeChangedInd;
517     }
518 
519     /**
520      * Gets the disbursementVoucherCheckNbr attribute.
521      *
522      * @return Returns the disbursementVoucherCheckNbr
523      */
524     public String getDisbursementVoucherCheckNbr() {
525         return disbursementVoucherCheckNbr;
526     }
527 
528 
529     /**
530      * Sets the disbursementVoucherCheckNbr attribute.
531      *
532      * @param disbursementVoucherCheckNbr The disbursementVoucherCheckNbr to set.
533      */
534     public void setDisbursementVoucherCheckNbr(String disbursementVoucherCheckNbr) {
535         this.disbursementVoucherCheckNbr = disbursementVoucherCheckNbr;
536     }
537 
538     /**
539      * Gets the disbursementVoucherCheckDate attribute.
540      *
541      * @return Returns the disbursementVoucherCheckDate
542      */
543     public Timestamp getDisbursementVoucherCheckDate() {
544         return disbursementVoucherCheckDate;
545     }
546 
547 
548     /**
549      * Sets the disbursementVoucherCheckDate attribute.
550      *
551      * @param disbursementVoucherCheckDate The disbursementVoucherCheckDate to set.
552      */
553     public void setDisbursementVoucherCheckDate(Timestamp disbursementVoucherCheckDate) {
554         this.disbursementVoucherCheckDate = disbursementVoucherCheckDate;
555     }
556 
557     /**
558      * Gets the disbVchrPayeeW9CompleteCode attribute.
559      *
560      * @return Returns the disbVchrPayeeW9CompleteCode
561      */
562     public boolean getDisbVchrPayeeW9CompleteCode() {
563         return disbVchrPayeeW9CompleteCode;
564     }
565 
566 
567     /**
568      * Sets the disbVchrPayeeW9CompleteCode attribute.
569      *
570      * @param disbVchrPayeeW9CompleteCode The disbVchrPayeeW9CompleteCode to set.
571      */
572     public void setDisbVchrPayeeW9CompleteCode(boolean disbVchrPayeeW9CompleteCode) {
573         this.disbVchrPayeeW9CompleteCode = disbVchrPayeeW9CompleteCode;
574     }
575 
576     /**
577      * Gets the disbVchrPaymentMethodCode attribute.
578      *
579      * @return Returns the disbVchrPaymentMethodCode
580      */
581     public String getDisbVchrPaymentMethodCode() {
582         return disbVchrPaymentMethodCode;
583     }
584 
585 
586     /**
587      * Sets the disbVchrPaymentMethodCode attribute.
588      *
589      * @param disbVchrPaymentMethodCode The disbVchrPaymentMethodCode to set.
590      */
591     public void setDisbVchrPaymentMethodCode(String disbVchrPaymentMethodCode) {
592         this.disbVchrPaymentMethodCode = disbVchrPaymentMethodCode;
593     }
594 
595     /**
596      * Gets the financialDocument attribute.
597      *
598      * @return Returns the financialDocument
599      */
600     public DocumentHeader getFinancialDocument() {
601         return financialDocument;
602     }
603 
604 
605     /**
606      * Sets the financialDocument attribute.
607      *
608      * @param financialDocument The financialDocument to set.
609      * @deprecated
610      */
611     @Deprecated
612     public void setFinancialDocument(DocumentHeader financialDocument) {
613         this.financialDocument = financialDocument;
614     }
615 
616     /**
617      * Gets the disbVchrDocumentationLoc attribute.
618      *
619      * @return Returns the disbVchrDocumentationLoc
620      */
621     public DisbursementVoucherDocumentationLocation getDisbVchrDocumentationLoc() {
622         return disbVchrDocumentationLoc;
623     }
624 
625 
626     /**
627      * Sets the disbVchrDocumentationLoc attribute.
628      *
629      * @param disbVchrDocumentationLoc The disbVchrDocumentationLoc to set.
630      * @deprecated
631      */
632     @Deprecated
633     public void setDisbVchrDocumentationLoc(DisbursementVoucherDocumentationLocation disbVchrDocumentationLoc) {
634         this.disbVchrDocumentationLoc = disbVchrDocumentationLoc;
635     }
636 
637 
638     /**
639      * @return Returns the dvNonEmployeeTravel.
640      */
641     public DisbursementVoucherNonEmployeeTravel getDvNonEmployeeTravel() {
642         return dvNonEmployeeTravel;
643     }
644 
645     /**
646      * @param dvNonEmployeeTravel The dvNonEmployeeTravel to set.
647      */
648     public void setDvNonEmployeeTravel(DisbursementVoucherNonEmployeeTravel dvNonEmployeeTravel) {
649         this.dvNonEmployeeTravel = dvNonEmployeeTravel;
650     }
651 
652     /**
653      * @return Returns the dvNonResidentAlienTax.
654      */
655     public DisbursementVoucherNonResidentAlienTax getDvNonResidentAlienTax() {
656         return dvNonResidentAlienTax;
657     }
658 
659     /**
660      * @param dvNonResidentAlienTax The dvNonResidentAlienTax to set.
661      */
662     public void setDvNonResidentAlienTax(DisbursementVoucherNonResidentAlienTax dvNonResidentAlienTax) {
663         this.dvNonResidentAlienTax = dvNonResidentAlienTax;
664     }
665 
666     /**
667      * @return Returns the dvPayeeDetail.
668      */
669     public DisbursementVoucherPayeeDetail getDvPayeeDetail() {
670         return dvPayeeDetail;
671     }
672 
673     /**
674      * @param dvPayeeDetail The dvPayeeDetail to set.
675      */
676     public void setDvPayeeDetail(DisbursementVoucherPayeeDetail dvPayeeDetail) {
677         this.dvPayeeDetail = dvPayeeDetail;
678     }
679 
680     /**
681      * @return Returns the dvPreConferenceDetail.
682      */
683     public DisbursementVoucherPreConferenceDetail getDvPreConferenceDetail() {
684         return dvPreConferenceDetail;
685     }
686 
687     /**
688      * @param dvPreConferenceDetail The dvPreConferenceDetail to set.
689      */
690     public void setDvPreConferenceDetail(DisbursementVoucherPreConferenceDetail dvPreConferenceDetail) {
691         this.dvPreConferenceDetail = dvPreConferenceDetail;
692     }
693 
694     /**
695      * @return Returns the dvWireTransfer.
696      */
697     public DisbursementVoucherWireTransfer getDvWireTransfer() {
698         return dvWireTransfer;
699     }
700 
701     /**
702      * @param dvWireTransfer The dvWireTransfer to set.
703      */
704     public void setDvWireTransfer(DisbursementVoucherWireTransfer dvWireTransfer) {
705         this.dvWireTransfer = dvWireTransfer;
706     }
707 
708     /**
709      * @return Returns the exceptionIndicator.
710      */
711     public boolean isExceptionIndicator() {
712         return exceptionIndicator;
713     }
714 
715     /**
716      * @param exceptionIndicator The exceptionIndicator to set.
717      */
718     public void setExceptionIndicator(boolean exceptionIndicator) {
719         this.exceptionIndicator = exceptionIndicator;
720     }
721 
722     /**
723      * Gets the cancelDate attribute.
724      *
725      * @return Returns the cancelDate.
726      */
727     public Date getCancelDate() {
728         return cancelDate;
729     }
730 
731     /**
732      * Sets the cancelDate attribute value.
733      *
734      * @param cancelDate The cancelDate to set.
735      */
736     public void setCancelDate(Date cancelDate) {
737         this.cancelDate = cancelDate;
738     }
739 
740     /**
741      * Gets the extractDate attribute.
742      *
743      * @return Returns the extractDate.
744      */
745     public Date getExtractDate() {
746         return extractDate;
747     }
748 
749     /**
750      * Sets the extractDate attribute value.
751      *
752      * @param extractDate The extractDate to set.
753      */
754     public void setExtractDate(Date extractDate) {
755         this.extractDate = extractDate;
756     }
757 
758     /**
759      * Gets the paidDate attribute.
760      *
761      * @return Returns the paidDate.
762      */
763     public Date getPaidDate() {
764         return paidDate;
765     }
766 
767     /**
768      * Sets the paidDate attribute value.
769      *
770      * @param paidDate The paidDate to set.
771      */
772     public void setPaidDate(Date paidDate) {
773         this.paidDate = paidDate;
774     }
775 
776     /**
777      * Based on which pdp dates are present (extract, paid, canceled), determines a String for the status
778      *
779      * @return a String representation of the status
780      */
781     public String getDisbursementVoucherPdpStatus() {
782         if (cancelDate != null) {
783             return "Canceled";
784         }
785         else if (paidDate != null) {
786             return "Paid";
787         }
788         else if (extractDate != null) {
789             return "Extracted";
790         }
791         else {
792             return "Pre-Extraction";
793         }
794     }
795 
796     /**
797      * Pretends to set the PDP status for this document
798      *
799      * @param status the status to pretend to set
800      */
801     public void setDisbursementVoucherPdpStatus(String status) {
802         // don't do nothing, 'cause this ain't a real field
803     }
804 
805     /**
806      * Adds a dv pre-paid registrant line
807      *
808      * @param line
809      */
810     public void addDvPrePaidRegistrantLine(DisbursementVoucherPreConferenceRegistrant line) {
811         line.setFinancialDocumentLineNumber(getFinDocNextRegistrantLineNbr());
812         this.getDvPreConferenceDetail().getDvPreConferenceRegistrants().add(line);
813         this.finDocNextRegistrantLineNbr = new Integer(getFinDocNextRegistrantLineNbr().intValue() + 1);
814     }
815 
816     /**
817      * Returns the name associated with the payment method code
818      *
819      * @return String
820      */
821     public String getDisbVchrPaymentMethodName() {
822         return new PaymentMethodValuesFinder().getKeyLabel(disbVchrPaymentMethodCode);
823     }
824 
825     /**
826      * This method...
827      *
828      * @param method
829      * @deprecated This method should not be used. There is no protected attribute to store this value. The associated getter
830      *             retrieves the value remotely.
831      */
832     @Deprecated
833     public void setDisbVchrPaymentMethodName(String method) {
834     }
835 
836     /**
837      * Returns the name associated with the documentation location name
838      *
839      * @return String
840      */
841     public String getDisbursementVoucherDocumentationLocationName() {
842         return new DisbursementVoucherDocumentationLocationValuesFinder().getKeyLabel(disbursementVoucherDocumentationLocationCode);
843     }
844 
845     /**
846      * This method...
847      *
848      * @param name
849      * @deprecated This method should not be used. There is no protected attribute to store this value. The associated getter
850      *             retrieves the value remotely.
851      */
852     @Deprecated
853     public void setDisbursementVoucherDocumentationLocationName(String name) {
854     }
855 
856 
857     /**
858      * Gets the disbVchrBankCode attribute.
859      *
860      * @return Returns the disbVchrBankCode.
861      */
862     public String getDisbVchrBankCode() {
863         return disbVchrBankCode;
864     }
865 
866 
867     /**
868      * Sets the disbVchrBankCode attribute value.
869      *
870      * @param disbVchrBankCode The disbVchrBankCode to set.
871      */
872     public void setDisbVchrBankCode(String disbVchrBankCode) {
873         this.disbVchrBankCode = disbVchrBankCode;
874     }
875 
876     /**
877      * Gets the bank attribute.
878      *
879      * @return Returns the bank.
880      */
881     public Bank getBank() {
882         return bank;
883     }
884 
885 
886     /**
887      * Sets the bank attribute value.
888      *
889      * @param bank The bank to set.
890      */
891     public void setBank(Bank bank) {
892         this.bank = bank;
893     }
894 
895 
896     /**
897      * Gets the paymentMethod attribute. 
898      * @return Returns the paymentMethod.
899      */
900     public OlePaymentMethod getPaymentMethod() {
901         return paymentMethod;
902     }
903 
904 
905     /**
906      * Sets the paymentMethod attribute value.
907      * @param paymentMethod The paymentMethod to set.
908      */
909     public void setPaymentMethod(OlePaymentMethod paymentMethod) {
910         this.paymentMethod = paymentMethod;
911     }
912 
913 
914     /**
915      * Gets the paymentMethodId attribute. 
916      * @return Returns the paymentMethodId.
917      */
918     public Integer getPaymentMethodId() {
919         return paymentMethodId;
920     }
921 
922 
923     /**
924      * Sets the paymentMethodId attribute value.
925      * @param paymentMethodId The paymentMethodId to set.
926      */
927     public void setPaymentMethodId(Integer paymentMethodId) {
928         this.paymentMethodId = paymentMethodId;
929     }
930 
931 
932     /**
933      * Convenience method to set dv payee detail fields based on a given vendor.
934      *
935      * @param vendor
936      */
937     public void templateVendor(VendorDetail vendor, VendorAddress vendorAddress) {
938         if (vendor == null) {
939             return;
940         }
941         this.setPaymentMethodId(vendor.getPaymentMethodId());
942         this.getDvPayeeDetail().setDisbursementVoucherPayeeTypeCode(DisbursementVoucherConstants.DV_PAYEE_TYPE_VENDOR);
943         this.getDvPayeeDetail().setDisbVchrPayeeIdNumber(vendor.getVendorNumber());
944         this.getDvPayeeDetail().setDisbVchrPayeePersonName(vendor.getVendorName());
945 
946         this.getDvPayeeDetail().setDisbVchrAlienPaymentCode(vendor.getVendorHeader().getVendorForeignIndicator());
947 
948 
949         if (ObjectUtils.isNotNull(vendorAddress) && ObjectUtils.isNotNull(vendorAddress.getVendorAddressGeneratedIdentifier())) {
950             this.getDvPayeeDetail().setDisbVchrVendorAddressIdNumber(vendorAddress.getVendorAddressGeneratedIdentifier().toString());
951             this.getDvPayeeDetail().setDisbVchrPayeeLine1Addr(vendorAddress.getVendorLine1Address());
952             this.getDvPayeeDetail().setDisbVchrPayeeLine2Addr(vendorAddress.getVendorLine2Address());
953             this.getDvPayeeDetail().setDisbVchrPayeeCityName(vendorAddress.getVendorCityName());
954             this.getDvPayeeDetail().setDisbVchrPayeeStateCode(vendorAddress.getVendorStateCode());
955             this.getDvPayeeDetail().setDisbVchrPayeeZipCode(vendorAddress.getVendorZipCode());
956             this.getDvPayeeDetail().setDisbVchrPayeeCountryCode(vendorAddress.getVendorCountryCode());
957         }
958         else {
959             this.getDvPayeeDetail().setDisbVchrVendorAddressIdNumber(StringUtils.EMPTY);
960             this.getDvPayeeDetail().setDisbVchrPayeeLine1Addr(StringUtils.EMPTY);
961             this.getDvPayeeDetail().setDisbVchrPayeeLine2Addr(StringUtils.EMPTY);
962             this.getDvPayeeDetail().setDisbVchrPayeeCityName(StringUtils.EMPTY);
963             this.getDvPayeeDetail().setDisbVchrPayeeStateCode(StringUtils.EMPTY);
964             this.getDvPayeeDetail().setDisbVchrPayeeZipCode(StringUtils.EMPTY);
965             this.getDvPayeeDetail().setDisbVchrPayeeCountryCode(StringUtils.EMPTY);
966         }
967 
968         this.getDvPayeeDetail().setDisbVchrAlienPaymentCode(vendor.getVendorHeader().getVendorForeignIndicator());
969         this.getDvPayeeDetail().setDvPayeeSubjectPaymentCode(VendorConstants.VendorTypes.SUBJECT_PAYMENT.equals(vendor.getVendorHeader().getVendorTypeCode()));
970         this.getDvPayeeDetail().setDisbVchrEmployeePaidOutsidePayrollCode(getVendorService().isVendorInstitutionEmployee(vendor.getVendorHeaderGeneratedIdentifier()));
971 
972         this.getDvPayeeDetail().setHasMultipleVendorAddresses(1 < vendor.getVendorAddresses().size());
973 
974         boolean w9AndW8Checked = false;
975         if ( (ObjectUtils.isNotNull(vendor.getVendorHeader().getVendorW9ReceivedIndicator()) && vendor.getVendorHeader().getVendorW9ReceivedIndicator() == true) ||
976              (ObjectUtils.isNotNull(vendor.getVendorHeader().getVendorW8BenReceivedIndicator()) && vendor.getVendorHeader().getVendorW8BenReceivedIndicator() == true) ) {
977 
978             w9AndW8Checked = true;
979         }
980 
981     //    this.disbVchrPayeeW9CompleteCode = vendor.getVendorHeader().getVendorW8BenReceivedIndicator()  == null ? false : vendor.getVendorHeader().getVendorW8BenReceivedIndicator();
982         this.disbVchrPayeeW9CompleteCode = w9AndW8Checked;
983 
984         Date vendorFederalWithholdingTaxBeginDate = vendor.getVendorHeader().getVendorFederalWithholdingTaxBeginningDate();
985         Date vendorFederalWithholdingTaxEndDate = vendor.getVendorHeader().getVendorFederalWithholdingTaxEndDate();
986         java.util.Date today = getDateTimeService().getCurrentDate();
987         if ((vendorFederalWithholdingTaxBeginDate != null && vendorFederalWithholdingTaxBeginDate.before(today)) && (vendorFederalWithholdingTaxEndDate == null || vendorFederalWithholdingTaxEndDate.after(today))) {
988             this.disbVchrPayeeTaxControlCode = DisbursementVoucherConstants.TAX_CONTROL_CODE_BEGIN_WITHHOLDING;
989         }
990 
991         // if vendor is foreign, default alien payment code to true
992         if (getVendorService().isVendorForeign(vendor.getVendorHeaderGeneratedIdentifier())) {
993             getDvPayeeDetail().setDisbVchrAlienPaymentCode(true);
994         }
995     }
996 
997     /**
998      * Convenience method to set dv payee detail fields based on a given Employee.
999      *
1000      * @param employee
1001      */
1002     public void templateEmployee(Person employee) {
1003         if (employee == null) {
1004             return;
1005         }
1006 
1007         this.getDvPayeeDetail().setDisbursementVoucherPayeeTypeCode(DisbursementVoucherConstants.DV_PAYEE_TYPE_EMPLOYEE);
1008         this.getDvPayeeDetail().setDisbVchrPayeeIdNumber(employee.getEmployeeId());
1009         this.getDvPayeeDetail().setDisbVchrPayeePersonName(employee.getName());
1010 
1011         final ParameterService parameterService = this.getParameterService();
1012         //Commented for the jira issue OLE-3415
1013         /*if (parameterService.parameterExists(DisbursementVoucherDocument.class, DisbursementVoucherDocument.USE_DEFAULT_EMPLOYEE_ADDRESS_PARAMETER_NAME) && parameterService.getParameterValueAsBoolean(DisbursementVoucherDocument.class, DisbursementVoucherDocument.USE_DEFAULT_EMPLOYEE_ADDRESS_PARAMETER_NAME)) {*/
1014             this.getDvPayeeDetail().setDisbVchrPayeeLine1Addr(employee.getAddressLine1Unmasked());
1015             this.getDvPayeeDetail().setDisbVchrPayeeLine2Addr(employee.getAddressLine2Unmasked());
1016             this.getDvPayeeDetail().setDisbVchrPayeeCityName(employee.getAddressCityUnmasked());
1017             this.getDvPayeeDetail().setDisbVchrPayeeStateCode(employee.getAddressStateProvinceCodeUnmasked());
1018             this.getDvPayeeDetail().setDisbVchrPayeeZipCode(employee.getAddressPostalCodeUnmasked());
1019             this.getDvPayeeDetail().setDisbVchrPayeeCountryCode(employee.getAddressCountryCodeUnmasked());
1020             //Commented for the jira issue OLE-3415
1021         /*} else {
1022             final EntityAddress address = getNonDefaultAddress(employee);
1023             if (address != null) {
1024                 this.getDvPayeeDetail().setDisbVchrPayeeLine1Addr(address.getLine1Unmasked());
1025                 this.getDvPayeeDetail().setDisbVchrPayeeLine2Addr(address.getLine2Unmasked());
1026                 this.getDvPayeeDetail().setDisbVchrPayeeCityName(address.getCityUnmasked());
1027                 this.getDvPayeeDetail().setDisbVchrPayeeStateCode(address.getStateProvinceCodeUnmasked());
1028                 this.getDvPayeeDetail().setDisbVchrPayeeZipCode(address.getPostalCodeUnmasked());
1029                 this.getDvPayeeDetail().setDisbVchrPayeeCountryCode(address.getCountryCodeUnmasked());
1030             }
1031             else {
1032                 this.getDvPayeeDetail().setDisbVchrPayeeLine1Addr("");
1033                 this.getDvPayeeDetail().setDisbVchrPayeeLine2Addr("");
1034                 this.getDvPayeeDetail().setDisbVchrPayeeCityName("");
1035                 this.getDvPayeeDetail().setDisbVchrPayeeStateCode("");
1036                 this.getDvPayeeDetail().setDisbVchrPayeeZipCode("");
1037                 this.getDvPayeeDetail().setDisbVchrPayeeCountryCode("");
1038             }
1039         }*/
1040 
1041         //OLEMI-8935: When an employee is inactive, the Payment Type field on DV documents should display the message "Is this payee an employee" = No
1042         if (employee.isActive()) {
1043         this.getDvPayeeDetail().setDisbVchrPayeeEmployeeCode(true);
1044         } else {
1045             this.getDvPayeeDetail().setDisbVchrPayeeEmployeeCode(false);
1046         }
1047 
1048         // I'm assuming that if a tax id type code other than 'TAX' is present, then the employee must be foreign
1049         for ( String externalIdentifierTypeCode : employee.getExternalIdentifiers().keySet() ) {
1050             if (KimConstants.PersonExternalIdentifierTypes.TAX.equals(externalIdentifierTypeCode)) {
1051                 this.getDvPayeeDetail().setDisbVchrAlienPaymentCode(false);
1052             }
1053         }
1054         //Commented for the jira issue OLE-3415
1055         // Determine if employee is a research subject
1056        /* ParameterEvaluator researchPaymentReasonCodeEvaluator = SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.RESEARCH_PAYMENT_REASONS_PARM_NM, this.getDvPayeeDetail().getDisbVchrPaymentReasonCode());
1057         if (researchPaymentReasonCodeEvaluator.evaluationSucceeds()) {
1058             if (getParameterService().parameterExists(DisbursementVoucherDocument.class, DisbursementVoucherConstants.RESEARCH_NON_VENDOR_PAY_LIMIT_AMOUNT_PARM_NM)) {
1059                 String researchPayLimit = getParameterService().getParameterValueAsString(DisbursementVoucherDocument.class, DisbursementVoucherConstants.RESEARCH_NON_VENDOR_PAY_LIMIT_AMOUNT_PARM_NM);
1060                 if (StringUtils.isNotBlank(researchPayLimit)) {
1061                     KualiDecimal payLimit = new KualiDecimal(researchPayLimit);
1062 
1063                     if (getDisbVchrCheckTotalAmount().isLessThan(payLimit)) {
1064                         this.getDvPayeeDetail().setDvPayeeSubjectPaymentCode(true);
1065                     }
1066                 }
1067             }
1068         }*/
1069 
1070         this.disbVchrPayeeTaxControlCode = "";
1071         this.disbVchrPayeeW9CompleteCode = true;
1072     }
1073 
1074     /**
1075      * Finds the address for the given employee, matching the type in the OLE-FP / Disbursement Voucher/ DEFAULT_EMPLOYEE_ADDRESS_TYPE parameter,
1076      * to use as the address for the employee
1077      * @param employee the employee to find a non-default address for
1078      * @return the non-default address, or null if not found
1079      */
1080     protected EntityAddress getNonDefaultAddress(Person employee) {
1081         final String addressType = getParameterService().getParameterValueAsString(DisbursementVoucherDocument.class, DisbursementVoucherDocument.DEFAULT_EMPLOYEE_ADDRESS_TYPE_PARAMETER_NAME);
1082         final Entity entity = getIdentityManagementService().getEntityByPrincipalId(employee.getPrincipalId());
1083         if (entity != null) {
1084             final EntityTypeContactInfo entityEntityType = getPersonEntityEntityType(entity);
1085             if (entityEntityType != null) {
1086                 final List<? extends EntityAddress> addresses = entityEntityType.getAddresses();
1087 
1088                 return findAddressByType(addresses, addressType);
1089             }
1090         }
1091         return null;
1092     }
1093 
1094     /**
1095      * Someday this method will be in Rice.  But...'til it is...lazy loop through the entity entity types in the given
1096      * KimEntityInfo and return the one who has the type of "PERSON"
1097      * @param entityInfo the entity info to loop through entity entity types of
1098      * @return a found entity entity type or null if a PERSON entity entity type is not associated with the given KimEntityInfo record
1099      */
1100     protected EntityTypeContactInfo getPersonEntityEntityType(Entity entity) {
1101         final List<EntityTypeContactInfo> entityEntityTypes = entity.getEntityTypeContactInfos();
1102         int count = 0;
1103         EntityTypeContactInfo foundInfo = null;
1104 
1105         while (count < entityEntityTypes.size() && foundInfo == null) {
1106             if (entityEntityTypes.get(count).getEntityTypeCode().equals(KimConstants.EntityTypes.PERSON)) {
1107                 foundInfo = entityEntityTypes.get(count);
1108             }
1109             count += 1;
1110         }
1111 
1112         return foundInfo;
1113     }
1114 
1115     /**
1116      * Given a List of KimEntityAddress and an address type, finds the address in the List with the given type (or null if no matching KimEntityAddress is found)
1117      * @param addresses the List of KimEntityAddress records to search
1118      * @param addressType the address type of the address to return
1119      * @return the found KimEntityAddress, or null if not found
1120      */
1121     protected EntityAddress findAddressByType(List<? extends EntityAddress> addresses, String addressType) {
1122         EntityAddress foundAddress = null;
1123         int count = 0;
1124 
1125         while (count < addresses.size() && foundAddress == null) {
1126             final EntityAddress currentAddress = addresses.get(count);
1127             if (currentAddress.isActive() && currentAddress.getAddressType().getCode().equals(addressType)) {
1128                 foundAddress = currentAddress;
1129             }
1130             count += 1;
1131         }
1132 
1133         return foundAddress;
1134     }
1135 
1136     /**
1137      * @see org.kuali.rice.kns.document.Document#prepareForSave()
1138      */
1139     @Override
1140     public void prepareForSave() {
1141         if (this instanceof AmountTotaling) {
1142             if (getFinancialSystemDocumentHeader().getFinancialDocumentStatusCode().equals(OLEConstants.DocumentStatusCodes.ENROUTE)) {
1143                 if (getParameterService().parameterExists(OleParameterConstants.FINANCIAL_SYSTEM_DOCUMENT.class, UPDATE_TOTAL_AMOUNT_IN_POST_PROCESSING_PARAMETER_NAME)
1144                         && getParameterService().getParameterValueAsBoolean(OleParameterConstants.FINANCIAL_SYSTEM_DOCUMENT.class, UPDATE_TOTAL_AMOUNT_IN_POST_PROCESSING_PARAMETER_NAME)) {
1145                     getFinancialSystemDocumentHeader().setFinancialDocumentTotalAmount(((AmountTotaling) this).getTotalDollarAmount());
1146                 }
1147             } else {
1148                 getFinancialSystemDocumentHeader().setFinancialDocumentTotalAmount(((AmountTotaling) this).getTotalDollarAmount());
1149             }
1150         }
1151 
1152         if (dvWireTransfer != null) {
1153             dvWireTransfer.setDocumentNumber(this.documentNumber);
1154         }
1155 
1156         if (dvNonResidentAlienTax != null) {
1157             dvNonResidentAlienTax.setDocumentNumber(this.documentNumber);
1158         }
1159 
1160         dvPayeeDetail.setDocumentNumber(this.documentNumber);
1161 
1162         if (dvNonEmployeeTravel != null) {
1163             dvNonEmployeeTravel.setDocumentNumber(this.documentNumber);
1164             dvNonEmployeeTravel.setTotalTravelAmount(dvNonEmployeeTravel.getTotalTravelAmount());
1165         }
1166 
1167         if (dvPreConferenceDetail != null) {
1168             dvPreConferenceDetail.setDocumentNumber(this.documentNumber);
1169             dvPreConferenceDetail.setDisbVchrConferenceTotalAmt(dvPreConferenceDetail.getDisbVchrConferenceTotalAmt());
1170         }
1171 
1172         if (shouldClearSpecialHandling()) {
1173             clearSpecialHandling();
1174         }
1175     }
1176 
1177     /**
1178      * Determines if the special handling fields should be cleared, based on whether the special handling has been turned off and whether the current node is CAMPUS
1179      * @return true if special handling should be cleared, false otherwise
1180      */
1181     protected boolean shouldClearSpecialHandling() {
1182         if (!isDisbVchrSpecialHandlingCode()) {
1183             // are we at the campus route node?
1184             List<RouteNodeInstance> currentNodes = getDocumentHeader().getWorkflowDocument().getCurrentRouteNodeInstances();
1185             return (currentNodes.contains(DisbursementVoucherConstants.RouteLevelNames.CAMPUS));
1186         }
1187         return false;
1188     }
1189 
1190     /**
1191      * Clears all set special handling fields
1192      */
1193     protected void clearSpecialHandling() {
1194         DisbursementVoucherPayeeDetail payeeDetail = getDvPayeeDetail();
1195 
1196         if (!StringUtils.isBlank(payeeDetail.getDisbVchrSpecialHandlingPersonName())) {
1197             payeeDetail.setDisbVchrSpecialHandlingPersonName(null);
1198         }
1199         if (!StringUtils.isBlank(payeeDetail.getDisbVchrSpecialHandlingLine1Addr())) {
1200             payeeDetail.setDisbVchrSpecialHandlingLine1Addr(null);
1201         }
1202         if (!StringUtils.isBlank(payeeDetail.getDisbVchrSpecialHandlingLine2Addr())) {
1203             payeeDetail.setDisbVchrSpecialHandlingLine2Addr(null);
1204         }
1205         if (!StringUtils.isBlank(payeeDetail.getDisbVchrSpecialHandlingCityName())) {
1206             payeeDetail.setDisbVchrSpecialHandlingCityName(null);
1207         }
1208         if (!StringUtils.isBlank(payeeDetail.getDisbVchrSpecialHandlingStateCode())) {
1209             payeeDetail.setDisbVchrSpecialHandlingStateCode(null);
1210         }
1211         if (!StringUtils.isBlank(payeeDetail.getDisbVchrSpecialHandlingZipCode())) {
1212             payeeDetail.setDisbVchrSpecialHandlingZipCode(null);
1213         }
1214         if (!StringUtils.isBlank(payeeDetail.getDisbVchrSpecialHandlingCountryCode())) {
1215             payeeDetail.setDisbVchrSpecialHandlingCountryCode(null);
1216         }
1217     }
1218 
1219     /**
1220      * This method is overridden to populate some local variables that are not persisted to the database. These values need to be
1221      * computed and saved to the DV Payee Detail BO so they can be serialized to XML for routing. Some of the routing rules rely on
1222      * these variables.
1223      *
1224      * @see org.kuali.rice.kns.document.DocumentBase#populateDocumentForRouting()
1225      */
1226     @Override
1227     public void populateDocumentForRouting() {
1228         DisbursementVoucherPayeeDetail payeeDetail = getDvPayeeDetail();
1229 
1230         if (payeeDetail.isVendor()) {
1231             payeeDetail.setDisbVchrPayeeEmployeeCode(getVendorService().isVendorInstitutionEmployee(payeeDetail.getDisbVchrVendorHeaderIdNumberAsInteger()));
1232             payeeDetail.setDvPayeeSubjectPaymentCode(getVendorService().isSubjectPaymentVendor(payeeDetail.getDisbVchrVendorHeaderIdNumberAsInteger()));
1233         }
1234         else if (payeeDetail.isEmployee()) {
1235             //Commented for the jira issue OLE-3415
1236             // Determine if employee is a research subject
1237             /*ParameterEvaluator researchPaymentReasonCodeEvaluator = SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.RESEARCH_PAYMENT_REASONS_PARM_NM, payeeDetail.getDisbVchrPaymentReasonCode());
1238             if (researchPaymentReasonCodeEvaluator.evaluationSucceeds()) {
1239                 if (getParameterService().parameterExists(DisbursementVoucherDocument.class, DisbursementVoucherConstants.RESEARCH_NON_VENDOR_PAY_LIMIT_AMOUNT_PARM_NM)) {
1240                     String researchPayLimit = getParameterService().getParameterValueAsString(DisbursementVoucherDocument.class, DisbursementVoucherConstants.RESEARCH_NON_VENDOR_PAY_LIMIT_AMOUNT_PARM_NM);
1241                     if (StringUtils.isNotBlank(researchPayLimit)) {
1242                         KualiDecimal payLimit = new KualiDecimal(researchPayLimit);
1243 
1244                         if (getDisbVchrCheckTotalAmount().isLessThan(payLimit)) {
1245                             payeeDetail.setDvPayeeSubjectPaymentCode(true);
1246                         }
1247                     }
1248                 }
1249             }*/
1250         }
1251 
1252         super.populateDocumentForRouting(); // Call last, serializes to XML
1253     }
1254 
1255     /**
1256      * Clears information that might have been entered for sub tables, but because of changes to the document is longer needed and
1257      * should not be persisted.
1258      */
1259     protected void cleanDocumentData() {
1260         // TODO: warren: this method ain't called!!! maybe this should be called by prepare for save above
1261         if (!DisbursementVoucherConstants.PAYMENT_METHOD_WIRE.equals(this.getDisbVchrPaymentMethodCode()) && !DisbursementVoucherConstants.PAYMENT_METHOD_DRAFT.equals(this.getDisbVchrPaymentMethodCode())) {
1262             getBusinessObjectService().delete(dvWireTransfer);
1263             dvWireTransfer = null;
1264         }
1265 
1266         if (!dvPayeeDetail.isDisbVchrAlienPaymentCode()) {
1267             getBusinessObjectService().delete(dvNonResidentAlienTax);
1268             dvNonResidentAlienTax = null;
1269         }
1270 
1271         DisbursementVoucherPaymentReasonService paymentReasonService = SpringContext.getBean(DisbursementVoucherPaymentReasonService.class);
1272         String paymentReasonCode = this.getDvPayeeDetail().getDisbVchrPaymentReasonCode();
1273         //Commented for the jira issue OLE-3415
1274         /*if (!paymentReasonService.isNonEmployeeTravelPaymentReason(paymentReasonCode)) {
1275             getBusinessObjectService().delete(dvNonEmployeeTravel);
1276             dvNonEmployeeTravel = null;
1277         }
1278 
1279         if (!paymentReasonService.isPrepaidTravelPaymentReason(paymentReasonCode)) {
1280             getBusinessObjectService().delete(dvPreConferenceDetail);
1281             dvPreConferenceDetail = null;
1282         }*/
1283     }
1284 
1285     /**
1286      * @see org.kuali.ole.sys.document.AccountingDocumentBase#toCopy()
1287      */
1288     @Override
1289     public void toCopy() throws WorkflowException {
1290         super.toCopy();
1291         initiateDocument();
1292 
1293         // clear fields
1294         setDisbVchrContactPhoneNumber(StringUtils.EMPTY);
1295         setDisbVchrContactEmailId(StringUtils.EMPTY);
1296         setDisbVchrPayeeTaxControlCode(StringUtils.EMPTY);
1297 
1298         // clear nra
1299         SpringContext.getBean(DisbursementVoucherTaxService.class).clearNRATaxLines(this);
1300         setDvNonResidentAlienTax(new DisbursementVoucherNonResidentAlienTax());
1301 
1302         // clear waive wire
1303         getDvWireTransfer().setDisbursementVoucherWireTransferFeeWaiverIndicator(false);
1304 
1305         // check vendor id number to see if still valid, if not, clear dvPayeeDetail; otherwise, use the current dvPayeeDetail as is
1306         if (!StringUtils.isBlank(getDvPayeeDetail().getDisbVchrPayeeIdNumber())) {
1307             VendorDetail vendorDetail = getVendorService().getVendorDetail(getDvPayeeDetail().getDisbVchrVendorHeaderIdNumberAsInteger(), getDvPayeeDetail().getDisbVchrVendorDetailAssignedIdNumberAsInteger());
1308             if (vendorDetail == null) {
1309                 dvPayeeDetail = new DisbursementVoucherPayeeDetail();;
1310                 getDvPayeeDetail().setDisbVchrPayeeIdNumber(StringUtils.EMPTY);
1311                 KNSGlobalVariables.getMessageList().add(OLEKeyConstants.WARNING_DV_PAYEE_NONEXISTANT_CLEARED);
1312             }
1313         }
1314 
1315         // this copied DV has not been extracted
1316         this.extractDate = null;
1317         this.paidDate = null;
1318         this.cancelDate = null;
1319         getFinancialSystemDocumentHeader().setFinancialDocumentStatusCode(OLEConstants.DocumentStatusCodes.INITIATED);
1320     }
1321 
1322     /**
1323      * generic, shared logic used to initiate a dv document
1324      */
1325     public void initiateDocument() {
1326         PhoneNumberService phoneNumberService = SpringContext.getBean(PhoneNumberService.class);
1327         Person currentUser = GlobalVariables.getUserSession().getPerson();
1328         setDisbVchrContactPersonName(currentUser.getName());
1329 
1330         if(!phoneNumberService.isDefaultFormatPhoneNumber(currentUser.getPhoneNumber())) {
1331             setDisbVchrContactPhoneNumber(phoneNumberService.formatNumberIfPossible(currentUser.getPhoneNumber()));
1332         }
1333 
1334         setDisbVchrContactEmailId(currentUser.getEmailAddress());
1335         ChartOrgHolder chartOrg = SpringContext.getBean(org.kuali.ole.sys.service.FinancialSystemUserService.class).getPrimaryOrganization(currentUser, OLEConstants.ParameterNamespaces.FINANCIAL);
1336 
1337         // Does a valid campus code exist for this person?  If so, simply grab
1338         // the campus code via the business object service.
1339         if (chartOrg != null && chartOrg.getOrganization() != null) {
1340             setCampusCode(chartOrg.getOrganization().getOrganizationPhysicalCampusCode());
1341         }
1342         // A valid campus code was not found; therefore, use the default affiliated
1343         // campus code.
1344         else {
1345             String affiliatedCampusCode = currentUser.getCampusCode();
1346             setCampusCode(affiliatedCampusCode);
1347         }
1348 
1349         // due date
1350         Calendar calendar = getDateTimeService().getCurrentCalendar();
1351         calendar.add(Calendar.DAY_OF_MONTH, 1);
1352         setDisbursementVoucherDueDate(new Date(calendar.getTimeInMillis()));
1353 
1354         // default doc location
1355         if (StringUtils.isBlank(getDisbursementVoucherDocumentationLocationCode())) {
1356             setDisbursementVoucherDocumentationLocationCode(getParameterService().getParameterValueAsString(DisbursementVoucherDocument.class, DisbursementVoucherConstants.DEFAULT_DOC_LOCATION_PARM_NM));
1357         }
1358 
1359         // default bank code
1360         Bank defaultBank = SpringContext.getBean(BankService.class).getDefaultBankByDocType(this.getClass());
1361         if (defaultBank != null) {
1362             this.disbVchrBankCode = defaultBank.getBankCode();
1363             this.bank = defaultBank;
1364         }
1365     }
1366 
1367     /**
1368      * @see org.kuali.rice.kns.document.DocumentBase#buildListOfDeletionAwareLists()
1369      */
1370     @SuppressWarnings("unchecked")
1371     @Override
1372     public List buildListOfDeletionAwareLists() {
1373         List managedLists = super.buildListOfDeletionAwareLists();
1374 
1375         if (dvNonEmployeeTravel != null) {
1376             managedLists.add(dvNonEmployeeTravel.getDvNonEmployeeExpenses());
1377             managedLists.add(dvNonEmployeeTravel.getDvPrePaidEmployeeExpenses());
1378         }
1379 
1380         if (dvPreConferenceDetail != null) {
1381             managedLists.add(dvPreConferenceDetail.getDvPreConferenceRegistrants());
1382         }
1383 
1384         return managedLists;
1385     }
1386 
1387     /**
1388      * Returns check total.
1389      *
1390      * @see org.kuali.ole.sys.document.AccountingDocumentBase#getTotalDollarAmount()
1391      * @return KualiDecimal
1392      */
1393     @Override
1394     public KualiDecimal getTotalDollarAmount() {
1395         return this.getDisbVchrCheckTotalAmount();
1396     }
1397 
1398     /**
1399      * Returns true if accounting line debit
1400      *
1401      * @param financialDocument submitted accounting document
1402      * @param accountingLine accounting line in accounting document
1403      * @return true if document is debit
1404      * @see IsDebitUtils#isDebitConsideringNothingPositiveOnly(FinancialDocumentRuleBase, FinancialDocument, AccountingLine)
1405      * @see org.kuali.rice.kns.rule.AccountingLineRule#isDebit(org.kuali.rice.kns.document.FinancialDocument,
1406      *      org.kuali.rice.kns.bo.AccountingLine)
1407      */
1408     @Override
1409     public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) {
1410         // disallow error corrections
1411         DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
1412         isDebitUtils.disallowErrorCorrectionDocumentCheck(this);
1413 
1414         if (getDvNonResidentAlienTax() != null && getDvNonResidentAlienTax().getFinancialDocumentAccountingLineText() != null && getDvNonResidentAlienTax().getFinancialDocumentAccountingLineText().contains(((AccountingLine) postable).getSequenceNumber().toString())) {
1415             return postable.getAmount().isPositive();
1416         }
1417 
1418         return isDebitUtils.isDebitConsideringNothingPositiveOnly(this, postable);
1419     }
1420 
1421     /**
1422      * Override to change the doc type based on payment method. This is needed to pick up different offset definitions.
1423      *
1424      * @param financialDocument submitted accounting document
1425      * @param accountingLine accounting line in submitted accounting document
1426      * @param explicitEntry explicit GLPE
1427      * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.rice.kns.document.FinancialDocument,
1428      *      org.kuali.rice.kns.bo.AccountingLine, org.kuali.module.gl.bo.GeneralLedgerPendingEntry)
1429      */
1430     @Override
1431     public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail accountingLine, GeneralLedgerPendingEntry explicitEntry) {
1432 
1433         /* change document type based on payment method to pick up different offsets */
1434         if (DisbursementVoucherConstants.PAYMENT_METHOD_CHECK.equals(getDisbVchrPaymentMethodCode())) {
1435             if (LOG.isDebugEnabled()) {
1436                 LOG.debug("changing doc type on pending entry " + explicitEntry.getTransactionLedgerEntrySequenceNumber() + " to " + DisbursementVoucherConstants.DOCUMENT_TYPE_CHECKACH);
1437             }
1438             explicitEntry.setFinancialDocumentTypeCode(DisbursementVoucherConstants.DOCUMENT_TYPE_CHECKACH);
1439         }
1440         else {
1441             if (LOG.isDebugEnabled()) {
1442                 LOG.debug("changing doc type on pending entry " + explicitEntry.getTransactionLedgerEntrySequenceNumber() + " to " + DisbursementVoucherConstants.DOCUMENT_TYPE_CHECKACH);
1443             }
1444             explicitEntry.setFinancialDocumentTypeCode(DisbursementVoucherConstants.DOCUMENT_TYPE_WTFD);
1445         }
1446     }
1447 
1448     /**
1449      * Return true if GLPE's are generated successfully (i.e. there are either 0 GLPE's or 1 GLPE in disbursement voucher document)
1450      *
1451      * @param financialDocument submitted financial document
1452      * @param sequenceHelper helper class to keep track of GLPE sequence
1453      * @return true if GLPE's are generated successfully
1454      * @see org.kuali.rice.kns.rule.GenerateGeneralLedgerDocumentPendingEntriesRule#processGenerateDocumentGeneralLedgerPendingEntries(org.kuali.rice.kns.document.FinancialDocument,org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
1455      */
1456     @Override
1457     public boolean generateDocumentGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
1458         if (getGeneralLedgerPendingEntries() == null || getGeneralLedgerPendingEntries().size() < 2) {
1459             LOG.warn("No gl entries for accounting lines.");
1460             return true;
1461         }
1462 
1463         /*
1464          * only generate additional charge entries for payment method wire charge, and if the fee has not been waived
1465          */
1466         if (DisbursementVoucherConstants.PAYMENT_METHOD_WIRE.equals(getDisbVchrPaymentMethodCode()) && !getDvWireTransfer().isDisbursementVoucherWireTransferFeeWaiverIndicator()) {
1467             LOG.debug("generating wire charge gl pending entries.");
1468 
1469             // retrieve wire charge
1470             WireCharge wireCharge = retrieveWireCharge();
1471 
1472             // generate debits
1473             GeneralLedgerPendingEntry chargeEntry = processWireChargeDebitEntries(sequenceHelper, wireCharge);
1474 
1475             // generate credits
1476             processWireChargeCreditEntries(sequenceHelper, wireCharge, chargeEntry);
1477         }
1478 
1479         // for wire or drafts generate bank offset entry (if enabled), for ACH and checks offset will be generated by PDP
1480         if (DisbursementVoucherConstants.PAYMENT_METHOD_WIRE.equals(getDisbVchrPaymentMethodCode()) || DisbursementVoucherConstants.PAYMENT_METHOD_DRAFT.equals(getDisbVchrPaymentMethodCode())) {
1481             generateDocumentBankOffsetEntries(sequenceHelper);
1482         }
1483 
1484         return true;
1485     }
1486 
1487     /**
1488      * Builds an explicit and offset for the wire charge debit. The account associated with the first accounting is used for the
1489      * debit. The explicit and offset entries for the first accounting line and copied and customized for the wire charge.
1490      *
1491      * @param dvDocument submitted disbursement voucher document
1492      * @param sequenceHelper helper class to keep track of GLPE sequence
1493      * @param wireCharge wireCharge object from current fiscal year
1494      * @return GeneralLedgerPendingEntry generated wire charge debit
1495      */
1496     protected GeneralLedgerPendingEntry processWireChargeDebitEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper, WireCharge wireCharge) {
1497         LOG.debug("processWireChargeDebitEntries started");
1498 
1499         // grab the explicit entry for the first accounting line and adjust for wire charge entry
1500         GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry(getGeneralLedgerPendingEntry(0));
1501         explicitEntry.setTransactionLedgerEntrySequenceNumber(new Integer(sequenceHelper.getSequenceCounter()));
1502         explicitEntry.setFinancialObjectCode(wireCharge.getExpenseFinancialObjectCode());
1503         explicitEntry.setFinancialSubObjectCode(GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialSubObjectCode());
1504         explicitEntry.setTransactionDebitCreditCode(GL_DEBIT_CODE);
1505 
1506         String objectTypeCode = SpringContext.getBean(OptionsService.class).getCurrentYearOptions().getFinObjTypeExpenditureexpCd();
1507         explicitEntry.setFinancialObjectTypeCode(objectTypeCode);
1508 
1509         String originationCode = SpringContext.getBean(HomeOriginationService.class).getHomeOrigination().getFinSystemHomeOriginationCode();
1510         explicitEntry.setFinancialSystemOriginationCode(originationCode);
1511 
1512         if (OLEConstants.COUNTRY_CODE_UNITED_STATES.equals(getDvWireTransfer().getDisbVchrBankCountryCode())) {
1513             explicitEntry.setTransactionLedgerEntryAmount(wireCharge.getDomesticChargeAmt());
1514         }
1515         else {
1516             explicitEntry.setTransactionLedgerEntryAmount(wireCharge.getForeignChargeAmt());
1517         }
1518 
1519         explicitEntry.setTransactionLedgerEntryDescription("Automatic debit for wire transfer fee");
1520 
1521         addPendingEntry(explicitEntry);
1522         sequenceHelper.increment();
1523 
1524         // handle the offset entry
1525         GeneralLedgerPendingEntry offsetEntry = new GeneralLedgerPendingEntry(explicitEntry);
1526         GeneralLedgerPendingEntryService glpeService = SpringContext.getBean(GeneralLedgerPendingEntryService.class);
1527         glpeService.populateOffsetGeneralLedgerPendingEntry(getPostingYear(), explicitEntry, sequenceHelper, offsetEntry);
1528 
1529         addPendingEntry(offsetEntry);
1530         sequenceHelper.increment();
1531 
1532         return explicitEntry;
1533     }
1534 
1535     /**
1536      * Builds an explicit and offset for the wire charge credit. The account and income object code found in the wire charge table
1537      * is used for the entry.
1538      *
1539      * @param dvDocument submitted disbursement voucher document
1540      * @param sequenceHelper helper class to keep track of GLPE sequence
1541      * @param chargeEntry GLPE charge
1542      * @param wireCharge wireCharge object from current fiscal year
1543      */
1544     protected void processWireChargeCreditEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper, WireCharge wireCharge, GeneralLedgerPendingEntry chargeEntry) {
1545         LOG.debug("processWireChargeCreditEntries started");
1546 
1547         // copy the charge entry and adjust for credit
1548         GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry(chargeEntry);
1549         explicitEntry.setTransactionLedgerEntrySequenceNumber(new Integer(sequenceHelper.getSequenceCounter()));
1550         explicitEntry.setChartOfAccountsCode(wireCharge.getChartOfAccountsCode());
1551         explicitEntry.setAccountNumber(wireCharge.getAccountNumber());
1552         explicitEntry.setFinancialObjectCode(wireCharge.getIncomeFinancialObjectCode());
1553 
1554         // retrieve object type
1555         ObjectCode objectCode = wireCharge.getIncomeFinancialObject();
1556         explicitEntry.setFinancialObjectTypeCode(objectCode.getFinancialObjectTypeCode());
1557 
1558         explicitEntry.setTransactionDebitCreditCode(GL_CREDIT_CODE);
1559 
1560         explicitEntry.setFinancialSubObjectCode(GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankFinancialSubObjectCode());
1561         explicitEntry.setSubAccountNumber(GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankSubAccountNumber());
1562         explicitEntry.setProjectCode(GENERAL_LEDGER_PENDING_ENTRY_CODE.getBlankProjectCode());
1563 
1564         explicitEntry.setTransactionLedgerEntryDescription("Automatic credit for wire transfer fee");
1565 
1566         addPendingEntry(explicitEntry);
1567         sequenceHelper.increment();
1568 
1569         // handle the offset entry
1570         GeneralLedgerPendingEntry offsetEntry = new GeneralLedgerPendingEntry(explicitEntry);
1571         GeneralLedgerPendingEntryService glpeService = SpringContext.getBean(GeneralLedgerPendingEntryService.class);
1572         glpeService.populateOffsetGeneralLedgerPendingEntry(getPostingYear(), explicitEntry, sequenceHelper, offsetEntry);
1573 
1574         addPendingEntry(offsetEntry);
1575         sequenceHelper.increment();
1576     }
1577 
1578     /**
1579      * If bank specification is enabled generates bank offsetting entries for the document amount
1580      *
1581      * @param sequenceHelper helper class to keep track of GLPE sequence
1582      * @param paymentMethodCode the payment method of this DV
1583      */
1584     public boolean generateDocumentBankOffsetEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
1585         boolean success = true;
1586 
1587         if (!SpringContext.getBean(BankService.class).isBankSpecificationEnabled()) {
1588             return success;
1589         }
1590 
1591         this.refreshReferenceObject(OLEPropertyConstants.BANK);
1592 
1593         GeneralLedgerPendingEntryService glpeService = SpringContext.getBean(GeneralLedgerPendingEntryService.class);
1594 
1595         final KualiDecimal bankOffsetAmount = glpeService.getOffsetToCashAmount(this).negated();
1596         GeneralLedgerPendingEntry bankOffsetEntry = new GeneralLedgerPendingEntry();
1597         success &= glpeService.populateBankOffsetGeneralLedgerPendingEntry(getBank(), bankOffsetAmount, this, getPostingYear(), sequenceHelper, bankOffsetEntry, KRADConstants.DOCUMENT_PROPERTY_NAME + "." + OLEPropertyConstants.DISB_VCHR_BANK_CODE);
1598 
1599         if (success) {
1600             AccountingDocumentRuleHelperService accountingDocumentRuleUtil = SpringContext.getBean(AccountingDocumentRuleHelperService.class);
1601             bankOffsetEntry.setTransactionLedgerEntryDescription(accountingDocumentRuleUtil.formatProperty(OLEKeyConstants.Bank.DESCRIPTION_GLPE_BANK_OFFSET));
1602             bankOffsetEntry.setFinancialDocumentTypeCode(DisbursementVoucherConstants.DOCUMENT_TYPE_WTFD);
1603             addPendingEntry(bankOffsetEntry);
1604             sequenceHelper.increment();
1605 
1606             GeneralLedgerPendingEntry offsetEntry = new GeneralLedgerPendingEntry(bankOffsetEntry);
1607             success &= glpeService.populateOffsetGeneralLedgerPendingEntry(getPostingYear(), bankOffsetEntry, sequenceHelper, offsetEntry);
1608             bankOffsetEntry.setFinancialDocumentTypeCode(DisbursementVoucherConstants.DOCUMENT_TYPE_WTFD);
1609             addPendingEntry(offsetEntry);
1610             sequenceHelper.increment();
1611         }
1612 
1613         return success;
1614     }
1615 
1616     /**
1617      * Retrieves the wire transfer information for the current fiscal year.
1618      *
1619      * @return <code>WireCharge</code>
1620      */
1621     protected WireCharge retrieveWireCharge() {
1622         WireCharge wireCharge = new WireCharge();
1623         wireCharge.setUniversityFiscalYear(SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear());
1624 
1625         wireCharge = (WireCharge) SpringContext.getBean(BusinessObjectService.class).retrieve(wireCharge);
1626         if (wireCharge == null) {
1627             LOG.error("Wire charge information not found for current fiscal year.");
1628             throw new RuntimeException("Wire charge information not found for current fiscal year.");
1629         }
1630 
1631         return wireCharge;
1632     }
1633 
1634 
1635     /**
1636      * Gets the payeeAssigned attribute. This method returns a flag that is used to indicate if the payee type and value has been
1637      * set on the DV. This value is used to determine the correct page that should be loaded by the DV flow.
1638      *
1639      * @return Returns the payeeAssigned.
1640      */
1641     public boolean isPayeeAssigned() {
1642         // If value is false, check state of document. We should assume payee is assigned if document has been saved.
1643         // Otherwise, value will be set during creation process.
1644         if (!payeeAssigned) {
1645             payeeAssigned = !this.getDocumentHeader().getWorkflowDocument().isInitiated();
1646         }
1647         return payeeAssigned;
1648     }
1649 
1650 
1651     /**
1652      * Sets the payeeAssigned attribute value.
1653      *
1654      * @param payeeAssigned The payeeAssigned to set.
1655      */
1656     public void setPayeeAssigned(boolean payeeAssigned) {
1657         this.payeeAssigned = payeeAssigned;
1658     }
1659 
1660     /**
1661      * Gets the editW9W8BENbox attribute. This method returns a flag that is used to indicate if the W9/W8BEN check box can be edited
1662      * by the initiator on the DV.
1663      *
1664      * @return Returns the editW9W8BENbox.
1665      */
1666     public boolean isEditW9W8BENbox() {
1667         String initiatorPrincipalID = this.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId();
1668         if (GlobalVariables.getUserSession().getPrincipalId().equals(initiatorPrincipalID)) {
1669             editW9W8BENbox = true;
1670         }
1671         return editW9W8BENbox;
1672     }
1673 
1674     /**
1675      * Sets the editW9W8BENbox attribute value.
1676      *
1677      * @param editW9W8BENbox The editW9W8BENbox to set.
1678      */
1679     public void setEditW9W8BENbox(boolean editW9W8BENbox) {
1680         this.editW9W8BENbox = editW9W8BENbox;
1681     }
1682 
1683     /**
1684      * Gets the disbVchrPdpBankCode attribute.
1685      *
1686      * @return Returns the disbVchrPdpBankCode.
1687      */
1688     public String getDisbVchrPdpBankCode() {
1689         return disbVchrPdpBankCode;
1690     }
1691 
1692     /**
1693      * Sets the disbVchrPdpBankCode attribute value.
1694      *
1695      * @param disbVchrPdpBankCode The disbVchrPDPBankCode to set.
1696      */
1697     public void setDisbVchrPdpBankCode(String disbVchrPdpBankCode) {
1698         this.disbVchrPdpBankCode = disbVchrPdpBankCode;
1699     }
1700 
1701     /**
1702      * @return whether this document should be paid out immediately from PDP
1703      */
1704     public boolean isImmediatePaymentIndicator() {
1705         return immediatePaymentIndicator;
1706     }
1707 
1708     /**
1709      * Sets whether this document should be paid out as quickly as possible from PDP
1710      * @param immediatePaymentIndicator true if this should be immediately disbursed; false otherwise
1711      */
1712     public void setImmediatePaymentIndicator(boolean immediatePaymentIndicator) {
1713         this.immediatePaymentIndicator = immediatePaymentIndicator;
1714     }
1715 
1716     /**
1717      * @see org.kuali.rice.kns.document.DocumentBase#getDocumentTitle()
1718      */
1719     @Override
1720     public String getDocumentTitle() {
1721         String documentTitle = super.getDocumentTitle();
1722         return this.buildDocumentTitle(documentTitle);
1723     }
1724 
1725     /**
1726      * build document title based on the properties of current document
1727      *
1728      * @param the default document title
1729      * @return the combine information of the given title and additional payment indicators
1730      */
1731     protected String buildDocumentTitle(String title) {
1732         DisbursementVoucherPayeeDetail payee = getDvPayeeDetail();
1733         if(payee == null) {
1734             return title;
1735         }
1736 
1737         Object[] indicators = new String[2];
1738         indicators[0] = payee.isEmployee() ? AdHocPaymentIndicator.EMPLOYEE_PAYEE : AdHocPaymentIndicator.OTHER;
1739         indicators[1] = payee.isDisbVchrAlienPaymentCode() ? AdHocPaymentIndicator.ALIEN_PAYEE : AdHocPaymentIndicator.OTHER;
1740 
1741 //        DisbursementVoucherPaymentReasonService paymentReasonService = SpringContext.getBean(DisbursementVoucherPaymentReasonService.class);
1742         //Commented for the jira OLE-3415
1743         /*boolean isTaxReviewRequired = paymentReasonService.isTaxReviewRequired(payee.getDisbVchrPaymentReasonCode());
1744         indicators[2] = isTaxReviewRequired ? AdHocPaymentIndicator.PAYMENT_REASON_REQUIRING_TAX_REVIEW : AdHocPaymentIndicator.OTHER;*/
1745 
1746         for(Object indicator : indicators) {
1747             if(!AdHocPaymentIndicator.OTHER.equals(indicator)) {
1748                 String titlePattern = title + " [{0}:{1}]";
1749                 return MessageFormat.format(titlePattern, indicators);
1750             }
1751         }
1752 
1753         return title;
1754     }
1755 
1756 
1757     /**
1758      * Provides answers to the following splits: PayeeIsPurchaseOrderVendor RequiresTaxReview RequiresTravelReview
1759      *
1760      * @see org.kuali.ole.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(java.lang.String)
1761      */
1762     @Override
1763     public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
1764         if (nodeName.equals(DisbursementVoucherDocument.PAYEE_IS_PURCHASE_ORDER_VENDOR_SPLIT)) {
1765             return isPayeePurchaseOrderVendor();
1766         }
1767         if (nodeName.equals(DisbursementVoucherDocument.DOCUMENT_REQUIRES_TAX_REVIEW_SPLIT)) {
1768             return isTaxReviewRequired();
1769         }
1770         if (nodeName.equals(DisbursementVoucherDocument.DOCUMENT_REQUIRES_TRAVEL_REVIEW_SPLIT)) {
1771             return true;
1772         }
1773         if (nodeName.equals(DOCUMENT_REQUIRES_SEPARATION_OF_DUTIES)) {
1774             return isSeparationOfDutiesReviewRequired();
1775         }
1776         throw new UnsupportedOperationException("Cannot answer split question for this node you call \""+nodeName+"\"");
1777     }
1778 
1779 
1780     protected boolean isSeparationOfDutiesReviewRequired() {
1781         ParameterService parameterService = SpringContext.getBean(ParameterService.class);
1782         boolean sepOfDutiesRequired = parameterService.getParameterValueAsBoolean(OLEConstants.CoreModuleNamespaces.FINANCIAL, DISBURSEMENT_VOUCHER_TYPE, SEPARATION_OF_DUTIES_PARAMETER_NAME);
1783 
1784         if (sepOfDutiesRequired) {
1785             try {
1786                 Set<Person> priorApprovers = getAllPriorApprovers();
1787                 // The payee cannot be the only approver
1788                 String payeeEmployeeId = this.getDvPayeeDetail().getDisbVchrPayeeIdNumber();
1789                 Person payee = SpringContext.getBean(PersonService.class).getPersonByEmployeeId(payeeEmployeeId);
1790                 // If there is only one approver, and that approver is also the payee, then Separation of Duties is required.
1791                 boolean priorApproverIsPayee = priorApprovers.contains(payee);
1792                 boolean onlyOneApprover = (priorApprovers.size() == 1);
1793                 if ( priorApproverIsPayee && onlyOneApprover) {
1794                     return true;
1795                 }
1796 
1797                 // if there are more than 0 prior approvers which means there had been at least another approver than the current approver
1798                 // then no need for separation of duties
1799                 if (priorApprovers.size() > 0) {
1800                     return false;
1801                 }
1802             }catch (WorkflowException we) {
1803                 LOG.error("Exception while attempting to retrieve all prior approvers from workflow: " + we);
1804             }
1805         }
1806             return false;
1807     }
1808 
1809     public Set<Person> getAllPriorApprovers() throws WorkflowException {
1810         PersonService personService = KimApiServiceLocator.getPersonService();
1811          List<ActionTaken> actionsTaken = getDocumentHeader().getWorkflowDocument().getActionsTaken();
1812         Set<String> principalIds = new HashSet<String>();
1813         Set<Person> persons = new HashSet<Person>();
1814 
1815         for (ActionTaken actionTaken : actionsTaken) {
1816             if (KewApiConstants.ACTION_TAKEN_APPROVED_CD.equals(actionTaken.getActionTaken())) {
1817                 String principalId = actionTaken.getPrincipalId();
1818                 if (!principalIds.contains(principalId)) {
1819                     principalIds.add(principalId);
1820                     persons.add(personService.getPerson(principalId));
1821                 }
1822             }
1823         }
1824         return persons;
1825     }
1826 
1827     /**
1828      * @return true if the payee is a purchase order vendor and therefore should receive vendor review, false otherwise
1829      */
1830     protected boolean isPayeePurchaseOrderVendor() {
1831        /* if (!this.getDvPayeeDetail().getDisbursementVoucherPayeeTypeCode().equals(DisbursementVoucherConstants.DV_PAYEE_TYPE_VENDOR)) {
1832             return false;
1833         }*/
1834 
1835         VendorDetail vendor = getVendorService().getByVendorNumber(this.getDvPayeeDetail().getDisbVchrPayeeIdNumber());
1836         if (vendor == null) {
1837             return false;
1838         }
1839 
1840         vendor.refreshReferenceObject("vendorHeader");
1841         return vendor.getVendorHeader().getVendorTypeCode().equals(DisbursementVoucherDocument.PURCHASE_ORDER_VENDOR_TYPE);
1842     }
1843 
1844     /**
1845      * Tax review is required under the following circumstances: the payee was an employee the payee was a non-resident alien vendor
1846      * the tax control code = "B" or "H" the payment reason code was "D" the payment reason code was "M" and the campus was listed
1847      * in the CAMPUSES_TAXED_FOR_MOVING_REIMBURSEMENTS_PARAMETER_NAME parameter
1848      *
1849      * @return true if any of the above conditions exist and this document should receive tax review, false otherwise
1850      */
1851     protected boolean isTaxReviewRequired() {
1852         if (isPayeePurchaseOrderVendorHasWithholding()) {
1853             return true;
1854         }
1855 
1856         //String payeeTypeCode = this.getDvPayeeDetail().getDisbursementVoucherPayeeTypeCode();
1857        /* if (payeeTypeCode.equals(DisbursementVoucherConstants.DV_PAYEE_TYPE_EMPLOYEE)) {
1858             return false;
1859         } else if (payeeTypeCode.equals(DisbursementVoucherConstants.DV_PAYEE_TYPE_VENDOR)) {
1860             if(vendorService.isVendorInstitutionEmployee(this.getDvPayeeDetail().getDisbVchrVendorHeaderIdNumberAsInteger())){
1861             return true;
1862         }
1863         }
1864 
1865         if (payeeTypeCode.equals(DisbursementVoucherConstants.DV_PAYEE_TYPE_VENDOR) && this.getVendorService().isVendorForeign(getDvPayeeDetail().getDisbVchrVendorHeaderIdNumberAsInteger())) {
1866             return true;
1867         }*/
1868 
1869         String taxControlCode = this.getDisbVchrPayeeTaxControlCode();
1870         if (StringUtils.equals(taxControlCode, DisbursementVoucherDocument.TAX_CONTROL_BACKUP_HOLDING) || StringUtils.equals(taxControlCode,DisbursementVoucherDocument.TAX_CONTROL_HOLD_PAYMENTS)) {
1871             return true;
1872         }
1873 
1874         String paymentReasonCode = this.getDvPayeeDetail().getDisbVchrPaymentReasonCode();
1875         //Commented for the jira issue OLE-3415
1876         /*if (this.getDvPymentReasonService().isDecedentCompensationPaymentReason(paymentReasonCode)) {
1877             return true;
1878         }
1879 
1880         if (this.getDvPymentReasonService().isMovingPaymentReason(paymentReasonCode)) {
1881                 && taxedCampusForMovingReimbursements()) {
1882             return true;
1883         }
1884         if (SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(this.getClass(), DisbursementVoucherDocument.PAYMENT_REASONS_REQUIRING_TAX_REVIEW_PARAMETER_NAME, paymentReasonCode).evaluationSucceeds()) {
1885             return true;
1886         }*/
1887 
1888         return false;
1889     }
1890 
1891     /**
1892      * @return true if the payee is a vendor and has withholding dates therefore should receive tax review, false otherwise
1893      */
1894     protected boolean isPayeePurchaseOrderVendorHasWithholding() {
1895         /*if (!this.getDvPayeeDetail().getDisbursementVoucherPayeeTypeCode().equals(DisbursementVoucherConstants.DV_PAYEE_TYPE_VENDOR)) {
1896             return false;
1897         }
1898 */
1899         VendorDetail vendor = getVendorService().getByVendorNumber(this.getDvPayeeDetail().getDisbVchrPayeeIdNumber());
1900         if (vendor == null) {
1901             return false;
1902         }
1903 
1904         vendor.refreshReferenceObject("vendorHeader");
1905         return (vendor.getVendorHeader().getVendorFederalWithholdingTaxBeginningDate()!= null || vendor.getVendorHeader().getVendorFederalWithholdingTaxEndDate()!= null);
1906     }
1907 
1908 
1909     /**
1910      * Determines if the campus this DV is related to is taxed (and should get tax review routing) for moving reimbursements
1911      *
1912      * @return true if the campus is taxed for moving reimbursements, false otherwise
1913      */
1914     //Commented for the jira issue OLE-3415
1915    /* protected boolean taxedCampusForMovingReimbursements() {
1916         return SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(this.getClass(), DisbursementVoucherConstants.CAMPUSES_TAXED_FOR_MOVING_REIMBURSEMENTS_PARM_NM, this.getCampusCode()).evaluationSucceeds();
1917     }
1918     */
1919     /**
1920      * Travel review is required under the following circumstances: payment reason code is "P" or "N"
1921      *
1922      * @return
1923      */
1924     public boolean isTravelReviewRequired() {
1925         String paymentReasonCode = this.getDvPayeeDetail().getDisbVchrPaymentReasonCode();
1926 
1927         return this.getDvPymentReasonService().isPrepaidTravelPaymentReason(paymentReasonCode) || this.getDvPymentReasonService().isNonEmployeeTravelPaymentReason(paymentReasonCode);
1928         }
1929 
1930     /**
1931      * Overridden to immediately extract DV, if it has been marked for immediate extract
1932      * @see org.kuali.ole.sys.document.GeneralLedgerPostingDocumentBase#doRouteStatusChange(org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO)
1933      */
1934     @Override
1935     public void doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) {
1936         super.doRouteStatusChange(statusChangeEvent);
1937         if (getDocumentHeader().getWorkflowDocument().isProcessed()) {
1938             if (isImmediatePaymentIndicator()) {
1939                 getDisbursementVoucherExtractService().extractImmediatePayment(this);
1940             }
1941         }
1942     }
1943 
1944 
1945     protected PersonService getPersonService() {
1946         if ( personService == null ) {
1947             personService = SpringContext.getBean(PersonService.class);
1948         }
1949         return personService;
1950     }
1951 
1952 
1953     @Override
1954     protected ParameterService getParameterService() {
1955         if ( parameterService == null ) {
1956             parameterService = SpringContext.getBean(ParameterService.class);
1957         }
1958         return parameterService;
1959     }
1960 
1961 
1962     protected VendorService getVendorService() {
1963         if ( vendorService == null ) {
1964             vendorService = SpringContext.getBean(VendorService.class);
1965         }
1966         return vendorService;
1967     }
1968 
1969     /**
1970      * Gets the dvPymentReasonService attribute.
1971      *
1972      * @return Returns the dvPymentReasonService.
1973      */
1974     public DisbursementVoucherPaymentReasonService getDvPymentReasonService() {
1975         if (dvPymentReasonService == null) {
1976             dvPymentReasonService = SpringContext.getBean(DisbursementVoucherPaymentReasonService.class);
1977         }
1978         return dvPymentReasonService;
1979     }
1980 
1981 
1982     /**
1983      * Gets the identityManagementService attribute.
1984      * @return Returns the identityManagementService.
1985      */
1986     public static IdentityManagementService getIdentityManagementService() {
1987         if (identityManagementService == null) {
1988             identityManagementService = SpringContext.getBean(IdentityManagementService.class);
1989         }
1990         return identityManagementService;
1991     }
1992 
1993     /**
1994      * Sets the identityManagementService attribute value.
1995      * @param identityManagementService The identityManagementService to set.
1996      */
1997     public static void setIdentityManagementService(IdentityManagementService identityManagementService) {
1998         DisbursementVoucherDocument.identityManagementService = identityManagementService;
1999     }
2000 
2001     /**
2002      * @return the default implementation of the DisbursementVoucherExtractService
2003      */
2004     public static DisbursementVoucherExtractService getDisbursementVoucherExtractService() {
2005         if (disbursementVoucherExtractService == null) {
2006             disbursementVoucherExtractService = SpringContext.getBean(DisbursementVoucherExtractService.class);
2007         }
2008         return disbursementVoucherExtractService;
2009     }
2010 
2011     /**
2012      * @return Returns the disbExcptAttachedIndicator.
2013      */
2014     public boolean isDisbExcptAttachedIndicator() {
2015         return disbExcptAttachedIndicator;
2016     }
2017 
2018     /**
2019      * @param disbExcptAttachedIndicator The disbExcptAttachedIndicator to set.
2020      */
2021     public void setDisbExcptAttachedIndicator(boolean disbExcptAttachedIndicator) {
2022         this.disbExcptAttachedIndicator = disbExcptAttachedIndicator;
2023     }
2024     
2025     //MSU Contribution AER:RQ_AP_0760 OLEMI-8876 OLECNTRB-980
2026     
2027     /**
2028      * RQ_AP_0760: Ability to view disbursement information on the
2029      * Disbursement Voucher Document.
2030      * 
2031      * This method returns the document type of payment detail of the
2032      * Disbursement Voucher Document. It is invoked when the user clicks
2033      * on the disbursement info button on the Pre-Disbursement Processor
2034      * Status tab on Disbursement Voucher Document.
2035      * 
2036      * 
2037      * @return
2038      */
2039     public String getPaymentDetailDocumentType() {
2040         return DisbursementVoucherConstants.DOCUMENT_TYPE_CHECKACH;
2041     }
2042 }