/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.gl.report;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.kuali.kfs.gl.businessobject.Transaction;
import org.kuali.kfs.sys.Message;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.rice.core.api.datetime.DateTimeService;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.ExceptionConverter;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfPageEventHelper;
import com.lowagie.text.pdf.PdfWriter;
/**
* This class represents the functionality related to the generating the Transaction Report. The transaction report
* shows the primary key from transactions and a list of messages for each one.
*
*/
public class TransactionReport {
private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(TransactionReport.class);
static public class PageHelper extends PdfPageEventHelper {
public Date runDate;
public Font headerFont;
public String title;
/**
* Generates the end page for this transaction report
*
* @see com.lowagie.text.pdf.PdfPageEventHelper#onEndPage(com.lowagie.text.pdf.PdfWriter, com.lowagie.text.Document)
*/
public void onEndPage(PdfWriter writer, Document document) {
try {
Rectangle page = document.getPageSize();
PdfPTable head = new PdfPTable(3);
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
PdfPCell cell = new PdfPCell(new Phrase(sdf.format(runDate), headerFont));
cell.setBorder(Rectangle.NO_BORDER);
head.addCell(cell);
cell = new PdfPCell(new Phrase(title, headerFont));
cell.setBorder(Rectangle.NO_BORDER);
cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
head.addCell(cell);
cell = new PdfPCell(new Phrase("Page: " + new Integer(writer.getPageNumber()), headerFont));
cell.setBorder(Rectangle.NO_BORDER);
cell.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);
head.addCell(cell);
head.setTotalWidth(page.width() - document.leftMargin() - document.rightMargin());
head.writeSelectedRows(0, -1, document.leftMargin(), page.height() - document.topMargin() + head.getTotalHeight(), writer.getDirectContent());
}
catch (Exception e) {
throw new ExceptionConverter(e);
}
}
}
public TransactionReport() {
super();
}
/**
* Generates transaction report
*
* @param reportErrors map containing transactions and the errors associated with each transaction
* @param reportSummary list of summary objects
* @param runDate date report is run
* @param title title of report
* @param fileprefix file prefix of report file
* @param destinationDirectory destination of where report file will reside
*/
public void generateReport(Map<Transaction, List<Message>> reportErrors, List<Summary> reportSummary, Date runDate, String title, String fileprefix, String destinationDirectory) {
LOG.debug("generateReport() started");
List transactions = new ArrayList();
if (reportErrors != null) {
transactions.addAll(reportErrors.keySet());
}
generateReport(transactions, reportErrors, reportSummary, runDate, title, fileprefix, destinationDirectory);
}
/**
* Generates transaction report
*
* @param errorSortedList list of error'd transactions
* @param reportErrors map containing transactions and the errors associated with each transaction
* @param reportSummary list of summary objects
* @param runDate date report is run
* @param title title of report
* @param fileprefix file prefix of report file
* @param destinationDirectory destination of where report file will reside
*/
public void generateReport(List<Transaction> errorSortedList, Map<Transaction, List<Message>> reportErrors, List<Summary> reportSummary, Date runDate, String title, String fileprefix, String destinationDirectory) {
LOG.debug("generateReport() started");
Font headerFont = FontFactory.getFont(FontFactory.COURIER, 8, Font.BOLD);
Font textFont = FontFactory.getFont(FontFactory.COURIER, 8, Font.NORMAL);
Document document = new Document(PageSize.A4.rotate());
PageHelper helper = new PageHelper();
helper.runDate = runDate;
helper.headerFont = headerFont;
helper.title = title;
try {
DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class);
String filename = destinationDirectory + "/" + fileprefix + "_";
filename = filename + dateTimeService.toDateTimeStringForFilename(runDate);
filename = filename + ".pdf";
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
writer.setPageEvent(helper);
document.open();
appendReport(document, headerFont, textFont, errorSortedList, reportErrors, reportSummary, runDate);
}
catch (DocumentException de) {
LOG.error("generateReport() Error creating PDF report", de);
throw new RuntimeException("Report Generation Failed: " + de.getMessage());
}
catch (FileNotFoundException fnfe) {
LOG.error("generateReport() Error writing PDF report", fnfe);
throw new RuntimeException("Report Generation Failed: Error writing to file " + fnfe.getMessage());
}
finally {
if ((document != null) && document.isOpen()) {
document.close();
}
}
}
/**
* Appends the scrubber totals/statistics and error report to the given (iText) document object.
*
* @param document the PDF document
* @param headerFont font for header
* @param textFont font for report text
* @param errorSortedList list of error'd transactions
* @param reportErrors map containing transactions and the errors associated with each transaction
* @param reportSummary list of summary objects
* @param runDate date report was run
* @throws DocumentException
*/
public void appendReport(Document document, Font headerFont, Font textFont, List<Transaction> errorSortedList, Map<Transaction, List<Message>> reportErrors, List<Summary> reportSummary, Date runDate) throws DocumentException {
// Sort what we get
Collections.sort(reportSummary);
float[] summaryWidths = { 80, 20 };
PdfPTable summary = new PdfPTable(summaryWidths);
summary.setWidthPercentage(40);
PdfPCell cell = new PdfPCell(new Phrase("S T A T I S T I C S", headerFont));
cell.setColspan(2);
cell.setBorder(Rectangle.NO_BORDER);
cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
summary.addCell(cell);
for (Iterator iter = reportSummary.iterator(); iter.hasNext();) {
Summary s = (Summary) iter.next();
cell = new PdfPCell(new Phrase(s.getDescription(), textFont));
cell.setBorder(Rectangle.NO_BORDER);
summary.addCell(cell);
if ("".equals(s.getDescription())) {
cell = new PdfPCell(new Phrase("", textFont));
cell.setBorder(Rectangle.NO_BORDER);
summary.addCell(cell);
}
else {
DecimalFormat nf = new DecimalFormat("###,###,###,##0");
cell = new PdfPCell(new Phrase(nf.format(s.getCount()), textFont));
cell.setBorder(Rectangle.NO_BORDER);
cell.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);
summary.addCell(cell);
}
}
cell = new PdfPCell(new Phrase(""));
cell.setColspan(2);
cell.setBorder(Rectangle.NO_BORDER);
summary.addCell(cell);
document.add(summary);
if (reportErrors != null && reportErrors.size() > 0) {
float[] warningWidths = { 4, 3, 6, 5, 5, 4, 5, 5, 4, 5, 5, 9, 4, 36 };
PdfPTable warnings = new PdfPTable(warningWidths);
warnings.setHeaderRows(2);
warnings.setWidthPercentage(100);
cell = new PdfPCell(new Phrase("W A R N I N G S", headerFont));
cell.setColspan(14);
cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
warnings.addCell(cell);
// Add headers
cell = new PdfPCell(new Phrase("Year", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("COA", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("Account", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("Sacct", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("Obj", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("SObj", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("BalTyp", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("ObjTyp", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("Prd", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("DocType", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("Origin", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("DocNbr", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("Seq", headerFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase("Warning", headerFont));
warnings.addCell(cell);
for (Iterator errorIter = errorSortedList.iterator(); errorIter.hasNext();) {
Transaction tran = (Transaction) errorIter.next();
boolean first = true;
List errors = (List) reportErrors.get(tran);
for (Iterator listIter = errors.iterator(); listIter.hasNext();) {
String msg = null;
Object m = listIter.next();
if (m instanceof Message) {
Message mm = (Message) m;
msg = mm.getMessage();
}
else {
if (m == null) {
msg = "";
}
else {
msg = m.toString();
}
}
if (first) {
first = false;
if (tran.getUniversityFiscalYear() == null) {
cell = new PdfPCell(new Phrase("NULL", textFont));
}
else {
cell = new PdfPCell(new Phrase(tran.getUniversityFiscalYear().toString(), textFont));
}
warnings.addCell(cell);
cell = new PdfPCell(new Phrase(tran.getChartOfAccountsCode(), textFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase(tran.getAccountNumber(), textFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase(tran.getSubAccountNumber(), textFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase(tran.getFinancialObjectCode(), textFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase(tran.getFinancialSubObjectCode(), textFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase(tran.getFinancialBalanceTypeCode(), textFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase(tran.getFinancialObjectTypeCode(), textFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase(tran.getUniversityFiscalPeriodCode(), textFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase(tran.getFinancialDocumentTypeCode(), textFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase(tran.getFinancialSystemOriginationCode(), textFont));
warnings.addCell(cell);
cell = new PdfPCell(new Phrase(tran.getDocumentNumber(), textFont));
warnings.addCell(cell);
if (tran.getTransactionLedgerEntrySequenceNumber() == null) {
cell = new PdfPCell(new Phrase("NULL", textFont));
}
else {
cell = new PdfPCell(new Phrase(tran.getTransactionLedgerEntrySequenceNumber().toString(), textFont));
}
warnings.addCell(cell);
}
else {
cell = new PdfPCell(new Phrase("", textFont));
cell.setColspan(13);
warnings.addCell(cell);
}
cell = new PdfPCell(new Phrase(msg, textFont));
warnings.addCell(cell);
}
}
document.add(warnings);
}
}
}