001 /*
002 * Copyright 2011 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 */
016 package org.kuali.kfs.gl.report;
017
018 import java.io.FileNotFoundException;
019 import java.io.FileOutputStream;
020 import java.text.DecimalFormat;
021 import java.text.SimpleDateFormat;
022 import java.util.ArrayList;
023 import java.util.Collections;
024 import java.util.Date;
025 import java.util.Iterator;
026 import java.util.List;
027 import java.util.Map;
028
029 import org.kuali.kfs.gl.businessobject.Transaction;
030 import org.kuali.kfs.sys.Message;
031 import org.kuali.kfs.sys.context.SpringContext;
032 import org.kuali.rice.kns.service.DateTimeService;
033
034 import com.lowagie.text.Document;
035 import com.lowagie.text.DocumentException;
036 import com.lowagie.text.ExceptionConverter;
037 import com.lowagie.text.Font;
038 import com.lowagie.text.FontFactory;
039 import com.lowagie.text.PageSize;
040 import com.lowagie.text.Phrase;
041 import com.lowagie.text.Rectangle;
042 import com.lowagie.text.pdf.PdfPCell;
043 import com.lowagie.text.pdf.PdfPTable;
044 import com.lowagie.text.pdf.PdfPageEventHelper;
045 import 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 */
052 public 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 }