/*
* @(#)StatisticsAction.java
*
* Copyright 2009 Instituto Superior Tecnico
* Founding Authors: Luis Cruz, Nuno Ochoa, Paulo Abrantes
*
* https://fenix-ashes.ist.utl.pt/
*
* This file is part of the Expenditure Tracking Module.
*
* The Expenditure Tracking Module is free software: you can
* redistribute it and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation, either version
* 3 of the License, or (at your option) any later version.
*
* The Expenditure Tracking Module 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Expenditure Tracking Module. If not, see <http://www.gnu.org/licenses/>.
*
*/
package pt.ist.expenditureTrackingSystem.presentationTier.actions.statistics;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import module.finance.util.Money;
import module.workflow.domain.ActivityLog;
import module.workflow.domain.ProcessFile;
import module.workflow.domain.WorkflowLog;
import org.apache.commons.collections.comparators.ComparatorChain;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.fenixedu.bennu.core.domain.Bennu;
import org.fenixedu.bennu.struts.annotations.Mapping;
import org.fenixedu.commons.StringNormalizer;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.AcquisitionProcessStateType;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.AcquisitionRequest;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.CPVReference;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.Invoice;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.PaymentProcess;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.PaymentProcessYear;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.RefundProcessStateType;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.RequestItem;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.afterthefact.AfterTheFactAcquisitionType;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.refund.RefundProcess;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.simplified.SimplifiedProcedureProcess;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.simplified.SimplifiedProcedureProcess.ProcessClassification;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.simplified.activities.SendPurchaseOrderToSupplier;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.simplified.activities.SkipPurchaseOrderDocument;
import pt.ist.expenditureTrackingSystem.domain.organization.CostCenter;
import pt.ist.expenditureTrackingSystem.domain.organization.Person;
import pt.ist.expenditureTrackingSystem.domain.organization.Project;
import pt.ist.expenditureTrackingSystem.domain.organization.SubProject;
import pt.ist.expenditureTrackingSystem.domain.organization.Unit;
import pt.ist.expenditureTrackingSystem.domain.processes.GenericProcess;
import pt.ist.expenditureTrackingSystem.domain.statistics.AfterTheFactProcessTotalValueStatistics;
import pt.ist.expenditureTrackingSystem.domain.statistics.ChartData;
import pt.ist.expenditureTrackingSystem.domain.statistics.RefundProcessActivityLogStatistics;
import pt.ist.expenditureTrackingSystem.domain.statistics.RefundProcessStateCountChartData;
import pt.ist.expenditureTrackingSystem.domain.statistics.RefundProcessStateTimeAverageChartData;
import pt.ist.expenditureTrackingSystem.domain.statistics.RefundProcessStateTimeChartData;
import pt.ist.expenditureTrackingSystem.domain.statistics.RefundProcessStatistics;
import pt.ist.expenditureTrackingSystem.domain.statistics.RefundProcessTotalValueStatistics;
import pt.ist.expenditureTrackingSystem.domain.statistics.SimplifiedProcedureProcessActivityTimeChartData;
import pt.ist.expenditureTrackingSystem.domain.statistics.SimplifiedProcedureProcessStateCountChartData;
import pt.ist.expenditureTrackingSystem.domain.statistics.SimplifiedProcedureProcessStateTimeAverageChartData;
import pt.ist.expenditureTrackingSystem.domain.statistics.SimplifiedProcedureProcessStateTimeChartData;
import pt.ist.expenditureTrackingSystem.domain.statistics.SimplifiedProcessStatistics;
import pt.ist.expenditureTrackingSystem.domain.statistics.SimplifiedProcessTotalValueStatistics;
import pt.ist.expenditureTrackingSystem.presentationTier.actions.BaseAction;
import pt.ist.expenditureTrackingSystem.util.Calculation.Operation;
import pt.ist.fenixWebFramework.rendererExtensions.util.IPresentableEnum;
import pt.utl.ist.fenix.tools.util.excel.Spreadsheet;
import pt.utl.ist.fenix.tools.util.excel.Spreadsheet.Row;
@Mapping(path = "/statistics")
/**
*
* @author Shezad Anavarali
* @author Paulo Abrantes
* @author Luis Cruz
*
*/
public class StatisticsAction extends BaseAction {
private final static Logger logger = LoggerFactory.getLogger(StatisticsAction.class);
public ActionForward showStatistics(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request,
final HttpServletResponse response) {
return forward("/statistics/showStatistics.jsp");
}
public ActionForward showSimplifiedProcessStatistics(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
YearBean yearBean = getRenderedObject();
if (yearBean == null) {
yearBean = new YearBean();
}
request.setAttribute("yearBean", yearBean);
final SimplifiedProcessStatistics simplifiedProcessStatistics = SimplifiedProcessStatistics.create(yearBean.getYear());
request.setAttribute("simplifiedProcessStatistics", simplifiedProcessStatistics);
return forward("/statistics/showStatisticsSimplifiedProcess.jsp");
}
protected ActionForward generateChart(final HttpServletResponse response, final ChartData chartData, final long t1) {
OutputStream outputStream = null;
try {
final byte[] image = ChartGenerator.createBarChartImage(chartData);
long t2 = System.currentTimeMillis();
outputStream = response.getOutputStream();
response.setContentType("image/jpeg");
outputStream.write(image);
outputStream.flush();
} catch (final FileNotFoundException e) {
e.printStackTrace();
throw new Error(e);
} catch (final RuntimeException e) {
e.printStackTrace();
throw new Error(e);
} catch (final IOException e) {
e.printStackTrace();
throw new Error(e);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (final IOException e) {
e.printStackTrace();
throw new Error(e);
}
try {
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
throw new Error(e);
}
}
}
return null;
}
public ActionForward simplifiedProcessStatisticsStateChart(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
final String year = request.getParameter("year");
long t1 = System.currentTimeMillis();
final PaymentProcessYear paymentProcessYear = PaymentProcessYear.getPaymentProcessYearByYear(Integer.valueOf(year));
final SimplifiedProcedureProcessStateCountChartData chartData =
new SimplifiedProcedureProcessStateCountChartData(paymentProcessYear);
chartData.calculateData();
return generateChart(response, chartData, t1);
}
public ActionForward simplifiedProcessStatisticsStateTimeChart(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
final String year = request.getParameter("year");
long t1 = System.currentTimeMillis();
final PaymentProcessYear paymentProcessYear = PaymentProcessYear.getPaymentProcessYearByYear(Integer.valueOf(year));
final SimplifiedProcedureProcessStateTimeChartData chartData =
new SimplifiedProcedureProcessStateTimeChartData(paymentProcessYear);
chartData.calculateData();
return generateChart(response, chartData, t1);
}
public ActionForward simplifiedProcessStatisticsStateTimeAverageChart(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
final String year = request.getParameter("year");
long t1 = System.currentTimeMillis();
final PaymentProcessYear paymentProcessYear = PaymentProcessYear.getPaymentProcessYearByYear(Integer.valueOf(year));
final SimplifiedProcedureProcessStateTimeAverageChartData chartData =
new SimplifiedProcedureProcessStateTimeAverageChartData(paymentProcessYear);
chartData.calculateData();
return generateChart(response, chartData, t1);
}
public ActionForward simplifiedProcessStatisticsActivityTimeChart(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
final String year = request.getParameter("year");
long t1 = System.currentTimeMillis();
final PaymentProcessYear paymentProcessYear = PaymentProcessYear.getPaymentProcessYearByYear(Integer.valueOf(year));
final SimplifiedProcedureProcessActivityTimeChartData chartData =
new SimplifiedProcedureProcessActivityTimeChartData(paymentProcessYear);
chartData.calculateData();
return generateChart(response, chartData, t1);
}
public ActionForward simplifiedProcessStatistics(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
final Integer year = Integer.valueOf(request.getParameter("year"));
return streamSpreadsheet(response, "simplifiedProcedure", simplifiedProcessStatistics(year), year);
}
private Spreadsheet simplifiedProcessStatistics(final Integer year) {
final PaymentProcessYear paymentProcessYear = PaymentProcessYear.getPaymentProcessYearByYear(Integer.valueOf(year));
final SimplifiedProcedureProcessStateCountChartData countData =
new SimplifiedProcedureProcessStateCountChartData(paymentProcessYear);
countData.calculateData();
final SimplifiedProcedureProcessStateTimeChartData medianData =
new SimplifiedProcedureProcessStateTimeChartData(paymentProcessYear);
medianData.calculateData();
final SimplifiedProcedureProcessStateTimeAverageChartData averageData =
new SimplifiedProcedureProcessStateTimeAverageChartData(paymentProcessYear);
averageData.calculateData();
final SortedMap<Object, BigDecimal> sumMap = (SortedMap) countData.getResults(Operation.SUM);
final SortedMap<Object, BigDecimal> averageMap = (SortedMap) averageData.getResults(Operation.AVERAGE);
final SortedMap<Object, BigDecimal> medianMap = (SortedMap) medianData.getResults(Operation.MEDIAN);
final SortedMap<Object, BigDecimal> minsMap = (SortedMap) medianData.getMinResults();
final SortedMap<Object, BigDecimal> maxsMap = (SortedMap) medianData.getMaxResults();
return generateSpreadSheet(sumMap, medianMap, averageMap, minsMap, maxsMap);
}
public ActionForward refundProcessStatistics(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
final Integer year = Integer.valueOf(request.getParameter("year"));
return streamSpreadsheet(response, "refund", refundProcessStatistics(year), year);
}
private Spreadsheet refundProcessStatistics(final Integer year) {
final PaymentProcessYear paymentProcessYear = PaymentProcessYear.getPaymentProcessYearByYear(Integer.valueOf(year));
final RefundProcessStateCountChartData countData = new RefundProcessStateCountChartData(paymentProcessYear);
countData.calculateData();
final RefundProcessStateTimeChartData medianData = new RefundProcessStateTimeChartData(paymentProcessYear);
medianData.calculateData();
final RefundProcessStateTimeAverageChartData averageData = new RefundProcessStateTimeAverageChartData(paymentProcessYear);
averageData.calculateData();
final SortedMap<Object, BigDecimal> sumMap = (SortedMap) countData.getResults(Operation.SUM);
final SortedMap<Object, BigDecimal> averageMap = (SortedMap) averageData.getResults(Operation.AVERAGE);
final SortedMap<Object, BigDecimal> medianMap = (SortedMap) medianData.getResults(Operation.MEDIAN);
final SortedMap<Object, BigDecimal> minsMap = (SortedMap) medianData.getMinResults();
final SortedMap<Object, BigDecimal> maxsMap = (SortedMap) medianData.getMaxResults();
return generateSpreadSheet(sumMap, medianMap, averageMap, minsMap, maxsMap);
}
private Spreadsheet generateSpreadSheet(final SortedMap<Object, BigDecimal> sumMap,
final SortedMap<Object, BigDecimal> medianMap, final SortedMap<Object, BigDecimal> averageMap,
final SortedMap<Object, BigDecimal> minsMap, final SortedMap<Object, BigDecimal> maxsMap) {
final Spreadsheet spreadsheet = new Spreadsheet("Estatísticas");
spreadsheet.setHeader("Estado");
spreadsheet.setHeader("Soma");
spreadsheet.setHeader("Mediana Tempo (em dias)");
spreadsheet.setHeader("Média Tempo (em dias)");
spreadsheet.setHeader("Tempo Mínimo (em dias)");
spreadsheet.setHeader("Tempo Máximo (em dias)");
final SortedSet<Object> types = new TreeSet<Object>();
types.addAll(sumMap.keySet());
types.addAll(medianMap.keySet());
types.addAll(averageMap.keySet());
BigDecimal DAYS_CONST = new BigDecimal(1000 * 3600 * 24);
for (final Object type : types) {
final BigDecimal sum = sumMap.get(type);
final BigDecimal median = medianMap.get(type);
final BigDecimal average = averageMap.get(type);
final BigDecimal min = minsMap.get(type);
final BigDecimal max = maxsMap.get(type);
final Row row = spreadsheet.addRow();
row.setCell(((IPresentableEnum) type).getLocalizedName());
row.setCell(sum == null ? "0" : sum.toString());
row.setCell(median == null ? "" : median.divide(DAYS_CONST, 2, BigDecimal.ROUND_HALF_UP).toString());
row.setCell(average == null ? "" : average.divide(DAYS_CONST, 2, BigDecimal.ROUND_HALF_UP).toString());
row.setCell(min == null ? "" : min.divide(DAYS_CONST, 2, BigDecimal.ROUND_HALF_UP).toString());
row.setCell(max == null ? "" : max.divide(DAYS_CONST, 2, BigDecimal.ROUND_HALF_UP).toString());
}
return spreadsheet;
}
public ActionForward showRefundProcessStatistics(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
YearBean yearBean = getRenderedObject();
if (yearBean == null) {
yearBean = new YearBean();
}
request.setAttribute("yearBean", yearBean);
final RefundProcessStatistics refundProcessStatistics = RefundProcessStatistics.create(yearBean.getYear());
request.setAttribute("refundProcessStatistics", refundProcessStatistics);
return forward("/statistics/showStatisticsRefundProcess.jsp");
}
public ActionForward refundProcessStatisticsChart(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
final String year = request.getParameter("year");
long t1 = System.currentTimeMillis();
final PaymentProcessYear paymentProcessYear = PaymentProcessYear.getPaymentProcessYearByYear(Integer.valueOf(year));
final RefundProcessStateCountChartData chartData = new RefundProcessStateCountChartData(paymentProcessYear);
chartData.calculateData();
return generateChart(response, chartData, t1);
}
public ActionForward refundProcessStatisticsStateTimeChart(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
final String year = request.getParameter("year");
long t1 = System.currentTimeMillis();
final PaymentProcessYear paymentProcessYear = PaymentProcessYear.getPaymentProcessYearByYear(Integer.valueOf(year));
final RefundProcessStateTimeChartData chartData = new RefundProcessStateTimeChartData(paymentProcessYear);
chartData.calculateData();
return generateChart(response, chartData, t1);
}
public ActionForward refundProcessStatisticsStateTimeAverageChart(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
final String year = request.getParameter("year");
long t1 = System.currentTimeMillis();
final PaymentProcessYear paymentProcessYear = PaymentProcessYear.getPaymentProcessYearByYear(Integer.valueOf(year));
final RefundProcessStateTimeAverageChartData chartData = new RefundProcessStateTimeAverageChartData(paymentProcessYear);
chartData.calculateData();
return generateChart(response, chartData, t1);
}
public ActionForward refundProcessStatisticsActivityTimeChartForProcess(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
final RefundProcess refundProcess = getDomainObject(request, "processId");
final RefundProcessActivityLogStatistics refundProcessActivityLogStatistics =
RefundProcessActivityLogStatistics.create(refundProcess);
OutputStream outputStream = null;
try {
final byte[] image = ChartGenerator.refundProcessStatisticsActivityTimeImage(refundProcessActivityLogStatistics);
outputStream = response.getOutputStream();
response.setContentType("image/jpeg");
outputStream.write(image);
outputStream.flush();
} catch (final FileNotFoundException e) {
e.printStackTrace();
throw new Error(e);
} catch (final RuntimeException e) {
e.printStackTrace();
throw new Error(e);
} catch (final IOException e) {
e.printStackTrace();
throw new Error(e);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (final IOException e) {
e.printStackTrace();
throw new Error(e);
}
try {
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
throw new Error(e);
}
}
}
return null;
}
public ActionForward showStatisticsReports(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
YearBean yearBean = getRenderedObject();
if (yearBean == null) {
yearBean = new YearBean();
}
request.setAttribute("yearBean", yearBean);
return forward("/statistics/showStatisticsReports.jsp");
}
public ActionForward downloadStatisticsByCPV(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
final Integer year = Integer.valueOf((String) getAttribute(request, "year"));
return streamSpreadsheet(response, "cvp", createStatisticsByCPV(year), year);
}
private Spreadsheet createStatisticsByCPV(final Integer year) {
final Spreadsheet spreadsheet = new Spreadsheet("CPV " + year);
spreadsheet.setHeader("CPV");
spreadsheet.setHeader("CPV desc.");
spreadsheet.setHeader("Montante");
for (final CPVReference reference : Bennu.getInstance().getCPVReferencesSet()) {
final Money money = reference.getTotalAmountAllocated(year);
if (!money.isZero()) {
final Row row = spreadsheet.addRow();
row.setCell(reference.getCode());
row.setCell(reference.getDescription());
row.setCell(money.toFormatStringWithoutCurrency());
}
}
return spreadsheet;
}
public ActionForward downloadTotalValuesStatistics(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
final Integer year = Integer.valueOf((String) getAttribute(request, "year"));
return streamSpreadsheet(response, "values", createTotalValuesStatistics(year), year);
}
private Spreadsheet createTotalValuesStatistics(final Integer year) {
final Spreadsheet spreadsheet = new Spreadsheet("Valores por Tipo - " + year);
spreadsheet.setHeader("Tipo");
spreadsheet.setHeader("Montante");
final Map<AcquisitionProcessStateType, Money> values =
SimplifiedProcessTotalValueStatistics.create(year).getTotalValuesOfProcessesByAcquisitionProcessStateType();
for (final Entry<AcquisitionProcessStateType, Money> valueEntry : values.entrySet()) {
final Row row = spreadsheet.addRow();
row.setCell(valueEntry.getKey().getLocalizedName());
row.setCell(valueEntry.getValue().toFormatStringWithoutCurrency());
}
return spreadsheet;
}
public ActionForward downloadRefundTotalValuesStatistics(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
final Integer year = Integer.valueOf((String) getAttribute(request, "year"));
return streamSpreadsheet(response, "refundValues", createRefundTotalValuesStatistics(year), year);
}
private Spreadsheet createRefundTotalValuesStatistics(final Integer year) {
final Spreadsheet spreadsheet = new Spreadsheet("Valores por Tipo - " + year);
spreadsheet.setHeader("Tipo");
spreadsheet.setHeader("Montante");
final Map<RefundProcessStateType, Money> values =
RefundProcessTotalValueStatistics.create(year).getTotalValuesOfProcessesByRefundProcessStateType();
for (final Entry<RefundProcessStateType, Money> valueEntry : values.entrySet()) {
final Row row = spreadsheet.addRow();
row.setCell(valueEntry.getKey().getLocalizedName());
row.setCell(valueEntry.getValue().toFormatStringWithoutCurrency());
}
return spreadsheet;
}
private ActionForward streamSpreadsheet(final HttpServletResponse response, final String fileName,
final Spreadsheet resultSheet, final Integer year) throws IOException {
response.setContentType("application/xls ");
response.setHeader("Content-disposition", "attachment; filename=" + fileName + year + ".xls");
ServletOutputStream outputStream = response.getOutputStream();
resultSheet.exportToXLSSheet(outputStream);
outputStream.flush();
outputStream.close();
return null;
}
private ActionForward streamCSV(final HttpServletResponse response, final String fileName, final String csvContent)
throws IOException {
response.setContentType("application/csv");
response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".csv");
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(csvContent.getBytes());
outputStream.flush();
outputStream.close();
return null;
}
public ActionForward downloadAfterTheFactTotalValuesStatistics(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
final Integer year = Integer.valueOf((String) getAttribute(request, "year"));
return streamSpreadsheet(response, "afterTheFact", createAfterTheFactTotalValuesStatistics(year), year);
}
private Spreadsheet createAfterTheFactTotalValuesStatistics(final Integer year) {
final Spreadsheet spreadsheet = new Spreadsheet("Valores por Tipo - " + year);
spreadsheet.setHeader("Tipo");
spreadsheet.setHeader("Montante");
final Map<AfterTheFactAcquisitionType, Money> values =
AfterTheFactProcessTotalValueStatistics.create(year).getTotalValuesOfProcessesByAquisitionProcessStateType();
for (final Entry<AfterTheFactAcquisitionType, Money> valueEntry : values.entrySet()) {
final Row row = spreadsheet.addRow();
row.setCell(valueEntry.getKey().getLocalizedName());
row.setCell(valueEntry.getValue().toFormatStringWithoutCurrency());
}
return spreadsheet;
}
private static final ComparatorChain DEFAULT_COMPARATOR = new ComparatorChain();
static {
DEFAULT_COMPARATOR.addComparator(new Comparator<PaymentProcess>() {
@Override
public int compare(PaymentProcess process1, PaymentProcess process2) {
return process1.getPaymentProcessYear().getYear().compareTo(process2.getPaymentProcessYear().getYear());
}
});
DEFAULT_COMPARATOR.addComparator(new Comparator<PaymentProcess>() {
@Override
public int compare(PaymentProcess process1, PaymentProcess process2) {
return process1.getAcquisitionProcessNumber().compareTo(process2.getAcquisitionProcessNumber());
}
});
}
private List<SimplifiedProcedureProcess> collectInterestingProcessesForCSVStats(HttpServletRequest request) {
List<SimplifiedProcedureProcess> processes = new ArrayList<SimplifiedProcedureProcess>();
final Integer year = Integer.valueOf((String) getAttribute(request, "year"));
PaymentProcessYear paymentYear = PaymentProcessYear.getPaymentProcessYearByYear(year);
for (SimplifiedProcedureProcess process : GenericProcess.getAllProcesses(SimplifiedProcedureProcess.class, paymentYear)) {
ProcessClassification classification = process.getProcessClassification();
if (classification == ProcessClassification.CCP || classification == ProcessClassification.CT10000) {
processes.add(process);
}
}
Collections.sort(processes, DEFAULT_COMPARATOR);
return processes;
}
public ActionForward generateProcessesStatsCSV(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
String year = (String) getAttribute(request, "year");
return streamCSV(response, "processos-" + year, generateProcessesFile(collectInterestingProcessesForCSVStats(request)));
}
public ActionForward generateLogStatsCSV(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
String year = (String) getAttribute(request, "year");
return streamCSV(response, "actividades-" + year,
generateProcessActivities(collectInterestingProcessesForCSVStats(request)));
}
private String generateProcessesFile(List<SimplifiedProcedureProcess> processes) {
return processes.stream().flatMap(p -> p.getPayingUnitStream())
.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString();
}
private String generateProcessActivities(List<SimplifiedProcedureProcess> processes) {
StringBuilder buffer = new StringBuilder();
for (SimplifiedProcedureProcess process : processes) {
Set<WorkflowLog> logs = new TreeSet<WorkflowLog>(WorkflowLog.COMPARATOR_BY_WHEN);
logs.addAll(process.getExecutionLogs());
for (WorkflowLog log : logs) {
String description = null;
try {
description = log.getDescription();
} catch (NullPointerException e) {
logger.warn("No description for: " + ((ActivityLog) log).getOperation());
}
if (description != null) {
Person expenditurePerson = log.getActivityExecutor().getExpenditurePerson();
buffer.append(process.getProcessNumber() + "\t" + process.getProcessClassification() + "\t"
+ log.getWhenOperationWasRan().toString("dd-MM-yyyy HH:mm") + "\t"
+ expenditurePerson.getUser().getDisplayName() + "\t" + expenditurePerson.getUsername() + "\t"
+ StringNormalizer.normalize(description.replaceAll("<span.*", "")) + "\n");
}
}
}
return buffer.toString();
}
public ActionForward downloadStatisticsForConfirmedProcesses(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
final Integer year = Integer.valueOf((String) getAttribute(request, "year"));
return streamSpreadsheet(response, "confirmedProcesses", createStatisticsForConfirmedProcesses(year), year);
}
private Spreadsheet createStatisticsForConfirmedProcesses(final Integer year) {
final Spreadsheet spreadsheet = new Spreadsheet("ConfirmedProcesses " + year);
spreadsheet.setHeader("Processo");
spreadsheet.setHeader("Estado");
spreadsheet.setHeader("Unidades");
spreadsheet.setHeader("CPV's");
spreadsheet.setHeader("Valor");
spreadsheet.setHeader("Valor Final");
final PaymentProcessYear paymentProcessYear = PaymentProcessYear.getPaymentProcessYearByYear(year);
for (final PaymentProcess paymentProcess : paymentProcessYear.getPaymentProcessSet()) {
if (paymentProcess instanceof SimplifiedProcedureProcess) {
final SimplifiedProcedureProcess simplifiedProcedureProcess = (SimplifiedProcedureProcess) paymentProcess;
final AcquisitionRequest acquisitionRequest = simplifiedProcedureProcess.getRequest();
final Row row = spreadsheet.addRow();
row.setCell(simplifiedProcedureProcess.getProcessNumber());
final AcquisitionProcessStateType acquisitionProcessStateType =
simplifiedProcedureProcess.getAcquisitionProcessStateType();
row.setCell(acquisitionProcessStateType.getLocalizedName());
final StringBuilder units = new StringBuilder();
for (final Unit unit : simplifiedProcedureProcess.getFinancingUnits()) {
final String unitCode = getUnitCode(unit);
if (units.length() > 1) {
units.append(", ");
}
units.append(unitCode);
}
row.setCell(units.length() == 0 ? " " : units.toString());
final Set<CPVReference> cpvReferences = new TreeSet<CPVReference>(CPVReference.COMPARATOR_BY_DESCRIPTION);
for (final RequestItem requestItem : acquisitionRequest.getRequestItemsSet()) {
cpvReferences.add(requestItem.getCPVReference());
}
final StringBuilder cpvs = new StringBuilder();
for (final CPVReference cpvReference : cpvReferences) {
if (cpvs.length() > 1) {
cpvs.append(", ");
}
cpvs.append(cpvReference.getCode());
}
row.setCell(cpvs.length() == 0 ? " " : cpvs.toString());
row.setCell(acquisitionRequest.getTotalValue().toFormatStringWithoutCurrency());
final Money realTotalValue = acquisitionRequest.getRealTotalValue();
row.setCell(realTotalValue == null ? " " : realTotalValue.toFormatStringWithoutCurrency());
}
}
return spreadsheet;
}
private String getUnitCode(final Unit unit) {
if (unit instanceof CostCenter) {
final CostCenter costCenter = (CostCenter) unit;
return "CC. " + costCenter.getCostCenter();
}
if (unit instanceof Project) {
final Project project = (Project) unit;
return "P. " + project.getProjectCode();
}
if (unit instanceof SubProject) {
return getUnitCode(unit.getParentUnit());
}
throw new Error("Unreachable Code.");
}
public ActionForward downloadInformationForExpenseReports(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
final Integer year = Integer.valueOf((String) getAttribute(request, "year"));
return streamSpreadsheet(response, "expenseReport", createInformationForExpenseReports(year), year);
}
private Spreadsheet createInformationForExpenseReports(final Integer year) {
final Spreadsheet spreadsheet = new Spreadsheet("ExpenseReport " + year);
spreadsheet.setHeader("Ano");
spreadsheet.setHeader("Processo");
spreadsheet.setHeader("Classificação");
spreadsheet.setHeader("Caso de excepção");
spreadsheet.setHeader("Estado");
spreadsheet.setHeader("CPV");
spreadsheet.setHeader("Valor sem IVA");
spreadsheet.setHeader("Valor com IVA");
spreadsheet.setHeader("Data envio nota de encomenda");
spreadsheet.setHeader("Data salto envio nota de encomenda");
spreadsheet.setHeader("Data factura");
final PaymentProcessYear paymentProcessYear = PaymentProcessYear.getPaymentProcessYearByYear(year);
for (final PaymentProcess paymentProcess : paymentProcessYear.getPaymentProcessSet()) {
if (paymentProcess instanceof SimplifiedProcedureProcess) {
final SimplifiedProcedureProcess simplifiedProcedureProcess = (SimplifiedProcedureProcess) paymentProcess;
final AcquisitionRequest acquisitionRequest = simplifiedProcedureProcess.getRequest();
final Row row = spreadsheet.addRow();
row.setCell(simplifiedProcedureProcess.getYear());
row.setCell(simplifiedProcedureProcess.getProcessNumber());
row.setCell(simplifiedProcedureProcess.getProcessClassification().getLocalizedName());
final boolean isException = simplifiedProcedureProcess.getSkipSupplierFundAllocation().booleanValue();
row.setCell(isException ? "Sim" : "Não");
final AcquisitionProcessStateType acquisitionProcessStateType =
simplifiedProcedureProcess.getAcquisitionProcessStateType();
row.setCell(acquisitionProcessStateType.getLocalizedName());
final Set<CPVReference> cpvReferences = new TreeSet<CPVReference>(CPVReference.COMPARATOR_BY_DESCRIPTION);
for (final RequestItem requestItem : acquisitionRequest.getRequestItemsSet()) {
cpvReferences.add(requestItem.getCPVReference());
}
final StringBuilder cpvs = new StringBuilder();
for (final CPVReference cpvReference : cpvReferences) {
if (cpvs.length() > 1) {
cpvs.append(", ");
}
cpvs.append(cpvReference.getCode());
}
row.setCell(cpvs.length() == 0 ? " " : cpvs.toString());
final Money currentValue = acquisitionRequest.getCurrentValue();
row.setCell(currentValue == null ? " " : currentValue.toFormatStringWithoutCurrency());
final Money currentTotalValue = acquisitionRequest.getCurrentTotalItemValueWithAdditionalCostsAndVat();
row.setCell(currentTotalValue == null ? " " : currentTotalValue.toFormatStringWithoutCurrency());
final DateTime sendDate = findSendDate(simplifiedProcedureProcess, SendPurchaseOrderToSupplier.class);
row.setCell(sendDate == null ? " " : sendDate.toString("yyyy-MM-dd"));
final DateTime skipDate = findSendDate(simplifiedProcedureProcess, SkipPurchaseOrderDocument.class);
row.setCell(skipDate == null ? " " : skipDate.toString("yyyy-MM-dd"));
final StringBuilder invoiceDateStringBuilder = new StringBuilder();
for (final LocalDate localDate : getInvoiceDates(simplifiedProcedureProcess)) {
if (invoiceDateStringBuilder.length() > 0) {
invoiceDateStringBuilder.append(", ");
}
invoiceDateStringBuilder.append(localDate.toString("yyyy-MM-dd"));
}
row.setCell(invoiceDateStringBuilder.toString());
}
}
return spreadsheet;
}
private DateTime findSendDate(final SimplifiedProcedureProcess process, final Class clazz) {
final List<WorkflowLog> logs = new ArrayList<WorkflowLog>(process.getExecutionLogsSet());
Collections.sort(logs, WorkflowLog.COMPARATOR_BY_WHEN_REVERSED);
for (final WorkflowLog workflowLog : logs) {
if (workflowLog instanceof ActivityLog) {
final ActivityLog operationLog = (ActivityLog) workflowLog;
if (clazz.getSimpleName().equals(operationLog.getOperation())) {
return operationLog.getWhenOperationWasRan();
}
}
}
return null;
}
private SortedSet<LocalDate> getInvoiceDates(final SimplifiedProcedureProcess process) {
final SortedSet<LocalDate> invoiceDates = new TreeSet<LocalDate>();
for (final ProcessFile file : process.getFilesSet()) {
if (file instanceof Invoice) {
final Invoice invoice = (Invoice) file;
final LocalDate invoiceDate = invoice.getInvoiceDate();
invoiceDates.add(invoiceDate);
}
}
return invoiceDates;
}
}