Preliminar business logic implementation for time KPI "Lead/Lag in task completion".

FEA: ItEr75S27PerProjectDashboard
This commit is contained in:
Nacho Barrientos 2011-11-22 18:01:05 +01:00 committed by Manuel Rego Casasnovas
parent 4ad151a17a
commit f3134887c0
3 changed files with 108 additions and 4 deletions

View file

@ -69,6 +69,8 @@ import org.libreplan.business.templates.entities.OrderElementTemplate;
import org.libreplan.business.trees.ITreeNode;
import org.libreplan.business.util.deepcopy.DeepCopy;
import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.business.workreports.daos.IWorkReportLineDAO;
import org.libreplan.business.workreports.entities.WorkReportLine;
public abstract class OrderElement extends IntegrationEntity implements
ICriterionRequirable, ITreeNode<OrderElement> {
@ -1459,4 +1461,9 @@ public abstract class OrderElement extends IntegrationEntity implements
return super.toString() + " :: " + getName();
}
public List<WorkReportLine> getWorkReportLines(boolean sortedByDate) {
IWorkReportLineDAO workReportLineDAO = Registry.getWorkReportLineDAO();
return workReportLineDAO.findByOrderElementAndChildren(this, sortedByDate);
}
}

View file

@ -0,0 +1,70 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2011 Igalia, S.L.
*
* 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.libreplan.business.planner.entities.visitors;
/**
* This visitor calculates lastWorkReportDate/EndDate deviation
* for all finished tasks with work report lines attached.
* @author Nacho Barrientos <nacho@igalia.com>
*/
import java.util.ArrayList;
import java.util.List;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.libreplan.business.planner.entities.Task;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.planner.entities.TaskGroup;
import org.libreplan.business.util.TaskElementVisitor;
import org.libreplan.business.workreports.entities.WorkReportLine;
public class CalculateFinishedTasksLagInCompletionVisitor extends TaskElementVisitor {
private List<Double> deviations;
public CalculateFinishedTasksLagInCompletionVisitor() {
this.deviations = new ArrayList<Double>();
}
public List<Double> getDeviations() {
return this.deviations;
}
public void visit(Task task) {
if (task.isFinished()) {
List<WorkReportLine> workReportLines = task.
getOrderElement().getWorkReportLines(true);
if (workReportLines.size() > 0) {
LocalDate lastRLDate = LocalDate.fromDateFields(
workReportLines.get(workReportLines.size()-1).getDate());
LocalDate endDate = task.getEndAsLocalDate();
deviations.add((double)Days.
daysBetween(endDate, lastRLDate).getDays());
}
}
}
public void visit(TaskGroup taskGroup) {
for (TaskElement each: taskGroup.getChildren()) {
each.acceptVisitor(this);
}
}
}

View file

@ -22,6 +22,7 @@ package org.libreplan.web.dashboard;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
@ -36,6 +37,7 @@ import org.libreplan.business.planner.entities.TaskStatusEnum;
import org.libreplan.business.planner.entities.visitors.AccumulateTasksDeadlineStatusVisitor;
import org.libreplan.business.planner.entities.visitors.AccumulateTasksStatusVisitor;
import org.libreplan.business.planner.entities.visitors.CalculateFinishedTasksEstimationDeviationVisitor;
import org.libreplan.business.planner.entities.visitors.CalculateFinishedTasksLagInCompletionVisitor;
import org.libreplan.business.planner.entities.visitors.ResetTasksStatusVisitor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
@ -52,6 +54,7 @@ public class DashboardModel {
public final static int EA_STRETCHES_PERCENTAGE_STEP = 10;
public final static int EA_STRETCHES_MIN_VALUE = -100;
public final static int EA_STRETCHES_MAX_VALUE = 150;
public final static int LTC_NUMBER_OF_INTERVALS = 10;
private Order currentOrder;
private Integer taskCount = null;
@ -60,6 +63,7 @@ public class DashboardModel {
private Map<TaskDeadlineViolationStatusEnum, BigDecimal> taskDeadlineViolationStatusStats;
private List<Double> taskEstimationAccuracyHistogram;
private BigDecimal marginWithDeadLine;
private List<Double> lagInTaskCompletionHistogram;
public DashboardModel() {
taskStatusStats = new EnumMap<TaskStatusEnum, BigDecimal>(
@ -75,6 +79,7 @@ public class DashboardModel {
this.calculateTaskViolationStatusStatistics();
this.calculateMarginWithDeadLine();
this.calculateFinishedTasksEstimationAccuracyHistogram();
this.calculateLagInTaskCompletionHistogram();
}
/* Progress KPI: "Number of tasks by status" */
@ -208,10 +213,32 @@ public class DashboardModel {
deviations);
}
private List<Double> createHistogram(int lowBound, int highBound,
int intervalStep, List<Double> values) {
int variableRange = highBound - lowBound;
int numberOfClasses = variableRange/intervalStep;
/* Time KPI: Lead/Lag in task completion */
public List<Double> getLagInTaskCompletionHistogram() {
return this.lagInTaskCompletionHistogram;
}
private void calculateLagInTaskCompletionHistogram() {
CalculateFinishedTasksLagInCompletionVisitor visitor =
new CalculateFinishedTasksLagInCompletionVisitor();
TaskElement rootTask = getRootTask();
rootTask.acceptVisitor(visitor);
List<Double> deviations = visitor.getDeviations();
Double minDeviation = Collections.min(deviations);
Double maxDeviation = Collections.max(deviations);
this.lagInTaskCompletionHistogram = createHistogram(
Collections.min(deviations),
Collections.max(deviations),
(maxDeviation - minDeviation)/LTC_NUMBER_OF_INTERVALS,
deviations);
}
private List<Double> createHistogram(double lowBound, double highBound,
double intervalStep, List<Double> values) {
double variableRange = highBound - lowBound;
/* TODO: What if highBound == lowBound? */
int numberOfClasses = (int)(variableRange/intervalStep);
int[] classes = new int[numberOfClasses+1];
for(Double value: values) {