Remove date attribute from Stretch
Date is a relative value depending on allocation dates and length percentage defined by Stretch. FEA: ItEr75S23FixAllocationModel
This commit is contained in:
parent
1f85934e30
commit
7da6dafc62
9 changed files with 251 additions and 261 deletions
|
|
@ -39,28 +39,43 @@ import org.joda.time.LocalDate;
|
|||
*/
|
||||
public class Stretch {
|
||||
|
||||
public static Stretch create(LocalDate date, BigDecimal datePercent, BigDecimal workPercent) {
|
||||
return new Stretch(date, datePercent, workPercent);
|
||||
public static Stretch create(BigDecimal datePercent, BigDecimal workPercent) {
|
||||
return new Stretch(datePercent, workPercent);
|
||||
}
|
||||
|
||||
public static LocalDate getDateByLengthProportion(
|
||||
ResourceAllocation<?> allocation, BigDecimal lengthProportion) {
|
||||
int allocationDuration = Days.daysBetween(allocation.getStartDate(),
|
||||
allocation.getEndDate()).getDays();
|
||||
int days = lengthProportion.multiply(
|
||||
BigDecimal.valueOf(allocationDuration)).intValue();
|
||||
return allocation.getStartDate().plusDays(days);
|
||||
}
|
||||
|
||||
public static BigDecimal getLengthProportionByDate(
|
||||
ResourceAllocation<?> allocation, LocalDate date) {
|
||||
int allocationDuration = Days.daysBetween(allocation.getStartDate(),
|
||||
allocation.getEndDate()).getDays();
|
||||
int days = Days.daysBetween(allocation.getStartDate(), date).getDays();
|
||||
return daysProportion(days, allocationDuration);
|
||||
}
|
||||
|
||||
private static BigDecimal daysProportion(int daysPartial, int daysTotal) {
|
||||
if (daysTotal == 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return BigDecimal.valueOf(daysPartial).divide(
|
||||
BigDecimal.valueOf(daysTotal), 2, BigDecimal.ROUND_HALF_EVEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Infers the datePercent based on duration of task and the date of the
|
||||
* Stretch
|
||||
*
|
||||
* @param date
|
||||
* @param task
|
||||
* @param workPercent
|
||||
* @return
|
||||
* Infers the lengthPercent based on duration of resource allocation and the
|
||||
* date of the Stretch
|
||||
*/
|
||||
public static Stretch create(LocalDate date, Task task,
|
||||
BigDecimal workPercent) {
|
||||
LocalDate start = task.getStartAsLocalDate();
|
||||
LocalDate end = task.getEndAsLocalDate();
|
||||
|
||||
Days taskDuration = Days.daysBetween(start, end);
|
||||
Days daysDuration = Days.daysBetween(start, date);
|
||||
BigDecimal daysPercent = daysPercent(daysDuration, taskDuration);
|
||||
return new Stretch(date, daysPercent, workPercent);
|
||||
public static Stretch create(LocalDate date,
|
||||
ResourceAllocation<?> allocation, BigDecimal workPercent) {
|
||||
return new Stretch(getLengthProportionByDate(allocation, date),
|
||||
workPercent);
|
||||
}
|
||||
|
||||
protected static BigDecimal daysPercent(Days daysPartial, Days daysTotal) {
|
||||
|
|
@ -81,7 +96,6 @@ public class Stretch {
|
|||
|
||||
public static Stretch copy(Stretch stretch) {
|
||||
Stretch result = new Stretch();
|
||||
result.date = stretch.date;
|
||||
result.lengthPercentage = stretch.lengthPercentage;
|
||||
result.amountWorkPercentage = stretch.amountWorkPercentage;
|
||||
result.consolidated = stretch.consolidated;
|
||||
|
|
@ -93,20 +107,18 @@ public class Stretch {
|
|||
return ConsolidatedStretch.fromConsolidatedProgress(resourceAllocation);
|
||||
}
|
||||
|
||||
public static List<Stretch> sortByDate(
|
||||
public static List<Stretch> sortByLengthPercentage(
|
||||
List<Stretch> stretches) {
|
||||
Collections.sort(stretches, new Comparator<Stretch>() {
|
||||
@Override
|
||||
public int compare(Stretch o1, Stretch o2) {
|
||||
return o1.getDate().compareTo(o2.getDate());
|
||||
return o1.getLengthPercentage().compareTo(
|
||||
o2.getLengthPercentage());
|
||||
}
|
||||
});
|
||||
return stretches;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private LocalDate date = new LocalDate();
|
||||
|
||||
@NotNull
|
||||
private BigDecimal lengthPercentage = BigDecimal.ZERO;
|
||||
|
||||
|
|
@ -119,8 +131,7 @@ public class Stretch {
|
|||
// Transient value, a stretch is consolidated if it's a consolidated stretch
|
||||
private boolean consolidated = false;
|
||||
|
||||
private Stretch(LocalDate date, BigDecimal lengthPercent, BigDecimal progressPercent) {
|
||||
this.date = date;
|
||||
private Stretch(BigDecimal lengthPercent, BigDecimal progressPercent) {
|
||||
this.lengthPercentage = lengthPercent;
|
||||
this.amountWorkPercentage = progressPercent;
|
||||
}
|
||||
|
|
@ -129,12 +140,12 @@ public class Stretch {
|
|||
|
||||
}
|
||||
|
||||
public void setDate(LocalDate date) {
|
||||
this.date = date;
|
||||
public void setDateIn(ResourceAllocation<?> allocation, LocalDate date) {
|
||||
setLengthPercentage(getLengthProportionByDate(allocation, date));
|
||||
}
|
||||
|
||||
public LocalDate getDate() {
|
||||
return date;
|
||||
public LocalDate getDateIn(ResourceAllocation<?> allocation) {
|
||||
return getDateByLengthProportion(allocation, lengthPercentage);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -178,7 +189,8 @@ public class Stretch {
|
|||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("(%s, %s, %s, readOnly: %s) ", date, lengthPercentage, amountWorkPercentage, readOnly);
|
||||
return String.format("(%s, %s, readOnly: %s) ", lengthPercentage,
|
||||
amountWorkPercentage, readOnly);
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
|
|
@ -219,15 +231,8 @@ class ConsolidatedStretch {
|
|||
final Task task = resourceAllocation.getTask();
|
||||
final LocalDate consolidatedEnd = lastDay(consolidated);
|
||||
|
||||
return create(consolidatedEnd.plusDays(1), task.getAdvancePercentage(), task);
|
||||
}
|
||||
|
||||
private static Stretch create(LocalDate date, BigDecimal advancePercentage,
|
||||
Task task) {
|
||||
Stretch result = Stretch.create(date, task, advancePercentage);
|
||||
result.readOnly(true);
|
||||
result.consolidated(true);
|
||||
return result;
|
||||
return Stretch.create(consolidatedEnd.plusDays(1), resourceAllocation,
|
||||
task.getAdvancePercentage());
|
||||
}
|
||||
|
||||
private ConsolidatedStretch() {
|
||||
|
|
|
|||
|
|
@ -206,8 +206,8 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
// Transient. Calculated from resourceAllocation
|
||||
private Stretch consolidatedStretch;
|
||||
|
||||
// Transient. Used to calculate read-only last stretch
|
||||
private LocalDate taskEndDate;
|
||||
// Transient. Used to calculate stretches dates
|
||||
private ResourceAllocation<?> resourceAllocation;
|
||||
|
||||
public static StretchesFunction create() {
|
||||
return (StretchesFunction) create(new StretchesFunction());
|
||||
|
|
@ -220,14 +220,14 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
|
||||
}
|
||||
|
||||
public static List<Interval> intervalsFor(
|
||||
public static List<Interval> intervalsFor(ResourceAllocation<?> allocation,
|
||||
Collection<? extends Stretch> streches) {
|
||||
ArrayList<Interval> result = new ArrayList<Interval>();
|
||||
LocalDate previous = null, stretchDate = null;
|
||||
BigDecimal sumOfProportions = BigDecimal.ZERO, loadedProportion = BigDecimal.ZERO;
|
||||
|
||||
for (Stretch each : streches) {
|
||||
stretchDate = each.getDate();
|
||||
stretchDate = each.getDateIn(allocation);
|
||||
loadedProportion = each.getAmountWorkPercentage().subtract(
|
||||
sumOfProportions);
|
||||
if (loadedProportion.signum() < 0) {
|
||||
|
|
@ -251,7 +251,7 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
result.type = type;
|
||||
result.desiredType = desiredType;
|
||||
result.consolidatedStretch = consolidatedStretch;
|
||||
result.taskEndDate = taskEndDate;
|
||||
result.resourceAllocation = resourceAllocation;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -264,20 +264,28 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
}
|
||||
|
||||
public List<Stretch> getStretchesDefinedByUser() {
|
||||
return Collections.unmodifiableList(Stretch.sortByDate(stretches));
|
||||
return Collections.unmodifiableList(Stretch
|
||||
.sortByLengthPercentage(stretches));
|
||||
}
|
||||
|
||||
@Valid
|
||||
public List<Stretch> getStretches() {
|
||||
List<Stretch> result = new ArrayList<Stretch>(stretches);
|
||||
if (taskEndDate != null) {
|
||||
result.add(getLastStretch());
|
||||
}
|
||||
return Collections.unmodifiableList(Stretch.sortByDate(result));
|
||||
List<Stretch> result = new ArrayList<Stretch>();
|
||||
result.add(getFirstStretch());
|
||||
result.addAll(stretches);
|
||||
result.add(getLastStretch());
|
||||
return Collections.unmodifiableList(Stretch
|
||||
.sortByLengthPercentage(result));
|
||||
}
|
||||
|
||||
private Stretch getLastStretch() {
|
||||
Stretch result = Stretch.create(taskEndDate, BigDecimal.ONE, BigDecimal.ONE);
|
||||
Stretch result = Stretch.create(BigDecimal.ONE, BigDecimal.ONE);
|
||||
result.readOnly(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Stretch getFirstStretch() {
|
||||
Stretch result = Stretch.create(BigDecimal.ZERO, BigDecimal.ZERO);
|
||||
result.readOnly(true);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -308,7 +316,8 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
|
||||
@AssertTrue(message = "At least one stretch is needed")
|
||||
public boolean checkNoEmpty() {
|
||||
return !getStretchesPlusConsolidated().isEmpty();
|
||||
// first 0%-0% and last 100%-100% stretches are added automatically
|
||||
return getStretchesPlusConsolidated().size() > 2;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "Some stretch has lower or equal values than the "
|
||||
|
|
@ -323,9 +332,6 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
Stretch previous = iterator.next();
|
||||
while (iterator.hasNext()) {
|
||||
Stretch current = iterator.next();
|
||||
if (current.getDate().compareTo(previous.getDate()) <= 0) {
|
||||
return false;
|
||||
}
|
||||
if (current.getLengthPercentage().compareTo(
|
||||
previous.getLengthPercentage()) <= 0) {
|
||||
return false;
|
||||
|
|
@ -345,7 +351,8 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
if (consolidatedStretch != null) {
|
||||
result.add(consolidatedStretch);
|
||||
}
|
||||
return Collections.unmodifiableList(Stretch.sortByDate(result));
|
||||
return Collections.unmodifiableList(Stretch
|
||||
.sortByLengthPercentage(result));
|
||||
}
|
||||
|
||||
@AssertTrue(message = "Last stretch should have one hundred percent for "
|
||||
|
|
@ -374,16 +381,11 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
if (resourceAllocation.getFirstNonConsolidatedDate() == null) {
|
||||
return;
|
||||
}
|
||||
updateStretchesDates(resourceAllocation);
|
||||
taskEndDate = getTaskEndDate(resourceAllocation);
|
||||
this.resourceAllocation = resourceAllocation;
|
||||
getDesiredType().applyTo(resourceAllocation, this);
|
||||
type = getDesiredType();
|
||||
}
|
||||
|
||||
private LocalDate getTaskEndDate(ResourceAllocation<?> resourceAllocation) {
|
||||
return resourceAllocation.getTask().getEndAsLocalDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
if (StretchesFunctionTypeEnum.INTERPOLATED.equals(type)) {
|
||||
|
|
@ -399,7 +401,7 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
checkStretchesSumOneHundredPercent();
|
||||
return intervalsFor(stretches);
|
||||
return intervalsFor(resourceAllocation, stretches);
|
||||
}
|
||||
|
||||
private List<Stretch> stretchesFor(StretchesFunctionTypeEnum type) {
|
||||
|
|
@ -428,8 +430,8 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
}
|
||||
|
||||
public boolean checkFirstIntervalIsPosteriorToDate(LocalDate date) {
|
||||
List<Interval> intervals = StretchesFunction
|
||||
.intervalsFor(getStretchesPlusConsolidated());
|
||||
List<Interval> intervals = StretchesFunction.intervalsFor(
|
||||
resourceAllocation, getStretchesPlusConsolidated());
|
||||
if (intervals.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -449,31 +451,8 @@ public class StretchesFunction extends AssignmentFunction {
|
|||
return consolidatedStretch;
|
||||
}
|
||||
|
||||
public void setTaskEndDate(LocalDate taskEndDate) {
|
||||
this.taskEndDate = taskEndDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Stretch} is storing date in an attribute. When a task is moved
|
||||
* these dates have to be updated.
|
||||
*
|
||||
* FIXME: Maybe in the future we could remove these dates as they could be
|
||||
* calculated from task information.
|
||||
*/
|
||||
private void updateStretchesDates(ResourceAllocation<?> resourceAllocation) {
|
||||
Task task = resourceAllocation.getTask();
|
||||
|
||||
long startDate = task.getStartDate().getTime();
|
||||
long endDate = task.getEndDate().getTime();
|
||||
|
||||
for (Stretch stretch : stretches) {
|
||||
// startDate + (percentage * (endDate - startDate))
|
||||
long stretchDate = startDate
|
||||
+ stretch.getLengthPercentage()
|
||||
.multiply(new BigDecimal(endDate - startDate))
|
||||
.longValue();
|
||||
stretch.setDate(new LocalDate(stretchDate));
|
||||
}
|
||||
public void setResourceAllocation(ResourceAllocation<?> resourceAllocation) {
|
||||
this.resourceAllocation = resourceAllocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -296,4 +296,8 @@
|
|||
columnDataType="BIGINT" />
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="drop-column-date-in-stretches-table" author="mrego">
|
||||
<dropColumn tableName="stretches" columnName="date" />
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
|
|
|
|||
|
|
@ -312,8 +312,6 @@
|
|||
<list-index column="stretch_position" />
|
||||
|
||||
<composite-element class="Stretch">
|
||||
<property name="date" not-null="true"
|
||||
type="org.joda.time.contrib.hibernate.PersistentLocalDate" />
|
||||
<property name="lengthPercentage" not-null="true" column="length_percentage" />
|
||||
<property name="amountWorkPercentage" not-null="true" column="amount_work_percentage" />
|
||||
</composite-element>
|
||||
|
|
|
|||
|
|
@ -21,16 +21,22 @@
|
|||
|
||||
package org.navalplanner.business.test.planner.entities;
|
||||
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.classextension.EasyMock.createNiceMock;
|
||||
import static org.easymock.classextension.EasyMock.replay;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.junit.Test;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.Stretch;
|
||||
import org.navalplanner.business.planner.entities.StretchesFunction;
|
||||
import org.navalplanner.business.planner.entities.StretchesFunction.Interval;
|
||||
|
|
@ -41,10 +47,26 @@ import org.navalplanner.business.planner.entities.StretchesFunction.Interval;
|
|||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
public class StretchesFunctionTest {
|
||||
|
||||
private static final LocalDate START_DATE = new LocalDate();
|
||||
private static final LocalDate END_DATE = START_DATE.plusDays(10);
|
||||
|
||||
private StretchesFunction stretchesFunction;
|
||||
private ResourceAllocation<?> resourceAllocation;
|
||||
|
||||
private ResourceAllocation<?> givenResourceAllocation() {
|
||||
resourceAllocation = createNiceMock(ResourceAllocation.class);
|
||||
|
||||
expect(resourceAllocation.getStartDate()).andReturn(START_DATE).anyTimes();
|
||||
expect(resourceAllocation.getEndDate()).andReturn(END_DATE).anyTimes();
|
||||
|
||||
replay(resourceAllocation);
|
||||
return resourceAllocation;
|
||||
}
|
||||
|
||||
private StretchesFunction givenStretchesFunction() {
|
||||
stretchesFunction = StretchesFunction.create();
|
||||
stretchesFunction.setResourceAllocation(givenResourceAllocation());
|
||||
return stretchesFunction;
|
||||
}
|
||||
|
||||
|
|
@ -54,11 +76,9 @@ public class StretchesFunctionTest {
|
|||
return result;
|
||||
}
|
||||
|
||||
private Stretch givenStretchAsChild(LocalDate date,
|
||||
BigDecimal lengthPercentage,
|
||||
private Stretch givenStretchAsChild(BigDecimal lengthPercentage,
|
||||
BigDecimal amountWorkPercentage) {
|
||||
Stretch stretch = givenStretchAsChild();
|
||||
stretch.setDate(date);
|
||||
stretch.setLengthPercentage(lengthPercentage);
|
||||
stretch.setAmountWorkPercentage(amountWorkPercentage);
|
||||
return stretch;
|
||||
|
|
@ -66,7 +86,9 @@ public class StretchesFunctionTest {
|
|||
|
||||
private Stretch givenStretchAsChild(LocalDate date,
|
||||
BigDecimal amountWorkPercentage) {
|
||||
return givenStretchAsChild(date, BigDecimal.ZERO, amountWorkPercentage);
|
||||
return givenStretchAsChild(
|
||||
Stretch.getLengthProportionByDate(resourceAllocation, date),
|
||||
amountWorkPercentage);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -85,48 +107,27 @@ public class StretchesFunctionTest {
|
|||
@Test
|
||||
public void stretchesFunctionCheckOneHundredPercent1() {
|
||||
givenStretchesFunction();
|
||||
assertFalse(stretchesFunction.checkOneHundredPercent());
|
||||
assertTrue(stretchesFunction.checkOneHundredPercent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stretchesFunctionCheckOneHundredPercent2() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild();
|
||||
assertFalse(stretchesFunction.checkOneHundredPercent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stretchesFunctionCheckOneHundredPercent3() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild(new LocalDate(), BigDecimal.ONE, BigDecimal.ZERO);
|
||||
assertFalse(stretchesFunction.checkOneHundredPercent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stretchesFunctionCheckOneHundredPercent4() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild(new LocalDate(), BigDecimal.ZERO, BigDecimal.ONE);
|
||||
assertFalse(stretchesFunction.checkOneHundredPercent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stretchesFunctionCheckOneHundredPercent5() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild(new LocalDate(), BigDecimal.ONE, BigDecimal.ONE);
|
||||
assertTrue(stretchesFunction.checkOneHundredPercent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stretchesFunctionCheckStretchesOrder1() {
|
||||
givenStretchesFunction();
|
||||
assertFalse(stretchesFunction.checkStretchesOrder());
|
||||
assertTrue(stretchesFunction.checkStretchesOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stretchesFunctionCheckStretchesOrder2() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild();
|
||||
assertTrue(stretchesFunction.checkStretchesOrder());
|
||||
assertFalse(stretchesFunction.checkStretchesOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -141,7 +142,7 @@ public class StretchesFunctionTest {
|
|||
public void stretchesFunctionCheckStretchesOrder4() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild();
|
||||
givenStretchAsChild(new LocalDate(), BigDecimal.ONE, BigDecimal.ONE);
|
||||
givenStretchAsChild(BigDecimal.ONE, BigDecimal.ONE);
|
||||
assertFalse(stretchesFunction.checkStretchesOrder());
|
||||
}
|
||||
|
||||
|
|
@ -149,8 +150,7 @@ public class StretchesFunctionTest {
|
|||
public void stretchesFunctionCheckStretchesOrder5() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild();
|
||||
givenStretchAsChild(new LocalDate().plusMonths(1), BigDecimal.ZERO,
|
||||
BigDecimal.ZERO);
|
||||
givenStretchAsChild(BigDecimal.ZERO, BigDecimal.ZERO);
|
||||
assertFalse(stretchesFunction.checkStretchesOrder());
|
||||
}
|
||||
|
||||
|
|
@ -158,8 +158,7 @@ public class StretchesFunctionTest {
|
|||
public void stretchesFunctionCheckStretchesOrder7() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild();
|
||||
givenStretchAsChild(new LocalDate().minusMonths(1), BigDecimal.ONE,
|
||||
BigDecimal.ONE);
|
||||
givenStretchAsChild(BigDecimal.ONE, BigDecimal.ONE);
|
||||
assertFalse(stretchesFunction.checkStretchesOrder());
|
||||
}
|
||||
|
||||
|
|
@ -167,43 +166,63 @@ public class StretchesFunctionTest {
|
|||
public void stretchesFunctionCheckStretchesOrder6() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild();
|
||||
givenStretchAsChild(new LocalDate().plusMonths(1), BigDecimal.ONE,
|
||||
BigDecimal.ONE);
|
||||
assertTrue(stretchesFunction.checkStretchesOrder());
|
||||
givenStretchAsChild(BigDecimal.ONE, BigDecimal.ONE);
|
||||
assertFalse(stretchesFunction.checkStretchesOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stretchesFunctionCheckStretchesOrder8() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild(BigDecimal.ONE, BigDecimal.ONE);
|
||||
assertFalse(stretchesFunction.checkStretchesOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stretchesFunctionCheckStretchesOrder9() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild(BigDecimal.ZERO, BigDecimal.ZERO);
|
||||
assertFalse(stretchesFunction.checkStretchesOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ifNoStrechesNoIntervalDefinedByStreches() {
|
||||
givenStretchesFunction();
|
||||
assertTrue(stretchesFunction.getIntervalsDefinedByStreches().isEmpty());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void theLastStrechMustHaveAllTheLoad() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild(new LocalDate().plusMonths(1), new BigDecimal(0.6));
|
||||
stretchesFunction.getIntervalsDefinedByStreches();
|
||||
assertThat(stretchesFunction.getIntervalsDefinedByStreches().size(),
|
||||
equalTo(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void oneStrechImpliesOneInterval() {
|
||||
public void theLastStrechMustHaveAllTheLoad() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild(new LocalDate().plusMonths(1), new BigDecimal(1));
|
||||
givenStretchAsChild(new LocalDate().plusDays(1),
|
||||
BigDecimal.valueOf(0.6));
|
||||
List<Interval> intervals = stretchesFunction
|
||||
.getIntervalsDefinedByStreches();
|
||||
assertThat(intervals.size(), equalTo(3));
|
||||
assertThat(intervals.get(intervals.size() - 1).getLoadProportion(),
|
||||
equalTo(BigDecimal.valueOf(0.4).setScale(2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void oneStrechImpliesThreeInterval() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild(new LocalDate().plusDays(1), new BigDecimal(1));
|
||||
assertThat(stretchesFunction.getIntervalsDefinedByStreches().size(),
|
||||
equalTo(1));
|
||||
equalTo(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void oneStrechImpliesOneIntervalUntilDateWithLoadSpecifiedByStrech() {
|
||||
givenStretchesFunction();
|
||||
LocalDate strechDate = new LocalDate().plusMonths(1);
|
||||
BigDecimal amountOfWorkProportion = new BigDecimal(0.5).setScale(2);
|
||||
LocalDate strechDate = new LocalDate().plusDays(1);
|
||||
BigDecimal amountOfWorkProportion = BigDecimal.valueOf(0.5).setScale(2);
|
||||
givenStretchAsChild(strechDate, amountOfWorkProportion);
|
||||
givenStretchAsChild(new LocalDate().plusMonths(2), new BigDecimal(1.0));
|
||||
givenStretchAsChild(new LocalDate().plusDays(2),
|
||||
BigDecimal.valueOf(1.0));
|
||||
Interval firstInterval = stretchesFunction
|
||||
.getIntervalsDefinedByStreches().get(0);
|
||||
.getIntervalsDefinedByStreches().get(1);
|
||||
assertThat(firstInterval.getEnd(), equalTo(strechDate));
|
||||
assertTrue(firstInterval.hasNoStart());
|
||||
assertFalse(firstInterval.hasNoStart());
|
||||
assertThat(firstInterval.getLoadProportion(),
|
||||
equalTo(amountOfWorkProportion));
|
||||
}
|
||||
|
|
@ -211,24 +230,24 @@ public class StretchesFunctionTest {
|
|||
@Test
|
||||
public void theLastIntervalHasStart() {
|
||||
givenStretchesFunction();
|
||||
LocalDate strechDate = new LocalDate().plusMonths(1);
|
||||
LocalDate strechDate = new LocalDate().plusDays(1);
|
||||
givenStretchAsChild(strechDate, new BigDecimal(0.5));
|
||||
givenStretchAsChild(strechDate.plusDays(20), new BigDecimal(1));
|
||||
givenStretchAsChild(strechDate.plusDays(2), new BigDecimal(1));
|
||||
Interval lastInterval = stretchesFunction
|
||||
.getIntervalsDefinedByStreches().get(1);
|
||||
.getIntervalsDefinedByStreches().get(2);
|
||||
assertThat(lastInterval.getStart(), equalTo(strechDate));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aIntervalInTheMiddleHasStart() {
|
||||
givenStretchesFunction();
|
||||
LocalDate start = new LocalDate().plusMonths(1);
|
||||
LocalDate start = new LocalDate().plusDays(1);
|
||||
givenStretchAsChild(start, new BigDecimal(0.5));
|
||||
LocalDate middleEnd = start.plusMonths(2);
|
||||
LocalDate middleEnd = start.plusDays(2);
|
||||
givenStretchAsChild(middleEnd, new BigDecimal(0.6));
|
||||
givenStretchAsChild(middleEnd.plusDays(10), new BigDecimal(1));
|
||||
Interval middle = stretchesFunction.getIntervalsDefinedByStreches().get(
|
||||
1);
|
||||
givenStretchAsChild(middleEnd.plusDays(3), new BigDecimal(1));
|
||||
Interval middle = stretchesFunction.getIntervalsDefinedByStreches()
|
||||
.get(2);
|
||||
assertFalse(middle.hasNoStart());
|
||||
assertThat(middle.getStart(), equalTo(start));
|
||||
assertThat(middle.getEnd(), equalTo(middleEnd));
|
||||
|
|
@ -237,17 +256,17 @@ public class StretchesFunctionTest {
|
|||
@Test
|
||||
public void eachIntervalHasTheCorrespondingLoadForThatInterval() {
|
||||
givenStretchesFunction();
|
||||
LocalDate start = new LocalDate().plusMonths(1);
|
||||
LocalDate start = new LocalDate().plusDays(1);
|
||||
givenStretchAsChild(start, new BigDecimal(0.5));
|
||||
LocalDate middleEnd = start.plusMonths(2);
|
||||
LocalDate middleEnd = start.plusDays(2);
|
||||
givenStretchAsChild(middleEnd, new BigDecimal(0.8));
|
||||
givenStretchAsChild(middleEnd.plusDays(10), new BigDecimal(1));
|
||||
givenStretchAsChild(middleEnd.plusDays(3), new BigDecimal(1));
|
||||
Interval first = stretchesFunction.getIntervalsDefinedByStreches().get(
|
||||
0);
|
||||
1);
|
||||
Interval middle = stretchesFunction.getIntervalsDefinedByStreches()
|
||||
.get(1);
|
||||
Interval last = stretchesFunction.getIntervalsDefinedByStreches()
|
||||
.get(2);
|
||||
Interval last = stretchesFunction.getIntervalsDefinedByStreches()
|
||||
.get(3);
|
||||
assertThat(first.getLoadProportion(), equalTo(new BigDecimal(0.5)
|
||||
.setScale(2)));
|
||||
assertThat(middle.getLoadProportion(), equalTo(new BigDecimal(0.3)
|
||||
|
|
@ -286,4 +305,22 @@ public class StretchesFunctionTest {
|
|||
assertThat(interval.getEnd(), equalTo(end));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkCalculatedDateForStretches() {
|
||||
givenStretchesFunction();
|
||||
givenStretchAsChild(BigDecimal.valueOf(0.2), BigDecimal.valueOf(0.5));
|
||||
givenStretchAsChild(BigDecimal.valueOf(0.5), BigDecimal.valueOf(0.8));
|
||||
|
||||
List<Interval> intervals = stretchesFunction
|
||||
.getIntervalsDefinedByStreches();
|
||||
assertNull(intervals.get(0).getStart());
|
||||
assertThat(intervals.get(0).getEnd(), equalTo(START_DATE));
|
||||
assertThat(intervals.get(1).getStart(), equalTo(START_DATE));
|
||||
assertThat(intervals.get(1).getEnd(), equalTo(START_DATE.plusDays(2)));
|
||||
assertThat(intervals.get(2).getStart(), equalTo(START_DATE.plusDays(2)));
|
||||
assertThat(intervals.get(2).getEnd(), equalTo(START_DATE.plusDays(5)));
|
||||
assertThat(intervals.get(3).getStart(), equalTo(START_DATE.plusDays(5)));
|
||||
assertThat(intervals.get(3).getEnd(), equalTo(END_DATE));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import java.util.List;
|
|||
import org.joda.time.Days;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.calendars.entities.BaseCalendar;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation;
|
||||
import org.navalplanner.business.planner.entities.Stretch;
|
||||
import org.navalplanner.business.planner.entities.StretchesFunction;
|
||||
import org.navalplanner.business.planner.entities.StretchesFunction.Interval;
|
||||
|
|
@ -60,7 +61,7 @@ public abstract class GraphicForStreches implements IGraphicGenerator {
|
|||
return new SimpleXYModel();
|
||||
}
|
||||
return getAccumulatedHoursChartData(stretches,
|
||||
stretchesFunctionModel.getTaskStartDate(), new BigDecimal(
|
||||
stretchesFunctionModel.getResourceAllocation(), new BigDecimal(
|
||||
stretchesFunctionModel.getAllocationHours()));
|
||||
}
|
||||
|
||||
|
|
@ -73,17 +74,18 @@ public abstract class GraphicForStreches implements IGraphicGenerator {
|
|||
return new SimpleXYModel();
|
||||
}
|
||||
return getDedicationChart(stretches,
|
||||
stretchesFunctionModel.getTaskStartDate(),
|
||||
new BigDecimal(stretchesFunctionModel.getAllocationHours()),
|
||||
stretchesFunctionModel.getResourceAllocation(), new BigDecimal(
|
||||
stretchesFunctionModel.getAllocationHours()),
|
||||
stretchesFunctionModel.getTaskCalendar());
|
||||
}
|
||||
|
||||
protected abstract XYModel getDedicationChart(List<Stretch> stretches,
|
||||
LocalDate startDate, BigDecimal totalHours,
|
||||
ResourceAllocation<?> allocation, BigDecimal totalHours,
|
||||
BaseCalendar taskCalendar);
|
||||
|
||||
protected abstract XYModel getAccumulatedHoursChartData(
|
||||
List<Stretch> stretches, LocalDate startDate, BigDecimal taskHours);
|
||||
List<Stretch> stretches, ResourceAllocation<?> allocation,
|
||||
BigDecimal taskHours);
|
||||
|
||||
private static class ForDefaultStreches extends GraphicForStreches {
|
||||
|
||||
|
|
@ -94,19 +96,19 @@ public abstract class GraphicForStreches implements IGraphicGenerator {
|
|||
|
||||
@Override
|
||||
public XYModel getAccumulatedHoursChartData(List<Stretch> stretches,
|
||||
LocalDate startDate, BigDecimal taskHours) {
|
||||
ResourceAllocation<?> allocation, BigDecimal taskHours) {
|
||||
XYModel xymodel = new SimpleXYModel();
|
||||
|
||||
String title = "percentage";
|
||||
|
||||
xymodel.addValue(title, startDate.toDateTimeAtStartOfDay()
|
||||
.getMillis(), 0);
|
||||
xymodel.addValue(title, allocation.getStartDate()
|
||||
.toDateTimeAtStartOfDay().getMillis(), 0);
|
||||
|
||||
for (Stretch stretch : stretches) {
|
||||
BigDecimal amountWork = stretch.getAmountWorkPercentage()
|
||||
.multiply(taskHours);
|
||||
|
||||
xymodel.addValue(title, stretch.getDate()
|
||||
xymodel.addValue(title, stretch.getDateIn(allocation)
|
||||
.toDateTimeAtStartOfDay().getMillis(), amountWork);
|
||||
}
|
||||
|
||||
|
|
@ -114,12 +116,12 @@ public abstract class GraphicForStreches implements IGraphicGenerator {
|
|||
}
|
||||
|
||||
protected XYModel getDedicationChart(List<Stretch> stretches,
|
||||
LocalDate startDate, BigDecimal taskHours,
|
||||
ResourceAllocation<?> allocation, BigDecimal taskHours,
|
||||
BaseCalendar calendar){
|
||||
XYModel xymodel = new SimpleXYModel();
|
||||
String title = "hours";
|
||||
|
||||
LocalDate previousDate = startDate;
|
||||
LocalDate previousDate = allocation.getStartDate();
|
||||
BigDecimal previousPercentage = BigDecimal.ZERO;
|
||||
xymodel.addValue(title, previousDate.toDateTimeAtStartOfDay()
|
||||
.getMillis(), 0);
|
||||
|
|
@ -127,12 +129,12 @@ public abstract class GraphicForStreches implements IGraphicGenerator {
|
|||
for (Stretch stretch : stretches) {
|
||||
BigDecimal amountWork = stretch.getAmountWorkPercentage()
|
||||
.subtract(previousPercentage).multiply(taskHours);
|
||||
Integer days = Days
|
||||
.daysBetween(previousDate, stretch.getDate()).getDays();
|
||||
Integer days = Days.daysBetween(previousDate,
|
||||
stretch.getDateIn(allocation)).getDays();
|
||||
|
||||
if (calendar != null) {
|
||||
days -= calendar.getNonWorkableDays(previousDate,
|
||||
stretch.getDate()).size();
|
||||
stretch.getDateIn(allocation)).size();
|
||||
}
|
||||
|
||||
BigDecimal hoursPerDay = BigDecimal.ZERO;
|
||||
|
|
@ -143,10 +145,10 @@ public abstract class GraphicForStreches implements IGraphicGenerator {
|
|||
|
||||
xymodel.addValue(title, previousDate.toDateTimeAtStartOfDay()
|
||||
.getMillis() + 1, hoursPerDay);
|
||||
xymodel.addValue(title, stretch.getDate()
|
||||
xymodel.addValue(title, stretch.getDateIn(allocation)
|
||||
.toDateTimeAtStartOfDay().getMillis(), hoursPerDay);
|
||||
|
||||
previousDate = stretch.getDate();
|
||||
previousDate = stretch.getDateIn(allocation);
|
||||
previousPercentage = stretch.getAmountWorkPercentage();
|
||||
}
|
||||
|
||||
|
|
@ -162,51 +164,53 @@ public abstract class GraphicForStreches implements IGraphicGenerator {
|
|||
|
||||
@Override
|
||||
public boolean areChartsEnabled(IStretchesFunctionModel model) {
|
||||
return canComputeChartFrom(model.getStretchesPlusConsolidated(),
|
||||
model.getTaskStartDate());
|
||||
return canComputeChartFrom(model.getResourceAllocation(),
|
||||
model.getStretchesPlusConsolidated());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XYModel getAccumulatedHoursChartData(List<Stretch> stretches,
|
||||
LocalDate startDate, BigDecimal taskHours) {
|
||||
if (!canComputeChartFrom(stretches, startDate)) {
|
||||
ResourceAllocation<?> allocation, BigDecimal taskHours) {
|
||||
if (!canComputeChartFrom(allocation, stretches)) {
|
||||
return new SimpleXYModel();
|
||||
}
|
||||
int[] hoursForEachDayUsingSplines = hoursForEachDayInterpolatedUsingSplines(
|
||||
stretches, startDate, taskHours);
|
||||
return createModelFrom(startDate,
|
||||
stretches, allocation, taskHours);
|
||||
return createModelFrom(allocation.getStartDate(),
|
||||
accumulatedFrom(hoursForEachDayUsingSplines));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XYModel getDedicationChart(List<Stretch> stretches,
|
||||
LocalDate startDate, BigDecimal totalHours,
|
||||
ResourceAllocation<?> allocation, BigDecimal totalHours,
|
||||
BaseCalendar taskCalendar) {
|
||||
if (!canComputeChartFrom(stretches, startDate)) {
|
||||
if (!canComputeChartFrom(allocation, stretches)) {
|
||||
return new SimpleXYModel();
|
||||
}
|
||||
int[] dataForChart = hoursForEachDayInterpolatedUsingSplines(
|
||||
stretches, startDate, totalHours);
|
||||
return createModelFrom(startDate, dataForChart);
|
||||
stretches, allocation, totalHours);
|
||||
return createModelFrom(allocation.getStartDate(), dataForChart);
|
||||
}
|
||||
|
||||
private boolean canComputeChartFrom(List<Stretch> stretches,
|
||||
LocalDate start) {
|
||||
return StretchesFunctionModel.areValidForInterpolation(stretches,
|
||||
start);
|
||||
private boolean canComputeChartFrom(ResourceAllocation<?> allocation,
|
||||
List<Stretch> stretches) {
|
||||
return StretchesFunctionModel.areValidForInterpolation(allocation,
|
||||
stretches);
|
||||
}
|
||||
|
||||
private int[] hoursForEachDayInterpolatedUsingSplines(
|
||||
List<Stretch> stretches, LocalDate startDate,
|
||||
List<Stretch> stretches, ResourceAllocation<?> allocation,
|
||||
BigDecimal taskHours) {
|
||||
List<Interval> intervals = StretchesFunction
|
||||
.intervalsFor(stretches);
|
||||
double[] dayPoints = Interval.getDayPointsFor(startDate, intervals);
|
||||
List<Interval> intervals = StretchesFunction.intervalsFor(
|
||||
allocation, stretches);
|
||||
double[] dayPoints = Interval.getDayPointsFor(
|
||||
allocation.getStartDate(), intervals);
|
||||
double[] hourPoints = Interval.getHoursPointsFor(taskHours
|
||||
.intValue(), intervals);
|
||||
final Stretch lastStretch = stretches.get(stretches.size() - 1);
|
||||
return StretchesFunctionTypeEnum.hoursForEachDayUsingSplines(
|
||||
dayPoints, hourPoints, startDate, lastStretch.getDate());
|
||||
dayPoints, hourPoints, allocation.getStartDate(),
|
||||
lastStretch.getDateIn(allocation));
|
||||
}
|
||||
|
||||
private int[] accumulatedFrom(int[] hoursForEachDayUsingSplines) {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ public interface IStretchesFunctionModel {
|
|||
|
||||
AssignmentFunction getStretchesFunction();
|
||||
|
||||
Date getStretchDate(Stretch stretch);
|
||||
|
||||
void setStretchDate(Stretch stretch, Date date) throws IllegalArgumentException;
|
||||
|
||||
void setStretchLengthPercentage(Stretch stretch, BigDecimal lengthPercentage)
|
||||
|
|
@ -78,6 +80,8 @@ public interface IStretchesFunctionModel {
|
|||
|
||||
BaseCalendar getTaskCalendar();
|
||||
|
||||
ResourceAllocation<?> getResourceAllocation();
|
||||
|
||||
/*
|
||||
* Final conversation steps
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ public class StretchesFunctionController extends GenericForwardComposer {
|
|||
Datebox datebox = Util.bind(tempDatebox, new Util.Getter<Date>() {
|
||||
@Override
|
||||
public Date get() {
|
||||
return stretch.getDate().toDateTimeAtStartOfDay().toDate();
|
||||
return stretchesFunctionModel.getStretchDate(stretch);
|
||||
}
|
||||
}, new Util.Setter<Date>() {
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -24,9 +24,7 @@ package org.navalplanner.web.planner.allocation.streches;
|
|||
import static org.navalplanner.web.I18nHelper._;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
|
@ -101,7 +99,7 @@ public class StretchesFunctionModel implements IStretchesFunctionModel {
|
|||
this.taskEndDate = task.getEndDate();
|
||||
|
||||
// Initialize stretchesFunction
|
||||
stretchesFunction.setTaskEndDate(task.getEndAsLocalDate());
|
||||
stretchesFunction.setResourceAllocation(resourceAllocation);
|
||||
this.originalStretchesFunction = stretchesFunction;
|
||||
this.stretchesFunction = stretchesFunction.copy();
|
||||
this.stretchesFunction.changeTypeTo(type);
|
||||
|
|
@ -150,10 +148,7 @@ public class StretchesFunctionModel implements IStretchesFunctionModel {
|
|||
* @return
|
||||
*/
|
||||
private List<Stretch> allStretches() {
|
||||
List<Stretch> result = new ArrayList<Stretch>();
|
||||
result.add(firstStretch());
|
||||
result.addAll(stretchesFunction.getStretchesPlusConsolidated());
|
||||
return result;
|
||||
return stretchesFunction.getStretchesPlusConsolidated();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -165,18 +160,6 @@ public class StretchesFunctionModel implements IStretchesFunctionModel {
|
|||
.getStretchesPlusConsolidated());
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines an initial read-only stretch with 0% hours worked and 0% progress
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Stretch firstStretch() {
|
||||
Stretch result = Stretch.create(task.getStartAsLocalDate(),
|
||||
BigDecimal.ZERO, BigDecimal.ZERO);
|
||||
result.readOnly(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void confirm() throws ValidationException {
|
||||
if (stretchesFunction != null) {
|
||||
|
|
@ -214,10 +197,11 @@ public class StretchesFunctionModel implements IStretchesFunctionModel {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean areValidForInterpolation(List<Stretch> stretches,
|
||||
LocalDate start) {
|
||||
public static boolean areValidForInterpolation(
|
||||
ResourceAllocation<?> resourceAllocation, List<Stretch> stretches) {
|
||||
return atLeastTwoStreches(stretches)
|
||||
&& theFirstIntervalIsPosteriorToFirstDay(stretches, start);
|
||||
&& theFirstIntervalIsPosteriorToFirstDay(resourceAllocation,
|
||||
stretches);
|
||||
}
|
||||
|
||||
private static boolean atLeastTwoStreches(List<Stretch> stretches) {
|
||||
|
|
@ -225,13 +209,14 @@ public class StretchesFunctionModel implements IStretchesFunctionModel {
|
|||
}
|
||||
|
||||
private static boolean theFirstIntervalIsPosteriorToFirstDay(
|
||||
List<Stretch> stretches, LocalDate start) {
|
||||
List<Interval> intervals = StretchesFunction.intervalsFor(stretches);
|
||||
ResourceAllocation<?> resourceAllocation, List<Stretch> stretches) {
|
||||
List<Interval> intervals = StretchesFunction.intervalsFor(
|
||||
resourceAllocation, stretches);
|
||||
if (intervals.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Interval first = intervals.get(0);
|
||||
return first.getEnd().compareTo(start) > 0;
|
||||
return first.getEnd().compareTo(resourceAllocation.getStartDate()) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -253,10 +238,11 @@ public class StretchesFunctionModel implements IStretchesFunctionModel {
|
|||
Stretch consolidatedStretch = stretchesFunction
|
||||
.getConsolidatedStretch();
|
||||
if (consolidatedStretch != null) {
|
||||
startDate = consolidatedStretch.getDate().plusDays(1);
|
||||
startDate = consolidatedStretch.getDateIn(resourceAllocation)
|
||||
.plusDays(1);
|
||||
amountWorkPercent = consolidatedStretch.getAmountWorkPercentage().add(BigDecimal.ONE.divide(BigDecimal.valueOf(100)));
|
||||
}
|
||||
return Stretch.create(startDate, task, amountWorkPercent);
|
||||
return Stretch.create(startDate, resourceAllocation, amountWorkPercent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -279,6 +265,12 @@ public class StretchesFunctionModel implements IStretchesFunctionModel {
|
|||
return stretchesFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getStretchDate(Stretch stretch) {
|
||||
return stretch.getDateIn(resourceAllocation).toDateTimeAtStartOfDay()
|
||||
.toDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStretchDate(Stretch stretch, Date date)
|
||||
throws IllegalArgumentException {
|
||||
|
|
@ -294,15 +286,7 @@ public class StretchesFunctionModel implements IStretchesFunctionModel {
|
|||
+ sameFormatAsDefaultZK(taskEndDate)));
|
||||
}
|
||||
|
||||
stretch.setDate(new LocalDate(date));
|
||||
|
||||
if ((date.compareTo(taskEndDate) > 0)
|
||||
|| (stretch.getAmountWorkPercentage().compareTo(BigDecimal.ONE) == 0)) {
|
||||
taskEndDate = date;
|
||||
recalculateStretchesPercentages();
|
||||
} else {
|
||||
calculatePercentage(stretch);
|
||||
}
|
||||
stretch.setDateIn(resourceAllocation, new LocalDate(date));
|
||||
}
|
||||
|
||||
private String sameFormatAsDefaultZK(Date date) {
|
||||
|
|
@ -312,40 +296,10 @@ public class StretchesFunctionModel implements IStretchesFunctionModel {
|
|||
return formatter.format(date);
|
||||
}
|
||||
|
||||
private void recalculateStretchesPercentages() {
|
||||
List<Stretch> stretches = stretchesFunction.getStretches();
|
||||
if (!stretches.isEmpty()) {
|
||||
for (Stretch stretch : stretches) {
|
||||
calculatePercentage(stretch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void calculatePercentage(Stretch stretch) {
|
||||
long stretchDate = stretch.getDate().toDateTimeAtStartOfDay().toDate()
|
||||
.getTime();
|
||||
long startDate = task.getStartDate().getTime();
|
||||
long endDate = taskEndDate.getTime();
|
||||
|
||||
// (stretchDate - startDate) / (endDate - startDate)
|
||||
BigDecimal lengthPercenage = (new BigDecimal(stretchDate - startDate)
|
||||
.setScale(2)).divide(new BigDecimal(endDate - startDate),
|
||||
RoundingMode.DOWN);
|
||||
stretch.setLengthPercentage(lengthPercenage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStretchLengthPercentage(Stretch stretch,
|
||||
BigDecimal lengthPercentage) throws IllegalArgumentException {
|
||||
stretch.setLengthPercentage(lengthPercentage);
|
||||
|
||||
long startDate = task.getStartDate().getTime();
|
||||
long endDate = taskEndDate.getTime();
|
||||
|
||||
// startDate + (percentage * (endDate - startDate))
|
||||
long stretchDate = startDate + lengthPercentage.multiply(
|
||||
new BigDecimal(endDate - startDate)).longValue();
|
||||
stretch.setDate(new LocalDate(stretchDate));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -364,4 +318,9 @@ public class StretchesFunctionModel implements IStretchesFunctionModel {
|
|||
return task.getCalendar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceAllocation<?> getResourceAllocation() {
|
||||
return resourceAllocation;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue