View Javadoc
1   /*
2    * Copyright 2007 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.fp.batch.service.impl;
17  
18  import java.sql.Timestamp;
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.Date;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Set;
26  
27  import org.apache.commons.lang.StringUtils;
28  import org.apache.commons.lang.WordUtils;
29  import org.kuali.ole.fp.batch.DvToPdpExtractStep;
30  import org.kuali.ole.fp.batch.service.DisbursementVoucherExtractService;
31  import org.kuali.ole.fp.businessobject.DisbursementVoucherPayeeDetail;
32  import org.kuali.ole.fp.dataaccess.DisbursementVoucherDao;
33  import org.kuali.ole.fp.document.DisbursementVoucherConstants;
34  import org.kuali.ole.fp.document.DisbursementVoucherDocument;
35  import org.kuali.ole.pdp.PdpConstants;
36  import org.kuali.ole.pdp.PdpParameterConstants;
37  import org.kuali.ole.pdp.businessobject.Batch;
38  import org.kuali.ole.pdp.businessobject.CustomerProfile;
39  import org.kuali.ole.pdp.businessobject.PaymentAccountDetail;
40  import org.kuali.ole.pdp.businessobject.PaymentDetail;
41  import org.kuali.ole.pdp.businessobject.PaymentGroup;
42  import org.kuali.ole.pdp.businessobject.PaymentNoteText;
43  import org.kuali.ole.pdp.service.CustomerProfileService;
44  import org.kuali.ole.pdp.service.PaymentFileService;
45  import org.kuali.ole.pdp.service.PaymentGroupService;
46  import org.kuali.ole.pdp.service.PdpEmailService;
47  import org.kuali.ole.select.document.OleDisbursementVoucherDocument;
48  import org.kuali.ole.sys.OLEConstants;
49  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry;
50  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper;
51  import org.kuali.ole.sys.businessobject.SourceAccountingLine;
52  import org.kuali.ole.sys.context.SpringContext;
53  import org.kuali.ole.sys.document.service.FinancialSystemDocumentService;
54  import org.kuali.ole.sys.document.validation.event.AccountingDocumentSaveWithNoLedgerEntryGenerationEvent;
55  import org.kuali.ole.sys.service.GeneralLedgerPendingEntryService;
56  import org.kuali.ole.sys.service.impl.OleParameterConstants;
57  import org.kuali.ole.vnd.businessobject.VendorDetail;
58  import org.kuali.ole.vnd.document.service.VendorService;
59  import org.kuali.rice.core.api.datetime.DateTimeService;
60  import org.kuali.rice.core.api.parameter.ParameterEvaluator;
61  import org.kuali.rice.core.api.parameter.ParameterEvaluatorService;
62  import org.kuali.rice.core.api.util.type.KualiDecimal;
63  import org.kuali.rice.core.api.util.type.KualiInteger;
64  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
65  import org.kuali.rice.kew.api.exception.WorkflowException;
66  import org.kuali.rice.kim.api.identity.Person;
67  import org.kuali.rice.kim.api.identity.PersonService;
68  import org.kuali.rice.krad.service.BusinessObjectService;
69  import org.kuali.rice.krad.service.DocumentService;
70  import org.kuali.rice.krad.util.ObjectUtils;
71  import org.springframework.transaction.annotation.Transactional;
72  
73  /**
74   * This is the default implementation of the DisbursementVoucherExtractService interface.
75   */
76  @Transactional
77  public class DisbursementVoucherExtractServiceImpl implements DisbursementVoucherExtractService {
78      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DisbursementVoucherExtractServiceImpl.class);
79  
80      private PersonService personService;
81      private ParameterService parameterService;
82      private DisbursementVoucherDao disbursementVoucherDao;
83      private DateTimeService dateTimeService;
84      private CustomerProfileService customerProfileService;
85      private PaymentFileService paymentFileService;
86      private PaymentGroupService paymentGroupService;
87      private BusinessObjectService businessObjectService;
88      private PdpEmailService paymentFileEmailService;
89      private int maxNoteLines;
90  
91      // This should only be set to true when testing this system. Setting this to true will run the code but
92      // won't set the doc status to extracted
93      boolean testMode = false;
94  
95      /**
96       * This method extracts all payments from a disbursement voucher with a status code of "A" and uploads them as a batch for
97       * processing.
98       *
99       * @return Always returns true if the method completes.
100      * @see org.kuali.ole.fp.batch.service.DisbursementVoucherExtractService#extractPayments()
101      */
102     @Override
103     public boolean extractPayments() {
104         LOG.debug("extractPayments() started");
105 
106         Date processRunDate = dateTimeService.getCurrentDate();
107 
108         String noteLines = parameterService.getParameterValueAsString(OleParameterConstants.PRE_DISBURSEMENT_ALL.class, PdpParameterConstants.MAX_NOTE_LINES);
109 
110         try {
111             maxNoteLines = Integer.parseInt(noteLines);
112         }
113         catch (NumberFormatException nfe) {
114             throw new IllegalArgumentException("Invalid Max Notes Lines parameter");
115         }
116 
117         Person uuser = getPersonService().getPersonByPrincipalName(OLEConstants.SYSTEM_USER);
118         if (uuser == null) {
119             if (LOG.isDebugEnabled()) {
120                 LOG.debug("extractPayments() Unable to find user " + OLEConstants.SYSTEM_USER);
121             }
122             throw new IllegalArgumentException("Unable to find user " + OLEConstants.SYSTEM_USER);
123         }
124 
125         // Get a list of campuses that have documents with an 'A' (approved) status.
126         Set<String> campusList = getCampusListByDocumentStatusCode(DisbursementVoucherConstants.DocumentStatusCodes.APPROVED);
127 
128         // Process each campus one at a time
129         for (String campusCode : campusList) {
130             extractPaymentsForCampus(campusCode, uuser, processRunDate);
131         }
132 
133         return true;
134     }
135 
136     /**
137      * Pulls all disbursement vouchers with status of "A" and marked for immediate payment from the database and builds payment records for them
138      * @see org.kuali.ole.fp.batch.service.DisbursementVoucherExtractService#extractImmediatePayments()
139      */
140     @Override
141     public void extractImmediatePayments() {
142         LOG.debug("extractImmediatePayments() started");
143 
144         Date processRunDate = dateTimeService.getCurrentDate();
145 
146         String noteLines = parameterService.getParameterValueAsString(OleParameterConstants.PRE_DISBURSEMENT_ALL.class, PdpParameterConstants.MAX_NOTE_LINES);
147 
148         try {
149             maxNoteLines = Integer.parseInt(noteLines);
150         }
151         catch (NumberFormatException nfe) {
152             throw new IllegalArgumentException("Invalid Max Notes Lines parameter");
153         }
154 
155         Person uuser = getPersonService().getPersonByPrincipalName(OLEConstants.SYSTEM_USER);
156         if (uuser == null) {
157             LOG.debug("extractPayments() Unable to find user " + OLEConstants.SYSTEM_USER);
158             throw new IllegalArgumentException("Unable to find user " + OLEConstants.SYSTEM_USER);
159         }
160 
161         // Get a list of campuses that have documents with an 'A' (approved) status.
162         Set<String> campusList = getImmediatesCampusListByDocumentStatusCode(DisbursementVoucherConstants.DocumentStatusCodes.APPROVED);
163 
164         // Process each campus one at a time
165         for (String campusCode : campusList) {
166             extractImmediatePaymentsForCampus(campusCode, uuser, processRunDate);
167         }
168     }
169 
170     /**
171      * This method extracts all outstanding payments from all the disbursement vouchers in approved status for a given campus and
172      * adds these payments to a batch file that is uploaded for processing.
173      *
174      * @param campusCode The id code of the campus the payments will be retrieved for.
175      * @param user The user object used when creating the batch file to upload with outstanding payments.
176      * @param processRunDate This is the date that the batch file is created, often this value will be today's date.
177      */
178     protected void extractPaymentsForCampus(String campusCode, Person user, Date processRunDate) {
179         if (LOG.isDebugEnabled()) {
180             LOG.debug("extractPaymentsForCampus() started for campus: " + campusCode);
181         }
182 
183         Batch batch = createBatch(campusCode, user, processRunDate);
184         Integer count = 0;
185         KualiDecimal totalAmount = KualiDecimal.ZERO;
186 
187         Collection<DisbursementVoucherDocument> dvd = getListByDocumentStatusCodeCampus(DisbursementVoucherConstants.DocumentStatusCodes.APPROVED, campusCode, false);
188         for (DisbursementVoucherDocument document : dvd) {
189             addPayment(document, batch, processRunDate, false);
190             count++;
191             totalAmount = totalAmount.add(document.getDisbVchrCheckTotalAmount());
192         }
193 
194         batch.setPaymentCount(new KualiInteger(count));
195         batch.setPaymentTotalAmount(totalAmount);
196 
197         businessObjectService.save(batch);
198         paymentFileEmailService.sendLoadEmail(batch);
199     }
200 
201     /**
202      * Builds payment batch for Disbursement Vouchers marked as immediate
203      * @param campusCode the campus code the disbursement vouchers should be associated with
204      * @param user the user responsible building the payment batch (typically the System User, kfs)
205      * @param processRunDate the time that the job to build immediate payments is run
206      */
207     protected void extractImmediatePaymentsForCampus(String campusCode, Person user, Date processRunDate) {
208         LOG.debug("extractImmediatesPaymentsForCampus() started for campus: " + campusCode);
209 
210         Batch batch = createBatch(campusCode, user, processRunDate);
211         Integer count = 0;
212         KualiDecimal totalAmount = KualiDecimal.ZERO;
213 
214         Collection<DisbursementVoucherDocument> dvd = getListByDocumentStatusCodeCampus(DisbursementVoucherConstants.DocumentStatusCodes.APPROVED, campusCode, true);
215         for (DisbursementVoucherDocument document : dvd) {
216             addPayment(document, batch, processRunDate, false);
217             count++;
218             totalAmount = totalAmount.add(document.getDisbVchrCheckTotalAmount());
219         }
220 
221         batch.setPaymentCount(new KualiInteger(count));
222         batch.setPaymentTotalAmount(totalAmount);
223 
224         businessObjectService.save(batch);
225         paymentFileEmailService.sendLoadEmail(batch);
226     }
227 
228     /**
229      * This method creates a payment group from the disbursement voucher and batch provided and persists that group to the database.
230      *
231      * @param document The document used to build a payment group detail.
232      * @param batch The batch file used to build a payment group and detail.
233      * @param processRunDate The date the batch file is to post.
234      */
235     protected void addPayment(DisbursementVoucherDocument document, Batch batch, Date processRunDate, boolean immediate) {
236         LOG.debug("addPayment() started");
237 
238         PaymentGroup pg = buildPaymentGroup(document, batch);
239         if (immediate) {
240             pg.setProcessImmediate(Boolean.TRUE);
241         }
242         PaymentDetail pd = buildPaymentDetail(document, batch, processRunDate);
243 
244         pd.setPaymentGroup(pg);
245         pg.addPaymentDetails(pd);
246         this.businessObjectService.save(pg);
247 
248         if (!testMode) {
249             try {
250                 document.getFinancialSystemDocumentHeader().setFinancialDocumentStatusCode(DisbursementVoucherConstants.DocumentStatusCodes.EXTRACTED);
251                 document.setExtractDate(new java.sql.Date(processRunDate.getTime()));
252                 SpringContext.getBean(DocumentService.class).saveDocument(document, AccountingDocumentSaveWithNoLedgerEntryGenerationEvent.class);
253             }
254             catch (WorkflowException we) {
255                 LOG.error("Could not save disbursement voucher document #" + document.getDocumentNumber() + ": " + we);
256                 throw new RuntimeException(we);
257             }
258         }
259     }
260 
261     /**
262      * This method creates a PaymentGroup from the disbursement voucher and batch provided. The values provided by the disbursement
263      * voucher are used to assign appropriate attributes to the payment group, including address and vendor detail information. The
264      * information added to the payment group includes tax encoding to identify if taxes should be taken out of the payment. The tax
265      * rules vary depending on the type of individual or entity being paid
266      *
267      * @param document The document to be used for retrieving the information about the vendor being paid.
268      * @param batch The batch that the payment group will be associated with.
269      * @return A PaymentGroup object fully populated with all the values necessary to make a payment.
270      */
271     protected PaymentGroup buildPaymentGroup(DisbursementVoucherDocument document, Batch batch) {
272         LOG.debug("buildPaymentGroup() started");
273 
274         PaymentGroup pg = new PaymentGroup();
275         pg.setBatch(batch);
276         pg.setCombineGroups(Boolean.TRUE);
277         pg.setCampusAddress(Boolean.FALSE);
278 
279         DisbursementVoucherPayeeDetail pd = document.getDvPayeeDetail();
280         String rc = pd.getDisbVchrPaymentReasonCode();
281 
282         // If the payee is an employee, set these flags accordingly
283         if ((document.getDvPayeeDetail().isVendor() && SpringContext.getBean(VendorService.class).isVendorInstitutionEmployee(pd.getDisbVchrVendorHeaderIdNumberAsInteger())) || document.getDvPayeeDetail().isEmployee()) {
284             pg.setEmployeeIndicator(Boolean.TRUE);
285             pg.setPayeeIdTypeCd(PdpConstants.PayeeIdTypeCodes.EMPLOYEE);
286             //Commented for the jira issue OLE-3415
287 //            pg.setTaxablePayment(
288 //                    !/*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.RESEARCH_PAYMENT_REASONS_PARM_NM, rc).evaluationSucceeds()
289 //                        && !parameterService.getParameterValueAsString(DisbursementVoucherDocument.class, DisbursementVoucherConstants.PAYMENT_REASON_CODE_RENTAL_PAYMENT_PARM_NM).equals(rc)
290 //                        && !parameterService.getParameterValueAsString(DisbursementVoucherDocument.class, DisbursementVoucherConstants.PAYMENT_REASON_CODE_ROYALTIES_PARM_NM).equals(rc));
291         }
292         // Payee is not an employee
293         else {
294 
295             // These are taxable
296             VendorDetail vendDetail = SpringContext.getBean(VendorService.class).getVendorDetail(pd.getDisbVchrVendorHeaderIdNumberAsInteger(), pd.getDisbVchrVendorDetailAssignedIdNumberAsInteger());
297             String vendorOwnerCode = vendDetail.getVendorHeader().getVendorOwnershipCode();
298             String vendorOwnerCategoryCode = vendDetail.getVendorHeader().getVendorOwnershipCategoryCode();
299             String payReasonCode = pd.getDisbVchrPaymentReasonCode();
300 
301             pg.setPayeeIdTypeCd(PdpConstants.PayeeIdTypeCodes.VENDOR_ID);
302 
303             // Assume it is not taxable until proven otherwise
304             pg.setTaxablePayment(Boolean.FALSE);
305             pg.setPayeeOwnerCd(vendorOwnerCode);
306 
307             ParameterEvaluator parameterEvaluator1 = /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DvToPdpExtractStep.class, PdpParameterConstants.TAXABLE_PAYMENT_REASON_CODES_BY_OWNERSHIP_CODES_PARAMETER_NAME, PdpParameterConstants.NON_TAXABLE_PAYMENT_REASON_CODES_BY_OWNERSHIP_CODES_PARAMETER_NAME, vendorOwnerCode, payReasonCode);
308             ParameterEvaluator parameterEvaluator2 = /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DvToPdpExtractStep.class, PdpParameterConstants.TAXABLE_PAYMENT_REASON_CODES_BY_CORPORATION_OWNERSHIP_TYPE_CATEGORY_PARAMETER_NAME, PdpParameterConstants.NON_TAXABLE_PAYMENT_REASON_CODES_BY_CORPORATION_OWNERSHIP_TYPE_CATEGORY_PARAMETER_NAME, vendorOwnerCategoryCode, payReasonCode);
309 
310             if ( parameterEvaluator1.evaluationSucceeds() ) {
311                 pg.setTaxablePayment(Boolean.TRUE);
312             }
313             else if (this.parameterService.getParameterValueAsString(DvToPdpExtractStep.class, PdpParameterConstants.CORPORATION_OWNERSHIP_TYPE_PARAMETER_NAME).equals("CP") &&
314                       StringUtils.isEmpty(vendorOwnerCategoryCode) &&
315                       /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DvToPdpExtractStep.class, PdpParameterConstants.TAXABLE_PAYMENT_REASON_CODES_FOR_BLANK_CORPORATION_OWNERSHIP_TYPE_CATEGORIES_PARAMETER_NAME, payReasonCode).evaluationSucceeds()) {
316                 pg.setTaxablePayment(Boolean.TRUE);
317             }
318             else if (this.parameterService.getParameterValueAsString(DvToPdpExtractStep.class, PdpParameterConstants.CORPORATION_OWNERSHIP_TYPE_PARAMETER_NAME).equals("CP")
319                         && !StringUtils.isEmpty(vendorOwnerCategoryCode)
320                         && parameterEvaluator2.evaluationSucceeds() ) {
321                 pg.setTaxablePayment(Boolean.TRUE);
322             }
323         }
324 
325         pg.setCity(pd.getDisbVchrPayeeCityName());
326         pg.setCountry(pd.getDisbVchrPayeeCountryCode());
327         pg.setLine1Address(pd.getDisbVchrPayeeLine1Addr());
328         pg.setLine2Address(pd.getDisbVchrPayeeLine2Addr());
329         pg.setPayeeName(pd.getDisbVchrPayeePersonName());
330         pg.setPayeeId(pd.getDisbVchrPayeeIdNumber());
331         pg.setState(pd.getDisbVchrPayeeStateCode());
332         pg.setZipCd(pd.getDisbVchrPayeeZipCode());
333         pg.setPaymentDate(document.getDisbursementVoucherDueDate());
334 
335         // It doesn't look like the DV has a way to do immediate processes
336         pg.setProcessImmediate(Boolean.FALSE);
337         pg.setPymtAttachment(document.isDisbVchrAttachmentCode());
338         pg.setPymtSpecialHandling(document.isDisbVchrSpecialHandlingCode());
339         pg.setNraPayment(pd.isDisbVchrAlienPaymentCode());
340 
341         pg.setBankCode(document.getDisbVchrBankCode());
342         pg.setPaymentStatusCode(OLEConstants.PdpConstants.PAYMENT_OPEN_STATUS_CODE);
343 
344         return pg;
345     }
346 
347     /**
348      * This method builds a payment detail object from the disbursement voucher document provided and links that detail file to the
349      * batch and process run date given.
350      *
351      * @param document The disbursement voucher document to retrieve payment information from to populate the PaymentDetail.
352      * @param batch The batch file associated with the payment.
353      * @param processRunDate The date of the payment detail invoice.
354      * @return A fully populated PaymentDetail instance.
355      */
356     protected PaymentDetail buildPaymentDetail(DisbursementVoucherDocument document, Batch batch, Date processRunDate) {
357         LOG.debug("buildPaymentDetail() started");
358 
359         PaymentDetail pd = new PaymentDetail();
360         if (StringUtils.isNotEmpty(document.getDocumentHeader().getOrganizationDocumentNumber())) {
361             pd.setOrganizationDocNbr(document.getDocumentHeader().getOrganizationDocumentNumber());
362         }
363         if(((OleDisbursementVoucherDocument) document).getInvoiceNumber() != null) {
364             pd.setInvoiceNbr(((OleDisbursementVoucherDocument) document).getInvoiceNumber());
365         }
366         pd.setCustPaymentDocNbr(document.getDocumentNumber());
367         pd.setInvoiceDate(new java.sql.Date(processRunDate.getTime()));
368         pd.setOrigInvoiceAmount(document.getDisbVchrCheckTotalAmount());
369         pd.setInvTotDiscountAmount(KualiDecimal.ZERO);
370         pd.setInvTotOtherCreditAmount(KualiDecimal.ZERO);
371         pd.setInvTotOtherDebitAmount(KualiDecimal.ZERO);
372         pd.setInvTotShipAmount(KualiDecimal.ZERO);
373         pd.setNetPaymentAmount(document.getDisbVchrCheckTotalAmount());
374         pd.setPrimaryCancelledPayment(Boolean.FALSE);
375         pd.setFinancialDocumentTypeCode(DisbursementVoucherConstants.DOCUMENT_TYPE_CHECKACH);
376         pd.setFinancialSystemOriginCode(OLEConstants.ORIGIN_CODE_KUALI);
377 
378         if(document.getDisbVchrPaymentMethodCode().equalsIgnoreCase(DisbursementVoucherConstants.PAYMENT_METHOD_CHECK)) {
379             pd.setPaymentMethodCode("Check");
380         }
381         else if(document.getDisbVchrPaymentMethodCode().equalsIgnoreCase(DisbursementVoucherConstants.PAYMENT_METHOD_WIRE)) {
382             pd.setPaymentMethodCode("Wire");
383         }
384         else if(document.getDisbVchrPaymentMethodCode().equalsIgnoreCase(DisbursementVoucherConstants.PAYMENT_METHOD_DRAFT)) {
385             pd.setPaymentMethodCode("Draft");
386         }
387 
388         // Handle accounts
389         for (Iterator iter = document.getSourceAccountingLines().iterator(); iter.hasNext();) {
390             SourceAccountingLine sal = (SourceAccountingLine) iter.next();
391 
392             PaymentAccountDetail pad = new PaymentAccountDetail();
393             pad.setFinChartCode(sal.getChartOfAccountsCode());
394             pad.setAccountNbr(sal.getAccountNumber());
395             if (StringUtils.isNotEmpty(sal.getSubAccountNumber())) {
396                 pad.setSubAccountNbr(sal.getSubAccountNumber());
397             }
398             else {
399                 pad.setSubAccountNbr(OLEConstants.getDashSubAccountNumber());
400             }
401             pad.setFinObjectCode(sal.getFinancialObjectCode());
402             if (StringUtils.isNotEmpty(sal.getFinancialSubObjectCode())) {
403                 pad.setFinSubObjectCode(sal.getFinancialSubObjectCode());
404             }
405             else {
406                 pad.setFinSubObjectCode(OLEConstants.getDashFinancialSubObjectCode());
407             }
408             if (StringUtils.isNotEmpty(sal.getOrganizationReferenceId())) {
409                 pad.setOrgReferenceId(sal.getOrganizationReferenceId());
410             }
411             if (StringUtils.isNotEmpty(sal.getProjectCode())) {
412                 pad.setProjectCode(sal.getProjectCode());
413             }
414             else {
415                 pad.setProjectCode(OLEConstants.getDashProjectCode());
416             }
417             pad.setAccountNetAmount(sal.getAmount());
418             pd.addAccountDetail(pad);
419         }
420 
421         // Handle notes
422         DisbursementVoucherPayeeDetail dvpd = document.getDvPayeeDetail();
423 
424         int line = 0;
425         PaymentNoteText pnt = new PaymentNoteText();
426         pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
427         pnt.setCustomerNoteText("Info: " + document.getDisbVchrContactPersonName() + " " + document.getDisbVchrContactPhoneNumber());
428         pd.addNote(pnt);
429 
430         String dvSpecialHandlingPersonName = null;
431         String dvSpecialHandlingLine1Address = null;
432         String dvSpecialHandlingLine2Address = null;
433         String dvSpecialHandlingCity = null;
434         String dvSpecialHandlingState = null;
435         String dvSpecialHandlingZip = null;
436 
437         dvSpecialHandlingPersonName = dvpd.getDisbVchrSpecialHandlingPersonName();
438         dvSpecialHandlingLine1Address = dvpd.getDisbVchrSpecialHandlingLine1Addr();
439         dvSpecialHandlingLine2Address = dvpd.getDisbVchrSpecialHandlingLine2Addr();
440         dvSpecialHandlingCity = dvpd.getDisbVchrSpecialHandlingCityName();
441         dvSpecialHandlingState = dvpd.getDisbVchrSpecialHandlingStateCode();
442         dvSpecialHandlingZip = dvpd.getDisbVchrSpecialHandlingZipCode();
443 
444         if (StringUtils.isNotEmpty(dvSpecialHandlingPersonName)) {
445             pnt = new PaymentNoteText();
446             pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
447             pnt.setCustomerNoteText("Send Check To: " + dvSpecialHandlingPersonName);
448             if (LOG.isDebugEnabled()) {
449                 LOG.debug("Creating special handling person name note: "+pnt.getCustomerNoteText());
450             }
451             pd.addNote(pnt);
452         }
453         if (StringUtils.isNotEmpty(dvSpecialHandlingLine1Address)) {
454             pnt = new PaymentNoteText();
455             pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
456             pnt.setCustomerNoteText(dvSpecialHandlingLine1Address);
457             if (LOG.isDebugEnabled()) {
458                 LOG.debug("Creating special handling address 1 note: "+pnt.getCustomerNoteText());
459             }
460             pd.addNote(pnt);
461         }
462         if (StringUtils.isNotEmpty(dvSpecialHandlingLine2Address)) {
463             pnt = new PaymentNoteText();
464             pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
465             pnt.setCustomerNoteText(dvSpecialHandlingLine2Address);
466             if (LOG.isDebugEnabled()) {
467                 LOG.debug("Creating special handling address 2 note: "+pnt.getCustomerNoteText());
468             }
469             pd.addNote(pnt);
470         }
471         if (StringUtils.isNotEmpty(dvSpecialHandlingCity)) {
472             pnt = new PaymentNoteText();
473             pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
474             pnt.setCustomerNoteText(dvSpecialHandlingCity + ", " + dvSpecialHandlingState + " " + dvSpecialHandlingZip);
475             if (LOG.isDebugEnabled()) {
476                 LOG.debug("Creating special handling city note: "+pnt.getCustomerNoteText());
477             }
478             pd.addNote(pnt);
479         }
480         if (document.isDisbVchrAttachmentCode()) {
481             pnt = new PaymentNoteText();
482             pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
483             pnt.setCustomerNoteText("Attachment Included");
484             if (LOG.isDebugEnabled()) {
485                 LOG.debug("create attachment note: "+pnt.getCustomerNoteText());
486             }
487             pd.addNote(pnt);
488         }
489 
490         String paymentReasonCode = dvpd.getDisbVchrPaymentReasonCode();
491         //Commented for the jira issue OLE-3415
492         /*if (SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.NONEMPLOYEE_TRAVEL_PAY_REASONS_PARM_NM, paymentReasonCode).evaluationSucceeds()) {
493             DisbursementVoucherNonEmployeeTravel dvnet = document.getDvNonEmployeeTravel();
494 
495             pnt = new PaymentNoteText();
496             pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
497             pnt.setCustomerNoteText("Reimbursement associated with " + dvnet.getDisbVchrServicePerformedDesc());
498             if (LOG.isDebugEnabled()) {
499                 LOG.debug("Creating non employee travel notes: "+pnt.getCustomerNoteText());
500             }
501             pd.addNote(pnt);
502 
503             pnt = new PaymentNoteText();
504             pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
505             pnt.setCustomerNoteText("The total per diem amount for your daily expenses is " + dvnet.getDisbVchrPerdiemCalculatedAmt());
506             if (LOG.isDebugEnabled()) {
507                 LOG.debug("Creating non employee travel notes: "+pnt.getCustomerNoteText());
508             }
509             pd.addNote(pnt);
510 
511             if (dvnet.getDisbVchrPersonalCarAmount() != null && dvnet.getDisbVchrPersonalCarAmount().compareTo(KualiDecimal.ZERO) != 0) {
512                 pnt = new PaymentNoteText();
513                 pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
514                 pnt.setCustomerNoteText("The total dollar amount for your vehicle mileage is " + dvnet.getDisbVchrPersonalCarAmount());
515                 if (LOG.isDebugEnabled()) {
516                     LOG.debug("Creating non employee travel vehicle note: "+pnt.getCustomerNoteText());
517                 }
518                 pd.addNote(pnt);
519 
520                 for (Iterator iter = dvnet.getDvNonEmployeeExpenses().iterator(); iter.hasNext();) {
521                     DisbursementVoucherNonEmployeeExpense exp = (DisbursementVoucherNonEmployeeExpense) iter.next();
522 
523                     if (line < (maxNoteLines - 8)) {
524                         pnt = new PaymentNoteText();
525                         pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
526                         pnt.setCustomerNoteText(exp.getDisbVchrExpenseCompanyName() + " " + exp.getDisbVchrExpenseAmount());
527                         if (LOG.isDebugEnabled()) {
528                             LOG.debug("Creating non employee travel expense note: "+pnt.getCustomerNoteText());
529                         }
530                         pd.addNote(pnt);
531                     }
532                 }
533             }
534         }
535          else if (SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(DisbursementVoucherDocument.class, DisbursementVoucherConstants.PREPAID_TRAVEL_PAYMENT_REASONS_PARM_NM, paymentReasonCode).evaluationSucceeds()) {
536             pnt = new PaymentNoteText();
537             pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
538             pnt.setCustomerNoteText("Payment is for the following individuals/charges:");
539             pd.addNote(pnt);
540             if (LOG.isDebugEnabled()) {
541                 LOG.info("Creating prepaid travel note note: "+pnt.getCustomerNoteText());
542             }
543 
544             DisbursementVoucherPreConferenceDetail dvpcd = document.getDvPreConferenceDetail();
545 
546             for (Iterator iter = dvpcd.getDvPreConferenceRegistrants().iterator(); iter.hasNext();) {
547                 DisbursementVoucherPreConferenceRegistrant dvpcr = (DisbursementVoucherPreConferenceRegistrant) iter.next();
548 
549                 if (line < (maxNoteLines - 8)) {
550                     pnt = new PaymentNoteText();
551                     pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
552                     pnt.setCustomerNoteText(dvpcr.getDvConferenceRegistrantName() + " " + dvpcr.getDisbVchrExpenseAmount());
553                     if (LOG.isDebugEnabled()) {
554                         LOG.debug("Creating pre-paid conference registrants note: "+pnt.getCustomerNoteText());
555                     }
556                     pd.addNote(pnt);
557                 }
558             }
559         }*/
560 
561         // Get the original, raw form, note text from the DV document.
562         String text = document.getDisbVchrCheckStubText();
563         if (text != null && text.length() > 0) {
564 
565             // The WordUtils should be sufficient for the majority of cases.  This method will
566             // word wrap the whole string based on the MAX_NOTE_LINE_SIZE, separating each wrapped
567             // word by a newline character.  The 'wrap' method adds line feeds to the end causing
568             // the character length to exceed the max length by 1, hence the need for the replace
569             // method before splitting.
570             String   wrappedText = WordUtils.wrap(text, DisbursementVoucherConstants.MAX_NOTE_LINE_SIZE);
571             String[] noteLines   = wrappedText.replaceAll("[\r]", "").split("\\n");
572 
573             // Loop through all the note lines.
574             for (String noteLine : noteLines) {
575                 if (line < (maxNoteLines - 3) && !StringUtils.isEmpty(noteLine)) {
576 
577                     // This should only happen if we encounter a word that is greater than the max length.
578                     // The only concern I have for this occurring is with URLs/email addresses.
579                     if (noteLine.length() > DisbursementVoucherConstants.MAX_NOTE_LINE_SIZE) {
580                         for (String choppedWord : chopWord(noteLine, DisbursementVoucherConstants.MAX_NOTE_LINE_SIZE)) {
581 
582                             // Make sure we're still under the maximum number of note lines.
583                             if (line < (maxNoteLines - 3) && !StringUtils.isEmpty(choppedWord)) {
584                                 pnt = new PaymentNoteText();
585                                 pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
586                                 pnt.setCustomerNoteText(choppedWord.replaceAll("\\n", "").trim());
587                             }
588                             // We can't add any additional note lines, or we'll exceed the maximum, therefore
589                             // just break out of the loop early - there's nothing left to do.
590                             else {
591                                 break;
592                             }
593                         }
594                     }
595                     // This should be the most common case.  Simply create a new PaymentNoteText,
596                     // add the line at the correct line location.
597                     else {
598                         pnt = new PaymentNoteText();
599                         pnt.setCustomerNoteLineNbr(new KualiInteger(line++));
600                         pnt.setCustomerNoteText(noteLine.replaceAll("\\n", "").trim());
601                     }
602 
603                     // Logging...
604                     if (LOG.isDebugEnabled()) {
605                         LOG.debug("Creating check stub text note: " + pnt.getCustomerNoteText());
606                     }
607                     pd.addNote(pnt);
608                 }
609             }
610         }
611 
612         return pd;
613     }
614 
615     /**
616      * This method will take a word and simply chop into smaller
617      * text segments that satisfy the limit requirements.  All words
618      * brute force chopped, with no regard to preserving whole words.
619      *
620      * For example:
621      *
622      *      "Java is a fun programming language!"
623      *
624      * Might be chopped into:
625      *
626      *      "Java is a fun prog"
627      *      "ramming language!"
628      *
629      * @param word The word that needs chopping
630      * @param limit Number of character that should represent a chopped word
631      * @return String [] of chopped words
632      */
633     private String [] chopWord(String word, int limit)
634     {
635         StringBuilder builder = new StringBuilder();
636         if (word != null && word.trim().length() > 0) {
637 
638             char[] chars = word.toCharArray();
639             int index = 0;
640 
641             // First process all the words that fit into the limit.
642             for (int i = 0; i < chars.length/limit; i++) {
643                 builder.append(String.copyValueOf(chars, index, limit));
644                 builder.append("\n");
645 
646                 index += limit;
647             }
648 
649             // Not all words will fit perfectly into the limit amount, so
650             // calculate the modulus value to determine any remaining characters.
651             int modValue =  chars.length%limit;
652             if (modValue > 0) {
653                 builder.append(String.copyValueOf(chars, index, modValue));
654             }
655 
656         }
657 
658         // Split the chopped words into individual segments.
659         return builder.toString().split("\\n");
660     }
661 
662     /**
663      * This method creates a Batch instance and populates it with the information provided.
664      *
665      * @param campusCode The campus code used to retrieve a customer profile to be set on the batch.
666      * @param user The user who submitted the batch.
667      * @param processRunDate The date the batch was submitted and the date the customer profile was generated.
668      * @return A fully populated batch instance.
669      */
670     protected Batch createBatch(String campusCode, Person user, Date processRunDate) {
671         String orgCode = parameterService.getParameterValueAsString(DisbursementVoucherDocument.class, DisbursementVoucherConstants.DvPdpExtractGroup.DV_PDP_ORG_CODE);
672         String subUnitCode = parameterService.getParameterValueAsString(DisbursementVoucherDocument.class, DisbursementVoucherConstants.DvPdpExtractGroup.DV_PDP_SBUNT_CODE);
673         CustomerProfile customer = customerProfileService.get(campusCode, orgCode, subUnitCode);
674         if (customer == null) {
675             throw new IllegalArgumentException("Unable to find customer profile for " + campusCode + "/" + orgCode + "/" + subUnitCode);
676         }
677 
678         // Create the group for this campus
679         Batch batch = new Batch();
680         batch.setCustomerProfile(customer);
681         batch.setCustomerFileCreateTimestamp(new Timestamp(processRunDate.getTime()));
682         batch.setFileProcessTimestamp(new Timestamp(processRunDate.getTime()));
683         batch.setPaymentFileName(OLEConstants.DISBURSEMENT_VOUCHER_PDP_EXTRACT_FILE_NAME);
684         batch.setSubmiterUserId(user.getPrincipalId());
685 
686         // Set these for now, we will update them later
687         batch.setPaymentCount(KualiInteger.ZERO);
688         batch.setPaymentTotalAmount(KualiDecimal.ZERO);
689 
690         businessObjectService.save(batch);
691 
692         return batch;
693     }
694 
695     /**
696      * This method retrieves a collection of campus instances representing all the campuses which currently have disbursement
697      * vouchers with the status code provided.
698      *
699      * @param statusCode The status code to retrieve disbursement vouchers by.
700      * @return A collection of campus codes of all the campuses with disbursement vouchers in the status given.
701      */
702     protected Set<String> getCampusListByDocumentStatusCode(String statusCode) {
703         LOG.debug("getCampusListByDocumentStatusCode() started");
704 
705         Set<String> campusSet = new HashSet<String>();
706 
707         Collection<DisbursementVoucherDocument> docs = disbursementVoucherDao.getDocumentsByHeaderStatus(statusCode, false);
708         for (DisbursementVoucherDocument element : docs) {
709             String dvdCampusCode = element.getCampusCode();
710             campusSet.add(dvdCampusCode);
711         }
712 
713         return campusSet;
714     }
715 
716     /**
717      * Retrieves a list of campuses which have Disbursement Vouchers ready to be process which are marked for immediate processing
718      * @param statusCode the status code of the documents to retrieve
719      * @return the Set of campuses which have DV which are up for immediate disbursement
720      */
721     protected Set<String> getImmediatesCampusListByDocumentStatusCode(String statusCode) {
722         LOG.debug("getCampusListByDocumentStatusCode() started");
723 
724         Set<String> campusSet = new HashSet<String>();
725 
726         Collection<DisbursementVoucherDocument> docs = disbursementVoucherDao.getDocumentsByHeaderStatus(statusCode, true);
727         for (DisbursementVoucherDocument element : docs) {
728 
729             final String dvdCampusCode = element.getCampusCode();
730             campusSet.add(dvdCampusCode);
731         }
732 
733         return campusSet;
734     }
735 
736     /**
737      * This method retrieves a list of disbursement voucher documents that are in the status provided for the campus code given.
738      *
739      * @param statusCode The status of the disbursement vouchers to be retrieved.
740      * @param campusCode The campus code that the disbursement vouchers will be associated with.
741      * @param immediatesOnly only retrieve Disbursement Vouchers marked for immediate payment
742      * @return A collection of disbursement voucher objects that meet the search criteria given.
743      */
744     protected Collection<DisbursementVoucherDocument> getListByDocumentStatusCodeCampus(String statusCode, String campusCode, boolean immediatesOnly) {
745         LOG.debug("getListByDocumentStatusCodeCampus() started");
746 
747         Collection<DisbursementVoucherDocument> list = new ArrayList<DisbursementVoucherDocument>();
748 
749         try {
750             Collection<DisbursementVoucherDocument> docs = SpringContext.getBean(FinancialSystemDocumentService.class).findByDocumentHeaderStatusCode(DisbursementVoucherDocument.class, statusCode);
751             for (DisbursementVoucherDocument element : docs) {
752                 String dvdCampusCode = element.getCampusCode();
753 
754                 if (dvdCampusCode.equals(campusCode) && DisbursementVoucherConstants.PAYMENT_METHOD_CHECK.equals(element.getDisbVchrPaymentMethodCode())) {
755                     if ((immediatesOnly && element.isImmediatePaymentIndicator()) || !immediatesOnly) {
756                     list.add(element);
757                 }
758             }
759         }
760         }
761         catch (WorkflowException we) {
762             LOG.error("Could not load Disbursement Voucher Documents with status code = " + statusCode + ": " + we);
763             throw new RuntimeException(we);
764         }
765 
766         return list;
767     }
768 
769     /**
770      * This cancels the disbursement voucher
771      *
772      * @param dv the disbursement voucher document to cancel
773      * @param processDate the date of the cancelation
774      * @see org.kuali.ole.fp.batch.service.DisbursementVoucherExtractService#cancelExtractedDisbursementVoucher(org.kuali.ole.fp.document.DisbursementVoucherDocument, java.sql.Date)
775      */
776     @Override
777     public void cancelExtractedDisbursementVoucher(DisbursementVoucherDocument dv, java.sql.Date processDate) {
778         if (dv.getCancelDate() == null) {
779             try {
780                 BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class);
781                 // set the canceled date
782                 dv.setCancelDate(processDate);
783                 dv.refreshReferenceObject("generalLedgerPendingEntries");
784                 if (ObjectUtils.isNull(dv.getGeneralLedgerPendingEntries()) || dv.getGeneralLedgerPendingEntries().size() == 0) {
785                     // generate all the pending entries for the document
786                     SpringContext.getBean(GeneralLedgerPendingEntryService.class).generateGeneralLedgerPendingEntries(dv);
787                     // for each pending entry, opposite-ify it and reattach it to the document
788                     GeneralLedgerPendingEntrySequenceHelper glpeSeqHelper = new GeneralLedgerPendingEntrySequenceHelper();
789                     for (GeneralLedgerPendingEntry glpe : dv.getGeneralLedgerPendingEntries()) {
790                         oppositifyEntry(glpe, boService, glpeSeqHelper);
791                     }
792                 }
793                 else {
794                     List<GeneralLedgerPendingEntry> newGLPEs = new ArrayList<GeneralLedgerPendingEntry>();
795                     GeneralLedgerPendingEntrySequenceHelper glpeSeqHelper = new GeneralLedgerPendingEntrySequenceHelper(dv.getGeneralLedgerPendingEntries().size() + 1);
796                     for (GeneralLedgerPendingEntry glpe : dv.getGeneralLedgerPendingEntries()) {
797                         glpe.refresh();
798                         if (glpe.getFinancialDocumentApprovedCode().equals(OLEConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.PROCESSED)) {
799                             // damn! it got processed! well, make a copy, oppositify, and save
800                             GeneralLedgerPendingEntry undoer = new GeneralLedgerPendingEntry(glpe);
801                             oppositifyEntry(undoer, boService, glpeSeqHelper);
802                             newGLPEs.add(undoer);
803                         }
804                         else {
805                             // just delete the GLPE before anything happens to it
806                             boService.delete(glpe);
807                         }
808                     }
809                     dv.setGeneralLedgerPendingEntries(newGLPEs);
810                 }
811                 // set the financial document status to canceled
812                 dv.getFinancialSystemDocumentHeader().setFinancialDocumentStatusCode(OLEConstants.DocumentStatusCodes.CANCELLED);
813                 // save the document
814                 SpringContext.getBean(DocumentService.class).saveDocument(dv, AccountingDocumentSaveWithNoLedgerEntryGenerationEvent.class);
815             }
816             catch (WorkflowException we) {
817                 LOG.error("encountered workflow exception while attempting to save Disbursement Voucher: " + dv.getDocumentNumber() + " " + we);
818                 throw new RuntimeException(we);
819             }
820         }
821     }
822 
823     /**
824      * Updates the given general ledger pending entry so that it will have the opposite effect of what it was created to do; this,
825      * in effect, undoes the entries that were already posted for this document
826      *
827      * @param glpe the general ledger pending entry to undo
828      */
829     protected void oppositifyEntry(GeneralLedgerPendingEntry glpe, BusinessObjectService boService, GeneralLedgerPendingEntrySequenceHelper glpeSeqHelper) {
830         if (glpe.getTransactionDebitCreditCode().equals(OLEConstants.GL_CREDIT_CODE)) {
831             glpe.setTransactionDebitCreditCode(OLEConstants.GL_DEBIT_CODE);
832         }
833         else if (glpe.getTransactionDebitCreditCode().equals(OLEConstants.GL_DEBIT_CODE)) {
834             glpe.setTransactionDebitCreditCode(OLEConstants.GL_CREDIT_CODE);
835         }
836         glpe.setTransactionLedgerEntrySequenceNumber(glpeSeqHelper.getSequenceCounter());
837         glpeSeqHelper.increment();
838         glpe.setFinancialDocumentApprovedCode(OLEConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.APPROVED);
839         boService.save(glpe);
840     }
841 
842     /**
843      * This updates the disbursement voucher so that when it is re-extracted, information about it will be accurate
844      *
845      * @param dv the disbursement voucher document to reset
846      * @param processDate the date of the reseting
847      * @see org.kuali.ole.fp.batch.service.DisbursementVoucherExtractService#resetExtractedDisbursementVoucher(org.kuali.ole.fp.document.DisbursementVoucherDocument, java.sql.Date)
848      */
849     @Override
850     public void resetExtractedDisbursementVoucher(DisbursementVoucherDocument dv, java.sql.Date processDate) {
851         try {
852             // 1. reset the extracted date
853             dv.setExtractDate(null);
854             dv.setPaidDate(null);
855             // 2. save the doc
856             SpringContext.getBean(DocumentService.class).saveDocument(dv, AccountingDocumentSaveWithNoLedgerEntryGenerationEvent.class);
857         }
858         catch (WorkflowException we) {
859             LOG.error("encountered workflow exception while attempting to save Disbursement Voucher: " + dv.getDocumentNumber() + " " + we);
860             throw new RuntimeException(we);
861         }
862     }
863 
864     /**
865      * Looks up the document using document service, and deals with any nasty WorkflowException or ClassCastExceptions that pop up
866      *
867      * @param documentNumber the number of the document to look up
868      * @return the dv doc if found, or null otherwise
869      * @see org.kuali.ole.fp.batch.service.DisbursementVoucherExtractService#getDocumentById(java.lang.String)
870      */
871     @Override
872     public DisbursementVoucherDocument getDocumentById(String documentNumber) {
873         DisbursementVoucherDocument dv = null;
874         try {
875             dv = (DisbursementVoucherDocument) SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(documentNumber);
876         }
877         catch (WorkflowException we) {
878             LOG.error("encountered workflow exception while attempting to retrieve Disbursement Voucher: " + dv.getDocumentNumber() + " " + we);
879             throw new RuntimeException(we);
880         }
881         return dv;
882     }
883 
884     /**
885      * Marks the disbursement voucher as paid by setting its paid date
886      *
887      * @param dv the dv document to mark as paid
888      * @param processDate the date when the dv was paid
889      * @see org.kuali.ole.fp.batch.service.DisbursementVoucherExtractService#markDisbursementVoucherAsPaid(org.kuali.ole.fp.document.DisbursementVoucherDocument, java.sql.Date)
890      */
891     @Override
892     public void markDisbursementVoucherAsPaid(DisbursementVoucherDocument dv, java.sql.Date processDate) {
893         try {
894             dv.setPaidDate(processDate);
895             SpringContext.getBean(DocumentService.class).saveDocument(dv, AccountingDocumentSaveWithNoLedgerEntryGenerationEvent.class);
896         }
897         catch (WorkflowException we) {
898             LOG.error("encountered workflow exception while attempting to save Disbursement Voucher: " + dv.getDocumentNumber() + " " + we);
899             throw new RuntimeException(we);
900         }
901     }
902 
903 
904 
905     /**
906      * Extracts a single DisbursementVoucherDocument
907      * @see org.kuali.ole.fp.batch.service.DisbursementVoucherExtractService#extractImmediatePayment(org.kuali.ole.fp.document.DisbursementVoucherDocument)
908      */
909     @Override
910     public void extractImmediatePayment(DisbursementVoucherDocument disbursementVoucher) {
911         if (LOG.isDebugEnabled()) {
912             LOG.debug("extractImmediatePayment(DisbursementVoucherDocument) started");
913         }
914         Date processRunDate = dateTimeService.getCurrentDate();
915         String noteLines = parameterService.getParameterValueAsString(OleParameterConstants.PRE_DISBURSEMENT_ALL.class, PdpParameterConstants.MAX_NOTE_LINES);
916         try {
917             maxNoteLines = Integer.parseInt(noteLines);
918         }
919         catch (NumberFormatException nfe) {
920             throw new IllegalArgumentException("Invalid Max Notes Lines parameter");
921         }
922         Person user = getPersonService().getPersonByPrincipalName(OLEConstants.SYSTEM_USER);
923         if (user == null) {
924             LOG.debug("extractPayments() Unable to find user " + OLEConstants.SYSTEM_USER);
925             throw new IllegalArgumentException("Unable to find user " + OLEConstants.SYSTEM_USER);
926         }
927 
928         Batch batch = createBatch(disbursementVoucher.getCampusCode(), user, processRunDate);
929         KualiDecimal totalAmount = KualiDecimal.ZERO;
930 
931         addPayment(disbursementVoucher, batch, processRunDate, true);
932         totalAmount = totalAmount.add(disbursementVoucher.getDisbVchrCheckTotalAmount());
933 
934         batch.setPaymentCount(new KualiInteger(1));
935         batch.setPaymentTotalAmount(totalAmount);
936 
937         businessObjectService.save(batch);
938         paymentFileEmailService.sendDisbursementVoucherImmediateExtractEmail(disbursementVoucher, user);
939     }
940 
941     /**
942      * This method sets the disbursementVoucherDao instance.
943      *
944      * @param disbursementVoucherDao The DisbursementVoucherDao to be set.
945      */
946     public void setDisbursementVoucherDao(DisbursementVoucherDao disbursementVoucherDao) {
947         this.disbursementVoucherDao = disbursementVoucherDao;
948     }
949 
950     /**
951      * This method sets the ParameterService instance.
952      *
953      * @param parameterService The ParameterService to be set.
954      */
955     public void setParameterService(ParameterService parameterService) {
956         this.parameterService = parameterService;
957     }
958 
959     /**
960      * This method sets the dateTimeService instance.
961      *
962      * @param dateTimeService The DateTimeService to be set.
963      */
964     public void setDateTimeService(DateTimeService dateTimeService) {
965         this.dateTimeService = dateTimeService;
966     }
967 
968     /**
969      * This method sets the customerProfileService instance.
970      *
971      * @param customerProfileService The CustomerProfileService to be set.
972      */
973     public void setCustomerProfileService(CustomerProfileService customerProfileService) {
974         this.customerProfileService = customerProfileService;
975     }
976 
977     /**
978      * This method sets the paymentFileService instance.
979      *
980      * @param paymentFileService The PaymentFileService to be set.
981      */
982     public void setPaymentFileService(PaymentFileService paymentFileService) {
983         this.paymentFileService = paymentFileService;
984     }
985 
986     /**
987      * This method sets the paymentGroupService instance.
988      *
989      * @param paymentGroupService The PaymentGroupService to be set.
990      */
991     public void setPaymentGroupService(PaymentGroupService paymentGroupService) {
992         this.paymentGroupService = paymentGroupService;
993     }
994 
995     /**
996      * Sets the businessObjectService attribute value.
997      *
998      * @param businessObjectService The businessObjectService to set.
999      */
1000     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
1001         this.businessObjectService = businessObjectService;
1002     }
1003 
1004     /**
1005      * Sets the paymentFileEmailService attribute value.
1006      *
1007      * @param paymentFileEmailService The paymentFileEmailService to set.
1008      */
1009     public void setPaymentFileEmailService(PdpEmailService paymentFileEmailService) {
1010         this.paymentFileEmailService = paymentFileEmailService;
1011     }
1012 
1013     /**
1014      * @return Returns the personService.
1015      */
1016     protected PersonService getPersonService() {
1017         if(personService==null) {
1018             personService = SpringContext.getBean(PersonService.class);
1019         }
1020         return personService;
1021     }
1022 
1023 }