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