diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/Order.java b/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/Order.java index ac65f620a..d0bd4d6a0 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/Order.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/Order.java @@ -354,8 +354,11 @@ public class Order extends OrderLineGroup { } @Override - protected void applyStartConstraintTo(Task task) { - // the initDate of order don't imply a start constraint at a task + protected boolean applyConstraintBasedOnInitOrEndDate(Task task, + boolean scheduleBackwards) { + // the initDate or the deadline of a order doesn't imply a start + // constraint at a task + return false; } public boolean getDependenciesConstraintsHavePriority() { diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/OrderElement.java b/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/OrderElement.java index d9a6098d5..952c0e827 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/OrderElement.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/OrderElement.java @@ -30,8 +30,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; import org.apache.commons.lang.Validate; import org.hibernate.validator.AssertTrue; @@ -56,6 +56,7 @@ import org.navalplanner.business.orders.entities.SchedulingState.Type; import org.navalplanner.business.orders.entities.TaskSource.TaskSourceSynchronization; import org.navalplanner.business.planner.entities.Task; import org.navalplanner.business.planner.entities.TaskElement; +import org.navalplanner.business.planner.entities.TaskStartConstraint; import org.navalplanner.business.qualityforms.entities.QualityForm; import org.navalplanner.business.qualityforms.entities.TaskQualityForm; import org.navalplanner.business.requirements.entities.CriterionRequirement; @@ -822,20 +823,39 @@ public abstract class OrderElement extends IntegrationEntity implements return criterionRequirementHandler.getIndirectCriterionRequirement(criterionRequirements); } - public void applyStartConstraintIfNeededTo(Task task) { - if (getInitDate() != null) { - applyStartConstraintTo(task); - return; + public void applyStartConstraintTo(Task task) { + boolean scheduleBackwards = getOrder().isScheduleBackwards(); + OrderElement current = this; + while (current != null) { + boolean applied = current.applyConstraintBasedOnInitOrEndDate(task, + scheduleBackwards); + if (applied) { + return; + } + current = current.getParent(); } - OrderLineGroup parent = getParent(); - if (parent != null) { - parent.applyStartConstraintIfNeededTo(task); + if (scheduleBackwards) { + task.getStartConstraint().asLateAsPossible(); + } else { + task.getStartConstraint().asSoonAsPossible(); } } - protected void applyStartConstraintTo(Task task) { - task.getStartConstraint().notEarlierThan( - LocalDate.fromDateFields(this.getInitDate())); + protected boolean applyConstraintBasedOnInitOrEndDate(Task task, + boolean scheduleBackwards) { + TaskStartConstraint constraint = task.getStartConstraint(); + if (getInitDate() != null + && (getDeadline() == null || !scheduleBackwards)) { + constraint.notEarlierThan( + LocalDate.fromDateFields(this.getInitDate())); + return true; + } + if (getDeadline() != null) { + constraint.finishNotLaterThan( + LocalDate.fromDateFields(this.getDeadline())); + return true; + } + return false; } public Set getDirectCriterionRequirement() { diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/Task.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/Task.java index c64a7889f..4eaac1c89 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/Task.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/Task.java @@ -66,7 +66,7 @@ public class Task extends TaskElement implements ITaskLeafConstraint { public static Task createTask(TaskSource taskSource) { Task task = new Task(); OrderElement orderElement = taskSource.getOrderElement(); - orderElement.applyStartConstraintIfNeededTo(task); + orderElement.applyStartConstraintTo(task); Task result = create(task, taskSource); result.initializeDates(); return result; diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/TaskStartConstraint.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/TaskStartConstraint.java index c4860d1ed..b0deec868 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/TaskStartConstraint.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/TaskStartConstraint.java @@ -64,6 +64,22 @@ public class TaskStartConstraint { this.startConstraintType = StartConstraintType.START_NOT_EARLIER_THAN; } + public void finishNotLaterThan(LocalDate date) { + Validate.notNull(date); + this.constraintDate = date; + this.startConstraintType = StartConstraintType.FINISH_NOT_LATER_THAN; + } + + public void asLateAsPossible() { + this.startConstraintType = StartConstraintType.AS_LATE_AS_POSSIBLE; + this.constraintDate = null; + } + + public void asSoonAsPossible() { + this.startConstraintType = StartConstraintType.AS_SOON_AS_POSSIBLE; + this.constraintDate = null; + } + public boolean isValid(StartConstraintType type, LocalDate value) { return type != null && type.isAssociatedDateRequired() == (value != null); diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/TaskElementTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/TaskElementTest.java index 751bb6584..7419631ce 100644 --- a/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/TaskElementTest.java +++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/TaskElementTest.java @@ -222,8 +222,6 @@ public class TaskElementTest { public void ifNoParentWithStartDateTheStartConstraintIsSoonAsPossible() { OrderLine orderLine = OrderLine.create(); addOrderTo(orderLine); - LocalDate deadline = new LocalDate(2007, 4, 4); - orderLine.setDeadline(asDate(deadline)); TaskSource taskSource = asTaskSource(orderLine); Task task = Task.createTask(taskSource); assertThat(task.getStartConstraint(), @@ -237,6 +235,18 @@ public class TaskElementTest { order.add(orderElement); } + @Test + public void ifTheOrderLineHasDeadlineTheStartConstraintIsNotLaterThan() { + OrderLine orderLine = OrderLine.create(); + addOrderTo(orderLine); + LocalDate deadline = new LocalDate(2007, 4, 4); + orderLine.setDeadline(asDate(deadline)); + TaskSource taskSource = asTaskSource(orderLine); + Task task = Task.createTask(taskSource); + assertThat(task.getStartConstraint(), + isOfType(StartConstraintType.FINISH_NOT_LATER_THAN)); + } + @Test @SuppressWarnings("unchecked") public void ifSomeParentHasInitDateTheStartConstraintIsNotEarlierThan() { @@ -246,8 +256,6 @@ public class TaskElementTest { group.setInitDate(asDate(initDate)); OrderLine orderLine = OrderLine.create(); group.add(orderLine); - LocalDate deadline = new LocalDate(2007, 4, 4); - orderLine.setDeadline(asDate(deadline)); TaskSource taskSource = asTaskSource(orderLine); Task task = Task.createTask(taskSource); assertThat(task.getStartConstraint(), allOf( @@ -262,8 +270,6 @@ public class TaskElementTest { Order order = orderLine.getOrder(); Date initDate = asDate(new LocalDate(2005, 10, 5)); order.setInitDate(initDate); - LocalDate deadline = new LocalDate(2007, 4, 4); - orderLine.setDeadline(asDate(deadline)); TaskSource taskSource = asTaskSource(orderLine); Task task = Task.createTask(taskSource); assertThat(task.getStartConstraint(),