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.module.purap.service.impl;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.commons.lang.builder.EqualsBuilder;
20  import org.apache.commons.lang.builder.HashCodeBuilder;
21  import org.kuali.ole.module.purap.PurapConstants;
22  import org.kuali.ole.module.purap.batch.service.PurapRunDateService;
23  import org.kuali.ole.module.purap.businessobject.CreditMemoItem;
24  import org.kuali.ole.module.purap.businessobject.PaymentRequestItem;
25  import org.kuali.ole.module.purap.document.AccountsPayableDocument;
26  import org.kuali.ole.module.purap.document.PaymentRequestDocument;
27  import org.kuali.ole.module.purap.document.VendorCreditMemoDocument;
28  import org.kuali.ole.module.purap.document.service.CreditMemoService;
29  import org.kuali.ole.module.purap.document.service.PaymentRequestService;
30  import org.kuali.ole.module.purap.document.service.PurapService;
31  import org.kuali.ole.module.purap.service.PdpExtractService;
32  import org.kuali.ole.module.purap.util.VendorGroupingHelper;
33  import org.kuali.ole.pdp.PdpConstants;
34  import org.kuali.ole.pdp.PdpParameterConstants;
35  import org.kuali.ole.pdp.businessobject.*;
36  import org.kuali.ole.pdp.service.*;
37  import org.kuali.ole.select.businessobject.OlePaymentMethod;
38  import org.kuali.ole.select.document.OlePaymentRequestDocument;
39  import org.kuali.ole.select.document.service.OleSelectDocumentService;
40  import org.kuali.ole.sys.OLEConstants;
41  import org.kuali.ole.sys.OLEParameterKeyConstants;
42  import org.kuali.ole.sys.businessobject.SourceAccountingLine;
43  import org.kuali.ole.sys.context.SpringContext;
44  import org.kuali.ole.sys.service.BankService;
45  import org.kuali.ole.sys.service.impl.OleParameterConstants;
46  import org.kuali.ole.sys.util.KfsDateUtils;
47  import org.kuali.ole.vnd.VendorConstants;
48  import org.kuali.ole.vnd.businessobject.AliasType;
49  import org.kuali.ole.vnd.businessobject.VendorAlias;
50  import org.kuali.rice.core.api.datetime.DateTimeService;
51  import org.kuali.rice.core.api.util.type.KualiDecimal;
52  import org.kuali.rice.core.api.util.type.KualiInteger;
53  import org.kuali.rice.coreservice.api.parameter.Parameter;
54  import org.kuali.rice.coreservice.api.parameter.Parameter.Builder;
55  import org.kuali.rice.coreservice.api.parameter.ParameterType;
56  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
57  import org.kuali.rice.kew.api.exception.WorkflowException;
58  import org.kuali.rice.kim.api.identity.Person;
59  import org.kuali.rice.kim.api.identity.PersonService;
60  import org.kuali.rice.kns.service.DataDictionaryService;
61  import org.kuali.rice.krad.document.Document;
62  import org.kuali.rice.krad.service.BusinessObjectService;
63  import org.kuali.rice.krad.service.DocumentService;
64  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
65  import org.springframework.transaction.annotation.Transactional;
66  
67  import java.sql.Timestamp;
68  import java.util.*;
69  
70  /**
71   * Implementation of PdpExtractService
72   */
73  @Transactional
74  public class PdpExtractServiceImpl implements PdpExtractService {
75      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PdpExtractServiceImpl.class);
76  
77      private PaymentRequestService paymentRequestService;
78      private BusinessObjectService businessObjectService;
79      private PaymentFileService paymentFileService;
80      private ParameterService parameterService;
81      private CustomerProfileService customerProfileService;
82      private DateTimeService dateTimeService;
83      private PersonService personService;
84      private PaymentGroupService paymentGroupService;
85      private PaymentDetailService paymentDetailService;
86      private CreditMemoService creditMemoService;
87      private DocumentService documentService;
88      private PurapRunDateService purapRunDateService;
89      private PdpEmailService paymentFileEmailService;
90      private BankService bankService;
91      private DataDictionaryService dataDictionaryService;
92      private PurapAccountingServiceImpl purapAccountingService;
93      private List<String> lockedDocuments;
94      private OleSelectDocumentService oleSelectDocumentService;
95  
96      /**
97       * @see org.kuali.ole.module.purap.service.PdpExtractService#extractImmediatePaymentsOnly()
98       */
99      @Override
100     public void extractImmediatePaymentsOnly() {
101         LOG.debug("extractImmediatePaymentsOnly() started");
102         Date processRunDate = dateTimeService.getCurrentDate();
103         lockUnlockDocuments(true);
104         try {
105             extractPayments(true, processRunDate);
106         } finally {
107             lockUnlockDocuments(false);
108         }
109     }
110 
111     /**
112      * @see org.kuali.ole.module.purap.service.PdpExtractService#extractPayments(Date)
113      */
114     @Override
115     public void extractPayments(Date runDate) {
116         LOG.debug("extractPayments() started");
117 
118         extractPayments(false, runDate);
119     }
120 
121     /**
122      * Extracts payments from the database
123      *
124      * @param immediateOnly  whether to pick up immediate payments only
125      * @param processRunDate time/date to use to put on the {@link Batch} that's created; and when immediateOnly is false, is also
126      *                       used as the maximum allowed PREQ pay date when searching PREQ documents eligible to have payments extracted
127      */
128     protected void extractPayments(boolean immediateOnly, Date processRunDate) {
129         LOG.debug("extractPayments() started");
130 
131         Person uuser = getPersonService().getPersonByPrincipalName(getOleSelectDocumentService().getSelectParameterValue(OLEConstants.SYSTEM_USER));
132         if (uuser == null) {
133             LOG.error("extractPayments() Unable to find user " + getOleSelectDocumentService().getSelectParameterValue(OLEConstants.SYSTEM_USER));
134             throw new IllegalArgumentException("Unable to find user " + getOleSelectDocumentService().getSelectParameterValue(OLEConstants.SYSTEM_USER));
135         }
136 
137         List<String> campusesToProcess = getChartCodes(immediateOnly, processRunDate);
138         for (String campus : campusesToProcess) {
139             extractPaymentsForCampus(campus, uuser, processRunDate, immediateOnly);
140         }
141     }
142 
143     /**
144      * Handle a single campus
145      *
146      * @param campusCode
147      * @param puser
148      * @param processRunDate
149      */
150     protected void extractPaymentsForCampus(String campusCode, Person puser, Date processRunDate, boolean immediateOnly) {
151         if (LOG.isDebugEnabled()) {
152             LOG.debug("extractPaymentsForCampus() started for campus: " + campusCode);
153         }
154 
155         Batch batch = createBatch(campusCode, puser, processRunDate);
156 
157         Integer count = 0;
158         KualiDecimal totalAmount = KualiDecimal.ZERO;
159 
160         // Do all the special ones
161         Totals totals = extractSpecialPaymentsForChart(campusCode, puser, processRunDate, batch, immediateOnly);
162         count = count + totals.count;
163         totalAmount = totalAmount.add(totals.totalAmount);
164 
165         if (!immediateOnly) {
166             // Do all the regular ones (including credit memos)
167             totals = extractRegularPaymentsForChart(campusCode, puser, processRunDate, batch);
168             count = count + totals.count;
169             totalAmount = totalAmount.add(totals.totalAmount);
170         }
171 
172         batch.setPaymentCount(new KualiInteger(count));
173         batch.setPaymentTotalAmount(totalAmount);
174 
175         businessObjectService.save(batch);
176         paymentFileEmailService.sendLoadEmail(batch);
177     }
178 
179     /**
180      * Get all the payments that could be combined with credit memos
181      *
182      * @param campusCode
183      * @param puser
184      * @param processRunDate
185      * @param batch
186      * @return Totals
187      */
188     protected Totals extractRegularPaymentsForChart(String campusCode, Person puser, Date processRunDate, Batch batch) {
189         LOG.debug("START - extractRegularPaymentsForChart()");
190 
191         Totals totals = new Totals();
192 
193         java.sql.Date onOrBeforePaymentRequestPayDate = KfsDateUtils.convertToSqlDate(purapRunDateService.calculateRunDate(processRunDate));
194 
195         List<String> preqsWithOutstandingCreditMemos = new ArrayList<String>();
196 
197         Set<VendorGroupingHelper> vendors = creditMemoService.getVendorsOnCreditMemosToExtract(campusCode);
198         for (VendorGroupingHelper vendor : vendors) {
199             if (LOG.isDebugEnabled()) {
200                 LOG.debug("Processing Vendor: " + vendor);
201             }
202 
203             Map<String, List<PaymentRequestDocument>> bankCodePaymentRequests = new HashMap<String, List<PaymentRequestDocument>>();
204             Map<String, List<VendorCreditMemoDocument>> bankCodeCreditMemos = new HashMap<String, List<VendorCreditMemoDocument>>();
205 
206             // Get all the matching credit memos
207             Collection<VendorCreditMemoDocument> vendorMemos = creditMemoService.getCreditMemosToExtractByVendor(campusCode, vendor);
208             for (VendorCreditMemoDocument cmd : vendorMemos) {
209                 List<VendorCreditMemoDocument> bankMemos = new ArrayList<VendorCreditMemoDocument>();
210                 if (bankCodeCreditMemos.containsKey(cmd.getBankCode())) {
211                     bankMemos = bankCodeCreditMemos.get(cmd.getBankCode());
212                 }
213 
214                 bankMemos.add(cmd);
215                 bankCodeCreditMemos.put(cmd.getBankCode(), bankMemos);
216             }
217 
218             // get all matching payment requests
219             Collection<PaymentRequestDocument> vendorPreqs = paymentRequestService.getPaymentRequestsToExtractByVendor(campusCode, vendor, onOrBeforePaymentRequestPayDate);
220             for (PaymentRequestDocument prd : vendorPreqs) {
221                 List<PaymentRequestDocument> bankPreqs = new ArrayList<PaymentRequestDocument>();
222                 if (bankCodePaymentRequests.containsKey(prd.getBankCode())) {
223                     bankPreqs = bankCodePaymentRequests.get(prd.getBankCode());
224                 }
225 
226                 bankPreqs.add(prd);
227                 bankCodePaymentRequests.put(prd.getBankCode(), bankPreqs);
228             }
229 
230             // if bank functionality enabled, create bundles by bank, else just by vendor
231             if (bankService.isBankSpecificationEnabled()) {
232                 for (String bankCode : bankCodePaymentRequests.keySet()) {
233                     // if we have credit memos with bank code, process together, else let the preq go and will get picked up below
234                     // and processed as a single payment group
235                     if (bankCodeCreditMemos.containsKey(bankCode)) {
236                         processPaymentBundle(bankCodePaymentRequests.get(bankCode), bankCodeCreditMemos.get(bankCode), totals, preqsWithOutstandingCreditMemos, puser, processRunDate, batch);
237                     }
238                 }
239             } else {
240                 if (vendorMemos.isEmpty()) {
241                     processPaymentBundle((List<PaymentRequestDocument>) vendorPreqs, (List<VendorCreditMemoDocument>) vendorMemos, totals, preqsWithOutstandingCreditMemos, puser, processRunDate, batch);
242                 }
243             }
244         }
245 
246         LOG.debug("processing PREQs without CMs");
247 
248         Iterator<PaymentRequestDocument> paymentRequests = paymentRequestService.getPaymentRequestToExtractByChart(campusCode, onOrBeforePaymentRequestPayDate).iterator();
249         while (paymentRequests.hasNext()) {
250             PaymentRequestDocument prd = paymentRequests.next();
251             // if in the list created above, don't create the payment group
252             if (!preqsWithOutstandingCreditMemos.contains(prd.getDocumentNumber())) {
253                 PaymentGroup paymentGroup = processSinglePaymentRequestDocument(prd, batch, puser, processRunDate);
254 
255                 totals.count = totals.count + paymentGroup.getPaymentDetails().size();
256                 totals.totalAmount = totals.totalAmount.add(paymentGroup.getNetPaymentAmount());
257             }
258         }
259 
260 
261         LOG.debug("END - extractRegularPaymentsForChart()");
262         return totals;
263     }
264 
265     /**
266      * Processes the list of payment requests and credit memos as a payment group pending
267      *
268      * @param paymentRequests
269      * @param creditMemos
270      * @param totals
271      * @param preqsWithOutstandingCreditMemos
272      *
273      * @param puser
274      * @param processRunDate
275      * @param batch
276      */
277     protected void processPaymentBundle(List<PaymentRequestDocument> paymentRequests, List<VendorCreditMemoDocument> creditMemos, Totals totals, List<String> preqsWithOutstandingCreditMemos, Person puser, Date processRunDate, Batch batch) {
278         KualiDecimal paymentRequestAmount = KualiDecimal.ZERO;
279         for (PaymentRequestDocument paymentRequestDocument : paymentRequests) {
280             paymentRequestAmount = paymentRequestAmount.add(paymentRequestDocument.getGrandTotal());
281         }
282 
283         KualiDecimal creditMemoAmount = KualiDecimal.ZERO;
284         for (VendorCreditMemoDocument creditMemoDocument : creditMemos) {
285             creditMemoAmount = creditMemoAmount.add(creditMemoDocument.getCreditMemoAmount());
286         }
287 
288         // if payment amount greater than credit, create bundle
289         boolean bundleCreated = false;
290         if (paymentRequestAmount.compareTo(creditMemoAmount) >= 0) {
291             PaymentGroup paymentGroup = buildPaymentGroup(paymentRequests, creditMemos, batch);
292 
293             if (validatePaymentGroup(paymentGroup)) {
294                 this.businessObjectService.save(paymentGroup);
295                 if (LOG.isDebugEnabled()) {
296                     LOG.debug("Created PaymentGroup: " + paymentGroup.getId());
297                 }
298 
299                 totals.count++;
300                 totals.totalAmount = totals.totalAmount.add(paymentGroup.getNetPaymentAmount());
301 
302                 // mark the CMs and PREQs as processed
303                 for (VendorCreditMemoDocument cm : creditMemos) {
304                     updateCreditMemo(cm, puser, processRunDate);
305                 }
306 
307                 for (PaymentRequestDocument pr : paymentRequests) {
308                     updatePaymentRequest(pr, puser, processRunDate);
309                 }
310 
311                 bundleCreated = true;
312             }
313         }
314 
315         if (!bundleCreated) {
316             // add payment request doc numbers to list so they don't get picked up later
317             for (PaymentRequestDocument doc : paymentRequests) {
318                 preqsWithOutstandingCreditMemos.add(doc.getDocumentNumber());
319             }
320         }
321     }
322 
323     /**
324      * Handle a single payment request with no credit memos
325      *
326      * @param paymentRequestDocument
327      * @param batch
328      * @param puser
329      * @param processRunDate
330      * @return PaymentGroup
331      */
332     protected PaymentGroup processSinglePaymentRequestDocument(PaymentRequestDocument paymentRequestDocument, Batch batch, Person puser, Date processRunDate) {
333         List<PaymentRequestDocument> prds = new ArrayList<PaymentRequestDocument>();
334         List<VendorCreditMemoDocument> cmds = new ArrayList<VendorCreditMemoDocument>();
335         prds.add(paymentRequestDocument);
336 
337         PaymentGroup paymentGroup = buildPaymentGroup(prds, cmds, batch);
338         if (validatePaymentGroup(paymentGroup)) {
339             this.businessObjectService.save(paymentGroup);
340             updatePaymentRequest(paymentRequestDocument, puser, processRunDate);
341         }
342 
343         return paymentGroup;
344     }
345 
346     /**
347      * Get all the special payments for a campus and process them
348      *
349      * @param campusCode
350      * @param puser
351      * @param processRunDate
352      * @param batch
353      * @return Totals
354      */
355     protected Totals extractSpecialPaymentsForChart(String campusCode, Person puser, Date processRunDate, Batch batch, boolean immediatesOnly) {
356         Totals totals = new Totals();
357 
358         Iterator<PaymentRequestDocument> paymentRequests = null;
359         if (immediatesOnly) {
360             paymentRequests = paymentRequestService.getImmediatePaymentRequestsToExtract(campusCode).iterator();
361         } else {
362             java.sql.Date onOrBeforePaymentRequestPayDate = KfsDateUtils.convertToSqlDate(purapRunDateService.calculateRunDate(processRunDate));
363             paymentRequests = paymentRequestService.getPaymentRequestsToExtractSpecialPayments(campusCode, onOrBeforePaymentRequestPayDate).iterator();
364         }
365 
366         while (paymentRequests.hasNext()) {
367             PaymentRequestDocument prd = paymentRequests.next();
368             PaymentGroup pg = processSinglePaymentRequestDocument(prd, batch, puser, processRunDate);
369 
370             totals.count = totals.count + pg.getPaymentDetails().size();
371             totals.totalAmount = totals.totalAmount.add(pg.getNetPaymentAmount());
372         }
373 
374         return totals;
375     }
376 
377 
378     /**
379      * Mark a credit memo as extracted
380      *
381      * @param creditMemoDocument
382      * @param puser
383      * @param processRunDate
384      */
385     protected void updateCreditMemo(VendorCreditMemoDocument creditMemoDocument, Person puser, Date processRunDate) {
386         try {
387             VendorCreditMemoDocument doc = (VendorCreditMemoDocument) documentService.getByDocumentHeaderId(creditMemoDocument.getDocumentNumber());
388             doc.setExtractedTimestamp(new Timestamp(processRunDate.getTime()));
389             doc.setApplicationDocumentStatus(PurapConstants.CreditMemoStatuses.APPDOC_EXTRACTED);
390             SpringContext.getBean(PurapService.class).saveDocumentNoValidation(doc);
391         } catch (WorkflowException e) {
392             throw new IllegalArgumentException("Unable to retrieve credit memo: " + creditMemoDocument.getDocumentNumber());
393         }
394     }
395 
396     /**
397      * Mark a payment request as extracted
398      *
399      * @param prd
400      * @param puser
401      * @param processRunDate
402      */
403     protected void updatePaymentRequest(PaymentRequestDocument paymentRequestDocument, Person puser, Date processRunDate) {
404         try {
405             PaymentRequestDocument doc = (PaymentRequestDocument) documentService.getByDocumentHeaderId(paymentRequestDocument.getDocumentNumber());
406             doc.setExtractedTimestamp(new Timestamp(processRunDate.getTime()));
407             doc.setApplicationDocumentStatus(PurapConstants.PaymentRequestStatuses.APPDOC_EXTRACTED);
408             SpringContext.getBean(PurapService.class).saveDocumentNoValidation(doc);
409         } catch (WorkflowException e) {
410             throw new IllegalArgumentException("Unable to retrieve payment request: " + paymentRequestDocument.getDocumentNumber());
411         }
412     }
413 
414     /**
415      * Create the PDP payment group from a list of payment requests & credit memos
416      *
417      * @param paymentRequests
418      * @param creditMemos
419      * @param batch
420      * @return PaymentGroup
421      */
422     protected PaymentGroup buildPaymentGroup(List<PaymentRequestDocument> paymentRequests, List<VendorCreditMemoDocument> creditMemos, Batch batch) {
423         // There should always be at least one Payment Request Document in the list.
424         PaymentGroup paymentGroup = null;
425         if (creditMemos.size() > 0) {
426             VendorCreditMemoDocument firstCmd = creditMemos.get(0);
427             paymentGroup = populatePaymentGroup(firstCmd, batch);
428         } else {
429             PaymentRequestDocument firstPrd = paymentRequests.get(0);
430             paymentGroup = populatePaymentGroup(firstPrd, batch);
431         }
432 
433         for (PaymentRequestDocument pr : paymentRequests) {
434             PaymentDetail pd = populatePaymentDetail(pr, batch);
435             paymentGroup.addPaymentDetails(pd);
436         }
437         for (VendorCreditMemoDocument cm : creditMemos) {
438             PaymentDetail pd = populatePaymentDetail(cm, batch);
439             paymentGroup.addPaymentDetails(pd);
440         }
441 
442         return paymentGroup;
443     }
444 
445     /**
446      * Checks payment group note lines does not exceed the maximum allowed
447      *
448      * @param paymentGroup group to validate
449      * @return true if group is valid, false otherwise
450      */
451     protected boolean validatePaymentGroup(PaymentGroup paymentGroup) {
452         // Check to see if the payment group has too many note lines to be printed on a check
453         List<PaymentDetail> payDetails = paymentGroup.getPaymentDetails();
454 
455         int noteLines = 0;
456         for (PaymentDetail paymentDetail : payDetails) {
457             noteLines++; // Add one for each payment detail; summary of each detail is included on check and counts as a line
458             noteLines += paymentDetail.getNotes().size(); // get all the possible notes for a given detail
459         }
460 
461         int maxNoteLines = getMaxNoteLines();
462         if (noteLines > maxNoteLines) {
463             // compile list of all doc numbers that make up payment group
464             List<String> preqDocIds = new ArrayList<String>();
465             List<String> cmDocIds = new ArrayList<String>();
466 
467             List<PaymentDetail> pds = paymentGroup.getPaymentDetails();
468             for (PaymentDetail payDetail : pds) {
469                 if (OLEConstants.FinancialDocumentTypeCodes.VENDOR_CREDIT_MEMO.equals(payDetail.getFinancialDocumentTypeCode())) {
470                     cmDocIds.add(payDetail.getCustPaymentDocNbr());
471                 } else {
472                     preqDocIds.add(payDetail.getCustPaymentDocNbr());
473                 }
474             }
475 
476             // send warning email and prevent group from being processed by returning false
477             paymentFileEmailService.sendExceedsMaxNotesWarningEmail(cmDocIds, preqDocIds, noteLines, maxNoteLines);
478 
479             return false;
480         }
481 
482         return true;
483     }
484 
485     /**
486      * @return configured maximum number of note lines allowed
487      */
488     protected int getMaxNoteLines() {
489         String maxLines = parameterService.getParameterValueAsString(OleParameterConstants.PRE_DISBURSEMENT_ALL.class, PdpParameterConstants.MAX_NOTE_LINES);
490         if (StringUtils.isBlank(maxLines)) {
491             throw new RuntimeException("System parameter for max note lines is blank");
492         }
493 
494         return Integer.parseInt(maxLines);
495     }
496 
497     /**
498      * Create a PDP payment detail record from a Credit Memo document
499      *
500      * @param creditMemoDocument Credit Memo to use for payment detail
501      * @param batch              current PDP batch object
502      * @return populated PaymentDetail line
503      */
504     protected PaymentDetail populatePaymentDetail(VendorCreditMemoDocument creditMemoDocument, Batch batch) {
505         PaymentDetail paymentDetail = new PaymentDetail();
506         if (creditMemoDocument.getCreditMemoNumber() != null) {
507             String invoiceNumber = creditMemoDocument.getCreditMemoNumber();
508             if (invoiceNumber.length() > 25) {
509                 invoiceNumber = invoiceNumber.substring(0, 25);
510             } else {
511                 paymentDetail.setInvoiceNbr(invoiceNumber);
512             }
513             paymentDetail.setInvoiceNbr(invoiceNumber);
514         } else {
515             paymentDetail.setInvoiceNbr("");
516         }
517         paymentDetail.setCustPaymentDocNbr(creditMemoDocument.getDocumentNumber());
518 
519 
520         if (creditMemoDocument.getPurchaseOrderIdentifier() != null) {
521             paymentDetail.setPurchaseOrderNbr(creditMemoDocument.getPurchaseOrderIdentifier().toString());
522         }
523 
524         if (creditMemoDocument.getPurchaseOrderDocument() != null) {
525             if (creditMemoDocument.getPurchaseOrderDocument().getRequisitionIdentifier() != null) {
526                 paymentDetail.setRequisitionNbr(creditMemoDocument.getPurchaseOrderDocument().getRequisitionIdentifier().toString());
527             }
528 
529             if (creditMemoDocument.getDocumentHeader().getOrganizationDocumentNumber() != null) {
530                 paymentDetail.setOrganizationDocNbr(creditMemoDocument.getDocumentHeader().getOrganizationDocumentNumber());
531             }
532         }
533 
534         paymentDetail.setCustomerInstitutionNumber(StringUtils.defaultString(creditMemoDocument.getVendorCustomerNumber()));
535 
536         final String creditMemoDocType = getDataDictionaryService().getDocumentTypeNameByClass(creditMemoDocument.getClass());
537         paymentDetail.setFinancialDocumentTypeCode(creditMemoDocType);
538         paymentDetail.setFinancialSystemOriginCode(OLEConstants.ORIGIN_CODE_KUALI);
539 
540         paymentDetail.setInvoiceDate(creditMemoDocument.getCreditMemoDate());
541         paymentDetail.setOrigInvoiceAmount(creditMemoDocument.getCreditMemoAmount().negated());
542         paymentDetail.setNetPaymentAmount(creditMemoDocument.getFinancialSystemDocumentHeader().getFinancialDocumentTotalAmount().negated());
543 
544         KualiDecimal shippingAmount = KualiDecimal.ZERO;
545         KualiDecimal discountAmount = KualiDecimal.ZERO;
546         KualiDecimal creditAmount = KualiDecimal.ZERO;
547         KualiDecimal debitAmount = KualiDecimal.ZERO;
548 
549         for (Iterator iter = creditMemoDocument.getItems().iterator(); iter.hasNext(); ) {
550             CreditMemoItem item = (CreditMemoItem) iter.next();
551 
552             KualiDecimal itemAmount = KualiDecimal.ZERO;
553             if (item.getExtendedPrice() != null) {
554                 itemAmount = item.getExtendedPrice();
555             }
556             if (PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE.equals(item.getItemTypeCode())) {
557                 discountAmount = discountAmount.subtract(itemAmount);
558             } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_SHIP_AND_HAND_CODE.equals(item.getItemTypeCode())) {
559                 shippingAmount = shippingAmount.subtract(itemAmount);
560             } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_FREIGHT_CODE.equals(item.getItemTypeCode())) {
561                 shippingAmount = shippingAmount.add(itemAmount);
562             } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_MIN_ORDER_CODE.equals(item.getItemTypeCode())) {
563                 debitAmount = debitAmount.subtract(itemAmount);
564             } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_MISC_CODE.equals(item.getItemTypeCode())) {
565                 if (itemAmount.isNegative()) {
566                     creditAmount = creditAmount.subtract(itemAmount);
567                 } else {
568                     debitAmount = debitAmount.subtract(itemAmount);
569                 }
570             }
571         }
572 
573         paymentDetail.setInvTotDiscountAmount(discountAmount);
574         paymentDetail.setInvTotShipAmount(shippingAmount);
575         paymentDetail.setInvTotOtherCreditAmount(creditAmount);
576         paymentDetail.setInvTotOtherDebitAmount(debitAmount);
577 
578         paymentDetail.setPrimaryCancelledPayment(Boolean.FALSE);
579 
580         addAccounts(creditMemoDocument, paymentDetail, creditMemoDocType);
581         addNotes(creditMemoDocument, paymentDetail);
582 
583         return paymentDetail;
584     }
585 
586     /**
587      * Create a PDP Payment Detail record from a Payment Request document
588      *
589      * @param paymentRequestDocument Payment Request to use for Payment Detail
590      * @param batch                  current PDP batch object
591      * @return populated PaymentDetail line
592      */
593     protected PaymentDetail populatePaymentDetail(PaymentRequestDocument paymentRequestDocument, Batch batch) {
594         PaymentDetail paymentDetail = new PaymentDetail();
595 
596         paymentDetail.setCustPaymentDocNbr(paymentRequestDocument.getDocumentNumber());
597         Map preqItemMap = new HashMap();
598         preqItemMap.put("purapDocumentIdentifier",  paymentRequestDocument.getPurapDocumentIdentifier());
599         OlePaymentRequestDocument olePaymentRequestDocument = (OlePaymentRequestDocument) getBusinessObjectService().findByPrimaryKey(OlePaymentRequestDocument.class, preqItemMap);
600 
601         if (olePaymentRequestDocument.getPaymentMethodId() != null) {
602             OlePaymentMethod olePaymentMethod = SpringContext.getBean(BusinessObjectService.class)
603                     .findBySinglePrimaryKey(OlePaymentMethod.class, olePaymentRequestDocument.getPaymentMethodId());
604             paymentDetail.setPaymentMethodCode(olePaymentMethod.getPaymentMethod());
605         }
606         String invoiceNumber = paymentRequestDocument.getInvoiceNumber();
607         if(invoiceNumber != null) {
608             if (invoiceNumber.length() > 25) {
609                 invoiceNumber = invoiceNumber.substring(0, 25);
610             }
611         }
612         paymentDetail.setInvoiceNbr(invoiceNumber);
613 
614         if (paymentRequestDocument.getPurchaseOrderIdentifier() != null) {
615             paymentDetail.setPurchaseOrderNbr(paymentRequestDocument.getPurchaseOrderIdentifier().toString());
616         }
617 
618         if (paymentRequestDocument.getPurchaseOrderDocument().getRequisitionIdentifier() != null) {
619             paymentDetail.setRequisitionNbr(paymentRequestDocument.getPurchaseOrderDocument().getRequisitionIdentifier().toString());
620         }
621 
622         if (paymentRequestDocument.getDocumentHeader().getOrganizationDocumentNumber() != null) {
623             paymentDetail.setOrganizationDocNbr(paymentRequestDocument.getDocumentHeader().getOrganizationDocumentNumber());
624         }
625 
626         paymentDetail.setCustomerInstitutionNumber(StringUtils.defaultString(paymentRequestDocument.getVendorCustomerNumber()));
627 
628         final String paymentRequestDocType = getDataDictionaryService().getDocumentTypeNameByClass(paymentRequestDocument.getClass());
629         paymentDetail.setFinancialDocumentTypeCode(paymentRequestDocType);
630         paymentDetail.setFinancialSystemOriginCode(OLEConstants.ORIGIN_CODE_KUALI);
631 
632         paymentDetail.setInvoiceDate(paymentRequestDocument.getInvoiceDate());
633         paymentDetail.setOrigInvoiceAmount(paymentRequestDocument.getVendorInvoiceAmount());
634         if (paymentRequestDocument.isUseTaxIndicator()) {
635             paymentDetail.setNetPaymentAmount(paymentRequestDocument.getGrandPreTaxTotal()); // including discounts
636         } else {
637             paymentDetail.setNetPaymentAmount(paymentRequestDocument.getGrandTotal()); // including discounts
638         }
639 
640         KualiDecimal shippingAmount = KualiDecimal.ZERO;
641         KualiDecimal discountAmount = KualiDecimal.ZERO;
642         KualiDecimal creditAmount = KualiDecimal.ZERO;
643         KualiDecimal debitAmount = KualiDecimal.ZERO;
644 
645         for (Iterator iter = paymentRequestDocument.getItems().iterator(); iter.hasNext(); ) {
646             PaymentRequestItem item = (PaymentRequestItem) iter.next();
647 
648             KualiDecimal itemAmount = KualiDecimal.ZERO;
649             if (item.getTotalRemitAmount() != null) {
650                 itemAmount = item.getTotalRemitAmount();
651             }
652             if (PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE.equals(item.getItemTypeCode())) {
653                 discountAmount = discountAmount.add(itemAmount);
654             } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_SHIP_AND_HAND_CODE.equals(item.getItemTypeCode())) {
655                 shippingAmount = shippingAmount.add(itemAmount);
656             } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_FREIGHT_CODE.equals(item.getItemTypeCode())) {
657                 shippingAmount = shippingAmount.add(itemAmount);
658             } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_MIN_ORDER_CODE.equals(item.getItemTypeCode())) {
659                 debitAmount = debitAmount.add(itemAmount);
660             } else if (PurapConstants.ItemTypeCodes.ITEM_TYPE_MISC_CODE.equals(item.getItemTypeCode())) {
661                 if (itemAmount.isNegative()) {
662                     creditAmount = creditAmount.add(itemAmount);
663                 } else {
664                     debitAmount = debitAmount.add(itemAmount);
665                 }
666             }
667         }
668 
669         paymentDetail.setInvTotDiscountAmount(discountAmount);
670         paymentDetail.setInvTotShipAmount(shippingAmount);
671         paymentDetail.setInvTotOtherCreditAmount(creditAmount);
672         paymentDetail.setInvTotOtherDebitAmount(debitAmount);
673 
674         paymentDetail.setPrimaryCancelledPayment(Boolean.FALSE);
675 
676         addAccounts(paymentRequestDocument, paymentDetail, paymentRequestDocType);
677         addNotes(paymentRequestDocument, paymentDetail);
678 
679         return paymentDetail;
680     }
681 
682     /**
683      * Add accounts to a PDP Payment Detail
684      *
685      * @param accountsPayableDocument
686      * @param paymentDetail
687      * @param documentType
688      */
689     protected void addAccounts(AccountsPayableDocument accountsPayableDocument, PaymentDetail paymentDetail, String documentType) {
690         String creditMemoDocType = getDataDictionaryService().getDocumentTypeNameByClass(VendorCreditMemoDocument.class);
691         List<SourceAccountingLine> sourceAccountingLines = purapAccountingService.generateSourceAccountsForVendorRemit(accountsPayableDocument);
692         for (SourceAccountingLine sourceAccountingLine : sourceAccountingLines) {
693             KualiDecimal lineAmount = sourceAccountingLine.getAmount();
694             PaymentAccountDetail paymentAccountDetail = new PaymentAccountDetail();
695             paymentAccountDetail.setAccountNbr(sourceAccountingLine.getAccountNumber());
696 
697             if (creditMemoDocType.equals(documentType)) {
698                 lineAmount = lineAmount.negated();
699             }
700 
701             paymentAccountDetail.setAccountNetAmount(sourceAccountingLine.getAmount());
702             paymentAccountDetail.setFinChartCode(sourceAccountingLine.getChartOfAccountsCode());
703             paymentAccountDetail.setFinObjectCode(sourceAccountingLine.getFinancialObjectCode());
704 
705             paymentAccountDetail.setFinSubObjectCode(StringUtils.defaultIfEmpty(sourceAccountingLine.getFinancialSubObjectCode(), OLEConstants.getDashFinancialSubObjectCode()));
706             paymentAccountDetail.setOrgReferenceId(sourceAccountingLine.getOrganizationReferenceId());
707             paymentAccountDetail.setProjectCode(StringUtils.defaultIfEmpty(sourceAccountingLine.getProjectCode(), OLEConstants.getDashProjectCode()));
708             paymentAccountDetail.setSubAccountNbr(StringUtils.defaultIfEmpty(sourceAccountingLine.getSubAccountNumber(), OLEConstants.getDashSubAccountNumber()));
709             paymentDetail.addAccountDetail(paymentAccountDetail);
710         }
711     }
712 
713     /**
714      * Add Notes to a PDP Payment Detail
715      *
716      * @param accountsPayableDocument
717      * @param paymentDetail
718      */
719     protected void addNotes(AccountsPayableDocument accountsPayableDocument, PaymentDetail paymentDetail) {
720         int count = 1;
721 
722         if (accountsPayableDocument instanceof PaymentRequestDocument) {
723             PaymentRequestDocument prd = (PaymentRequestDocument) accountsPayableDocument;
724 
725             if (prd.getSpecialHandlingInstructionLine1Text() != null) {
726                 PaymentNoteText pnt = new PaymentNoteText();
727                 pnt.setCustomerNoteLineNbr(new KualiInteger(count++));
728                 pnt.setCustomerNoteText(prd.getSpecialHandlingInstructionLine1Text());
729                 paymentDetail.addNote(pnt);
730             }
731 
732             if (prd.getSpecialHandlingInstructionLine2Text() != null) {
733                 PaymentNoteText pnt = new PaymentNoteText();
734                 pnt.setCustomerNoteLineNbr(new KualiInteger(count++));
735                 pnt.setCustomerNoteText(prd.getSpecialHandlingInstructionLine2Text());
736                 paymentDetail.addNote(pnt);
737             }
738 
739             if (prd.getSpecialHandlingInstructionLine3Text() != null) {
740                 PaymentNoteText pnt = new PaymentNoteText();
741                 pnt.setCustomerNoteLineNbr(new KualiInteger(count++));
742                 pnt.setCustomerNoteText(prd.getSpecialHandlingInstructionLine3Text());
743                 paymentDetail.addNote(pnt);
744             }
745         }
746 
747         if (accountsPayableDocument.getNoteLine1Text() != null) {
748             PaymentNoteText pnt = new PaymentNoteText();
749             pnt.setCustomerNoteLineNbr(new KualiInteger(count++));
750             pnt.setCustomerNoteText(accountsPayableDocument.getNoteLine1Text());
751             paymentDetail.addNote(pnt);
752         }
753 
754         if (accountsPayableDocument.getNoteLine2Text() != null) {
755             PaymentNoteText pnt = new PaymentNoteText();
756             pnt.setCustomerNoteLineNbr(new KualiInteger(count++));
757             pnt.setCustomerNoteText(accountsPayableDocument.getNoteLine2Text());
758             paymentDetail.addNote(pnt);
759         }
760 
761         if (accountsPayableDocument.getNoteLine3Text() != null) {
762             PaymentNoteText pnt = new PaymentNoteText();
763             pnt.setCustomerNoteLineNbr(new KualiInteger(count++));
764             pnt.setCustomerNoteText(accountsPayableDocument.getNoteLine3Text());
765             paymentDetail.addNote(pnt);
766         }
767 
768         PaymentNoteText pnt = new PaymentNoteText();
769         pnt.setCustomerNoteLineNbr(new KualiInteger(count++));
770         pnt.setCustomerNoteText("Sales Tax: " + accountsPayableDocument.getTotalRemitTax());
771     }
772 
773     /**
774      * Populate the PDP Payment Group from fields on a payment request
775      *
776      * @param paymentRequestDocument
777      * @param batch
778      * @return PaymentGroup
779      */
780     protected PaymentGroup populatePaymentGroup(PaymentRequestDocument paymentRequestDocument, Batch batch) {
781         if (LOG.isDebugEnabled()) {
782             LOG.debug("populatePaymentGroup() payment request documentNumber: " + paymentRequestDocument.getDocumentNumber());
783         }
784 
785         PaymentGroup paymentGroup = new PaymentGroup();
786 
787         paymentGroup.setBatchId(batch.getId());
788         paymentGroup.setPaymentStatusCode(OLEConstants.PdpConstants.PAYMENT_OPEN_STATUS_CODE);
789         paymentGroup.setBankCode(paymentRequestDocument.getBankCode());
790 
791         String postalCode = paymentRequestDocument.getVendorPostalCode();
792         if (OLEConstants.COUNTRY_CODE_UNITED_STATES.equals(paymentRequestDocument.getVendorCountry())) {
793             // Add a dash in the zip code if necessary
794             if (postalCode.length() > 5) {
795                 postalCode = postalCode.substring(0, 5) + "-" + postalCode.substring(5);
796             }
797         }
798 
799         Integer vendorHeaderGeneratedIdentifier = paymentRequestDocument.getVendorHeaderGeneratedIdentifier();
800         String aliasName = getVendorAliasName(vendorHeaderGeneratedIdentifier);
801         if(aliasName != null){
802             paymentGroup.setVendorAliasName(aliasName);
803         }
804 
805         paymentGroup.setPayeeName(paymentRequestDocument.getVendorName());
806         paymentGroup.setPayeeId(paymentRequestDocument.getVendorHeaderGeneratedIdentifier() + "-" + paymentRequestDocument.getVendorDetailAssignedIdentifier());
807         paymentGroup.setPayeeIdTypeCd(PdpConstants.PayeeIdTypeCodes.VENDOR_ID);
808 
809         if (paymentRequestDocument.getVendorDetail().getVendorHeader().getVendorOwnershipCategoryCode() != null) {
810             paymentGroup.setPayeeOwnerCd(paymentRequestDocument.getVendorDetail().getVendorHeader().getVendorOwnershipCategoryCode());
811         }
812 
813 //        if (paymentRequestDocument.getVendorCustomerNumber() != null) {
814 //            paymentGroup.setCustomerInstitutionNumber(paymentRequestDocument.getVendorCustomerNumber());
815 //        }
816 
817         paymentGroup.setLine1Address(paymentRequestDocument.getVendorLine1Address());
818         paymentGroup.setLine2Address(paymentRequestDocument.getVendorLine2Address());
819         paymentGroup.setLine3Address("");
820         paymentGroup.setLine4Address("");
821 
822         paymentGroup.setCity(paymentRequestDocument.getVendorCityName());
823         paymentGroup.setState(paymentRequestDocument.getVendorStateCode());
824         paymentGroup.setZipCd(postalCode);
825         paymentGroup.setCountry(paymentRequestDocument.getVendorCountryCode());
826         paymentGroup.setCampusAddress(Boolean.FALSE);
827 
828         if (paymentRequestDocument.getPaymentRequestPayDate() != null) {
829             paymentGroup.setPaymentDate(paymentRequestDocument.getPaymentRequestPayDate());
830         }
831 
832         paymentGroup.setPymtAttachment(paymentRequestDocument.getPaymentAttachmentIndicator());
833         paymentGroup.setProcessImmediate(paymentRequestDocument.getImmediatePaymentIndicator());
834         paymentGroup.setPymtSpecialHandling(StringUtils.isNotBlank(paymentRequestDocument.getSpecialHandlingInstructionLine1Text()) || StringUtils.isNotBlank(paymentRequestDocument.getSpecialHandlingInstructionLine2Text()) || StringUtils.isNotBlank(paymentRequestDocument.getSpecialHandlingInstructionLine3Text()));
835         paymentGroup.setTaxablePayment(Boolean.FALSE);
836         paymentGroup.setNraPayment(VendorConstants.OwnerTypes.NR.equals(paymentRequestDocument.getVendorDetail().getVendorHeader().getVendorOwnershipCode()));
837         paymentGroup.setCombineGroups(Boolean.TRUE);
838 
839         return paymentGroup;
840     }
841 
842     /**
843      * Populates a PaymentGroup record from a Credit Memo document
844      *
845      * @param creditMemoDocument
846      * @param batch
847      * @return PaymentGroup
848      */
849     protected PaymentGroup populatePaymentGroup(VendorCreditMemoDocument creditMemoDocument, Batch batch) {
850         if (LOG.isDebugEnabled()) {
851             LOG.debug("populatePaymentGroup() credit memo documentNumber: " + creditMemoDocument.getDocumentNumber());
852         }
853 
854         PaymentGroup paymentGroup = new PaymentGroup();
855         paymentGroup.setBatchId(batch.getId());
856         paymentGroup.setPaymentStatusCode(OLEConstants.PdpConstants.PAYMENT_OPEN_STATUS_CODE);
857         paymentGroup.setBankCode(creditMemoDocument.getBankCode());
858 
859         String postalCode = creditMemoDocument.getVendorPostalCode();
860         if (OLEConstants.COUNTRY_CODE_UNITED_STATES.equals(creditMemoDocument.getVendorCountry())) {
861             // Add a dash in the zip code if necessary
862             if (postalCode.length() > 5) {
863                 postalCode = postalCode.substring(0, 5) + "-" + postalCode.substring(5);
864             }
865         }
866 
867         paymentGroup.setPayeeName(creditMemoDocument.getVendorName());
868         paymentGroup.setPayeeId(creditMemoDocument.getVendorHeaderGeneratedIdentifier() + "-" + creditMemoDocument.getVendorDetailAssignedIdentifier());
869         paymentGroup.setPayeeIdTypeCd(PdpConstants.PayeeIdTypeCodes.VENDOR_ID);
870         Integer vendorHeaderGeneratedIdentifier = creditMemoDocument.getVendorHeaderGeneratedIdentifier();
871         String aliasName = getVendorAliasName(vendorHeaderGeneratedIdentifier);
872         if(aliasName != null){
873             paymentGroup.setVendorAliasName(aliasName);
874         }
875 
876         if (creditMemoDocument.getVendorDetail().getVendorHeader().getVendorOwnershipCategoryCode() != null) {
877             paymentGroup.setPayeeOwnerCd(creditMemoDocument.getVendorDetail().getVendorHeader().getVendorOwnershipCategoryCode());
878         }
879 
880 //        if (creditMemoDocument.getVendorCustomerNumber() != null) {
881 //            paymentGroup.setCustomerInstitutionNumber(creditMemoDocument.getVendorCustomerNumber());
882 //        }
883 
884         paymentGroup.setLine1Address(creditMemoDocument.getVendorLine1Address());
885         paymentGroup.setLine2Address(creditMemoDocument.getVendorLine2Address());
886         paymentGroup.setLine3Address("");
887         paymentGroup.setLine4Address("");
888 
889         paymentGroup.setCity(creditMemoDocument.getVendorCityName());
890         paymentGroup.setState(creditMemoDocument.getVendorStateCode());
891         paymentGroup.setZipCd(postalCode);
892         paymentGroup.setCountry(creditMemoDocument.getVendorCountryCode());
893         paymentGroup.setCampusAddress(Boolean.FALSE);
894 
895         if (creditMemoDocument.getCreditMemoDate() != null) {
896             paymentGroup.setPaymentDate(creditMemoDocument.getCreditMemoDate());
897         }
898 
899         paymentGroup.setPymtAttachment(Boolean.FALSE);
900         paymentGroup.setProcessImmediate(Boolean.FALSE);
901         paymentGroup.setPymtSpecialHandling(Boolean.FALSE);
902         paymentGroup.setTaxablePayment(Boolean.FALSE);
903         paymentGroup.setNraPayment(VendorConstants.OwnerTypes.NR.equals(creditMemoDocument.getVendorDetail().getVendorHeader().getVendorOwnershipCode()));
904         paymentGroup.setCombineGroups(Boolean.TRUE);
905 
906         return paymentGroup;
907     }
908 
909     /**
910      * Create a new PDP batch
911      *
912      * @param campusCode
913      * @param puser
914      * @param processRunDate
915      * @return Batch
916      */
917     protected Batch createBatch(String campusCode, Person puser, Date processRunDate) {
918         String orgCode = parameterService.getParameterValueAsString(OleParameterConstants.PURCHASING_BATCH.class, OLEParameterKeyConstants.PurapPdpParameterConstants.PURAP_PDP_ORG_CODE);
919         String subUnitCode = parameterService.getParameterValueAsString(OleParameterConstants.PURCHASING_BATCH.class, OLEParameterKeyConstants.PurapPdpParameterConstants.PURAP_PDP_SUB_UNIT_CODE);
920         CustomerProfile customer = customerProfileService.get(campusCode, orgCode, subUnitCode);
921         if (customer == null) {
922             throw new IllegalArgumentException("Unable to find customer profile for " + campusCode + "/" + orgCode + "/" + subUnitCode);
923         }
924 
925         // Create the group for this campus
926         Batch batch = new Batch();
927         batch.setCustomerProfile(customer);
928         batch.setCustomerFileCreateTimestamp(new Timestamp(processRunDate.getTime()));
929         batch.setFileProcessTimestamp(new Timestamp(processRunDate.getTime()));
930         batch.setPaymentFileName(PurapConstants.PDP_PURAP_EXTRACT_FILE_NAME);
931         batch.setSubmiterUserId(puser.getPrincipalId());
932 
933         // Set these for now, we will update them later
934         batch.setPaymentCount(KualiInteger.ZERO);
935         batch.setPaymentTotalAmount(KualiDecimal.ZERO);
936 
937         businessObjectService.save(batch);
938 
939         return batch;
940     }
941 
942     /**
943      * Find all the campuses that have payments to process
944      *
945      * @return List<String>
946      */
947 
948     protected List<String> getChartCodes(boolean immediatesOnly, Date processRunDate) {
949         List<String> output = new ArrayList<String>();
950 
951         Iterator<PaymentRequestDocument> paymentRequests = null;
952         if (immediatesOnly) {
953             paymentRequests = paymentRequestService.getImmediatePaymentRequestsToExtract(null).iterator();
954         } else {
955             java.sql.Date onOrBeforePaymentRequestPayDate = KfsDateUtils.convertToSqlDate(purapRunDateService.calculateRunDate(processRunDate));
956             paymentRequests = paymentRequestService.getPaymentRequestsToExtract(onOrBeforePaymentRequestPayDate).iterator();
957         }
958 
959         while (paymentRequests.hasNext()) {
960             PaymentRequestDocument prd = paymentRequests.next();
961             if (!output.contains(prd.getProcessingCampusCode())) {
962                 output.add(prd.getProcessingCampusCode());
963             }
964         }
965 
966         return output;
967     }
968 
969 
970     /**
971      * Holds total count and amount for extract
972      */
973     protected class Totals {
974         public Integer count = 0;
975         public KualiDecimal totalAmount = KualiDecimal.ZERO;
976     }
977 
978     /**
979      * Holds temporary accounting information for combining into payment accounting details
980      */
981     protected class AccountingInfo {
982         private String chart;
983         private String account;
984         private String subAccount;
985         private String objectCode;
986         private String subObjectCode;
987         private String orgReferenceId;
988         private String projectCode;
989 
990         public AccountingInfo(String c, String a, String s, String o, String so, String or, String pc) {
991             setChart(c);
992             setAccount(a);
993             setSubAccount(s);
994             setObjectCode(o);
995             setSubObjectCode(so);
996             setOrgReferenceId(or);
997             setProjectCode(pc);
998         }
999 
1000         public void setAccount(String account) {
1001             this.account = account;
1002         }
1003 
1004         public void setChart(String chart) {
1005             this.chart = chart;
1006         }
1007 
1008         public void setObjectCode(String objectCode) {
1009             this.objectCode = objectCode;
1010         }
1011 
1012         public void setOrgReferenceId(String orgReferenceId) {
1013             this.orgReferenceId = orgReferenceId;
1014         }
1015 
1016         public void setProjectCode(String projectCode) {
1017             if (projectCode == null) {
1018                 this.projectCode = OLEConstants.getDashProjectCode();
1019             } else {
1020                 this.projectCode = projectCode;
1021             }
1022         }
1023 
1024         public void setSubAccount(String subAccount) {
1025             if (subAccount == null) {
1026                 this.subAccount = OLEConstants.getDashSubAccountNumber();
1027             } else {
1028                 this.subAccount = subAccount;
1029             }
1030         }
1031 
1032         public void setSubObjectCode(String subObjectCode) {
1033             if (subObjectCode == null) {
1034                 this.subObjectCode = OLEConstants.getDashFinancialSubObjectCode();
1035             } else {
1036                 this.subObjectCode = subObjectCode;
1037             }
1038         }
1039 
1040         protected String key() {
1041             return chart + "~" + account + "~" + subAccount + "~" + objectCode + "~" + subObjectCode + "~" + orgReferenceId + "~" + projectCode;
1042         }
1043 
1044         @Override
1045         public int hashCode() {
1046             return new HashCodeBuilder(3, 5).append(key()).toHashCode();
1047         }
1048 
1049         @Override
1050         public boolean equals(Object obj) {
1051             if (!(obj instanceof AccountingInfo)) {
1052                 return false;
1053             }
1054             AccountingInfo thisobj = (AccountingInfo) obj;
1055             return new EqualsBuilder().append(key(), thisobj.key()).isEquals();
1056         }
1057     }
1058 
1059     private void lockUnlockDocuments(boolean locked) {
1060         for (String documentType : lockedDocuments) {
1061             Class<? extends Document> documentClass = dataDictionaryService.getDocumentClassByTypeName(documentType);
1062             if (parameterService.parameterExists(documentClass, OLEConstants.DOCUMENT_LOCKOUT_PARM_NM)) {
1063                 Parameter existingParam = parameterService.getParameter(documentClass, OLEConstants.DOCUMENT_LOCKOUT_PARM_NM);
1064                 Parameter.Builder updatedParam = Builder.create(existingParam);
1065                 updatedParam.setValue(locked ? "Y" : "N");
1066                 parameterService.updateParameter(updatedParam.build());
1067             } else {
1068                 String namespace = KRADServiceLocatorWeb.getKualiModuleService().getNamespaceCode(documentClass);
1069                 String detailType = KRADServiceLocatorWeb.getKualiModuleService().getComponentCode(documentClass);
1070                 Parameter.Builder newParam = Builder.create(OLEConstants.APPLICATION_NAMESPACE_CODE, namespace, detailType, OLEConstants.DOCUMENT_LOCKOUT_PARM_NM, ParameterType.Builder.create(OleParameterConstants.PARAMETER_CONFIG_TYPE_CODE));
1071                 newParam.setValue("Y");
1072                 newParam.setDescription(OLEConstants.DOCUMENT_LOCKOUT_PARM_DESC);
1073                 parameterService.createParameter(newParam.build());
1074             }
1075         }
1076     }
1077 
1078     /**
1079      * Sets the paymentRequestService attribute value.
1080      *
1081      * @param paymentRequestService The paymentRequestService to set.
1082      */
1083     public void setPaymentRequestService(PaymentRequestService paymentRequestService) {
1084         this.paymentRequestService = paymentRequestService;
1085     }
1086 
1087     /**
1088      * Sets the businessObjectService attribute value.
1089      *
1090      * @param businessObjectService The businessObjectService to set.
1091      */
1092     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
1093         this.businessObjectService = businessObjectService;
1094     }
1095 
1096     /**
1097      * Sets the paymentFileService attribute value.
1098      *
1099      * @param paymentFileService The paymentFileService to set.
1100      */
1101     public void setPaymentFileService(PaymentFileService paymentFileService) {
1102         this.paymentFileService = paymentFileService;
1103     }
1104 
1105     /**
1106      * Sets the parameterService attribute value.
1107      *
1108      * @param parameterService The parameterService to set.
1109      */
1110     public void setParameterService(ParameterService parameterService) {
1111         this.parameterService = parameterService;
1112     }
1113 
1114     /**
1115      * Sets the customerProfileService attribute value.
1116      *
1117      * @param customerProfileService The customerProfileService to set.
1118      */
1119     public void setCustomerProfileService(CustomerProfileService customerProfileService) {
1120         this.customerProfileService = customerProfileService;
1121     }
1122 
1123     /**
1124      * Sets the dateTimeService attribute value.
1125      *
1126      * @param dateTimeService The dateTimeService to set.
1127      */
1128     public void setDateTimeService(DateTimeService dateTimeService) {
1129         this.dateTimeService = dateTimeService;
1130     }
1131 
1132     /**
1133      * Sets the paymentGroupService attribute value.
1134      *
1135      * @param paymentGroupService The paymentGroupService to set.
1136      */
1137     public void setPaymentGroupService(PaymentGroupService paymentGroupService) {
1138         this.paymentGroupService = paymentGroupService;
1139     }
1140 
1141     /**
1142      * Sets the paymentDetailService attribute value.
1143      *
1144      * @param paymentDetailService The paymentDetailService to set.
1145      */
1146     public void setPaymentDetailService(PaymentDetailService paymentDetailService) {
1147         this.paymentDetailService = paymentDetailService;
1148     }
1149 
1150     /**
1151      * Sets the creditMemoService attribute value.
1152      *
1153      * @param creditMemoService The creditMemoService to set.
1154      */
1155     public void setCreditMemoService(CreditMemoService creditMemoService) {
1156         this.creditMemoService = creditMemoService;
1157     }
1158 
1159     /**
1160      * Sets the documentService attribute value.
1161      *
1162      * @param documentService The documentService to set.
1163      */
1164     public void setDocumentService(DocumentService documentService) {
1165         this.documentService = documentService;
1166     }
1167 
1168     /**
1169      * Sets the purapRunDateService attribute value.
1170      *
1171      * @param purapRunDateService The purapRunDateService to set.
1172      */
1173     public void setPurapRunDateService(PurapRunDateService purapRunDateService) {
1174         this.purapRunDateService = purapRunDateService;
1175     }
1176 
1177     /**
1178      * Sets the paymentFileEmailService attribute value.
1179      *
1180      * @param paymentFileEmailService The paymentFileEmailService to set.
1181      */
1182     public void setPaymentFileEmailService(PdpEmailService paymentFileEmailService) {
1183         this.paymentFileEmailService = paymentFileEmailService;
1184     }
1185 
1186     /**
1187      * Sets the bankService attribute value.
1188      *
1189      * @param bankService The bankService to set.
1190      */
1191     public void setBankService(BankService bankService) {
1192         this.bankService = bankService;
1193     }
1194 
1195     /**
1196      * Gets the dataDictionaryService attribute.
1197      *
1198      * @return Returns the dataDictionaryService.
1199      */
1200     public DataDictionaryService getDataDictionaryService() {
1201         return dataDictionaryService;
1202     }
1203 
1204     /**
1205      * Sets the dataDictionaryService attribute value.
1206      *
1207      * @param dataDictionaryService The dataDictionaryService to set.
1208      */
1209     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
1210         this.dataDictionaryService = dataDictionaryService;
1211     }
1212 
1213     public void setPurapAccountingService(PurapAccountingServiceImpl purapAccountingService) {
1214         this.purapAccountingService = purapAccountingService;
1215     }
1216 
1217     /**
1218      * @return Returns the personService.
1219      */
1220     protected PersonService getPersonService() {
1221         if (personService == null) {
1222             personService = SpringContext.getBean(PersonService.class);
1223         }
1224         return personService;
1225     }
1226 
1227     public void setLockedDocuments(List<String> lockedDocuments) {
1228         this.lockedDocuments = lockedDocuments;
1229     }
1230 
1231     protected BusinessObjectService getBusinessObjectService() {
1232         if (businessObjectService == null) {
1233             businessObjectService = SpringContext.getBean(BusinessObjectService.class);
1234         }
1235         return businessObjectService;
1236     }
1237 
1238     public String getVendorAliasName(Integer vendorHeaderGeneratedIdentifier) {
1239         Map searchMap = new HashMap();
1240         searchMap.put(OLEConstants.VENDOR_HDR_GEN_ID, vendorHeaderGeneratedIdentifier);
1241         List<VendorAlias> vendorAliasList = (List<VendorAlias>) SpringContext.getBean(BusinessObjectService.class).findMatching(VendorAlias.class, searchMap);
1242         Integer vendorAliasTypeId;
1243         if (vendorAliasList.size() > 0) {
1244             for (VendorAlias vendorAlias : vendorAliasList) {
1245                 vendorAliasTypeId = vendorAlias.getVendorAliasTypeId();
1246                 if (vendorAliasTypeId != null) {
1247                     String vendorAliasTypeName = getVendorAliasTypeName(vendorAliasTypeId);
1248                     if (vendorAliasTypeName != null && vendorAliasTypeName.equalsIgnoreCase(OLEConstants.EXTERNAL_VNDR_CD)) {
1249                         //return vendorAliasTypeName;
1250                         return vendorAlias.getVendorAliasName();
1251                     }
1252                 }
1253             }
1254         }
1255         return null;
1256     }
1257 
1258     public String getVendorAliasTypeName(Integer vendorAliasTypeId) {
1259         Map searchMap = new HashMap();
1260         searchMap.put(OLEConstants.ALIAS_TYP_ID, vendorAliasTypeId);
1261         AliasType aliasType = SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(AliasType.class, searchMap);
1262         if (aliasType != null) {
1263             return aliasType.getAliasType();
1264         }
1265         return null;
1266     }
1267 
1268     public OleSelectDocumentService getOleSelectDocumentService() {
1269         if(oleSelectDocumentService == null){
1270             oleSelectDocumentService = SpringContext.getBean(OleSelectDocumentService.class);
1271         }
1272         return oleSelectDocumentService;
1273     }
1274 
1275     public void setOleSelectDocumentService(OleSelectDocumentService oleSelectDocumentService) {
1276         this.oleSelectDocumentService = oleSelectDocumentService;
1277     }
1278 
1279 }