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.module.endow.report.util;
017    
018    import java.io.ByteArrayOutputStream;
019    import java.math.BigDecimal;
020    import java.util.ArrayList;
021    import java.util.Date;
022    import java.util.List;
023    
024    import org.kuali.kfs.module.endow.EndowConstants;
025    import org.kuali.kfs.module.endow.report.util.TransactionSummaryReportDataHolder.CashTransfersDataHolder;
026    import org.kuali.kfs.module.endow.report.util.TransactionSummaryReportDataHolder.ContributionsDataHolder;
027    import org.kuali.kfs.module.endow.report.util.TransactionSummaryReportDataHolder.ExpensesDataHolder;
028    import org.kuali.kfs.module.endow.report.util.TransactionSummaryReportDataHolder.SecurityTransfersDataHolder;
029    import org.kuali.rice.kns.util.ObjectUtils;
030    
031    import com.lowagie.text.Document;
032    import com.lowagie.text.DocumentException;
033    import com.lowagie.text.Element;
034    import com.lowagie.text.Font;
035    import com.lowagie.text.HeaderFooter;
036    import com.lowagie.text.Paragraph;
037    import com.lowagie.text.Phrase;
038    import com.lowagie.text.Rectangle;
039    import com.lowagie.text.pdf.PdfPTable;
040    import com.lowagie.text.pdf.PdfWriter;
041    
042    public class TransactionSummaryReportPrint extends EndowmentReportPrintBase {
043        final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(TransactionSummaryReportPrint.class);
044    
045        /**
046         * Generates the report in PDF using iText
047         * 
048         * @param reportRequestHeaderDataHolder
049         * @param transactionStatementDataReportHolders
050         * @return pdfStream
051         */
052        public ByteArrayOutputStream printTransactionSummaryReport(EndowmentReportHeaderDataHolder reportRequestHeaderDataHolder, List<TransactionSummaryReportDataHolder> transactionSummaryDataReportHolders, String listKemidsInHeader, String reportOption, String summaryTotalsOnly) {
053            Document document = new Document();
054            document.setPageSize(LETTER_PORTRAIT);
055            document.addTitle("Endowment Transaction Summary");
056            
057            ByteArrayOutputStream pdfStream = new ByteArrayOutputStream();
058    
059            try {            
060                PdfWriter.getInstance(document, pdfStream);            
061                document.open();
062    
063                // page
064                HeaderFooter header = new HeaderFooter(new Phrase(new Date().toString() + "     Page: ", headerFont), true);
065                header.setBorder(Rectangle.NO_BORDER);
066                header.setAlignment(Element.ALIGN_RIGHT);
067                header.setPageNumber(0);
068                document.setHeader(header);
069                
070                // print the report header
071                if (printReportHeaderPage(reportRequestHeaderDataHolder, document, listKemidsInHeader)) {                
072                    if (transactionSummaryDataReportHolders != null && transactionSummaryDataReportHolders.size() > 0) {
073                        if ("Y".equalsIgnoreCase(summaryTotalsOnly)) {
074                            printReportBodyBySummaryTotals(transactionSummaryDataReportHolders, document, reportOption);
075                        }
076                        else {
077                            printReportBodyByAllTotals(transactionSummaryDataReportHolders, document, reportOption);
078                        }
079                    } 
080                } else {
081                    LOG.error("Transaction Summary Report Header Error");
082                }
083    
084                document.close();
085    
086            } catch (Exception e) {
087                LOG.error("PDF Error: " + e.getMessage());
088                return null;
089            }
090            
091            return pdfStream;
092        }
093        
094        /**
095         * 
096         * Helper method to print body of the transaction summary report, listing only total field.
097         * @param transactionSummaryDataReportHolders
098         * @param document
099         * @param reportOption
100         * @return true if successful else return false
101         */
102        protected boolean printReportBodyBySummaryTotals(List<TransactionSummaryReportDataHolder> transactionSummaryDataReportHolders, Document document, String reportOption) {
103            boolean success = true;
104            
105            if (EndowConstants.EndowmentReport.DETAIL.equalsIgnoreCase(reportOption)) {
106                success &= printReportBodyForDetailReportOption(transactionSummaryDataReportHolders, document);
107            }
108            
109            if (EndowConstants.EndowmentReport.TOTAL.equalsIgnoreCase(reportOption)) {
110                success &= printReportBodyForSummaryReportOption(transactionSummaryDataReportHolders, document);
111            }
112            
113            if (EndowConstants.EndowmentReport.BOTH.equalsIgnoreCase(reportOption)) {
114                success &= printReportBodyForDetailReportOption(transactionSummaryDataReportHolders, document);
115                success &= printReportBodyForSummaryReportOption(transactionSummaryDataReportHolders, document);
116            }
117                
118            return success;
119        }
120        
121        /**
122         * Helper method to print body of the transaction summary report, listing all total fields.
123         * @param transactionSummaryDataReportHolders
124         * @param document
125         * @param reportOption
126         * @return true if successful else false
127         */
128        protected boolean printReportBodyByAllTotals(List<TransactionSummaryReportDataHolder> transactionSummaryDataReportHolders, Document document, String reportOption) {
129            boolean sucess = true;
130            
131            if (reportOption.equalsIgnoreCase(EndowConstants.EndowmentReport.DETAIL)) {
132                sucess &= printReportBodyByAllTotalsForDetailReportOption(transactionSummaryDataReportHolders, document);
133            }
134            if (reportOption.equalsIgnoreCase(EndowConstants.EndowmentReport.TOTAL)) {
135                sucess &= printReportBodyByAllTotalsForTotalReportOption(transactionSummaryDataReportHolders, document);
136            }
137            if (reportOption.equalsIgnoreCase(EndowConstants.EndowmentReport.BOTH)) {
138                sucess &= printReportBodyByAllTotalsForDetailReportOption(transactionSummaryDataReportHolders, document);
139                sucess &= printReportBodyByAllTotalsForTotalReportOption(transactionSummaryDataReportHolders, document);
140            }
141            
142            return true;
143        }
144    
145        /**
146         * Generates the Transaction Summary report showing all amounts fields.   
147         * 
148         * @param transactionSummaryReports
149         * @param document
150         * @return true if document created else return false
151         */
152        public boolean printReportBodyByAllTotalsForDetailReportOption(List<TransactionSummaryReportDataHolder> transactionSummaryReportDataHolders, Document document) {
153                
154            document.setPageCount(0);
155            
156            // for each kemid
157            try {                               
158                Font cellFont = regularFont;
159                for (TransactionSummaryReportDataHolder transactionSummaryReport : transactionSummaryReportDataHolders) {
160                    // new page
161                    document.setPageSize(LETTER_LANDSCAPE);
162                    document.newPage();
163                    
164                    // header
165                    writeDocumentHeader(document, transactionSummaryReport);
166                    
167                    // report table column headers
168                    PdfPTable table = writeDocumentTitleHeadings(EndowConstants.EndowmentReport.DETAIL);
169                    
170                    if (ObjectUtils.isNull(table)) {
171                        return false;
172                    }
173                    
174                    // write out Beginning Market value row values
175                    writeDetailLineRow(table, cellFont, "Beginning Market Value",  transactionSummaryReport.getIncomeBeginningMarketValue(), transactionSummaryReport.getPrincipalBeginningMarketValue(), transactionSummaryReport.getTotalBeginningMarketValue());
176                    
177                    // contributions rows
178                    writeContributionsRecordsForDetailReportOption(table, cellFont, transactionSummaryReport);
179                    
180                    // expenses rows....
181                    writeExpensesRecordsForDetailReportOption(table, cellFont, transactionSummaryReport);
182                    
183                    // cash transfer rows...
184                    writeCashTransfersRecordsForDetailReportOption(table, cellFont, transactionSummaryReport);
185                    
186                    // cash transfer rows...
187                    writeSecurityTransfersRecordsForDetailReportOption(table, cellFont, transactionSummaryReport);
188    
189                    //write change in market value row....
190                    writeDetailLineRow(table, cellFont, "Change in Market Value",  transactionSummaryReport.getIncomeChangeInMarketValue(), transactionSummaryReport.getPrincipalChangeInMarketValue(), transactionSummaryReport.getTotalChangeInMarketValue());
191                    
192                    //write period end total market value record....
193                    writeDetailLineRow(table, cellFont, "Period End total Market Value (Include Cash)",  transactionSummaryReport.getIncomeEndingMarketValue(), transactionSummaryReport.getPrincipalEndingMarketValue(), transactionSummaryReport.getTotalEndingMarketValue());
194                    
195                    // write out estimate income row
196                    writeDetailsLineWithTotalAmountOnly(table, cellFont, "Next 12 Months Estimated Income", transactionSummaryReport.getNext12MonthsEstimatedIncome(), EndowConstants.EndowmentReport.DETAIL);
197                    
198                    //write out the remainder FY estimated row...
199                    writeDetailsLineWithTotalAmountOnly(table, cellFont, "Remainder of Fiscal Year Estimated Income", transactionSummaryReport.getRemainderOfFYEstimatedIncome(), EndowConstants.EndowmentReport.DETAIL);
200                    
201                    //write out the next FY estimated row...
202                    writeDetailsLineWithTotalAmountOnly(table, cellFont, "Next Fiscal Year Estimated Income", transactionSummaryReport.getNextFYEstimatedIncome(), EndowConstants.EndowmentReport.DETAIL);
203                    
204                    document.add(table);
205                    
206                    //print the footer...
207                    if (ObjectUtils.isNotNull(transactionSummaryReport.getFooter())) {
208                        printFooter(transactionSummaryReport.getFooter(), document);
209                    }
210                }
211                
212            } catch (Exception e) {
213                return false;
214            }
215            
216            return true;
217        }
218        
219        /**
220         * Generates the Transaction Summary report showing only summary amount field.   
221         * This report will only show the total amount field for each kemid
222         * @param transactionSummaryReports
223         * @param document
224         * @return true if document created else return false
225         */
226        public boolean printReportBodyForDetailReportOption(List<TransactionSummaryReportDataHolder> transactionSummaryReportDataHolders, Document document) {
227    
228            document.setPageCount(0);
229            
230            try {                               
231                Font cellFont = regularFont;
232                for (TransactionSummaryReportDataHolder transactionSummaryReport : transactionSummaryReportDataHolders) {
233                    // new page
234                    document.setPageSize(LETTER_LANDSCAPE);
235                    document.newPage();
236                    
237                    // header
238                    writeDocumentHeader(document, transactionSummaryReport);
239                    
240                    // report table column headers
241                    PdfPTable table = writeDocumentTitleHeadings(EndowConstants.EndowmentReport.TOTAL);
242                    
243                    if (ObjectUtils.isNull(table)) {
244                        return false;
245                    }
246                    
247                    // write out Beginning Market value row values
248                    writeDetailLineRow(table, cellFont, "Beginning Market Value", transactionSummaryReport.getTotalBeginningMarketValue());
249                    
250                    // contributions rows
251                    writeContributionsRecordsForSummaryReportOption(table, cellFont, transactionSummaryReport);
252                    
253                    // expenses rows....
254                    writeExpensesRecordsForSummaryReportOption(table, cellFont, transactionSummaryReport);
255                    
256                    //cash transfers rows..
257                    writeCashTransfersRecordsForSummaryReportOption(table, cellFont, transactionSummaryReport);
258                    
259                    // security transfer rows...
260                    writeSecurityTransfersRecordsForSummaryReportOption(table, cellFont, transactionSummaryReport);
261                    
262                    //write change in market value row....
263                    writeDetailLineRow(table, cellFont, "Change in Market Value",  transactionSummaryReport.getTotalChangeInMarketValue());
264                    
265                    //write period end total market value record....
266                    writeDetailLineRow(table, cellFont, "Period End total Market Value (Include Cash)", transactionSummaryReport.getTotalEndingMarketValue());
267                    
268                    // write out estimate income row
269                    writeDetailsLineWithTotalAmountOnly(table, cellFont, "Next 12 Months Estimated Income", transactionSummaryReport.getNext12MonthsEstimatedIncome(), EndowConstants.EndowmentReport.TOTAL);
270                    
271                    //write out the remainder FY estimated row...
272                    writeDetailsLineWithTotalAmountOnly(table, cellFont, "Remainder of Fiscal Year Estimated Income", transactionSummaryReport.getRemainderOfFYEstimatedIncome(), EndowConstants.EndowmentReport.TOTAL);
273                    
274                    //write out the next FY estimated row...
275                    writeDetailsLineWithTotalAmountOnly(table, cellFont, "Next Fiscal Year Estimated Income", transactionSummaryReport.getNextFYEstimatedIncome(), EndowConstants.EndowmentReport.TOTAL);
276                    
277                    document.add(table);
278                    
279                    //print the footer...
280                    if (ObjectUtils.isNotNull(transactionSummaryReport.getFooter())) {
281                        printFooter(transactionSummaryReport.getFooter(), document);
282                    }
283                }
284                
285            } catch (Exception e) {
286                return false;
287            }
288            
289            return true;
290        }
291    
292        /**
293         * Method to combine the kemid totals into one data record and print all fields.
294         * @param transactionSummaryDataReportHolders
295         * @param document
296         * @return true if successful else return false
297         */
298    
299        protected boolean printReportBodyByAllTotalsForTotalReportOption(List<TransactionSummaryReportDataHolder> transactionSummaryDataReportHolders, Document document) {
300            List<TransactionSummaryReportDataHolder> summaryReportDataHolder = combineKemidTotals(transactionSummaryDataReportHolders);
301            
302            return printReportBodyByAllTotalsForDetailReportOption(summaryReportDataHolder, document);        
303        }
304    
305        /**
306         * Method to combine the kemid totals into one data record and print only summary field.
307         * @param transactionSummaryDataReportHolders
308         * @param document
309         * @return true if successful else return false
310         */
311    
312        protected boolean printReportBodyForSummaryReportOption(List<TransactionSummaryReportDataHolder> transactionSummaryDataReportHolders, Document document) {
313            List<TransactionSummaryReportDataHolder> summaryReportDataHolder = combineKemidTotals(transactionSummaryDataReportHolders);
314            
315            return printReportBodyForDetailReportOption(summaryReportDataHolder, document);        
316        }
317        
318        protected List<TransactionSummaryReportDataHolder> combineKemidTotals(List<TransactionSummaryReportDataHolder> transactionSummaryDataReportHolders) {
319            List<TransactionSummaryReportDataHolder> summaryReportDataHolder = new ArrayList<TransactionSummaryReportDataHolder>();
320            
321            TransactionSummaryReportDataHolder transactionSummaryReportDataHolder = new TransactionSummaryReportDataHolder();
322            
323            for (TransactionSummaryReportDataHolder reportDataHolder : transactionSummaryDataReportHolders) {
324                transactionSummaryReportDataHolder.setIncomeBeginningMarketValue(transactionSummaryReportDataHolder.getIncomeBeginningMarketValue().add(reportDataHolder.getIncomeBeginningMarketValue()));
325                transactionSummaryReportDataHolder.setPrincipalBeginningMarketValue(transactionSummaryReportDataHolder.getPrincipalBeginningMarketValue().add(reportDataHolder.getPrincipalBeginningMarketValue()));
326                transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().add(reportDataHolder.getIncomeChangeInMarketValue()));
327                transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().add(reportDataHolder.getPrincipalChangeInMarketValue()));
328                transactionSummaryReportDataHolder.setIncomeEndingMarketValue(transactionSummaryReportDataHolder.getIncomeEndingMarketValue().add(reportDataHolder.getIncomeEndingMarketValue()));
329                transactionSummaryReportDataHolder.setPrincipalEndingMarketValue(transactionSummaryReportDataHolder.getPrincipalEndingMarketValue().add(reportDataHolder.getPrincipalEndingMarketValue()));
330                transactionSummaryReportDataHolder.setNext12MonthsEstimatedIncome(transactionSummaryReportDataHolder.getNext12MonthsEstimatedIncome().add(reportDataHolder.getNext12MonthsEstimatedIncome()));
331                transactionSummaryReportDataHolder.setRemainderOfFYEstimatedIncome(transactionSummaryReportDataHolder.getRemainderOfFYEstimatedIncome().add(reportDataHolder.getRemainderOfFYEstimatedIncome()));
332                transactionSummaryReportDataHolder.setNextFYEstimatedIncome(transactionSummaryReportDataHolder.getNextFYEstimatedIncome().add(reportDataHolder.getNextFYEstimatedIncome()));
333                transactionSummaryReportDataHolder.setInstitution(reportDataHolder.getInstitution());
334                transactionSummaryReportDataHolder.setBeginningDate(reportDataHolder.getBeginningDate());
335                transactionSummaryReportDataHolder.setEndingDate(reportDataHolder.getEndingDate());
336            }
337            
338            transactionSummaryReportDataHolder.setKemid("All Kemids");
339            transactionSummaryReportDataHolder.setKemidLongTitle("");
340            
341            getSummaryTotalsForContributions(transactionSummaryDataReportHolders, transactionSummaryReportDataHolder);
342            getSummaryTotalsForExpenses(transactionSummaryDataReportHolders, transactionSummaryReportDataHolder);
343            getSummaryTotalsForCashTransfers(transactionSummaryDataReportHolders, transactionSummaryReportDataHolder);
344            getSummaryTotalsForSecurityTransfers(transactionSummaryDataReportHolders, transactionSummaryReportDataHolder);
345            
346            summaryReportDataHolder.add(transactionSummaryReportDataHolder);
347            
348            return summaryReportDataHolder;
349        }
350        
351        /**
352         * Method to summarize the expenses list records for the summary totals report.
353         * @param transactionSummaryDataReportHolders
354         * @param transactionSummaryReportDataHolder
355         */
356        protected void getSummaryTotalsForContributions(List<TransactionSummaryReportDataHolder> transactionSummaryDataReportHolders, TransactionSummaryReportDataHolder transactionSummaryReportDataHolder) {
357    
358            ExpensesDataHolder expensesDataHolder = transactionSummaryReportDataHolder.new ExpensesDataHolder();
359            
360            ExpensesDataHolder summaryExpensesData = transactionSummaryReportDataHolder.new ExpensesDataHolder();
361            summaryExpensesData.setExpensesDescription("Summary Totals for Expenses");
362    
363            for (TransactionSummaryReportDataHolder reportDataHolder : transactionSummaryDataReportHolders) {
364                List<ExpensesDataHolder> expensesDataHolders = reportDataHolder.getReportGroupsForExpenses();
365                for (ExpensesDataHolder expenseData : expensesDataHolders) {
366                    summaryExpensesData.setIncomeExpenses(summaryExpensesData.getIncomeExpenses().add(expenseData.getIncomeExpenses()));
367                    summaryExpensesData.setPrincipalExpenses(summaryExpensesData.getPrincipalExpenses().add(expenseData.getPrincipalExpenses()));
368                }
369            }
370            
371            transactionSummaryReportDataHolder.getReportGroupsForExpenses().add(summaryExpensesData);
372        }
373    
374        /**
375         * Method to summarize the expenses list records for the summary totals report.
376         * @param transactionSummaryDataReportHolders
377         * @param transactionSummaryReportDataHolder
378         */
379        protected void getSummaryTotalsForExpenses(List<TransactionSummaryReportDataHolder> transactionSummaryDataReportHolders, TransactionSummaryReportDataHolder transactionSummaryReportDataHolder) {
380            ContributionsDataHolder summaryContributionsData = transactionSummaryReportDataHolder.new ContributionsDataHolder();
381            summaryContributionsData.setContributionsDescription("Summary Totals for Contibutions and Other Income");
382    
383            for (TransactionSummaryReportDataHolder reportDataHolder : transactionSummaryDataReportHolders) {
384                List<ContributionsDataHolder> contributionDataHolders = reportDataHolder.getReportGroupsForContributions();
385                for (ContributionsDataHolder contributionData : contributionDataHolders) {
386                    summaryContributionsData.setIncomeContributions(summaryContributionsData.getIncomeContributions().add(contributionData.getIncomeContributions()));
387                    summaryContributionsData.setPrincipalContributions(summaryContributionsData.getPrincipalContributions().add(contributionData.getPrincipalContributions()));
388                }
389            }
390            
391            transactionSummaryReportDataHolder.getReportGroupsForContributions().add(summaryContributionsData);
392        }
393    
394        /**
395         * Method to summarize the cash transfers list records for the summary totals report.
396         * @param transactionSummaryDataReportHolders
397         * @param transactionSummaryReportDataHolder
398         */
399        protected void getSummaryTotalsForCashTransfers(List<TransactionSummaryReportDataHolder> transactionSummaryDataReportHolders, TransactionSummaryReportDataHolder transactionSummaryReportDataHolder) {
400            CashTransfersDataHolder summaryCashTransferData = transactionSummaryReportDataHolder.new CashTransfersDataHolder();
401            summaryCashTransferData.setCashTransfersDescription("Summary Totals for Cash Transactions");
402    
403            for (TransactionSummaryReportDataHolder reportDataHolder : transactionSummaryDataReportHolders) {
404                List<CashTransfersDataHolder> cashTransfersDataHolders = reportDataHolder.getReportGroupsForCashTransfers();
405                for (CashTransfersDataHolder cashTransferData : cashTransfersDataHolders) {
406                    summaryCashTransferData.setIncomeCashTransfers(summaryCashTransferData.getIncomeCashTransfers().add(cashTransferData.getIncomeCashTransfers()));
407                    summaryCashTransferData.setPrincipalCashTransfers(summaryCashTransferData.getPrincipalCashTransfers().add(cashTransferData.getPrincipalCashTransfers()));
408                }
409            }
410            
411            transactionSummaryReportDataHolder.getReportGroupsForCashTransfers().add(summaryCashTransferData);
412        }
413        
414        /**
415         * Method to summarize the Security transfers list records for the summary totals report.
416         * @param transactionSummaryDataReportHolders
417         * @param transactionSummaryReportDataHolder
418         */
419        protected void getSummaryTotalsForSecurityTransfers(List<TransactionSummaryReportDataHolder> transactionSummaryDataReportHolders, TransactionSummaryReportDataHolder transactionSummaryReportDataHolder) {
420            SecurityTransfersDataHolder summarySecurityTransferData = transactionSummaryReportDataHolder.new SecurityTransfersDataHolder();
421            summarySecurityTransferData.setSecurityTransfersDescription("Summary Totals for Security Transactions");
422    
423            for (TransactionSummaryReportDataHolder reportDataHolder : transactionSummaryDataReportHolders) {
424                List<SecurityTransfersDataHolder> securityTransfersDataHolders = reportDataHolder.getReportGroupsForSecurityTransfers();
425                for (SecurityTransfersDataHolder securityTransferData : securityTransfersDataHolders) {
426                    summarySecurityTransferData.setIncomeSecurityTransfers(summarySecurityTransferData.getIncomeSecurityTransfers().add(securityTransferData.getIncomeSecurityTransfers()));
427                    summarySecurityTransferData.setPrincipalSecurityTransfers(summarySecurityTransferData.getPrincipalSecurityTransfers().add(securityTransferData.getPrincipalSecurityTransfers()));
428                }
429            }
430            
431            transactionSummaryReportDataHolder.getReportGroupsForSecurityTransfers().add(summarySecurityTransferData);
432        }
433    
434        /**
435         * Helper method to write the details line.
436         * 
437         * @param table
438         * @param cellFont
439         * @param description
440         * @param incomeAmount
441         * @param principalAmount
442         * @param totalAmount
443         */
444        protected void writeDetailLineRow(PdfPTable table, Font cellFont, String description,  BigDecimal incomeAmount, BigDecimal principalAmount, BigDecimal totalAmount) {
445            table.addCell("\t\t".concat(description));  
446            table.addCell(createCell(formatAmount(incomeAmount), cellFont, Element.ALIGN_RIGHT, true));
447            table.addCell(createCell(formatAmount(principalAmount), cellFont, Element.ALIGN_RIGHT, true));
448            table.addCell(createCell(formatAmount(totalAmount), cellFont, Element.ALIGN_RIGHT, true));
449        }
450    
451        /**
452         * Helper method to write the details line.
453         * 
454         * @param table
455         * @param cellFont
456         * @param description
457         * @param incomeAmount
458         * @param principalAmount
459         * @param totalAmount
460         */
461        protected void writeDetailLineRow(PdfPTable table, Font cellFont, String description, BigDecimal totalAmount) {
462            table.addCell("\t\t".concat(description));  
463            table.addCell(createCell(formatAmount(totalAmount), cellFont, Element.ALIGN_RIGHT, true));
464        }
465        
466        /**
467         * Helper method to go through the contributions list and write the lines..
468         * @param table
469         * @param cellFont
470         * @param transactionSummaryReport
471         */
472        protected void writeContributionsRecordsForDetailReportOption(PdfPTable table, Font cellFont, TransactionSummaryReportDataHolder transactionSummaryReport) {
473            String amount;
474            BigDecimal totalIncomeAmounts = BigDecimal.ZERO;
475            BigDecimal totalPrincipalAmounts = BigDecimal.ZERO;
476            
477            //write Contributions header....
478            writeSubHeader(table, "Contibutions and Other Income", EndowConstants.EndowmentReport.DETAIL);
479            
480            //now write out the records....
481            List<ContributionsDataHolder> contributionsData = transactionSummaryReport.getReportGroupsForContributions();
482            
483            if (contributionsData != null) {
484                for (ContributionsDataHolder contribution : contributionsData) {
485                    table.addCell(createCell("\t\t\t\t\t\t\t".concat(contribution.getContributionsDescription()), cellFont, Element.ALIGN_LEFT, true));
486                    totalIncomeAmounts = totalIncomeAmounts.add(contribution.getIncomeContributions());
487                    amount = formatAmount(contribution.getIncomeContributions());
488                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
489                    totalPrincipalAmounts = totalPrincipalAmounts.add(contribution.getPrincipalContributions());
490                    amount = formatAmount(contribution.getPrincipalContributions());
491                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
492                    amount = formatAmount(contribution.getTotalContributions());
493                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
494                }
495            }
496            
497            //now write out the sub-total line....amount
498            table.addCell("\t\t\t\t\t\t\t\tActivity Sub-Total");
499            amount = formatAmount(totalIncomeAmounts);
500            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
501            amount = formatAmount(totalPrincipalAmounts);
502            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
503            amount = formatAmount(totalIncomeAmounts.add(totalPrincipalAmounts));
504            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
505        }
506    
507        /**
508         * Helper method to go through the contributions list and write the lines..For summary report
509         * @param table
510         * @param cellFont
511         * @param transactionSummaryReport
512         */
513        protected void writeContributionsRecordsForSummaryReportOption(PdfPTable table, Font cellFont, TransactionSummaryReportDataHolder transactionSummaryReport) {
514            String amount;
515            BigDecimal totalIncomeAmounts = BigDecimal.ZERO;
516            BigDecimal totalPrincipalAmounts = BigDecimal.ZERO;
517            
518            //write Contributions header....
519            writeSubHeader(table, "Contibutions and Other Income", EndowConstants.EndowmentReport.TOTAL);
520            
521            //now write out the records....
522            List<ContributionsDataHolder> contributionsData = transactionSummaryReport.getReportGroupsForContributions();
523            
524            if (contributionsData != null) {
525                for (ContributionsDataHolder contribution : contributionsData) {
526                    table.addCell(createCell("\t\t\t\t\t\t\t".concat(contribution.getContributionsDescription()), cellFont, Element.ALIGN_LEFT, true));
527                    totalIncomeAmounts = totalIncomeAmounts.add(contribution.getIncomeContributions());
528                    totalPrincipalAmounts = totalPrincipalAmounts.add(contribution.getPrincipalContributions());
529                    amount = formatAmount(contribution.getTotalContributions());
530                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
531                }
532            }
533            
534            //now write out the sub-total line....amount
535            table.addCell("\t\t\t\t\t\t\t\tActivity Sub-Total");
536            amount = formatAmount(totalIncomeAmounts.add(totalPrincipalAmounts));
537            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
538        }
539        
540        /**
541         * Helper method to go through the expenses list and write the lines..
542         * @param table
543         * @param cellFont
544         * @param transactionSummaryReport
545         */
546        protected void writeExpensesRecordsForDetailReportOption(PdfPTable table, Font cellFont, TransactionSummaryReportDataHolder transactionSummaryReport) {
547            String amount;
548            BigDecimal totalIncomeAmounts = BigDecimal.ZERO;
549            BigDecimal totalPrincipalAmounts = BigDecimal.ZERO;
550            
551            //write Contributions header....
552            writeSubHeader(table, "Expenses", EndowConstants.EndowmentReport.DETAIL);
553            
554            //now write out the records....
555            List<ExpensesDataHolder> expensesData = transactionSummaryReport.getReportGroupsForExpenses();
556            
557            if (expensesData != null) {
558                for (ExpensesDataHolder expenses : expensesData) {
559                    table.addCell(createCell("\t\t\t\t\t\t\t".concat(expenses.getExpensesDescription()), cellFont, Element.ALIGN_LEFT, true));
560                    totalIncomeAmounts = totalIncomeAmounts.add(expenses.getIncomeExpenses());
561                    amount = formatAmount(expenses.getIncomeExpenses());
562                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
563                    totalPrincipalAmounts = totalPrincipalAmounts.add(expenses.getPrincipalExpenses());
564                    amount = formatAmount(expenses.getPrincipalExpenses());
565                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
566                    amount = formatAmount(expenses.getTotalExpenses());
567                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
568                }
569            }
570            
571            //now write out the sub-total line....amount
572            table.addCell("\t\t\t\t\t\t\t\tActivity Sub-Total");
573            amount = formatAmount(totalIncomeAmounts);
574            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
575            amount = formatAmount(totalPrincipalAmounts);
576            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
577            amount = formatAmount(totalIncomeAmounts.add(totalPrincipalAmounts));
578            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
579        }
580    
581        /**
582         * Helper method to go through the expenses list and write the lines..
583         * @param table
584         * @param cellFont
585         * @param transactionSummaryReport
586         */
587        protected void writeExpensesRecordsForSummaryReportOption(PdfPTable table, Font cellFont, TransactionSummaryReportDataHolder transactionSummaryReport) {
588            String amount;
589            BigDecimal totalIncomeAmounts = BigDecimal.ZERO;
590            BigDecimal totalPrincipalAmounts = BigDecimal.ZERO;
591            
592            //write Contributions header....
593            writeSubHeader(table, "Expenses", EndowConstants.EndowmentReport.TOTAL);
594            
595            //now write out the records....
596            List<ExpensesDataHolder> expensesData = transactionSummaryReport.getReportGroupsForExpenses();
597            
598            if (expensesData != null) {
599                for (ExpensesDataHolder expenses : expensesData) {
600                    table.addCell(createCell("\t\t\t\t\t\t\t".concat(expenses.getExpensesDescription()), cellFont, Element.ALIGN_LEFT, true));
601                    totalIncomeAmounts = totalIncomeAmounts.add(expenses.getIncomeExpenses());
602                    totalPrincipalAmounts = totalPrincipalAmounts.add(expenses.getPrincipalExpenses());
603                    amount = formatAmount(expenses.getTotalExpenses());
604                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
605                }
606            }
607            
608            //now write out the sub-total line....amount
609            table.addCell("\t\t\t\t\t\t\t\tActivity Sub-Total");
610            amount = formatAmount(totalIncomeAmounts.add(totalPrincipalAmounts));
611            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
612        }
613    
614        /**
615         * Helper method to go through the cash transfers list and write the lines..
616         * @param table
617         * @param cellFont
618         * @param transactionSummaryReport
619         */
620        protected void writeCashTransfersRecordsForDetailReportOption(PdfPTable table, Font cellFont, TransactionSummaryReportDataHolder transactionSummaryReport) {
621            String amount;
622            BigDecimal totalIncomeAmounts = BigDecimal.ZERO;
623            BigDecimal totalPrincipalAmounts = BigDecimal.ZERO;
624            
625            //write Contributions header....
626            writeSubHeader(table, "Cash Transfers", EndowConstants.EndowmentReport.DETAIL);
627            
628            //now write out the records....
629            List<CashTransfersDataHolder> cashTransfersData = transactionSummaryReport.getReportGroupsForCashTransfers();
630            
631            if (cashTransfersData != null) {
632                for (CashTransfersDataHolder cashTransfer : cashTransfersData) {
633                    table.addCell(createCell("\t\t\t\t\t\t\t".concat(cashTransfer.getCashTransfersDescription()), cellFont, Element.ALIGN_LEFT, true));
634                    totalIncomeAmounts = totalIncomeAmounts.add(cashTransfer.getIncomeCashTransfers());
635                    amount = formatAmount(cashTransfer.getIncomeCashTransfers());
636                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
637                    totalPrincipalAmounts = totalPrincipalAmounts.add(cashTransfer.getPrincipalCashTransfers());
638                    amount = formatAmount(cashTransfer.getPrincipalCashTransfers());
639                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
640                    amount = formatAmount(cashTransfer.getTotalCashTransfers());
641                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
642                }
643            }
644            
645            //now write out the sub-total line....amount
646            table.addCell("\t\t\t\t\t\t\t\tActivity Sub-Total");
647            amount = formatAmount(totalIncomeAmounts);
648            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
649            amount = formatAmount(totalPrincipalAmounts);
650            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
651            amount = formatAmount(totalIncomeAmounts.add(totalPrincipalAmounts));
652            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
653        }
654    
655        /**
656         * Helper method to go through the expenses list and write the lines..
657         * @param table
658         * @param cellFont
659         * @param transactionSummaryReport
660         */
661        protected void writeCashTransfersRecordsForSummaryReportOption(PdfPTable table, Font cellFont, TransactionSummaryReportDataHolder transactionSummaryReport) {
662            String amount;
663            BigDecimal totalIncomeAmounts = BigDecimal.ZERO;
664            BigDecimal totalPrincipalAmounts = BigDecimal.ZERO;
665            
666            //write Contributions header....
667            writeSubHeader(table, "Cash Transfers", EndowConstants.EndowmentReport.TOTAL);
668            
669            //now write out the records....
670            List<CashTransfersDataHolder> cashTransfersData = transactionSummaryReport.getReportGroupsForCashTransfers();
671            
672            if (cashTransfersData != null) {
673                for (CashTransfersDataHolder cashTransfer : cashTransfersData) {
674                    table.addCell(createCell("\t\t\t\t\t\t\t".concat(cashTransfer.getCashTransfersDescription()), cellFont, Element.ALIGN_LEFT, true));
675                    totalIncomeAmounts = totalIncomeAmounts.add(cashTransfer.getIncomeCashTransfers());
676                    totalPrincipalAmounts = totalPrincipalAmounts.add(cashTransfer.getPrincipalCashTransfers());
677                    amount = formatAmount(cashTransfer.getTotalCashTransfers());
678                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
679                }
680            }
681            
682            //now write out the sub-total line....amount
683            table.addCell("\t\t\t\t\t\t\t\tActivity Sub-Total");
684            amount = formatAmount(totalIncomeAmounts.add(totalPrincipalAmounts));
685            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
686        }
687        
688        /**
689         * Helper method to go through the security list and write the lines..
690         * @param table
691         * @param cellFont
692         * @param transactionSummaryReport
693         */
694        protected void writeSecurityTransfersRecordsForSummaryReportOption(PdfPTable table, Font cellFont, TransactionSummaryReportDataHolder transactionSummaryReport) {
695            String amount;
696            BigDecimal totalIncomeAmounts = BigDecimal.ZERO;
697            BigDecimal totalPrincipalAmounts = BigDecimal.ZERO;
698            
699            //write Contributions header....
700            writeSubHeader(table, "Security Transfers", EndowConstants.EndowmentReport.TOTAL);
701            
702            //now write out the records....
703            List<SecurityTransfersDataHolder> securityTransfersData = transactionSummaryReport.getReportGroupsForSecurityTransfers();
704            
705            if (securityTransfersData != null) {
706                for (SecurityTransfersDataHolder securityTransfer : securityTransfersData) {
707                    table.addCell(createCell("\t\t\t\t\t\t\t".concat(securityTransfer.getSecurityTransfersDescription()), cellFont, Element.ALIGN_LEFT, true));
708                    totalIncomeAmounts = totalIncomeAmounts.add(securityTransfer.getIncomeSecurityTransfers());
709                    totalPrincipalAmounts = totalPrincipalAmounts.add(securityTransfer.getPrincipalSecurityTransfers());
710                    amount = formatAmount(securityTransfer.getTotalSecurityTransfers());
711                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
712                }
713            }
714            
715            //now write out the sub-total line....amount
716            table.addCell("\t\t\t\t\t\t\t\tActivity Sub-Total");
717            amount = formatAmount(totalIncomeAmounts.add(totalPrincipalAmounts));
718            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
719        }
720        
721        /**
722         * Helper method to go through the cash transfers list and write the lines..
723         * @param table
724         * @param cellFont
725         * @param transactionSummaryReport
726         */
727        protected void writeSecurityTransfersRecordsForDetailReportOption(PdfPTable table, Font cellFont, TransactionSummaryReportDataHolder transactionSummaryReport) {
728            String amount;
729            BigDecimal totalIncomeAmounts = BigDecimal.ZERO;
730            BigDecimal totalPrincipalAmounts = BigDecimal.ZERO;
731            
732            //write Contributions header....
733            writeSubHeader(table, "Security Transfers", EndowConstants.EndowmentReport.DETAIL);
734            
735            //now write out the records....
736            List<SecurityTransfersDataHolder> SecurityTransfersData = transactionSummaryReport.getReportGroupsForSecurityTransfers();
737            
738            if (SecurityTransfersData != null) {
739                for (SecurityTransfersDataHolder securityTransfer : SecurityTransfersData) {
740                    table.addCell(createCell("\t\t\t\t\t\t\t".concat(securityTransfer.getSecurityTransfersDescription()), cellFont, Element.ALIGN_LEFT, true));
741                    totalIncomeAmounts = totalIncomeAmounts.add(securityTransfer.getIncomeSecurityTransfers());
742                    amount = formatAmount(securityTransfer.getIncomeSecurityTransfers());
743                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
744                    totalPrincipalAmounts = totalPrincipalAmounts.add(securityTransfer.getPrincipalSecurityTransfers());
745                    amount = formatAmount(securityTransfer.getPrincipalSecurityTransfers());
746                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
747                    amount = formatAmount(securityTransfer.getTotalSecurityTransfers());
748                    table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
749                }
750            }
751            
752            //now write out the sub-total line....amount
753            table.addCell("\t\t\t\t\t\t\t\tActivity Sub-Total");
754            amount = formatAmount(totalIncomeAmounts);
755            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
756            amount = formatAmount(totalPrincipalAmounts);
757            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));
758            amount = formatAmount(totalIncomeAmounts.add(totalPrincipalAmounts));
759            table.addCell(createCell(amount, cellFont, Element.ALIGN_RIGHT, true));            
760        }
761        
762        /**
763         * Helper method to write the document header
764         * 
765         * @param document
766         * @param transactionSummaryReport
767         */
768        protected void writeDocumentHeader(Document document, TransactionSummaryReportDataHolder transactionSummaryReport) {
769            // header
770            StringBuffer title = new StringBuffer();
771            title.append(transactionSummaryReport.getInstitution()).append("\n");
772            title.append("SUMMARY OF ACTIVITY FROM ");
773            title.append(transactionSummaryReport.getBeginningDate()).append(" TO ").append(transactionSummaryReport.getEndingDate()).append("\n");
774            title.append(transactionSummaryReport.getKemid()).append("     ").append(transactionSummaryReport.getKemidLongTitle()).append("\n\n");
775            try {
776            Paragraph header = new Paragraph(title.toString());
777            header.setAlignment(Element.ALIGN_CENTER);                
778            document.add(header);
779            } catch (DocumentException de) {
780                LOG.info("writeDocumentHeader(): Unable to create the header for the report");  
781            }
782        }
783    
784        /**
785         * Helper method to write a line containing the column headings for the report
786         * 
787         * @return table
788         */
789        protected PdfPTable writeDocumentTitleHeadings(String reportOption) {
790            // report table
791            int pdfPTableColumns;
792            int[] relativeWidthsForDetails = {140, 25, 25, 25};
793            int[] relativeWidthsForSummary = {140, 25};
794            
795            if (EndowConstants.EndowmentReport.DETAIL.equalsIgnoreCase(reportOption)) {
796                pdfPTableColumns = 4;
797            }
798            else {
799                pdfPTableColumns = 2;
800            }
801            
802            try {
803                PdfPTable table = new PdfPTable(pdfPTableColumns);
804                table.setWidthPercentage(FULL_TABLE_WIDTH);
805                table.setWidths((EndowConstants.EndowmentReport.DETAIL.equalsIgnoreCase(reportOption)) ? relativeWidthsForDetails : relativeWidthsForSummary);
806                table.getDefaultCell().setPadding(5);
807                
808                // table titles
809                table.addCell(new Phrase("", titleFont));
810                
811                if(EndowConstants.EndowmentReport.DETAIL.equalsIgnoreCase(reportOption)) {
812                    table.addCell(createCell("INCOME", titleFont, Element.ALIGN_CENTER, true));
813                    table.addCell(createCell("PRINCIPAL", titleFont, Element.ALIGN_CENTER, true));
814                }
815                
816                table.addCell(createCell("TOTAL", titleFont, Element.ALIGN_CENTER, true));
817                return table;
818            }
819            catch (DocumentException ex) {
820                LOG.info("Unable to write column headers.");
821                return null;
822            }
823        }
824    
825        /**
826         * helper method to write out a sub-heading into the report.
827         */
828        protected void writeSubHeader(PdfPTable table, String subHeading, String reportOption) {
829            table.addCell("\t\t".concat(subHeading));
830            if (reportOption.equalsIgnoreCase(EndowConstants.EndowmentReport.DETAIL)) {
831                table.addCell("");
832                table.addCell("");
833            }
834            table.addCell("");
835        }
836    
837        /**
838         * helper method to write the details lines where only the last column exists for amounts..
839         * @param description
840         * @param amount
841         */
842        protected void writeDetailsLineWithTotalAmountOnly(PdfPTable table, Font cellFont, String description, BigDecimal amount, String reportOption) {
843            table.addCell("\t\t".concat(description));
844            if (reportOption.equalsIgnoreCase(EndowConstants.EndowmentReport.DETAIL)) {
845                table.addCell("");
846                table.addCell("");
847            }
848            table.addCell(createCell(formatAmount(amount), cellFont, Element.ALIGN_RIGHT, true));            
849        }
850    }
851