001/*
002 * Copyright 2006 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.gl.report;
017
018import java.io.FileNotFoundException;
019import java.io.FileOutputStream;
020import java.text.DecimalFormat;
021import java.text.SimpleDateFormat;
022import java.util.ArrayList;
023import java.util.Collections;
024import java.util.Date;
025import java.util.Iterator;
026import java.util.List;
027import java.util.Map;
028
029import org.kuali.ole.gl.businessobject.Transaction;
030import org.kuali.ole.sys.Message;
031import org.kuali.ole.sys.context.SpringContext;
032import org.kuali.rice.core.api.datetime.DateTimeService;
033
034import com.lowagie.text.Document;
035import com.lowagie.text.DocumentException;
036import com.lowagie.text.ExceptionConverter;
037import com.lowagie.text.Font;
038import com.lowagie.text.FontFactory;
039import com.lowagie.text.PageSize;
040import com.lowagie.text.Phrase;
041import com.lowagie.text.Rectangle;
042import com.lowagie.text.pdf.PdfPCell;
043import com.lowagie.text.pdf.PdfPTable;
044import com.lowagie.text.pdf.PdfPageEventHelper;
045import com.lowagie.text.pdf.PdfWriter;
046
047/**
048 * This class represents the functionality related to the generating the Transaction Report. The transaction report
049 * shows the primary key from transactions and a list of messages for each one.
050 * 
051 */
052public class TransactionReport {
053    private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(TransactionReport.class);
054
055    static public class PageHelper extends PdfPageEventHelper {
056        public Date runDate;
057        public Font headerFont;
058        public String title;
059
060        /**
061         * Generates the end page for this transaction report
062         * 
063         * @see com.lowagie.text.pdf.PdfPageEventHelper#onEndPage(com.lowagie.text.pdf.PdfWriter, com.lowagie.text.Document)
064         */
065        public void onEndPage(PdfWriter writer, Document document) {
066            try {
067                Rectangle page = document.getPageSize();
068                PdfPTable head = new PdfPTable(3);
069                SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
070                PdfPCell cell = new PdfPCell(new Phrase(sdf.format(runDate), headerFont));
071                cell.setBorder(Rectangle.NO_BORDER);
072                head.addCell(cell);
073
074                cell = new PdfPCell(new Phrase(title, headerFont));
075                cell.setBorder(Rectangle.NO_BORDER);
076                cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
077                head.addCell(cell);
078
079                cell = new PdfPCell(new Phrase("Page: " + new Integer(writer.getPageNumber()), headerFont));
080                cell.setBorder(Rectangle.NO_BORDER);
081                cell.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);
082                head.addCell(cell);
083
084                head.setTotalWidth(page.width() - document.leftMargin() - document.rightMargin());
085                head.writeSelectedRows(0, -1, document.leftMargin(), page.height() - document.topMargin() + head.getTotalHeight(), writer.getDirectContent());
086            }
087            catch (Exception e) {
088                throw new ExceptionConverter(e);
089            }
090        }
091    }
092
093    public TransactionReport() {
094        super();
095    }
096
097
098    /**
099     * Generates transaction report
100     * 
101     * @param reportErrors map containing transactions and the errors associated with each transaction
102     * @param reportSummary list of summary objects
103     * @param runDate date report is run
104     * @param title title of report
105     * @param fileprefix file prefix of report file
106     * @param destinationDirectory destination of where report file will reside
107     */
108    public void generateReport(Map<Transaction, List<Message>> reportErrors, List<Summary> reportSummary, Date runDate, String title, String fileprefix, String destinationDirectory) {
109        LOG.debug("generateReport() started");
110
111        List transactions = new ArrayList();
112        if (reportErrors != null) {
113            transactions.addAll(reportErrors.keySet());
114        }
115        generateReport(transactions, reportErrors, reportSummary, runDate, title, fileprefix, destinationDirectory);
116    }
117
118    /**
119     * Generates transaction report
120     * 
121     * @param errorSortedList list of error'd transactions
122     * @param reportErrors map containing transactions and the errors associated with each transaction
123     * @param reportSummary list of summary objects
124     * @param runDate date report is run
125     * @param title title of report
126     * @param fileprefix file prefix of report file
127     * @param destinationDirectory destination of where report file will reside
128     */
129    public void generateReport(List<Transaction> errorSortedList, Map<Transaction, List<Message>> reportErrors, List<Summary> reportSummary, Date runDate, String title, String fileprefix, String destinationDirectory) {
130        LOG.debug("generateReport() started");
131
132        Font headerFont = FontFactory.getFont(FontFactory.COURIER, 8, Font.BOLD);
133        Font textFont = FontFactory.getFont(FontFactory.COURIER, 8, Font.NORMAL);
134
135        Document document = new Document(PageSize.A4.rotate());
136
137        PageHelper helper = new PageHelper();
138        helper.runDate = runDate;
139        helper.headerFont = headerFont;
140        helper.title = title;
141
142        try {
143            DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class);
144            
145            String filename = destinationDirectory + "/" + fileprefix + "_";
146            filename = filename + dateTimeService.toDateTimeStringForFilename(runDate);
147            filename = filename + ".pdf";
148            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
149            writer.setPageEvent(helper);
150
151            document.open();
152            appendReport(document, headerFont, textFont, errorSortedList, reportErrors, reportSummary, runDate);
153        }
154        catch (DocumentException de) {
155            LOG.error("generateReport() Error creating PDF report", de);
156            throw new RuntimeException("Report Generation Failed: " + de.getMessage());
157        }
158        catch (FileNotFoundException fnfe) {
159            LOG.error("generateReport() Error writing PDF report", fnfe);
160            throw new RuntimeException("Report Generation Failed: Error writing to file " + fnfe.getMessage());
161        }
162        finally {
163            if ((document != null) && document.isOpen()) {
164                document.close();
165            }
166        }
167    }
168
169    /**
170     * Appends the scrubber totals/statistics and error report to the given (iText) document object.
171     * 
172     * @param document the PDF document
173     * @param headerFont font for header
174     * @param textFont font for report text
175     * @param errorSortedList list of error'd transactions
176     * @param reportErrors map containing transactions and the errors associated with each transaction
177     * @param reportSummary list of summary objects
178     * @param runDate date report was run
179     * @throws DocumentException
180     */
181    public void appendReport(Document document, Font headerFont, Font textFont, List<Transaction> errorSortedList, Map<Transaction, List<Message>> reportErrors, List<Summary> reportSummary, Date runDate) throws DocumentException {
182        // Sort what we get
183        Collections.sort(reportSummary);
184
185        float[] summaryWidths = { 80, 20 };
186        PdfPTable summary = new PdfPTable(summaryWidths);
187        summary.setWidthPercentage(40);
188        PdfPCell cell = new PdfPCell(new Phrase("S T A T I S T I C S", headerFont));
189        cell.setColspan(2);
190        cell.setBorder(Rectangle.NO_BORDER);
191        cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
192        summary.addCell(cell);
193
194        for (Iterator iter = reportSummary.iterator(); iter.hasNext();) {
195            Summary s = (Summary) iter.next();
196
197            cell = new PdfPCell(new Phrase(s.getDescription(), textFont));
198            cell.setBorder(Rectangle.NO_BORDER);
199            summary.addCell(cell);
200
201            if ("".equals(s.getDescription())) {
202                cell = new PdfPCell(new Phrase("", textFont));
203                cell.setBorder(Rectangle.NO_BORDER);
204                summary.addCell(cell);
205            }
206            else {
207                DecimalFormat nf = new DecimalFormat("###,###,###,##0");
208                cell = new PdfPCell(new Phrase(nf.format(s.getCount()), textFont));
209                cell.setBorder(Rectangle.NO_BORDER);
210                cell.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);
211                summary.addCell(cell);
212            }
213        }
214        cell = new PdfPCell(new Phrase(""));
215        cell.setColspan(2);
216        cell.setBorder(Rectangle.NO_BORDER);
217        summary.addCell(cell);
218
219        document.add(summary);
220
221        if (reportErrors != null && reportErrors.size() > 0) {
222            float[] warningWidths = { 4, 3, 6, 5, 5, 4, 5, 5, 4, 5, 5, 9, 4, 36 };
223            PdfPTable warnings = new PdfPTable(warningWidths);
224            warnings.setHeaderRows(2);
225            warnings.setWidthPercentage(100);
226            cell = new PdfPCell(new Phrase("W A R N I N G S", headerFont));
227            cell.setColspan(14);
228            cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
229            warnings.addCell(cell);
230
231            // Add headers
232            cell = new PdfPCell(new Phrase("Year", headerFont));
233            warnings.addCell(cell);
234            cell = new PdfPCell(new Phrase("COA", headerFont));
235            warnings.addCell(cell);
236            cell = new PdfPCell(new Phrase("Account", headerFont));
237            warnings.addCell(cell);
238            cell = new PdfPCell(new Phrase("Sacct", headerFont));
239            warnings.addCell(cell);
240            cell = new PdfPCell(new Phrase("Obj", headerFont));
241            warnings.addCell(cell);
242            cell = new PdfPCell(new Phrase("SObj", headerFont));
243            warnings.addCell(cell);
244            cell = new PdfPCell(new Phrase("BalTyp", headerFont));
245            warnings.addCell(cell);
246            cell = new PdfPCell(new Phrase("ObjTyp", headerFont));
247            warnings.addCell(cell);
248            cell = new PdfPCell(new Phrase("Prd", headerFont));
249            warnings.addCell(cell);
250            cell = new PdfPCell(new Phrase("DocType", headerFont));
251            warnings.addCell(cell);
252            cell = new PdfPCell(new Phrase("Origin", headerFont));
253            warnings.addCell(cell);
254            cell = new PdfPCell(new Phrase("DocNbr", headerFont));
255            warnings.addCell(cell);
256            cell = new PdfPCell(new Phrase("Seq", headerFont));
257            warnings.addCell(cell);
258            cell = new PdfPCell(new Phrase("Warning", headerFont));
259            warnings.addCell(cell);
260
261            for (Iterator errorIter = errorSortedList.iterator(); errorIter.hasNext();) {
262                Transaction tran = (Transaction) errorIter.next();
263                boolean first = true;
264
265                List errors = (List) reportErrors.get(tran);
266                for (Iterator listIter = errors.iterator(); listIter.hasNext();) {
267                    String msg = null;
268                    Object m = listIter.next();
269                    if (m instanceof Message) {
270                        Message mm = (Message) m;
271                        msg = mm.getMessage();
272                    }
273                    else {
274                        if (m == null) {
275                            msg = "";
276                        }
277                        else {
278                            msg = m.toString();
279                        }
280                    }
281
282                    if (first) {
283                        first = false;
284
285                        if (tran.getUniversityFiscalYear() == null) {
286                            cell = new PdfPCell(new Phrase("NULL", textFont));
287                        }
288                        else {
289                            cell = new PdfPCell(new Phrase(tran.getUniversityFiscalYear().toString(), textFont));
290                        }
291                        warnings.addCell(cell);
292                        cell = new PdfPCell(new Phrase(tran.getChartOfAccountsCode(), textFont));
293                        warnings.addCell(cell);
294                        cell = new PdfPCell(new Phrase(tran.getAccountNumber(), textFont));
295                        warnings.addCell(cell);
296                        cell = new PdfPCell(new Phrase(tran.getSubAccountNumber(), textFont));
297                        warnings.addCell(cell);
298                        cell = new PdfPCell(new Phrase(tran.getFinancialObjectCode(), textFont));
299                        warnings.addCell(cell);
300                        cell = new PdfPCell(new Phrase(tran.getFinancialSubObjectCode(), textFont));
301                        warnings.addCell(cell);
302                        cell = new PdfPCell(new Phrase(tran.getFinancialBalanceTypeCode(), textFont));
303                        warnings.addCell(cell);
304                        cell = new PdfPCell(new Phrase(tran.getFinancialObjectTypeCode(), textFont));
305                        warnings.addCell(cell);
306                        cell = new PdfPCell(new Phrase(tran.getUniversityFiscalPeriodCode(), textFont));
307                        warnings.addCell(cell);
308                        cell = new PdfPCell(new Phrase(tran.getFinancialDocumentTypeCode(), textFont));
309                        warnings.addCell(cell);
310                        cell = new PdfPCell(new Phrase(tran.getFinancialSystemOriginationCode(), textFont));
311                        warnings.addCell(cell);
312                        cell = new PdfPCell(new Phrase(tran.getDocumentNumber(), textFont));
313                        warnings.addCell(cell);
314                        if (tran.getTransactionLedgerEntrySequenceNumber() == null) {
315                            cell = new PdfPCell(new Phrase("NULL", textFont));
316                        }
317                        else {
318                            cell = new PdfPCell(new Phrase(tran.getTransactionLedgerEntrySequenceNumber().toString(), textFont));
319                        }
320                        warnings.addCell(cell);
321                    }
322                    else {
323                        cell = new PdfPCell(new Phrase("", textFont));
324                        cell.setColspan(13);
325                        warnings.addCell(cell);
326                    }
327                    cell = new PdfPCell(new Phrase(msg, textFont));
328                    warnings.addCell(cell);
329                }
330            }
331            document.add(warnings);
332        }
333    }
334}