001/*
002 * Copyright 2009 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.util.ArrayList;
019import java.util.LinkedHashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.commons.lang.StringUtils;
024import org.kuali.ole.gl.businessobject.LedgerBalanceTypeSummaryTotalLine;
025import org.kuali.ole.gl.businessobject.LedgerSummaryDetailLine;
026import org.kuali.ole.gl.businessobject.LedgerSummaryTotalLine;
027import org.kuali.ole.gl.businessobject.OriginEntryInformation;
028import org.kuali.ole.sys.DynamicCollectionComparator;
029import org.kuali.ole.sys.OLEConstants;
030import org.kuali.ole.sys.service.ReportWriterService;
031
032/**
033 * Helper class which can summarize entries by balance type and then print out a ledger summary report
034 */
035public class LedgerSummaryReport {
036    private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LedgerSummaryReport.class);
037    
038    private LedgerSummaryTotalLine ledgerTotalLine;
039    private Map<String, LedgerBalanceTypeSummaryTotalLine> balanceTypeTotals;
040    Map<String, LedgerSummaryDetailLine> details;
041    
042    /**
043     * Constructs a LedgerSummaryReport
044     */
045    public LedgerSummaryReport() {
046        ledgerTotalLine = new LedgerSummaryTotalLine();
047        balanceTypeTotals = new LinkedHashMap<String, LedgerBalanceTypeSummaryTotalLine>();
048        details = new LinkedHashMap<String, LedgerSummaryDetailLine>();
049    }
050    
051    /**
052     * Summarizes an entry into the various totals which this report is keeping
053     * @param entry an entry to summarize
054     */
055    public void summarizeEntry(OriginEntryInformation entry) {
056        LedgerBalanceTypeSummaryTotalLine balanceTypeTotal = getBalanceTypeSummaryTotalLine(entry, balanceTypeTotals);
057        LedgerSummaryDetailLine detailLine = getDetailLine(entry, details);
058        addEntryToLedgerSummaries(entry, ledgerTotalLine, balanceTypeTotal, detailLine);
059    }
060    
061    /**
062     * Retrieves the proper balance type summarizer from the given map, or creates a new summarizer and puts it in the Map if it doesn't already exist
063     * @param entry the origin entry to find a balance type summarizer for
064     * @param balanceTypeTotals the Map of balance type summarizers
065     * @return the proper balance type summarizer
066     */
067    protected LedgerBalanceTypeSummaryTotalLine getBalanceTypeSummaryTotalLine(OriginEntryInformation entry, Map<String, LedgerBalanceTypeSummaryTotalLine> balanceTypeTotals) {
068        final String balanceTypeCode = (StringUtils.isBlank(entry.getFinancialBalanceTypeCode())) ? " " : entry.getFinancialBalanceTypeCode();
069        LedgerBalanceTypeSummaryTotalLine balanceTypeTotal = balanceTypeTotals.get(balanceTypeCode);
070        if (balanceTypeTotal == null) {
071            balanceTypeTotal = new LedgerBalanceTypeSummaryTotalLine(balanceTypeCode);
072            balanceTypeTotals.put(balanceTypeCode, balanceTypeTotal);
073        }
074        return balanceTypeTotal;
075    }
076    
077    /**
078     * Retrieves the proper detail line summarizer from the given map, or creates a new summarizer and adds it to the map if needed
079     * @param entry the origin entry to find a detail line summarizer for
080     * @param detailLines a Map of detail line summarizers
081     * @return the proper detail line summarizer
082     */
083    protected LedgerSummaryDetailLine getDetailLine(OriginEntryInformation entry, Map<String, LedgerSummaryDetailLine> detailLines) {
084        final String key = LedgerSummaryDetailLine.getKeyString(entry);
085        LedgerSummaryDetailLine detailLine = detailLines.get(key);
086        if (detailLine == null) {
087            detailLine = new LedgerSummaryDetailLine(entry.getFinancialBalanceTypeCode(), entry.getFinancialSystemOriginationCode(), entry.getUniversityFiscalYear(), entry.getUniversityFiscalPeriodCode());
088            detailLines.put(detailLine.getKey(), detailLine);
089        }
090        return detailLine;
091    }
092    
093    /**
094     * Adds the amount of the origin entry into the appropriate total - debit, credit, or budget - on the various ledger summarizers
095     * @param originEntry the origin entry to add the total from
096     * @param totalLine a complete total to add the amount to
097     * @param balanceTypeTotal the total for the entries with the same balance type as the origin entry to add the amount to
098     * @param detailLine the proper detail amount to add the amoun tto
099     */
100    protected void addEntryToLedgerSummaries(OriginEntryInformation originEntry, LedgerSummaryTotalLine totalLine, LedgerBalanceTypeSummaryTotalLine balanceTypeTotal, LedgerSummaryDetailLine detailLine) {
101        if (originEntry.getTransactionDebitCreditCode() != null && originEntry.getTransactionDebitCreditCode().equals(OLEConstants.GL_DEBIT_CODE)) {
102            totalLine.addDebitAmount(originEntry.getTransactionLedgerEntryAmount());
103            balanceTypeTotal.addDebitAmount(originEntry.getTransactionLedgerEntryAmount());
104            detailLine.addDebitAmount(originEntry.getTransactionLedgerEntryAmount());
105        } else if (originEntry.getTransactionDebitCreditCode() != null && originEntry.getTransactionDebitCreditCode().equals(OLEConstants.GL_CREDIT_CODE)) {
106            totalLine.addCreditAmount(originEntry.getTransactionLedgerEntryAmount());
107            balanceTypeTotal.addCreditAmount(originEntry.getTransactionLedgerEntryAmount());
108            detailLine.addCreditAmount(originEntry.getTransactionLedgerEntryAmount());
109        } else{
110            totalLine.addBudgetAmount(originEntry.getTransactionLedgerEntryAmount());
111            balanceTypeTotal.addBudgetAmount(originEntry.getTransactionLedgerEntryAmount());
112            detailLine.addBudgetAmount(originEntry.getTransactionLedgerEntryAmount());
113        }
114    }
115    
116    /**
117     * Writes the report of totals to the given reportWriterService
118     * @param reportWriterService a report writer service to write the ledger summary report to
119     */
120    public void writeReport(ReportWriterService reportWriterService) {
121        if (details.size() > 0) {
122            List<LedgerSummaryDetailLine> detailList = new ArrayList<LedgerSummaryDetailLine>(details.values());
123            DynamicCollectionComparator.sort(detailList, LedgerSummaryDetailLine.keyFields);
124        
125            reportWriterService.writeTableHeader(detailList.get(0));
126            String currentBalanceType = detailList.get(0).getFinancialBalanceTypeCode();
127            currentBalanceType = StringUtils.isBlank(currentBalanceType) ? " " : currentBalanceType;
128            
129            for (LedgerSummaryDetailLine detailLine : detailList) {
130                String detailLineBalanceType = (StringUtils.isBlank(detailLine.getFinancialBalanceTypeCode())) ? " " : detailLine.getFinancialBalanceTypeCode();
131                if (!detailLineBalanceType.equals(currentBalanceType)) {
132                    LedgerBalanceTypeSummaryTotalLine subTitleLine = balanceTypeTotals.get(currentBalanceType);
133                    
134                    if (subTitleLine != null) {
135                        reportWriterService.writeTableRow(subTitleLine);
136                        reportWriterService.writeTableRowSeparationLine(subTitleLine);
137                    }
138                    currentBalanceType = detailLineBalanceType;
139                }
140
141                reportWriterService.writeTableRow(detailLine);
142            }
143            final LedgerBalanceTypeSummaryTotalLine lastLine = balanceTypeTotals.get(detailList.get(detailList.size()-1).getFinancialBalanceTypeCode());
144            if (lastLine != null) {
145                reportWriterService.writeTableRow(lastLine);
146            }
147            
148            reportWriterService.writeTableRowSeparationLine(ledgerTotalLine);
149            reportWriterService.writeTableRow(ledgerTotalLine);
150        }
151    }
152    
153}