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.batch;
017    
018    import java.io.File;
019    import java.text.SimpleDateFormat;
020    import java.util.ArrayList;
021    import java.util.Date;
022    import java.util.Iterator;
023    import java.util.List;
024    
025    import org.apache.commons.io.filefilter.RegexFileFilter;
026    import org.kuali.kfs.gl.GeneralLedgerConstants;
027    import org.kuali.kfs.gl.batch.service.impl.OriginEntryFileIterator;
028    import org.kuali.kfs.gl.businessobject.GlSummary;
029    import org.kuali.kfs.gl.businessobject.OriginEntryInformation;
030    import org.kuali.kfs.gl.businessobject.Reversal;
031    import org.kuali.kfs.gl.report.PosterOutputSummaryReport;
032    import org.kuali.kfs.gl.service.BalanceService;
033    import org.kuali.kfs.gl.service.ReversalService;
034    import org.kuali.kfs.sys.FileUtil;
035    import org.kuali.kfs.sys.batch.AbstractWrappedBatchStep;
036    import org.kuali.kfs.sys.batch.service.WrappingBatchService;
037    import org.kuali.kfs.sys.batch.service.WrappedBatchExecutorService.CustomBatchExecutor;
038    import org.kuali.kfs.sys.businessobject.SystemOptions;
039    import org.kuali.kfs.sys.service.FiscalYearAwareReportWriterService;
040    import org.kuali.kfs.sys.service.OptionsService;
041    import org.kuali.kfs.sys.service.ReportWriterService;
042    
043    /**
044     * A step to generate summary reports from a recent poster run
045     */
046    public class PosterSummaryReportStep extends AbstractWrappedBatchStep {
047        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PosterSummaryReportStep.class);
048        private static final String DATE_FORMAT = "MMdd";
049        private static final String BUD = "bud";
050        private static final String ACT = "act";
051        private static final String ENC = "enc";
052        private OptionsService optionsService;
053        private ReportWriterService posterOutputSummaryReportWriterService;
054        private FiscalYearAwareReportWriterService posterActualBalanceSummaryReportWriterService;
055        private FiscalYearAwareReportWriterService posterBudgetBalanceSummaryReportWriterService;
056        private FiscalYearAwareReportWriterService posterEncumbranceSummaryReportWriterService;
057        private ReversalService reversalService;
058        private BalanceService balanceService;
059        private String batchFileDirectoryName;
060    
061        /**
062         * @see org.kuali.kfs.sys.batch.AbstractWrappedBatchStep#getCustomBatchExecutor()
063         */
064        @Override
065        protected CustomBatchExecutor getCustomBatchExecutor() {
066            return new CustomBatchExecutor() {
067                /**
068                 * Runs the process that generates poster summary reports.
069                 * 
070                 * @return true if the step completed successfully, false if otherwise
071                 * @see org.kuali.kfs.sys.batch.Step#execute(java.lang.String)
072                 */
073                public boolean execute() {
074                    synchronized(this) { // why the synchronization?
075                        final String CURRENT_YEAR_LOWER = getCurrentYearLowerParameter();
076                        final String CURRENT_YEAR_UPPER = getCurrentYearUpperParameter();
077                        final String CURRENT_AND_LAST_YEAR = getCurrentAndLastYearParameter();
078        
079                        SystemOptions currentYear = optionsService.getCurrentYearOptions();
080                        SystemOptions nextYear = optionsService.getOptions(currentYear.getUniversityFiscalYear() + 1);
081                        SystemOptions previousYear = optionsService.getOptions(currentYear.getUniversityFiscalYear() - 1);
082        
083                        Date runDate = getDateTimeService().getCurrentDate();
084                        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
085                        String md = sdf.format(runDate);
086                        generatePosterOutputReport(runDate);
087                        if ((md.compareTo(CURRENT_YEAR_UPPER) > 0) || (md.compareTo(CURRENT_YEAR_LOWER) < 0)) {
088                            // Current year
089                            generateGlSummary(runDate, currentYear, BUD);
090                            generateGlSummary(runDate, currentYear, ACT);
091                            generateGlSummary(runDate, currentYear, ENC);
092                        }
093                        else if ((md.compareTo(CURRENT_AND_LAST_YEAR) > 0)) {
094                            // Current year and Last year
095                            generateGlSummary(runDate, currentYear, BUD);
096                            generateGlSummary(runDate, previousYear, BUD);
097                            generateGlSummary(runDate, currentYear, ACT);
098                            generateGlSummary(runDate, previousYear, ACT);
099                            generateGlSummary(runDate, currentYear, ENC);
100                            generateGlSummary(runDate, previousYear, ENC);
101                        }
102                        else {
103                            // Current year and next year
104                            generateGlSummary(runDate, currentYear, BUD);
105                            generateGlSummary(runDate, nextYear, BUD);
106                            generateGlSummary(runDate, currentYear, ACT);
107                            generateGlSummary(runDate, nextYear, ACT);
108                            generateGlSummary(runDate, currentYear, ENC);
109                            generateGlSummary(runDate, nextYear, ENC);
110                        }
111                    }
112                    return true;
113                }
114            };
115        }
116        
117        /**
118         * Generates reports about the output of a poster run.
119         * 
120         * @param runDate the date the poster was run.
121         */
122        private void generatePosterOutputReport(Date runDate) {
123            PosterOutputSummaryReport posterOutputSummaryReport = new PosterOutputSummaryReport();
124            
125            // summarize all the entries for the main poster
126            File mainPosterFile = FileUtil.getNewestFile(new File(batchFileDirectoryName), new RegexFileFilter((GeneralLedgerConstants.BatchFileSystem.POSTER_INPUT_FILE + "\\.[0-9_\\-]+\\" + GeneralLedgerConstants.BatchFileSystem.EXTENSION)));
127            if (mainPosterFile != null && mainPosterFile.exists()) {
128                OriginEntryFileIterator mainPosterIterator = new OriginEntryFileIterator(mainPosterFile);
129                while (mainPosterIterator.hasNext()) {
130                    final OriginEntryInformation originEntry = mainPosterIterator.next();
131                    posterOutputSummaryReport.summarize(originEntry);
132                }
133            } else {
134                LOG.warn("Could not Main Poster Input file with prefix "+GeneralLedgerConstants.BatchFileSystem.POSTER_INPUT_FILE+" for tabulation in the Poster Output Summary Report");
135            }
136    
137            // summarize today's reversals
138            File reversalPosterFile = FileUtil.getNewestFile(new File(batchFileDirectoryName), new RegexFileFilter((GeneralLedgerConstants.BatchFileSystem.REVERSAL_POSTER_VALID_OUTPUT_FILE + "\\.[0-9_\\-]+\\" + GeneralLedgerConstants.BatchFileSystem.EXTENSION)));
139            if (reversalPosterFile != null && reversalPosterFile.exists()) {
140                OriginEntryFileIterator reversalOriginEntryIterator = new OriginEntryFileIterator(reversalPosterFile);
141                while (reversalOriginEntryIterator.hasNext()) {
142                    final Reversal reversal = new Reversal (reversalOriginEntryIterator.next());
143                    posterOutputSummaryReport.summarize(reversal);
144                }
145            } else {
146                LOG.warn("Could not Reversal Output file with prefix "+GeneralLedgerConstants.BatchFileSystem.REVERSAL_POSTER_VALID_OUTPUT_FILE+" for tabulation in the Poster Output Summary Report");
147            }
148            
149            // summarize the icr poster
150            File icrPosterFile = FileUtil.getNewestFile(new File(batchFileDirectoryName), new RegexFileFilter(GeneralLedgerConstants.BatchFileSystem.ICR_POSTER_INPUT_FILE + "\\.[0-9_\\-]+\\" + GeneralLedgerConstants.BatchFileSystem.EXTENSION));
151            if (icrPosterFile != null && icrPosterFile.exists()) {
152                OriginEntryFileIterator icrIterator = new OriginEntryFileIterator(icrPosterFile);
153                while (icrIterator.hasNext()) {
154                    final OriginEntryInformation originEntry = icrIterator.next();
155                    posterOutputSummaryReport.summarize(originEntry);
156                }
157            } else {
158                LOG.warn("Could not Indirect Cost Recovery Poster Input file with prefix "+GeneralLedgerConstants.BatchFileSystem.ICR_POSTER_INPUT_FILE+" for tabulation in the Poster Output Summary Report");
159            }
160            
161            posterOutputSummaryReport.writeReport(posterOutputSummaryReportWriterService);
162        }
163    
164        /**
165         * Generates the GL Summary report
166         * 
167         * @param runDate the run date of the poster service that should be reported
168         * @param options the options of the fiscal year the poster was run
169         * @param reportType the type of the report that should be generated
170         */
171        protected void generateGlSummary(Date runDate, SystemOptions year, String reportType) {
172            LOG.debug("generateGlSummary() started");
173    
174            FiscalYearAwareReportWriterService fiscalYearAwareReportWriterService;
175            
176            List<String> balanceTypeCodes = new ArrayList<String>();
177            if (ACT.equals(reportType)) {
178                fiscalYearAwareReportWriterService = posterActualBalanceSummaryReportWriterService;
179                balanceTypeCodes.add(year.getActualFinancialBalanceTypeCd());
180            }
181            else if (BUD.equals(reportType)) {
182                fiscalYearAwareReportWriterService = posterBudgetBalanceSummaryReportWriterService;
183                balanceTypeCodes.add(year.getBudgetCheckingBalanceTypeCd());
184                balanceTypeCodes.add(year.getBaseBudgetFinancialBalanceTypeCd());
185                balanceTypeCodes.add(year.getMonthlyBudgetFinancialBalanceTypeCd());
186            } else { // ENC
187                fiscalYearAwareReportWriterService = posterEncumbranceSummaryReportWriterService;
188                balanceTypeCodes.add(year.getExtrnlEncumFinBalanceTypCd());
189                balanceTypeCodes.add(year.getIntrnlEncumFinBalanceTypCd());
190                balanceTypeCodes.add(year.getPreencumbranceFinBalTypeCd());
191                balanceTypeCodes.add(year.getCostShareEncumbranceBalanceTypeCd());
192            }
193    
194            List<GlSummary> balances = balanceService.getGlSummary(year.getUniversityFiscalYear(), balanceTypeCodes);
195            
196            GlSummary totals = new GlSummary();
197            for(GlSummary balance : balances) {
198                totals.add(balance);
199            }        
200            totals.setFundGroup("Total");
201            
202            try {
203                fiscalYearAwareReportWriterService.setFiscalYear(year.getUniversityFiscalYear());
204                ((WrappingBatchService) fiscalYearAwareReportWriterService).initialize();
205                
206                fiscalYearAwareReportWriterService.writeSubTitle("Balance Type of " + balanceTypeCodes + " for Fiscal Year " + year.getUniversityFiscalYearName());
207                fiscalYearAwareReportWriterService.writeNewLines(1);
208                
209                fiscalYearAwareReportWriterService.writeTableRowSeparationLine(totals);
210                fiscalYearAwareReportWriterService.writeTable(balances, true, false);
211                
212                fiscalYearAwareReportWriterService.writeTableRowSeparationLine(totals);
213                fiscalYearAwareReportWriterService.writeTableRow(totals);
214            } finally {
215                ((WrappingBatchService) fiscalYearAwareReportWriterService).destroy();
216            }
217        }
218        
219        /**
220         * @return current year lower parameter for inner class
221         */
222        public String getCurrentYearLowerParameter() {
223            return getParameterService().getParameterValue(getClass(), GeneralLedgerConstants.GlSummaryReport.CURRENT_YEAR_LOWER);
224        }
225        
226        /**
227         * @return current year upper parameter for inner class
228         */
229        public String getCurrentYearUpperParameter() {
230            return getParameterService().getParameterValue(PosterSummaryReportStep.this.getClass(), GeneralLedgerConstants.GlSummaryReport.CURRENT_YEAR_UPPER);
231        }
232        
233        /**
234         * @return current and last year parameter for inner class
235         */
236        public String getCurrentAndLastYearParameter() {
237            return getParameterService().getParameterValue(PosterSummaryReportStep.this.getClass(), GeneralLedgerConstants.GlSummaryReport.CURRENT_AND_LAST_YEAR);
238        }
239    
240        /**
241         * Sets the optionsService attribute, allowing the injection of an implementation of that service
242         * 
243         * @param os the optionsService implementation to set
244         * @see org.kuali.kfs.sys.service.OptionsService
245         */
246        public void setOptionsService(OptionsService os) {
247            optionsService = os;
248        }
249    
250        /**
251         * Gets the posterOutputSummaryReportWriterService attribute. 
252         * @return Returns the posterOutputSummaryReportWriterService.
253         */
254        public ReportWriterService getPosterOutputSummaryReportWriterService() {
255            return posterOutputSummaryReportWriterService;
256        }
257    
258        /**
259         * Sets the posterOutputSummaryReportWriterService attribute value.
260         * @param posterOutputSummaryReportWriterService The posterOutputSummaryReportWriterService to set.
261         */
262        public void setPosterOutputSummaryReportWriterService(ReportWriterService posterOutputSummaryReportWriterService) {
263            this.posterOutputSummaryReportWriterService = posterOutputSummaryReportWriterService;
264        }
265    
266        /**
267         * Sets the posterActualBalanceSummaryReportWriterService attribute value.
268         * @param posterActualBalanceSummaryReportWriterService The posterActualBalanceSummaryReportWriterService to set.
269         */
270        public void setPosterActualBalanceSummaryReportWriterService(FiscalYearAwareReportWriterService posterActualBalanceSummaryReportWriterService) {
271            this.posterActualBalanceSummaryReportWriterService = posterActualBalanceSummaryReportWriterService;
272        }
273    
274        /**
275         * Sets the posterBudgetBalanceSummaryReportWriterService attribute value.
276         * @param posterBudgetBalanceSummaryReportWriterService The posterBudgetBalanceSummaryReportWriterService to set.
277         */
278        public void setPosterBudgetBalanceSummaryReportWriterService(FiscalYearAwareReportWriterService posterBudgetBalanceSummaryReportWriterService) {
279            this.posterBudgetBalanceSummaryReportWriterService = posterBudgetBalanceSummaryReportWriterService;
280        }
281    
282        /**
283         * Sets the posterEncumbranceSummaryReportWriterService attribute value.
284         * @param posterEncumbranceSummaryReportWriterService The posterEncumbranceSummaryReportWriterService to set.
285         */
286        public void setPosterEncumbranceSummaryReportWriterService(FiscalYearAwareReportWriterService posterEncumbranceSummaryReportWriterService) {
287            this.posterEncumbranceSummaryReportWriterService = posterEncumbranceSummaryReportWriterService;
288        }
289    
290        /**
291         * Gets the reversalService attribute. 
292         * @return Returns the reversalService.
293         */
294        public ReversalService getReversalService() {
295            return reversalService;
296        }
297    
298        /**
299         * Sets the reversalService attribute value.
300         * @param reversalService The reversalService to set.
301         */
302        public void setReversalService(ReversalService reversalService) {
303            this.reversalService = reversalService;
304        }
305    
306        /**
307         * Sets the balanceService attribute value.
308         * @param balanceService The balanceService to set.
309         */
310        public void setBalanceService(BalanceService balanceService) {
311            this.balanceService = balanceService;
312        }
313    
314        /**
315         * Gets the batchFileDirectoryName attribute. 
316         * @return Returns the batchFileDirectoryName.
317         */
318        public String getBatchFileDirectoryName() {
319            return batchFileDirectoryName;
320        }
321    
322        /**
323         * Sets the batchFileDirectoryName attribute value.
324         * @param batchFileDirectoryName The batchFileDirectoryName to set.
325         */
326        public void setBatchFileDirectoryName(String batchFileDirectoryName) {
327            this.batchFileDirectoryName = batchFileDirectoryName;
328        }
329    }