diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java b/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java index a70fc55d5..08c7a1347 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/Planner.java @@ -944,4 +944,18 @@ public class Planner extends HtmlMacroComponent { } } + public TaskComponent getTaskComponentRelatedTo( + org.zkoss.ganttz.data.Task task) { + TaskList taskList = getTaskList(); + if (taskList != null) { + for (TaskComponent each : taskList.getTaskComponents()) { + if (each.getTask().equals(task)) { + return each; + } + } + } + + return null; + } + } diff --git a/libreplan-business/src/main/java/org/libreplan/business/advance/entities/DirectAdvanceAssignment.java b/libreplan-business/src/main/java/org/libreplan/business/advance/entities/DirectAdvanceAssignment.java index 4ef909e66..b44c06c30 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/advance/entities/DirectAdvanceAssignment.java +++ b/libreplan-business/src/main/java/org/libreplan/business/advance/entities/DirectAdvanceAssignment.java @@ -263,4 +263,9 @@ public class DirectAdvanceAssignment extends AdvanceAssignment { return !nonCalculatedConsolidations.isEmpty(); } + public void resetAdvanceMeasurements(AdvanceMeasurement advanceMeasurement) { + advanceMeasurements.clear(); + addAdvanceMeasurements(advanceMeasurement); + } + } diff --git a/libreplan-business/src/main/java/org/libreplan/business/orders/entities/OrderElement.java b/libreplan-business/src/main/java/org/libreplan/business/orders/entities/OrderElement.java index 6c397a3ab..120e11f7a 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/orders/entities/OrderElement.java +++ b/libreplan-business/src/main/java/org/libreplan/business/orders/entities/OrderElement.java @@ -1584,4 +1584,18 @@ public abstract class OrderElement extends IntegrationEntity implements return false; } + public boolean hasTimesheetsReportingHours() { + if (sumChargedEffort == null) { + return false; + } + return sumChargedEffort.getFirstTimesheetDate() != null; + } + + public boolean isFinishedTimesheets() { + if (sumChargedEffort == null) { + return false; + } + return sumChargedEffort.isFinishedTimesheets(); + } + } diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/adaptplanning/AdaptPlanningCommand.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/adaptplanning/AdaptPlanningCommand.java index 018035c50..0e5435862 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/adaptplanning/AdaptPlanningCommand.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/adaptplanning/AdaptPlanningCommand.java @@ -20,11 +20,27 @@ package org.libreplan.web.planner.adaptplanning; import static org.libreplan.web.I18nHelper._; +import java.util.Date; +import java.util.List; + +import org.joda.time.LocalDate; +import org.libreplan.business.advance.bootstrap.PredefinedAdvancedTypes; +import org.libreplan.business.advance.entities.AdvanceMeasurement; +import org.libreplan.business.advance.entities.AdvanceType; +import org.libreplan.business.advance.entities.DirectAdvanceAssignment; +import org.libreplan.business.advance.exceptions.DuplicateAdvanceAssignmentForOrderElementException; +import org.libreplan.business.advance.exceptions.DuplicateValueTrueReportGlobalAdvanceException; +import org.libreplan.business.orders.entities.OrderElement; +import org.libreplan.business.planner.entities.PositionConstraintType; +import org.libreplan.business.planner.entities.Task; import org.libreplan.business.planner.entities.TaskElement; +import org.libreplan.business.workingday.IntraDayDate; import org.libreplan.web.planner.order.PlanningStateCreator.PlanningState; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; +import org.zkoss.ganttz.Planner; +import org.zkoss.ganttz.TaskComponent; import org.zkoss.ganttz.extensions.IContext; /** @@ -43,7 +59,123 @@ public class AdaptPlanningCommand implements IAdaptPlanningCommand { @Override public void doAction(IContext context) { - // TODO Auto-generated method stub + List taskElements = planningState.getRootTask() + .getAllChildren(); + for (TaskElement taskElement : taskElements) { + OrderElement orderElement = taskElement.getOrderElement(); + taskElement.setUpdatedFromTimesheets(orderElement + .hasTimesheetsReportingHours()); + + if (taskElement.isUpdatedFromTimesheets()) { + setStartDateAndConstraint(taskElement, orderElement + .getSumChargedEffort().getFirstTimesheetDate()); + Date lastTimesheetDate = orderElement.getSumChargedEffort() + .getLastTimesheetDate(); + setEndDateIfNeeded(taskElement, lastTimesheetDate); + + if (orderElement.isFinishedTimesheets()) { + setEndDate(taskElement, lastTimesheetDate); + addTimesheetsProgress(orderElement, lastTimesheetDate); + } else { + removeTimesheetsProgressIfAny(orderElement); + } + + updateTask(context, taskElement); + } + } + context.reloadCharts(); + } + + private void setStartDateAndConstraint(TaskElement taskElement, + Date startDate) { + taskElement.setStartDate(startDate); + setStartInFixedDateConstarint(taskElement, startDate); + } + + private void setStartInFixedDateConstarint(TaskElement taskElement, + Date startDate) { + if (taskElement.isTask()) { + Task task = (Task) taskElement; + task.getPositionConstraint() + .update(PositionConstraintType.START_IN_FIXED_DATE, + IntraDayDate.startOfDay(LocalDate + .fromDateFields(startDate))); + } + } + + private void setEndDateIfNeeded(TaskElement taskElement, Date endDate) { + if (taskElement.getEndDate().compareTo(endDate) <= 0) { + setEndDate(taskElement, endDate); + } + } + + private void setEndDate(TaskElement taskElement, Date endDate) { + taskElement.setEndDate(LocalDate.fromDateFields(endDate).plusDays(1) + .toDateTimeAtStartOfDay().toDate()); + } + + private void addTimesheetsProgress(OrderElement orderElement, + Date progressDate) { + AdvanceType timesheetsAdvanceType = getTimesheetsAdvanceType(); + + DirectAdvanceAssignment timesheetsAdvanceAssignment = orderElement + .getDirectAdvanceAssignmentByType(timesheetsAdvanceType); + + if (timesheetsAdvanceAssignment == null) { + timesheetsAdvanceAssignment = DirectAdvanceAssignment.create(false, + timesheetsAdvanceType.getDefaultMaxValue()); + timesheetsAdvanceAssignment.setAdvanceType(timesheetsAdvanceType); + try { + orderElement.addAdvanceAssignment(timesheetsAdvanceAssignment); + } catch (DuplicateValueTrueReportGlobalAdvanceException e) { + // This shouldn't happen as the new advanceAssignment is not + // marked as spread yet + throw new RuntimeException(e); + } catch (DuplicateAdvanceAssignmentForOrderElementException e) { + // If the same type already exists in other element we don't do + // anything + return; + } + } + + DirectAdvanceAssignment spreadAdvanceAssignment = orderElement + .getReportGlobalAdvanceAssignment(); + if (spreadAdvanceAssignment != null) { + spreadAdvanceAssignment.setReportGlobalAdvance(false); + } + + timesheetsAdvanceAssignment.setReportGlobalAdvance(true); + timesheetsAdvanceAssignment.resetAdvanceMeasurements(AdvanceMeasurement + .create(LocalDate.fromDateFields(progressDate), + timesheetsAdvanceType.getDefaultMaxValue())); + } + + private AdvanceType getTimesheetsAdvanceType() { + return PredefinedAdvancedTypes.TIMESHEETS.getType(); + } + + private void removeTimesheetsProgressIfAny(OrderElement orderElement) { + DirectAdvanceAssignment timesheetsAdvanceAssignment = orderElement + .getDirectAdvanceAssignmentByType(getTimesheetsAdvanceType()); + if (timesheetsAdvanceAssignment != null) { + orderElement.removeAdvanceAssignment(timesheetsAdvanceAssignment); + } + } + + private void updateTask(IContext context, + TaskElement taskElement) { + taskElement.updateAdvancePercentageFromOrderElement(); + + Planner planner = (Planner) context.getRelativeTo(); + TaskComponent taskComponent = planner.getTaskComponentRelatedTo(context + .getMapper().findAssociatedBean(taskElement)); + if (taskComponent != null) { + taskComponent.updateTooltipText(); + taskComponent.updateProperties(); + taskComponent.invalidate(); + } + + context.recalculatePosition(taskElement); } @Override