001/*
002 * Copyright 2007 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.ole.module.purap.service.impl;
017
018import org.apache.commons.lang.StringUtils;
019import org.apache.commons.lang.builder.EqualsBuilder;
020import org.apache.commons.lang.builder.HashCodeBuilder;
021import org.kuali.ole.module.purap.PurapConstants;
022import org.kuali.ole.module.purap.batch.service.PurapRunDateService;
023import org.kuali.ole.module.purap.businessobject.CreditMemoItem;
024import org.kuali.ole.module.purap.businessobject.PaymentRequestItem;
025import org.kuali.ole.module.purap.document.AccountsPayableDocument;
026import org.kuali.ole.module.purap.document.PaymentRequestDocument;
027import org.kuali.ole.module.purap.document.VendorCreditMemoDocument;
028import org.kuali.ole.module.purap.document.service.CreditMemoService;
029import org.kuali.ole.module.purap.document.service.PaymentRequestService;
030import org.kuali.ole.module.purap.document.service.PurapService;
031import org.kuali.ole.module.purap.service.PdpExtractService;
032import org.kuali.ole.module.purap.util.VendorGroupingHelper;
033import org.kuali.ole.pdp.PdpConstants;
034import org.kuali.ole.pdp.PdpParameterConstants;
035import org.kuali.ole.pdp.businessobject.*;
036import org.kuali.ole.pdp.service.*;
037import org.kuali.ole.select.businessobject.OlePaymentMethod;
038import org.kuali.ole.select.document.OlePaymentRequestDocument;
039import org.kuali.ole.select.document.service.OleSelectDocumentService;
040import org.kuali.ole.sys.OLEConstants;
041import org.kuali.ole.sys.OLEParameterKeyConstants;
042import org.kuali.ole.sys.businessobject.SourceAccountingLine;
043import org.kuali.ole.sys.context.SpringContext;
044import org.kuali.ole.sys.service.BankService;
045import org.kuali.ole.sys.service.impl.OleParameterConstants;
046import org.kuali.ole.sys.util.KfsDateUtils;
047import org.kuali.ole.vnd.VendorConstants;
048import org.kuali.ole.vnd.businessobject.AliasType;
049import org.kuali.ole.vnd.businessobject.VendorAlias;
050import org.kuali.rice.core.api.datetime.DateTimeService;
051import org.kuali.rice.core.api.util.type.KualiDecimal;
052import org.kuali.rice.core.api.util.type.KualiInteger;
053import org.kuali.rice.coreservice.api.parameter.Parameter;
054import org.kuali.rice.coreservice.api.parameter.Parameter.Builder;
055import org.kuali.rice.coreservice.api.parameter.ParameterType;
056import org.kuali.rice.coreservice.framework.parameter.ParameterService;
057import org.kuali.rice.kew.api.exception.WorkflowException;
058import org.kuali.rice.kim.api.identity.Person;
059import org.kuali.rice.kim.api.identity.PersonService;
060import org.kuali.rice.kns.service.DataDictionaryService;
061import org.kuali.rice.krad.document.Document;
062import org.kuali.rice.krad.service.BusinessObjectService;
063import org.kuali.rice.krad.service.DocumentService;
064import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
065import org.springframework.transaction.annotation.Transactional;
066
067import java.sql.Timestamp;
068import java.util.*;
069
070/**
071 * Implementation of PdpExtractService
072 */
073@Transactional
074public class PdpExtractServiceImpl implements PdpExtractService {
075    private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PdpExtractServiceImpl.class);
076
077    private PaymentRequestService paymentRequestService;
078    private BusinessObjectService businessObjectService;
079    private PaymentFileService paymentFileService;
080    private ParameterService parameterService;
081    private CustomerProfileService customerProfileService;
082    private DateTimeService dateTimeService;
083    private PersonService personService;
084    private PaymentGroupService paymentGroupService;
085    private PaymentDetailService paymentDetailService;
086    private CreditMemoService creditMemoService;
087    private DocumentService documentService;
088    private PurapRunDateService purapRunDateService;
089    private PdpEmailService paymentFileEmailService;
090    private BankService bankService;
091    private DataDictionaryService dataDictionaryService;
092    private PurapAccountingServiceImpl purapAccountingService;
093    private List<String> lockedDocuments;
094    private OleSelectDocumentService oleSelectDocumentService;
095
096    /**
097     * @see org.kuali.ole.module.purap.service.PdpExtractService#extractImmediatePaymentsOnly()
098     */
099    @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}