View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    * 
4    * Copyright 2005-2014 The Kuali Foundation
5    * 
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   * 
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package org.kuali.kfs.gl.report;
20  
21  import java.io.FileNotFoundException;
22  import java.io.FileOutputStream;
23  import java.text.DecimalFormat;
24  import java.text.SimpleDateFormat;
25  import java.util.ArrayList;
26  import java.util.Collections;
27  import java.util.Date;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Map;
31  
32  import org.kuali.kfs.gl.businessobject.Transaction;
33  import org.kuali.kfs.sys.Message;
34  import org.kuali.kfs.sys.context.SpringContext;
35  import org.kuali.rice.core.api.datetime.DateTimeService;
36  
37  import com.lowagie.text.Document;
38  import com.lowagie.text.DocumentException;
39  import com.lowagie.text.ExceptionConverter;
40  import com.lowagie.text.Font;
41  import com.lowagie.text.FontFactory;
42  import com.lowagie.text.PageSize;
43  import com.lowagie.text.Phrase;
44  import com.lowagie.text.Rectangle;
45  import com.lowagie.text.pdf.PdfPCell;
46  import com.lowagie.text.pdf.PdfPTable;
47  import com.lowagie.text.pdf.PdfPageEventHelper;
48  import com.lowagie.text.pdf.PdfWriter;
49  
50  /**
51   * This class represents the functionality related to the generating the Transaction Report. The transaction report
52   * shows the primary key from transactions and a list of messages for each one.
53   * 
54   */
55  public class TransactionReport {
56      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(TransactionReport.class);
57  
58      static public class PageHelper extends PdfPageEventHelper {
59          public Date runDate;
60          public Font headerFont;
61          public String title;
62  
63          /**
64           * Generates the end page for this transaction report
65           * 
66           * @see com.lowagie.text.pdf.PdfPageEventHelper#onEndPage(com.lowagie.text.pdf.PdfWriter, com.lowagie.text.Document)
67           */
68          public void onEndPage(PdfWriter writer, Document document) {
69              try {
70                  Rectangle page = document.getPageSize();
71                  PdfPTable head = new PdfPTable(3);
72                  SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
73                  PdfPCell cell = new PdfPCell(new Phrase(sdf.format(runDate), headerFont));
74                  cell.setBorder(Rectangle.NO_BORDER);
75                  head.addCell(cell);
76  
77                  cell = new PdfPCell(new Phrase(title, headerFont));
78                  cell.setBorder(Rectangle.NO_BORDER);
79                  cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
80                  head.addCell(cell);
81  
82                  cell = new PdfPCell(new Phrase("Page: " + new Integer(writer.getPageNumber()), headerFont));
83                  cell.setBorder(Rectangle.NO_BORDER);
84                  cell.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);
85                  head.addCell(cell);
86  
87                  head.setTotalWidth(page.width() - document.leftMargin() - document.rightMargin());
88                  head.writeSelectedRows(0, -1, document.leftMargin(), page.height() - document.topMargin() + head.getTotalHeight(), writer.getDirectContent());
89              }
90              catch (Exception e) {
91                  throw new ExceptionConverter(e);
92              }
93          }
94      }
95  
96      public TransactionReport() {
97          super();
98      }
99  
100 
101     /**
102      * Generates transaction report
103      * 
104      * @param reportErrors map containing transactions and the errors associated with each transaction
105      * @param reportSummary list of summary objects
106      * @param runDate date report is run
107      * @param title title of report
108      * @param fileprefix file prefix of report file
109      * @param destinationDirectory destination of where report file will reside
110      */
111     public void generateReport(Map<Transaction, List<Message>> reportErrors, List<Summary> reportSummary, Date runDate, String title, String fileprefix, String destinationDirectory) {
112         LOG.debug("generateReport() started");
113 
114         List transactions = new ArrayList();
115         if (reportErrors != null) {
116             transactions.addAll(reportErrors.keySet());
117         }
118         generateReport(transactions, reportErrors, reportSummary, runDate, title, fileprefix, destinationDirectory);
119     }
120 
121     /**
122      * Generates transaction report
123      * 
124      * @param errorSortedList list of error'd transactions
125      * @param reportErrors map containing transactions and the errors associated with each transaction
126      * @param reportSummary list of summary objects
127      * @param runDate date report is run
128      * @param title title of report
129      * @param fileprefix file prefix of report file
130      * @param destinationDirectory destination of where report file will reside
131      */
132     public void generateReport(List<Transaction> errorSortedList, Map<Transaction, List<Message>> reportErrors, List<Summary> reportSummary, Date runDate, String title, String fileprefix, String destinationDirectory) {
133         LOG.debug("generateReport() started");
134 
135         Font headerFont = FontFactory.getFont(FontFactory.COURIER, 8, Font.BOLD);
136         Font textFont = FontFactory.getFont(FontFactory.COURIER, 8, Font.NORMAL);
137 
138         Document document = new Document(PageSize.A4.rotate());
139 
140         PageHelper helper = new PageHelper();
141         helper.runDate = runDate;
142         helper.headerFont = headerFont;
143         helper.title = title;
144 
145         try {
146             DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class);
147             
148             String filename = destinationDirectory + "/" + fileprefix + "_";
149             filename = filename + dateTimeService.toDateTimeStringForFilename(runDate);
150             filename = filename + ".pdf";
151             PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
152             writer.setPageEvent(helper);
153 
154             document.open();
155             appendReport(document, headerFont, textFont, errorSortedList, reportErrors, reportSummary, runDate);
156         }
157         catch (DocumentException de) {
158             LOG.error("generateReport() Error creating PDF report", de);
159             throw new RuntimeException("Report Generation Failed: " + de.getMessage());
160         }
161         catch (FileNotFoundException fnfe) {
162             LOG.error("generateReport() Error writing PDF report", fnfe);
163             throw new RuntimeException("Report Generation Failed: Error writing to file " + fnfe.getMessage());
164         }
165         finally {
166             if ((document != null) && document.isOpen()) {
167                 document.close();
168             }
169         }
170     }
171 
172     /**
173      * Appends the scrubber totals/statistics and error report to the given (iText) document object.
174      * 
175      * @param document the PDF document
176      * @param headerFont font for header
177      * @param textFont font for report text
178      * @param errorSortedList list of error'd transactions
179      * @param reportErrors map containing transactions and the errors associated with each transaction
180      * @param reportSummary list of summary objects
181      * @param runDate date report was run
182      * @throws DocumentException
183      */
184     public void appendReport(Document document, Font headerFont, Font textFont, List<Transaction> errorSortedList, Map<Transaction, List<Message>> reportErrors, List<Summary> reportSummary, Date runDate) throws DocumentException {
185         // Sort what we get
186         Collections.sort(reportSummary);
187 
188         float[] summaryWidths = { 80, 20 };
189         PdfPTable summary = new PdfPTable(summaryWidths);
190         summary.setWidthPercentage(40);
191         PdfPCell cell = new PdfPCell(new Phrase("S T A T I S T I C S", headerFont));
192         cell.setColspan(2);
193         cell.setBorder(Rectangle.NO_BORDER);
194         cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
195         summary.addCell(cell);
196 
197         for (Iterator iter = reportSummary.iterator(); iter.hasNext();) {
198             Summary s = (Summary) iter.next();
199 
200             cell = new PdfPCell(new Phrase(s.getDescription(), textFont));
201             cell.setBorder(Rectangle.NO_BORDER);
202             summary.addCell(cell);
203 
204             if ("".equals(s.getDescription())) {
205                 cell = new PdfPCell(new Phrase("", textFont));
206                 cell.setBorder(Rectangle.NO_BORDER);
207                 summary.addCell(cell);
208             }
209             else {
210                 DecimalFormat nf = new DecimalFormat("###,###,###,##0");
211                 cell = new PdfPCell(new Phrase(nf.format(s.getCount()), textFont));
212                 cell.setBorder(Rectangle.NO_BORDER);
213                 cell.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);
214                 summary.addCell(cell);
215             }
216         }
217         cell = new PdfPCell(new Phrase(""));
218         cell.setColspan(2);
219         cell.setBorder(Rectangle.NO_BORDER);
220         summary.addCell(cell);
221 
222         document.add(summary);
223 
224         if (reportErrors != null && reportErrors.size() > 0) {
225             float[] warningWidths = { 4, 3, 6, 5, 5, 4, 5, 5, 4, 5, 5, 9, 4, 36 };
226             PdfPTable warnings = new PdfPTable(warningWidths);
227             warnings.setHeaderRows(2);
228             warnings.setWidthPercentage(100);
229             cell = new PdfPCell(new Phrase("W A R N I N G S", headerFont));
230             cell.setColspan(14);
231             cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
232             warnings.addCell(cell);
233 
234             // Add headers
235             cell = new PdfPCell(new Phrase("Year", headerFont));
236             warnings.addCell(cell);
237             cell = new PdfPCell(new Phrase("COA", headerFont));
238             warnings.addCell(cell);
239             cell = new PdfPCell(new Phrase("Account", headerFont));
240             warnings.addCell(cell);
241             cell = new PdfPCell(new Phrase("Sacct", headerFont));
242             warnings.addCell(cell);
243             cell = new PdfPCell(new Phrase("Obj", headerFont));
244             warnings.addCell(cell);
245             cell = new PdfPCell(new Phrase("SObj", headerFont));
246             warnings.addCell(cell);
247             cell = new PdfPCell(new Phrase("BalTyp", headerFont));
248             warnings.addCell(cell);
249             cell = new PdfPCell(new Phrase("ObjTyp", headerFont));
250             warnings.addCell(cell);
251             cell = new PdfPCell(new Phrase("Prd", headerFont));
252             warnings.addCell(cell);
253             cell = new PdfPCell(new Phrase("DocType", headerFont));
254             warnings.addCell(cell);
255             cell = new PdfPCell(new Phrase("Origin", headerFont));
256             warnings.addCell(cell);
257             cell = new PdfPCell(new Phrase("DocNbr", headerFont));
258             warnings.addCell(cell);
259             cell = new PdfPCell(new Phrase("Seq", headerFont));
260             warnings.addCell(cell);
261             cell = new PdfPCell(new Phrase("Warning", headerFont));
262             warnings.addCell(cell);
263 
264             for (Iterator errorIter = errorSortedList.iterator(); errorIter.hasNext();) {
265                 Transaction tran = (Transaction) errorIter.next();
266                 boolean first = true;
267 
268                 List errors = (List) reportErrors.get(tran);
269                 for (Iterator listIter = errors.iterator(); listIter.hasNext();) {
270                     String msg = null;
271                     Object m = listIter.next();
272                     if (m instanceof Message) {
273                         Message mm = (Message) m;
274                         msg = mm.getMessage();
275                     }
276                     else {
277                         if (m == null) {
278                             msg = "";
279                         }
280                         else {
281                             msg = m.toString();
282                         }
283                     }
284 
285                     if (first) {
286                         first = false;
287 
288                         if (tran.getUniversityFiscalYear() == null) {
289                             cell = new PdfPCell(new Phrase("NULL", textFont));
290                         }
291                         else {
292                             cell = new PdfPCell(new Phrase(tran.getUniversityFiscalYear().toString(), textFont));
293                         }
294                         warnings.addCell(cell);
295                         cell = new PdfPCell(new Phrase(tran.getChartOfAccountsCode(), textFont));
296                         warnings.addCell(cell);
297                         cell = new PdfPCell(new Phrase(tran.getAccountNumber(), textFont));
298                         warnings.addCell(cell);
299                         cell = new PdfPCell(new Phrase(tran.getSubAccountNumber(), textFont));
300                         warnings.addCell(cell);
301                         cell = new PdfPCell(new Phrase(tran.getFinancialObjectCode(), textFont));
302                         warnings.addCell(cell);
303                         cell = new PdfPCell(new Phrase(tran.getFinancialSubObjectCode(), textFont));
304                         warnings.addCell(cell);
305                         cell = new PdfPCell(new Phrase(tran.getFinancialBalanceTypeCode(), textFont));
306                         warnings.addCell(cell);
307                         cell = new PdfPCell(new Phrase(tran.getFinancialObjectTypeCode(), textFont));
308                         warnings.addCell(cell);
309                         cell = new PdfPCell(new Phrase(tran.getUniversityFiscalPeriodCode(), textFont));
310                         warnings.addCell(cell);
311                         cell = new PdfPCell(new Phrase(tran.getFinancialDocumentTypeCode(), textFont));
312                         warnings.addCell(cell);
313                         cell = new PdfPCell(new Phrase(tran.getFinancialSystemOriginationCode(), textFont));
314                         warnings.addCell(cell);
315                         cell = new PdfPCell(new Phrase(tran.getDocumentNumber(), textFont));
316                         warnings.addCell(cell);
317                         if (tran.getTransactionLedgerEntrySequenceNumber() == null) {
318                             cell = new PdfPCell(new Phrase("NULL", textFont));
319                         }
320                         else {
321                             cell = new PdfPCell(new Phrase(tran.getTransactionLedgerEntrySequenceNumber().toString(), textFont));
322                         }
323                         warnings.addCell(cell);
324                     }
325                     else {
326                         cell = new PdfPCell(new Phrase("", textFont));
327                         cell.setColspan(13);
328                         warnings.addCell(cell);
329                     }
330                     cell = new PdfPCell(new Phrase(msg, textFont));
331                     warnings.addCell(cell);
332                 }
333             }
334             document.add(warnings);
335         }
336     }
337 }