Bug #1413: Fix bug

The methods used to calculate the start and end of the task when
moving the task and when allocating in the form were different. This
caused the length of the task to change when being moved.

Now the method used when moving the task is the one always in use,
because it's more precise.
This commit is contained in:
Óscar González Fernández 2012-11-08 19:28:07 +01:00 committed by Manuel Rego Casasnovas
parent d27fabbbeb
commit 4780b1fad0
3 changed files with 65 additions and 61 deletions

View file

@ -581,6 +581,18 @@ public class Task extends TaskElement implements ITaskPositionConstrained {
return durationBetweenDates.fromStartToEnd(newStartDate); return durationBetweenDates.fromStartToEnd(newStartDate);
} }
public IntraDayDate calculateEndGivenWorkableDays(int days) {
Validate.isTrue(days >= 0);
DurationBetweenDates duration = fromFixedDuration(days);
return duration.fromStartToEnd(getIntraDayStartDate());
}
public IntraDayDate calculateStartGivenWorkableDays(int days) {
Validate.isTrue(days >= 0);
DurationBetweenDates duration = fromFixedDuration(days);
return duration.fromEndToStart(getIntraDayEndDate());
}
private IntraDayDate calculateStartKeepingLength(IntraDayDate newEnd) { private IntraDayDate calculateStartKeepingLength(IntraDayDate newEnd) {
DurationBetweenDates durationBetweenDates = getDurationBetweenDates(); DurationBetweenDates durationBetweenDates = getDurationBetweenDates();
return durationBetweenDates.fromEndToStart(newEnd); return durationBetweenDates.fromEndToStart(newEnd);
@ -645,12 +657,23 @@ public class Task extends TaskElement implements ITaskPositionConstrained {
} }
public IntraDayDate fromStartToEnd(IntraDayDate newStartDate) { public IntraDayDate fromStartToEnd(IntraDayDate newStartDate) {
LocalDate resultDay = calculateEndGivenWorkableDays( LocalDate resultDay = afterSomeWorkableDays(
newStartDate.getDate(), numberOfWorkableDays); newStartDate.getDate(), numberOfWorkableDays);
return plusDuration(IntraDayDate.startOfDay(resultDay), return plusDuration(IntraDayDate.startOfDay(resultDay),
remainderDuration.plus(newStartDate.getEffortDuration())); remainderDuration.plus(newStartDate.getEffortDuration()));
} }
private LocalDate afterSomeWorkableDays(LocalDate start,
int workableDays) {
LocalDate result = start;
for (int i = 0; i < workableDays; result = result.plusDays(1)) {
if (isWorkable(result)) {
i++;
}
}
return result;
}
private IntraDayDate plusDuration(IntraDayDate start, private IntraDayDate plusDuration(IntraDayDate start,
EffortDuration remaining) { EffortDuration remaining) {
IntraDayDate result = IntraDayDate.startOfDay(start.getDate()); IntraDayDate result = IntraDayDate.startOfDay(start.getDate());
@ -699,13 +722,23 @@ public class Task extends TaskElement implements ITaskPositionConstrained {
} }
public IntraDayDate fromEndToStart(IntraDayDate newEnd) { public IntraDayDate fromEndToStart(IntraDayDate newEnd) {
LocalDate resultDay = calculateStartGivenWorkableDays( LocalDate resultDay = someWorkableDaysBefore(
newEnd.getDate(), numberOfWorkableDays); newEnd.getDate(), numberOfWorkableDays);
return minusDuration(plusDuration( return minusDuration(plusDuration(
IntraDayDate.startOfDay(resultDay), IntraDayDate.startOfDay(resultDay),
newEnd.getEffortDuration()), remainderDuration); newEnd.getEffortDuration()), remainderDuration);
} }
private LocalDate someWorkableDaysBefore(LocalDate end, int workableDays) {
LocalDate result = end;
for (int i = 0; i < workableDays; result = result.minusDays(1)) {
if (isWorkable(result.minusDays(1))) {
i++;
}
}
return result;
}
private IntraDayDate minusDuration(IntraDayDate date, private IntraDayDate minusDuration(IntraDayDate date,
EffortDuration decrement) { EffortDuration decrement) {
IntraDayDate result = IntraDayDate.create( IntraDayDate result = IntraDayDate.create(
@ -1060,38 +1093,6 @@ public class Task extends TaskElement implements ITaskPositionConstrained {
return result; return result;
} }
public LocalDate calculateEndGivenWorkableDays(int workableDays) {
return calculateEndGivenWorkableDays(getIntraDayStartDate().getDate(),
workableDays);
}
public LocalDate calculateStartGivenWorkableDays(int workableDays) {
return calculateStartGivenWorkableDays(getEndAsLocalDate(),
workableDays);
}
private LocalDate calculateEndGivenWorkableDays(LocalDate start,
int workableDays) {
LocalDate result = start;
for (int i = 0; i < workableDays; result = result.plusDays(1)) {
if (isWorkable(result)) {
i++;
}
}
return result;
}
private LocalDate calculateStartGivenWorkableDays(LocalDate end,
int workableDays) {
LocalDate result = end;
for (int i = 0; i < workableDays; result = result.minusDays(1)) {
if (isWorkable(result.minusDays(1))) {
i++;
}
}
return result;
}
private boolean isWorkable(LocalDate day) { private boolean isWorkable(LocalDate day) {
ICalendar calendar = getCalendar(); ICalendar calendar = getCalendar();
assert calendar != null; assert calendar != null;

View file

@ -50,7 +50,6 @@ import org.libreplan.business.resources.entities.ResourceEnum;
import org.libreplan.business.scenarios.entities.Scenario; import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.business.workingday.EffortDuration; import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.EffortDuration.IEffortFrom; import org.libreplan.business.workingday.EffortDuration.IEffortFrom;
import org.libreplan.business.workingday.IntraDayDate;
public class AllocationRowsHandler { public class AllocationRowsHandler {
@ -299,10 +298,10 @@ public class AllocationRowsHandler {
.createAndAssociate(task, currentRows, requestedToRemove); .createAndAssociate(task, currentRows, requestedToRemove);
if (isForwardsAllocation()) { if (isForwardsAllocation()) {
ResourceAllocation.allocating(allocations).allocateUntil( ResourceAllocation.allocating(allocations).allocateUntil(
formBinder.getAllocationEnd()); formBinder.getAllocationEnd().asExclusiveEnd());
} else { } else {
ResourceAllocation.allocating(allocations).allocateFromEndUntil( ResourceAllocation.allocating(allocations).allocateFromEndUntil(
formBinder.getAllocationStart()); formBinder.getAllocationStart().getDate());
} }
return allocations; return allocations;
} }
@ -343,10 +342,10 @@ public class AllocationRowsHandler {
requestedToRemove); requestedToRemove);
if (isForwardsAllocation()) { if (isForwardsAllocation()) {
ResourceAllocation.allocatingHours(hours).allocateUntil( ResourceAllocation.allocatingHours(hours).allocateUntil(
IntraDayDate.startOfDay(formBinder.getAllocationEnd())); formBinder.getAllocationEnd());
} else { } else {
ResourceAllocation.allocatingHours(hours).allocateFromEndUntil( ResourceAllocation.allocatingHours(hours).allocateFromEndUntil(
IntraDayDate.startOfDay(formBinder.getAllocationStart())); formBinder.getAllocationStart());
} }
return hours; return hours;
} }

View file

@ -51,6 +51,7 @@ import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.resources.entities.ResourceEnum; import org.libreplan.business.resources.entities.ResourceEnum;
import org.libreplan.business.scenarios.entities.Scenario; import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.business.workingday.EffortDuration; import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.business.workingday.ResourcesPerDay; import org.libreplan.business.workingday.ResourcesPerDay;
import org.libreplan.web.common.EffortDurationBox; import org.libreplan.web.common.EffortDurationBox;
import org.libreplan.web.common.IMessagesForUser; import org.libreplan.web.common.IMessagesForUser;
@ -307,34 +308,36 @@ public class FormBinder {
Task task = getTask(); Task task = getTask();
Integer workableDays = taskWorkableDays.getValue(); Integer workableDays = taskWorkableDays.getValue();
if (allocationRowsHandler.isForwardsAllocation()) { if (allocationRowsHandler.isForwardsAllocation()) {
LocalDate newEnd = ensureItIsAfterConsolidation( IntraDayDate newEnd = ensureItIsAfterConsolidation(task
task.calculateEndGivenWorkableDays(workableDays)); .calculateEndGivenWorkableDays(workableDays));
updateWorkableDaysIfNecessary(workableDays, updateWorkableDaysIfNecessary(workableDays,
getTask().getStartAsLocalDate(), newEnd); getTask().getIntraDayStartDate(),
newEnd);
taskPropertiesController taskPropertiesController
.updateTaskEndDate(newEnd); .updateTaskEndDate(newEnd.getDate());
showValueOfDateOn(labelTaskEnd, newEnd); showValueOfDateOn(labelTaskEnd,
newEnd.getDate());
} else { } else {
LocalDate newStart = ensureItIsAfterConsolidation(task IntraDayDate newStart = ensureItIsAfterConsolidation(task
.calculateStartGivenWorkableDays(workableDays)); .calculateStartGivenWorkableDays(workableDays));
updateWorkableDaysIfNecessary(workableDays, updateWorkableDaysIfNecessary(workableDays,
newStart, task.getIntraDayEndDate() newStart, task.getIntraDayEndDate());
.asExclusiveEnd());
taskPropertiesController taskPropertiesController
.updateTaskStartDate(newStart); .updateTaskStartDate(newStart.getDate());
showValueOfDateOn(labelTaskStart, newStart); showValueOfDateOn(labelTaskStart,
newStart.getDate());
} }
} }
private void updateWorkableDaysIfNecessary( private void updateWorkableDaysIfNecessary(
int specifiedWorkableDays, int specifiedWorkableDays,
LocalDate allocationStart, IntraDayDate allocationStart,
LocalDate allocationEnd) { IntraDayDate allocationEnd) {
Integer effectiveWorkableDays = getTask() Integer effectiveWorkableDays = getTask()
.getWorkableDaysFrom(allocationStart, .getWorkableDaysFrom(
allocationEnd); allocationStart.getDate(),
if (!effectiveWorkableDays allocationEnd.asExclusiveEnd());
.equals(specifiedWorkableDays)) { if (effectiveWorkableDays < specifiedWorkableDays) {
Clients.response(new AuWrongValue( Clients.response(new AuWrongValue(
taskWorkableDays, taskWorkableDays,
_("The original workable days value {0} cannot be modified as it has consolidations", _("The original workable days value {0} cannot be modified as it has consolidations",
@ -345,10 +348,10 @@ public class FormBinder {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private LocalDate ensureItIsAfterConsolidation( private IntraDayDate ensureItIsAfterConsolidation(
LocalDate newDate) { IntraDayDate newDate) {
return Collections.max(Arrays.asList(newDate, return Collections.max(Arrays.asList(newDate,
firstPossibleDay)); IntraDayDate.startOfDay(firstPossibleDay)));
} }
}, onChangeEnableApply); }, onChangeEnableApply);
@ -403,7 +406,8 @@ public class FormBinder {
taskWorkableDays.setValue(lastSpecifiedWorkableDays); taskWorkableDays.setValue(lastSpecifiedWorkableDays);
showValueOfDateOn( showValueOfDateOn(
labelTaskEnd, labelTaskEnd,
task.calculateEndGivenWorkableDays(lastSpecifiedWorkableDays)); task.calculateEndGivenWorkableDays(
lastSpecifiedWorkableDays).getDate());
lastSpecifiedWorkableDays = null; lastSpecifiedWorkableDays = null;
} }
} }
@ -436,12 +440,12 @@ public class FormBinder {
| SimpleConstraint.NO_NEGATIVE); | SimpleConstraint.NO_NEGATIVE);
} }
public LocalDate getAllocationEnd() { public IntraDayDate getAllocationEnd() {
return getTask().calculateEndGivenWorkableDays( return getTask().calculateEndGivenWorkableDays(
workableDaysAndDatesBinder.getValue()); workableDaysAndDatesBinder.getValue());
} }
public LocalDate getAllocationStart() { public IntraDayDate getAllocationStart() {
return getTask().calculateStartGivenWorkableDays( return getTask().calculateStartGivenWorkableDays(
workableDaysAndDatesBinder.getValue()); workableDaysAndDatesBinder.getValue());
} }