diff --git a/libreplan-business/src/main/java/org/libreplan/business/planner/entities/IOrderEarnedValueCalculator.java b/libreplan-business/src/main/java/org/libreplan/business/planner/entities/IOrderEarnedValueCalculator.java index 232f3ee0d..ed1c5450a 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/planner/entities/IOrderEarnedValueCalculator.java +++ b/libreplan-business/src/main/java/org/libreplan/business/planner/entities/IOrderEarnedValueCalculator.java @@ -63,4 +63,8 @@ public interface IOrderEarnedValueCalculator extends IEarnedValueCalculator { BigDecimal getEstimateAtCompletion(BigDecimal budgetAtCompletion, BigDecimal costPerformanceIndex); + // ETC (Estimate To Complete) + BigDecimal getEstimateToComplete(BigDecimal estimateAtCompletion, + BigDecimal actualCostWorkPerformed); + } \ No newline at end of file diff --git a/libreplan-business/src/main/java/org/libreplan/business/planner/entities/OrderEarnedValueCalculator.java b/libreplan-business/src/main/java/org/libreplan/business/planner/entities/OrderEarnedValueCalculator.java index bda69cd0f..2b75265a6 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/planner/entities/OrderEarnedValueCalculator.java +++ b/libreplan-business/src/main/java/org/libreplan/business/planner/entities/OrderEarnedValueCalculator.java @@ -172,12 +172,12 @@ public class OrderEarnedValueCalculator extends EarnedValueCalculator implements if (BigDecimal.ZERO.compareTo(actualCost) == 0) { return BigDecimal.ZERO; } - return asPercentage(budgetedCost.divide(actualCost, + return multiplyByOneHundred(budgetedCost.setScale(2).divide(actualCost, RoundingMode.HALF_UP)); } - private BigDecimal asPercentage(BigDecimal value) { - return value.multiply(BigDecimal.valueOf(100)).setScale(2); + private BigDecimal multiplyByOneHundred(BigDecimal value) { + return value.multiply(BigDecimal.valueOf(100)); } @Override @@ -192,7 +192,14 @@ public class OrderEarnedValueCalculator extends EarnedValueCalculator implements if (BigDecimal.ZERO.compareTo(costPerformanceIndex) == 0) { return BigDecimal.ZERO; } - return asPercentage(budgetAtCompletion.divide(costPerformanceIndex)); + return multiplyByOneHundred(budgetAtCompletion.setScale(2).divide( + costPerformanceIndex, RoundingMode.HALF_UP)); + } + + @Override + public BigDecimal getEstimateToComplete(BigDecimal estimateAtCompletion, + BigDecimal actualCostWorkPerformed) { + return estimateAtCompletion.subtract(actualCostWorkPerformed); } } diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/CostStatusController.java b/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/CostStatusController.java index fd7f721c7..c0cc5f2e7 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/CostStatusController.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/CostStatusController.java @@ -22,6 +22,7 @@ package org.libreplan.web.dashboard; import static org.libreplan.web.I18nHelper._; import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.Date; import org.joda.time.LocalDate; @@ -60,6 +61,12 @@ public class CostStatusController extends GenericForwardComposer { // Variance at Completion public Label lblVAC; + // Cost Variance + public Label lblACWP; + + // Estimate To Complete + public Label lblETC; + @Override public void doAfterCompose(org.zkoss.zk.ui.Component comp) throws Exception { super.doAfterCompose(comp); @@ -73,11 +80,12 @@ public class CostStatusController extends GenericForwardComposer { public void render() { LocalDate today = LocalDate.fromDateFields(new Date()); - BigDecimal budgetedCost = costStatusModel - .getBudgetedCostWorkPerformedAt(today); BigDecimal actualCost = costStatusModel .getActualCostWorkPerformedAt(today); + setActualCostWorkPerformed(actualCost); + BigDecimal budgetedCost = costStatusModel + .getBudgetedCostWorkPerformedAt(today); BigDecimal costVariance = costStatusModel.getCostVariance(budgetedCost, actualCost); setCostVariance(costVariance); @@ -98,26 +106,38 @@ public class CostStatusController extends GenericForwardComposer { .getVarianceAtCompletion(budgetAtCompletion, estimateAtCompletion); setVarianceAtCompletion(varianceAtCompletion); + + BigDecimal estimateToComplete = costStatusModel.getEstimateToComplete( + estimateAtCompletion, actualCost); + setEstimateToComplete(estimateToComplete); } private void setEstimateAtCompletion(BigDecimal value) { - lblEAC.setValue(String.format("%.2f %%", value.doubleValue())); + lblEAC.setValue(_("{0} h", value.setScale(0, RoundingMode.HALF_UP))); } private void setCostPerformanceIndex(BigDecimal value) { - lblCPI.setValue(String.format("%.2f %%", value.doubleValue())); + lblCPI.setValue(value.setScale(0, RoundingMode.HALF_UP) + " %"); } private void setBudgetAtCompletion(BigDecimal value) { - lblBAC.setValue(String.format(_("%s h"), value.toString())); + lblBAC.setValue(_("{0} h", value.toString())); } private void setCostVariance(BigDecimal value) { - lblCV.setValue(String.format(_("%s h"), value.toString())); + lblCV.setValue(_("{0} h", value.toString())); } private void setVarianceAtCompletion(BigDecimal value) { - lblVAC.setValue(String.format(_("%s h"), value.toString())); + lblVAC.setValue(_("{0} h", value.toString())); + } + + private void setActualCostWorkPerformed(BigDecimal value) { + lblACWP.setValue(_("{0} h", value.setScale(0, RoundingMode.HALF_UP))); + } + + private void setEstimateToComplete(BigDecimal value) { + lblETC.setValue(_("{0} h", value.setScale(0, RoundingMode.HALF_UP))); } } diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/CostStatusModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/CostStatusModel.java index 838cf8629..88b3e0bc6 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/CostStatusModel.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/CostStatusModel.java @@ -104,4 +104,11 @@ public class CostStatusModel implements ICostStatusModel { .getBudgetedCostWorkPerformedAt(order, date); } + @Override + public BigDecimal getEstimateToComplete(BigDecimal estimateAtCompletion, + BigDecimal actualCost) { + return earnedValueCalculator.getEstimateToComplete( + estimateAtCompletion, actualCost); + } + } \ No newline at end of file diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/ICostStatusModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/ICostStatusModel.java index a150ab2da..c49bb601b 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/ICostStatusModel.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/ICostStatusModel.java @@ -55,6 +55,10 @@ interface ICostStatusModel { BigDecimal getVarianceAtCompletion(BigDecimal budgetAtCompletion, BigDecimal estimateAtCompletion); + // Estimate to Complete (ETC) + BigDecimal getEstimateToComplete(BigDecimal estimateAtCompletion, + BigDecimal actualCost); + void setCurrentOrder(Order order); } \ No newline at end of file diff --git a/libreplan-webapp/src/main/webapp/dashboard/_costStatus.zul b/libreplan-webapp/src/main/webapp/dashboard/_costStatus.zul index 0a46e193d..30c88507e 100644 --- a/libreplan-webapp/src/main/webapp/dashboard/_costStatus.zul +++ b/libreplan-webapp/src/main/webapp/dashboard/_costStatus.zul @@ -39,7 +39,8 @@