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