/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.module.ld.batch.service.impl;
import static org.kuali.kfs.gl.GeneralLedgerConstants.GlSummaryReport.CURRENT_AND_LAST_YEAR;
import static org.kuali.kfs.gl.GeneralLedgerConstants.GlSummaryReport.CURRENT_YEAR_LOWER;
import static org.kuali.kfs.gl.GeneralLedgerConstants.GlSummaryReport.CURRENT_YEAR_UPPER;
import java.io.File;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.gl.GeneralLedgerConstants;
import org.kuali.kfs.gl.batch.PosterSummaryReportStep;
import org.kuali.kfs.gl.businessobject.GlSummary;
import org.kuali.kfs.gl.businessobject.OriginEntryInformation;
import org.kuali.kfs.gl.report.PosterOutputSummaryReport;
import org.kuali.kfs.module.ld.LaborConstants;
import org.kuali.kfs.module.ld.batch.service.LaborBalanceSummaryReportService;
import org.kuali.kfs.module.ld.businessobject.LaborBalanceSummary;
import org.kuali.kfs.module.ld.service.LaborLedgerBalanceService;
import org.kuali.kfs.module.ld.util.LaborOriginEntryFileIterator;
import org.kuali.kfs.sys.FileUtil;
import org.kuali.kfs.sys.batch.service.WrappingBatchService;
import org.kuali.kfs.sys.businessobject.SystemOptions;
import org.kuali.kfs.sys.service.FiscalYearAwareReportWriterService;
import org.kuali.kfs.sys.service.OptionsService;
import org.kuali.kfs.sys.service.ReportWriterService;
import org.kuali.rice.core.api.datetime.DateTimeService;
import org.kuali.rice.coreservice.framework.parameter.ParameterService;
/**
* Implements a set of methods that can generate labor balance summary reports
*/
public class LaborBalanceSummaryReportServiceImpl implements LaborBalanceSummaryReportService {
private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LaborBalanceSummaryReportServiceImpl.class);
private DateTimeService dateTimeService;
private OptionsService optionsService;
private ParameterService parameterService;
private LaborLedgerBalanceService laborLedgerBalanceService;
private ReportWriterService laborPosterOutputSummaryReportWriterService;
private FiscalYearAwareReportWriterService laborActualBalanceSummaryReportWriterService;
private FiscalYearAwareReportWriterService laborBudgetBalanceSummaryReportWriterService;
private FiscalYearAwareReportWriterService laborEncumbranceSummaryReportWriterService;
private String batchFileDirectoryName;
/**
* @see org.kuali.kfs.module.ld.batch.service.LaborBalanceSummaryReportService#generateBalanceSummaryReports()
*/
public void generateBalanceSummaryReports() {
LOG.debug("generateBalanceSummaryReports() started");
Date runDate = dateTimeService.getCurrentSqlDate();
this.generatePosterOutputSummaryReport(runDate);
this.generateBalanceSummaryReports(runDate);
}
/**
* @see org.kuali.kfs.module.ld.batch.service.LaborBalanceSummaryReportService#generateBalanceSummaryReports(java.sql.Date)
*/
public void generateBalanceSummaryReports(Date runDate) {
LOG.debug("generateBalanceSummaryReports(Date) started");
String yearEndPeriodLowerBound = parameterService.getParameterValueAsString(PosterSummaryReportStep.class, CURRENT_YEAR_LOWER);
String lastDayOfFiscalYear = parameterService.getParameterValueAsString(PosterSummaryReportStep.class, CURRENT_AND_LAST_YEAR);
String yearEndPeriodUpperBound = parameterService.getParameterValueAsString(PosterSummaryReportStep.class, CURRENT_YEAR_UPPER);
Integer currentYear = optionsService.getCurrentYearOptions().getUniversityFiscalYear();
this.generateBalanceSummaryReports(currentYear, runDate);
// if today is within the lower bound of the year end period, then generate reports for the next fiscal year
if (this.isInYearEndLowerBound(runDate, yearEndPeriodLowerBound, lastDayOfFiscalYear)) {
this.generateBalanceSummaryReports(currentYear + 1, runDate);
}
// if today is within the upper bound of the year end period, then generate reports for the last fiscal year
if (this.isInYearEndUpperBound(runDate, yearEndPeriodUpperBound, lastDayOfFiscalYear)) {
this.generateBalanceSummaryReports(currentYear - 1, runDate);
}
}
// generate a set of balance summary reports for actual, budget and encumbrance balances
protected void generateBalanceSummaryReports(Integer fiscalYear, Date runDate) {
SystemOptions options = optionsService.getOptions(fiscalYear);
if(options == null) {
LOG.fatal("The data for " + fiscalYear + "have NOT been setup.");
return;
}
List<String> actualsBalanceTypes = this.getActualBalanceTypes(fiscalYear);
this.writeSummaryReport(fiscalYear, actualsBalanceTypes, laborActualBalanceSummaryReportWriterService);
List<String> budgetBalanceTypes = this.getBudgetBalanceTypes(fiscalYear);
this.writeSummaryReport(fiscalYear, budgetBalanceTypes, laborBudgetBalanceSummaryReportWriterService);
List<String> encumbranceBalanceTypes = this.getEncumbranceBalanceTypes(fiscalYear);
this.writeSummaryReport(fiscalYear, encumbranceBalanceTypes, laborEncumbranceSummaryReportWriterService);
}
protected void writeSummaryReport(Integer fiscalYear, List<String> balanceTypes, FiscalYearAwareReportWriterService reportWriterService) {
List<LaborBalanceSummary> balanceSummary = laborLedgerBalanceService.findBalanceSummary(fiscalYear, balanceTypes);
List<GlSummary> summaryList = new ArrayList<GlSummary>(balanceSummary);
GlSummary totals = new LaborBalanceSummary();
for(GlSummary summaryLine : summaryList) {
totals.add(summaryLine);
}
totals.setFundGroup("Total");
try {
reportWriterService.setFiscalYear(fiscalYear);
((WrappingBatchService)reportWriterService).initialize();
reportWriterService.writeSubTitle("Balance Type of " + balanceTypes + " for Fiscal Year " + fiscalYear);
reportWriterService.writeNewLines(1);
reportWriterService.writeTableRowSeparationLine(totals);
reportWriterService.writeTable(summaryList, true, false);
reportWriterService.writeTableRowSeparationLine(totals);
reportWriterService.writeTableRow(totals);
}
finally {
((WrappingBatchService)reportWriterService).destroy();
}
}
/**
* Generates reports about the output of a poster run.
*
* @param runDate the date the poster was run.
*/
protected void generatePosterOutputSummaryReport(Date runDate) {
PosterOutputSummaryReport posterOutputSummaryReport = new PosterOutputSummaryReport();
// summarize all the entries for the main poster
File mainPosterFile = FileUtil.getNewestFile(new File(batchFileDirectoryName), new RegexFileFilter((LaborConstants.BatchFileSystem.POSTER_INPUT_FILE + "\\.[0-9_\\-]+\\" + GeneralLedgerConstants.BatchFileSystem.EXTENSION)));
if (mainPosterFile != null && mainPosterFile.exists()) {
LaborOriginEntryFileIterator mainPosterIterator = new LaborOriginEntryFileIterator(mainPosterFile);
while (mainPosterIterator.hasNext()) {
OriginEntryInformation originEntry = mainPosterIterator.next();
posterOutputSummaryReport.summarize(originEntry);
}
} else {
LOG.warn("Could not Main Poster Input file, "+ LaborConstants.BatchFileSystem.POSTER_INPUT_FILE + ", for tabulation in the Poster Output Summary Report");
}
posterOutputSummaryReport.writeReport(laborPosterOutputSummaryReportWriterService);
}
/**
* get the encumbrance balance type codes for the given fiscal year
*
* @param fiscalYear the given fiscal year
* @return the encumbrance balance type codes for the given fiscal year
*/
protected List<String> getEncumbranceBalanceTypes(Integer fiscalYear) {
SystemOptions options = optionsService.getOptions(fiscalYear);
List<String> balanceTypes = new ArrayList<String>();
balanceTypes.add(options.getExtrnlEncumFinBalanceTypCd());
balanceTypes.add(options.getIntrnlEncumFinBalanceTypCd());
balanceTypes.add(options.getPreencumbranceFinBalTypeCd());
balanceTypes.add(options.getCostShareEncumbranceBalanceTypeCd());
return balanceTypes;
}
/**
* get the actual balance type codes for the given fiscal year
*
* @param fiscalYear the given fiscal year
* @return the actual balance type codes for the given fiscal year
*/
protected List<String> getActualBalanceTypes(Integer fiscalYear) {
SystemOptions options = optionsService.getOptions(fiscalYear);
List<String> balanceTypes = new ArrayList<String>();
balanceTypes.add(options.getActualFinancialBalanceTypeCd());
return balanceTypes;
}
/**
* get the budget balance type codes for the given fiscal year
*
* @param fiscalYear the given fiscal year
* @return the budget balance type codes for the given fiscal year
*/
protected List<String> getBudgetBalanceTypes(Integer fiscalYear) {
SystemOptions options = optionsService.getOptions(fiscalYear);
List<String> balanceTypes = new ArrayList<String>();
balanceTypes.add(options.getBudgetCheckingBalanceTypeCd());
balanceTypes.add(options.getBaseBudgetFinancialBalanceTypeCd());
balanceTypes.add(options.getMonthlyBudgetFinancialBalanceTypeCd());
return balanceTypes;
}
/**
* determine if the given date is within the year end period
*
* @param runDate the given date
* @param yearEndPeriodLowerBound the lower bound date of year end period
* @param yearEndPeriodUpperBound the upper bound date of year end period
* @param lastDayOfFiscalYear the last day of the current fiscal year
* @return true if the given date is within the lower bound of year end period; otherwise, false
*/
protected boolean isInYearEndPeriod(Date runDate, String yearEndPeriodLowerBound, String yearEndPeriodUpperBound, String lastDayOfFiscalYear) {
return isInYearEndLowerBound(runDate, yearEndPeriodLowerBound, lastDayOfFiscalYear) || isInYearEndUpperBound(runDate, yearEndPeriodUpperBound, lastDayOfFiscalYear);
}
/**
* determine if the given date is within the lower bound of year end period
*
* @param runDate the given date
* @param yearEndPeriodLowerBound the lower bound date of year end period
* @param lastDayOfFiscalYear the last day of the current fiscal year
* @return true if the given date is within the lower bound of year end period; otherwise, false
*/
protected boolean isInYearEndLowerBound(Date runDate, String yearEndPeriodLowerBound, String lastDayOfFiscalYear) {
SimpleDateFormat sdf = new SimpleDateFormat("MMdd");
String today = sdf.format(runDate);
return today.compareTo(yearEndPeriodLowerBound) >= 0 && today.compareTo(lastDayOfFiscalYear) <= 0;
}
/**
* determine if the given date is within the upper bound of year end period
*
* @param runDate the given date
* @param yearEndPeriodUpperBound the upper bound date of year end period
* @param lastDayOfFiscalYear the last day of the current fiscal year
* @return true if the given date is within the upper bound of year end period; otherwise, false
*/
protected boolean isInYearEndUpperBound(Date runDate, String yearEndPeriodUpperBound, String lastDayOfFiscalYear) {
SimpleDateFormat sdf = new SimpleDateFormat("MMdd");
String today = sdf.format(runDate);
String month = StringUtils.mid(lastDayOfFiscalYear, 0, 2);
String date = StringUtils.mid(lastDayOfFiscalYear, 2, 2);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, Integer.parseInt(month) - 1);
calendar.set(Calendar.DATE, Integer.parseInt(date));
calendar.add(Calendar.DATE, 1);
String firstDayOfNewFiscalYear = sdf.format(calendar.getTime());
return today.compareTo(yearEndPeriodUpperBound) <= 0 && today.compareTo(firstDayOfNewFiscalYear) >= 0;
}
/**
* Sets the dateTimeService attribute value.
*
* @param dateTimeService The dateTimeService to set.
*/
public void setDateTimeService(DateTimeService dateTimeService) {
this.dateTimeService = dateTimeService;
}
/**
* Sets the optionsService attribute value.
*
* @param optionsService The optionsService to set.
*/
public void setOptionsService(OptionsService optionsService) {
this.optionsService = optionsService;
}
/**
* Sets the parameterService attribute value.
* @param parameterService The parameterService to set.
*/
public void setParameterService(ParameterService parameterService) {
this.parameterService = parameterService;
}
/**
* Sets the laborLedgerBalanceService attribute value.
* @param laborLedgerBalanceService The laborLedgerBalanceService to set.
*/
public void setLaborLedgerBalanceService(LaborLedgerBalanceService laborLedgerBalanceService) {
this.laborLedgerBalanceService = laborLedgerBalanceService;
}
/**
* Sets the laborActualBalanceSummaryReportWriterService attribute value.
* @param laborActualBalanceSummaryReportWriterService The laborActualBalanceSummaryReportWriterService to set.
*/
public void setLaborActualBalanceSummaryReportWriterService(FiscalYearAwareReportWriterService laborActualBalanceSummaryReportWriterService) {
this.laborActualBalanceSummaryReportWriterService = laborActualBalanceSummaryReportWriterService;
}
/**
* Sets the laborBudgetBalanceSummaryReportWriterService attribute value.
* @param laborBudgetBalanceSummaryReportWriterService The laborBudgetBalanceSummaryReportWriterService to set.
*/
public void setLaborBudgetBalanceSummaryReportWriterService(FiscalYearAwareReportWriterService laborBudgetBalanceSummaryReportWriterService) {
this.laborBudgetBalanceSummaryReportWriterService = laborBudgetBalanceSummaryReportWriterService;
}
/**
* Sets the laborEncumbranceSummaryReportWriterService attribute value.
* @param laborEncumbranceSummaryReportWriterService The laborEncumbranceSummaryReportWriterService to set.
*/
public void setLaborEncumbranceSummaryReportWriterService(FiscalYearAwareReportWriterService laborEncumbranceSummaryReportWriterService) {
this.laborEncumbranceSummaryReportWriterService = laborEncumbranceSummaryReportWriterService;
}
/**
* Sets the laborPosterOutputSummaryReportWriterService attribute value.
* @param laborPosterOutputSummaryReportWriterService The laborPosterOutputSummaryReportWriterService to set.
*/
public void setLaborPosterOutputSummaryReportWriterService(ReportWriterService laborPosterOutputSummaryReportWriterService) {
this.laborPosterOutputSummaryReportWriterService = laborPosterOutputSummaryReportWriterService;
}
/**
* Sets the batchFileDirectoryName attribute value.
* @param batchFileDirectoryName The batchFileDirectoryName to set.
*/
public void setBatchFileDirectoryName(String batchFileDirectoryName) {
this.batchFileDirectoryName = batchFileDirectoryName;
}
}