001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.module.pdp.service.impl;
017:
018: import java.io.BufferedWriter;
019: import java.io.FileWriter;
020: import java.io.IOException;
021: import java.sql.Timestamp;
022: import java.text.SimpleDateFormat;
023: import java.util.Date;
024: import java.util.Iterator;
025: import java.util.List;
026:
027: import org.kuali.core.service.DateTimeService;
028: import org.kuali.kfs.service.ParameterService;
029: import org.kuali.kfs.service.impl.ParameterConstants;
030: import org.kuali.module.pdp.PdpConstants;
031: import org.kuali.module.pdp.bo.Bank;
032: import org.kuali.module.pdp.bo.CustomerProfile;
033: import org.kuali.module.pdp.bo.PaymentDetail;
034: import org.kuali.module.pdp.bo.PaymentGroup;
035: import org.kuali.module.pdp.bo.PaymentGroupHistory;
036: import org.kuali.module.pdp.bo.PaymentNoteText;
037: import org.kuali.module.pdp.bo.PaymentProcess;
038: import org.kuali.module.pdp.bo.PaymentStatus;
039: import org.kuali.module.pdp.dao.PaymentGroupHistoryDao;
040: import org.kuali.module.pdp.dao.ProcessDao;
041: import org.kuali.module.pdp.service.ExtractPaymentService;
042: import org.kuali.module.pdp.service.PaymentDetailService;
043: import org.kuali.module.pdp.service.PaymentGroupService;
044: import org.kuali.module.pdp.service.ReferenceService;
045: import org.springframework.transaction.annotation.Transactional;
046:
047: @Transactional
048: public class ExtractPaymentServiceImpl implements ExtractPaymentService {
049: private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
050: .getLogger(ExtractPaymentServiceImpl.class);
051:
052: public ReferenceService referenceService;
053: public DateTimeService dateTimeService;
054: public ParameterService parameterService;
055: public PaymentGroupService paymentGroupService;
056: public PaymentDetailService paymentDetailService;
057: public PaymentGroupHistoryDao paymentGroupHistoryDao;
058: public String directoryName;
059: public ProcessDao processDao;
060:
061: // Set this to true to run this process without updating the database. This
062: // should stay false for production.
063: public static boolean testMode = false;
064:
065: private String getOutputFile(String fileprefix, Date runDate) {
066: String filename = directoryName + fileprefix + "_";
067: SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
068: filename = filename + sdf.format(runDate);
069: filename = filename + ".xml";
070:
071: return filename;
072: }
073:
074: /**
075: * @see org.kuali.module.pdp.service.ExtractPaymentService#extractCancelledChecks()
076: */
077: public void extractCanceledChecks() {
078: LOG.debug("extractCancelledChecks() started");
079:
080: Date processDate = dateTimeService.getCurrentDate();
081: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
082:
083: String filename = getOutputFile("pdp_cancel", processDate);
084: LOG.debug("extractCanceledChecks() filename = " + filename);
085:
086: // Open file
087: BufferedWriter os = null;
088:
089: try {
090: os = new BufferedWriter(new FileWriter(filename));
091: os.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
092: writeOpenTag(os, 0, "canceledChecks");
093:
094: Iterator paymentIterator = paymentGroupHistoryDao
095: .getCanceledChecks();
096: while (paymentIterator.hasNext()) {
097: PaymentGroupHistory history = (PaymentGroupHistory) paymentIterator
098: .next();
099:
100: writeOpenTag(os, 2, "check");
101:
102: writeBank(os, 4, history.getPaymentGroup().getBank());
103: writePayee(os, 4, history.getPaymentGroup());
104:
105: writeTag(os, 4, "netAmount", history.getPaymentGroup()
106: .getNetPaymentAmount().toString());
107: if (history.getOrigDisburseNbr() != null) {
108: writeTag(os, 4, "disbursementNumber", history
109: .getOrigDisburseNbr().toString());
110: } else {
111: writeTag(os, 4, "disbursementNumber", history
112: .getPaymentGroup().getDisbursementNbr()
113: .toString());
114: }
115: if (history.getPaymentGroup().getDisbursementType() != null) {
116: writeTag(os, 4, "disbursementType", history
117: .getPaymentGroup().getDisbursementType()
118: .getCode());
119: } else {
120: writeTag(os, 4, "disbursementType", history
121: .getDisbursementType().getCode());
122: }
123:
124: writeCloseTag(os, 2, "check");
125:
126: if (!testMode) {
127: history.setLastUpdate(new Timestamp(processDate
128: .getTime()));
129: history.setPmtCancelExtractDate(new Timestamp(
130: processDate.getTime()));
131: history.setPmtCancelExtractStat(Boolean.TRUE);
132: paymentGroupHistoryDao.save(history);
133: }
134: }
135:
136: writeCloseTag(os, 0, "canceledChecks");
137: } catch (IOException ie) {
138: LOG.error("extractCanceledChecks() Problem reading file: "
139: + filename, ie);
140: throw new IllegalArgumentException(
141: "Error writing to output file: " + ie.getMessage());
142: } finally {
143: // Close file
144: if (os != null) {
145: try {
146: os.close();
147: } catch (IOException ie) {
148: // Not much we can do now
149: }
150: }
151: }
152: }
153:
154: /**
155: * @see org.kuali.module.pdp.service.ExtractPaymentService#extractAchPayments()
156: */
157: public void extractAchPayments() {
158: LOG.debug("extractAchPayments() started");
159:
160: Date processDate = dateTimeService.getCurrentDate();
161: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
162: PaymentStatus extractedStatus = (PaymentStatus) referenceService
163: .getCode("PaymentStatus",
164: PdpConstants.PaymentStatusCodes.EXTRACTED);
165:
166: String filename = getOutputFile("pdp_ach", processDate);
167: LOG.debug("extractAchPayments() filename = " + filename);
168:
169: // Open file
170: BufferedWriter os = null;
171:
172: try {
173: os = new BufferedWriter(new FileWriter(filename));
174: os.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
175: writeOpenTag(os, 0, "achPayments");
176:
177: Iterator iter = paymentGroupService
178: .getByDisbursementTypeStatusCode(
179: PdpConstants.DisbursementTypeCodes.ACH,
180: PdpConstants.PaymentStatusCodes.PENDING_ACH);
181: while (iter.hasNext()) {
182: PaymentGroup pg = (PaymentGroup) iter.next();
183: if (!testMode) {
184: pg.setDisbursementDate(new Timestamp(processDate
185: .getTime()));
186: pg.setLastUpdate(new Timestamp(processDate
187: .getTime()));
188: pg.setPaymentStatus(extractedStatus);
189: paymentGroupService.save(pg);
190: }
191:
192: writeOpenTagAttribute(os, 2, "ach", "disbursementNbr",
193: pg.getDisbursementNbr().toString());
194: PaymentProcess paymentProcess = pg.getProcess();
195: writeTag(os, 4, "processCampus", paymentProcess
196: .getCampus());
197: writeTag(os, 4, "processId", paymentProcess.getId()
198: .toString());
199:
200: writeBank(os, 4, pg.getBank());
201:
202: writeTag(os, 4, "disbursementDate", sdf
203: .format(processDate));
204: writeTag(os, 4, "netAmount", pg.getNetPaymentAmount()
205: .toString());
206:
207: writePayeeAch(os, 4, pg);
208: writeTag(os, 4, "customerUnivNbr", pg
209: .getCustomerInstitutionNumber());
210: writeTag(os, 4, "paymentDate", sdf.format(pg
211: .getPaymentDate()));
212:
213: // Write customer profile information
214: CustomerProfile cp = pg.getBatch().getCustomerProfile();
215: writeCustomerProfile(os, 4, cp);
216:
217: // Write all payment level information
218: writeOpenTag(os, 4, "payments");
219: List pdList = pg.getPaymentDetails();
220: for (Iterator iterator = pdList.iterator(); iterator
221: .hasNext();) {
222: PaymentDetail pd = (PaymentDetail) iterator.next();
223: writeOpenTag(os, 6, "payment");
224:
225: // Write detail info
226: writeTag(os, 6, "purchaseOrderNbr", pd
227: .getPurchaseOrderNbr());
228: writeTag(os, 6, "invoiceNbr", pd.getInvoiceNbr());
229: writeTag(os, 6, "requisitionNbr", pd
230: .getRequisitionNbr());
231: writeTag(os, 6, "custPaymentDocNbr", pd
232: .getCustPaymentDocNbr());
233: writeTag(os, 6, "invoiceDate", sdf.format(pd
234: .getInvoiceDate()));
235:
236: writeTag(os, 6, "origInvoiceAmount", pd
237: .getOrigInvoiceAmount().toString());
238: writeTag(os, 6, "netPaymentAmount", pd
239: .getNetPaymentAmount().toString());
240: writeTag(os, 6, "invTotDiscountAmount", pd
241: .getInvTotDiscountAmount().toString());
242: writeTag(os, 6, "invTotShipAmount", pd
243: .getInvTotShipAmount().toString());
244: writeTag(os, 6, "invTotOtherDebitAmount", pd
245: .getInvTotOtherDebitAmount().toString());
246: writeTag(os, 6, "invTotOtherCreditAmount", pd
247: .getInvTotOtherCreditAmount().toString());
248:
249: writeOpenTag(os, 6, "notes");
250: for (Iterator i = pd.getNotes().iterator(); i
251: .hasNext();) {
252: PaymentNoteText note = (PaymentNoteText) i
253: .next();
254: writeTag(os, 8, "note", escapeString(note
255: .getCustomerNoteText()));
256: }
257: writeCloseTag(os, 6, "notes");
258:
259: writeCloseTag(os, 4, "payment");
260: }
261: writeCloseTag(os, 4, "payments");
262: writeCloseTag(os, 2, "ach");
263: }
264: writeCloseTag(os, 0, "achPayments");
265: } catch (IOException ie) {
266: LOG.error("extractAchPayments() Problem reading file: "
267: + filename, ie);
268: throw new IllegalArgumentException(
269: "Error writing to output file: " + ie.getMessage());
270: } finally {
271: // Close file
272: if (os != null) {
273: try {
274: os.close();
275: } catch (IOException ie) {
276: // Not much we can do now
277: }
278: }
279: }
280: }
281:
282: /**
283: * @see org.kuali.module.pdp.service.ExtractPaymentService#extractChecks()
284: */
285: public void extractChecks() {
286: LOG.debug("extractChecks() started");
287:
288: Date processDate = dateTimeService.getCurrentDate();
289: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
290:
291: // Get the process ID
292:
293: if (!parameterService
294: .parameterExists(
295: ParameterConstants.PRE_DISBURSEMENT_ALL.class,
296: PdpConstants.ApplicationParameterKeys.EXTRACT_PROCESS_ID)) {
297: throw new RuntimeException(
298: "This job should only be triggered by the format process. It should not be run manually");
299: }
300: String pids = parameterService
301: .getParameterValue(
302: ParameterConstants.PRE_DISBURSEMENT_ALL.class,
303: PdpConstants.ApplicationParameterKeys.EXTRACT_PROCESS_ID);
304: pids = pids.trim();
305:
306: Integer processId = null;
307: try {
308: processId = Integer.parseInt(pids);
309: } catch (NumberFormatException nfe) {
310: throw new IllegalArgumentException(
311: "Unable to convert the process ID to a number");
312: }
313:
314: PaymentProcess p = processDao.get(processId);
315: if (p == null) {
316: throw new IllegalArgumentException("Invalid process ID");
317: }
318:
319: String filename = getOutputFile("pdp_check", processDate);
320: LOG.debug("extractChecks() filename: " + filename);
321:
322: // Open file
323: BufferedWriter os = null;
324:
325: try {
326: os = new BufferedWriter(new FileWriter(filename));
327: os.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
328: writeOpenTagAttribute(os, 0, "checks", "processId",
329: processId.toString(), "campus", p.getCampus());
330:
331: List<Integer> disbNbrs = paymentGroupService
332: .getDisbursementNumbersByDisbursementType(
333: processId,
334: PdpConstants.DisbursementTypeCodes.CHECK);
335: for (Iterator iter = disbNbrs.iterator(); iter.hasNext();) {
336: Integer disbursementNbr = (Integer) iter.next();
337:
338: boolean first = true;
339:
340: Iterator i = paymentDetailService
341: .getByDisbursementNumber(disbursementNbr);
342: while (i.hasNext()) {
343: PaymentDetail pd = (PaymentDetail) i.next();
344: PaymentGroup pg = pd.getPaymentGroup();
345: if (!testMode) {
346: if (pg.getDisbursementDate() == null) {
347: pg.setDisbursementDate(new Timestamp(
348: processDate.getTime()));
349: pg.setLastUpdate(new Timestamp(processDate
350: .getTime()));
351: paymentGroupService.save(pg);
352: }
353: }
354:
355: if (first) {
356: writeOpenTagAttribute(os, 2, "check",
357: "disbursementNbr", pg
358: .getDisbursementNbr()
359: .toString());
360:
361: // Write check level information
362:
363: writeBank(os, 4, pg.getBank());
364:
365: writeTag(os, 4, "disbursementDate", sdf
366: .format(processDate));
367: writeTag(os, 4, "netAmount", pg
368: .getNetPaymentAmount().toString());
369:
370: writePayee(os, 4, pg);
371: writeTag(
372: os,
373: 4,
374: "campusAddressIndicator",
375: pg.getCampusAddress().booleanValue() ? "Y"
376: : "N");
377: writeTag(
378: os,
379: 4,
380: "attachmentIndicator",
381: pg.getPymtAttachment().booleanValue() ? "Y"
382: : "N");
383: writeTag(os, 4, "specialHandlingIndicator", pg
384: .getPymtSpecialHandling()
385: .booleanValue() ? "Y" : "N");
386: writeTag(
387: os,
388: 4,
389: "immediatePaymentIndicator",
390: pg.getProcessImmediate().booleanValue() ? "Y"
391: : "N");
392: writeTag(os, 4, "customerUnivNbr", pg
393: .getCustomerInstitutionNumber());
394: writeTag(os, 4, "paymentDate", sdf.format(pg
395: .getPaymentDate()));
396:
397: // Write customer profile information
398: CustomerProfile cp = pg.getBatch()
399: .getCustomerProfile();
400: writeCustomerProfile(os, 4, cp);
401:
402: writeOpenTag(os, 4, "payments");
403:
404: }
405:
406: writeOpenTag(os, 6, "payment");
407:
408: writeTag(os, 8, "purchaseOrderNbr", pd
409: .getPurchaseOrderNbr());
410: writeTag(os, 8, "invoiceNbr", pd.getInvoiceNbr());
411: writeTag(os, 8, "requisitionNbr", pd
412: .getRequisitionNbr());
413: writeTag(os, 8, "custPaymentDocNbr", pd
414: .getCustPaymentDocNbr());
415: writeTag(os, 8, "invoiceDate", sdf.format(pd
416: .getInvoiceDate()));
417:
418: writeTag(os, 8, "origInvoiceAmount", pd
419: .getOrigInvoiceAmount().toString());
420: writeTag(os, 8, "netPaymentAmount", pd
421: .getNetPaymentAmount().toString());
422: writeTag(os, 8, "invTotDiscountAmount", pd
423: .getInvTotDiscountAmount().toString());
424: writeTag(os, 8, "invTotShipAmount", pd
425: .getInvTotShipAmount().toString());
426: writeTag(os, 8, "invTotOtherDebitAmount", pd
427: .getInvTotOtherDebitAmount().toString());
428: writeTag(os, 8, "invTotOtherCreditAmount", pd
429: .getInvTotOtherCreditAmount().toString());
430:
431: writeOpenTag(os, 8, "notes");
432: for (Iterator ix = pd.getNotes().iterator(); ix
433: .hasNext();) {
434: PaymentNoteText note = (PaymentNoteText) ix
435: .next();
436: writeTag(os, 10, "note", note
437: .getCustomerNoteText());
438: }
439: writeCloseTag(os, 8, "notes");
440:
441: writeCloseTag(os, 6, "payment");
442:
443: first = false;
444: }
445: writeCloseTag(os, 4, "payments");
446: writeCloseTag(os, 2, "check");
447: }
448: writeCloseTag(os, 0, "checks");
449: } catch (IOException ie) {
450: LOG.error("extractChecks() Problem reading file: "
451: + filename, ie);
452: throw new IllegalArgumentException(
453: "Error writing to output file: " + ie.getMessage());
454: } finally {
455: // Close file
456: if (os != null) {
457: try {
458: os.close();
459: } catch (IOException ie) {
460: // Not much we can do now
461: }
462: }
463: }
464: }
465:
466: private static String SPACES = " ";
467:
468: private void writeTag(BufferedWriter os, int indent, String tag,
469: String data) throws IOException {
470: if (data != null) {
471: os.write(SPACES.substring(0, indent));
472: os.write("<" + tag + ">" + escapeString(data) + "</" + tag
473: + ">\n");
474: }
475: }
476:
477: private void writeOpenTag(BufferedWriter os, int indent, String tag)
478: throws IOException {
479: os.write(SPACES.substring(0, indent));
480: os.write("<" + tag + ">\n");
481: }
482:
483: private void writeOpenTagAttribute(BufferedWriter os, int indent,
484: String tag, String attr, String attrVal) throws IOException {
485: os.write(SPACES.substring(0, indent));
486: os.write("<" + tag + " " + attr + "=\"" + escapeString(attrVal)
487: + "\">\n");
488: }
489:
490: private void writeOpenTagAttribute(BufferedWriter os, int indent,
491: String tag, String attr1, String attr1Val, String attr2,
492: String attr2Val) throws IOException {
493: os.write(SPACES.substring(0, indent));
494: os.write("<" + tag + " " + attr1 + "=\""
495: + escapeString(attr1Val) + "\" " + attr2 + "=\""
496: + escapeString(attr2Val) + "\">\n");
497: }
498:
499: private void writeCloseTag(BufferedWriter os, int indent, String tag)
500: throws IOException {
501: os.write(SPACES.substring(0, indent));
502: os.write("</" + tag + ">\n");
503: }
504:
505: private void writeBank(BufferedWriter os, int indent, Bank b)
506: throws IOException {
507: if (b != null) {
508: writeOpenTagAttribute(os, indent, "bank", "id", b.getId()
509: .toString());
510: writeTag(os, indent + 2, "accountNumber", b
511: .getAccountNumber());
512: writeTag(os, indent + 2, "routingNumber", b
513: .getRoutingNumber());
514: writeCloseTag(os, indent, "bank");
515: }
516: }
517:
518: private void writeCustomerProfile(BufferedWriter os, int indent,
519: CustomerProfile cp) throws IOException {
520: writeOpenTag(os, indent, "customerProfile");
521: writeTag(os, indent + 2, "chartCode", cp.getChartCode());
522: writeTag(os, indent + 2, "orgCode", cp.getOrgCode());
523: writeTag(os, indent + 2, "subUnitCode", cp.getSubUnitCode());
524: writeOpenTag(os, indent + 2, "checkHeaderNoteLines");
525: writeTag(os, indent + 4, "note", cp
526: .getCheckHeaderNoteTextLine1());
527: writeTag(os, indent + 4, "note", cp
528: .getCheckHeaderNoteTextLine2());
529: writeTag(os, indent + 4, "note", cp
530: .getCheckHeaderNoteTextLine3());
531: writeTag(os, indent + 4, "note", cp
532: .getCheckHeaderNoteTextLine4());
533: writeCloseTag(os, indent + 2, "checkHeaderNoteLines");
534: writeOpenTag(os, indent + 2, "additionalCheckNoteLines");
535: writeTag(os, indent + 4, "note", cp
536: .getAdditionalCheckNoteTextLine1());
537: writeTag(os, indent + 4, "note", cp
538: .getAdditionalCheckNoteTextLine2());
539: writeTag(os, indent + 4, "note", cp
540: .getAdditionalCheckNoteTextLine3());
541: writeTag(os, indent + 4, "note", cp
542: .getAdditionalCheckNoteTextLine4());
543: writeCloseTag(os, indent + 2, "additionalCheckNoteLines");
544: writeCloseTag(os, indent, "customerProfile");
545: }
546:
547: private void writePayeeAch(BufferedWriter os, int indent,
548: PaymentGroup pg) throws IOException {
549: writePayeeInformation(os, indent, pg, true);
550: }
551:
552: private void writePayee(BufferedWriter os, int indent,
553: PaymentGroup pg) throws IOException {
554: writePayeeInformation(os, indent, pg, false);
555: }
556:
557: private void writePayeeInformation(BufferedWriter os, int indent,
558: PaymentGroup pg, boolean includeAch) throws IOException {
559: os.write(SPACES.substring(0, indent));
560: os.write("<payee id=\"" + pg.getPayeeId() + "\" type=\""
561: + pg.getPayeeIdTypeCd() + "\">\n");
562: writeTag(os, indent + 2, "payeeName", pg.getPayeeName());
563: writeTag(os, indent + 2, "line1Address", pg.getLine1Address());
564: writeTag(os, indent + 2, "line2Address", pg.getLine2Address());
565: writeTag(os, indent + 2, "line3Address", pg.getLine3Address());
566: writeTag(os, indent + 2, "line4Address", pg.getLine4Address());
567: writeTag(os, indent + 2, "city", pg.getCity());
568: writeTag(os, indent + 2, "state", pg.getState());
569: writeTag(os, indent + 2, "zipCd", pg.getZipCd());
570: writeTag(os, indent + 2, "country", pg.getCountry());
571:
572: if (includeAch) {
573: writeTag(os, indent + 2, "achBankRoutingNbr", pg
574: .getAchBankRoutingNbr());
575: writeTag(os, indent + 2, "achBankAccountNbr", pg
576: .getAchAccountNumber().getAchBankAccountNbr());
577: writeTag(os, indent + 2, "achAccountType", pg
578: .getAchAccountType());
579: }
580: writeCloseTag(os, indent, "payee");
581: }
582:
583: private String escapeString(String input) {
584: String output = input.replaceAll("\\&", "&");
585: output = output.replaceAll("\"", """);
586: output = output.replaceAll("\\'", "'");
587: output = output.replaceAll("\\<", "<");
588: output = output.replaceAll("\\>", ">");
589: return output;
590: }
591:
592: public void setParameterService(ParameterService parameterService) {
593: this .parameterService = parameterService;
594: }
595:
596: public void setDirectoryName(String dn) {
597: directoryName = dn;
598: }
599:
600: public void setPaymentGroupService(PaymentGroupService pgs) {
601: paymentGroupService = pgs;
602: }
603:
604: public void setProcessDao(ProcessDao pd) {
605: processDao = pd;
606: }
607:
608: public void setDateTimeService(DateTimeService dts) {
609: dateTimeService = dts;
610: }
611:
612: public void setReferenceService(ReferenceService rs) {
613: referenceService = rs;
614: }
615:
616: public void setPaymentGroupHistoryDao(PaymentGroupHistoryDao p) {
617: paymentGroupHistoryDao = p;
618: }
619:
620: public void setPaymentDetailService(PaymentDetailService pds) {
621: paymentDetailService = pds;
622: }
623: }
|