/* * This file is part of LibrePlan * * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Desenvolvemento Tecnolóxico de Galicia * Copyright (C) 2010-2011 Igalia, S.L. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.libreplan.business.advance.entities; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import javax.validation.constraints.AssertTrue; import javax.validation.constraints.NotNull; import javax.validation.Valid; import org.joda.time.LocalDate; import org.libreplan.business.orders.entities.OrderElement; import org.libreplan.business.planner.entities.consolidations.NonCalculatedConsolidation; /** * Represents an {@link AdvanceAssignment} that is own of this {@link OrderElement}. * * @author Manuel Rego Casasnovas <mrego@igalia.com> */ public class DirectAdvanceAssignment extends AdvanceAssignment { public static DirectAdvanceAssignment create() { DirectAdvanceAssignment directAdvanceAssignment = new DirectAdvanceAssignment(); directAdvanceAssignment.setNewObject(true); return directAdvanceAssignment; } public static DirectAdvanceAssignment create(boolean reportGlobalAdvance, BigDecimal maxValue) { DirectAdvanceAssignment advanceAssignment = new DirectAdvanceAssignment( reportGlobalAdvance, maxValue); advanceAssignment.setNewObject(true); return advanceAssignment; } private BigDecimal maxValue; @Valid private SortedSet<AdvanceMeasurement> advanceMeasurements = new TreeSet<>(new AdvanceMeasurementComparator()); @Valid private Set<NonCalculatedConsolidation> nonCalculatedConsolidations = new HashSet<NonCalculatedConsolidation>(); private boolean fake = false; public DirectAdvanceAssignment() { super(); } private DirectAdvanceAssignment(boolean reportGlobalAdvance, BigDecimal maxValue) { super(reportGlobalAdvance); this.maxValue = maxValue; this.maxValue.setScale(2, BigDecimal.ROUND_HALF_UP); } @NotNull(message = "maximum value not specified") public BigDecimal getMaxValue() { return this.maxValue; } public void setMaxValue(BigDecimal maxValue) { this.maxValue = maxValue; if (maxValue != null) { this.maxValue.setScale(2); } } public SortedSet<AdvanceMeasurement> getAdvanceMeasurements() { return Collections.unmodifiableSortedSet(this.advanceMeasurements); } public void setAdvanceMeasurements( SortedSet<AdvanceMeasurement> advanceMeasurements) { this.advanceMeasurements.clear(); this.advanceMeasurements.addAll(advanceMeasurements); } public AdvanceMeasurement getLastAdvanceMeasurement() { if (advanceMeasurements.isEmpty()) { return null; } return advanceMeasurements.first(); } public AdvanceMeasurement getAdvanceMeasurementAtDateOrPrevious(LocalDate date) { if (advanceMeasurements.isEmpty()) { return null; } for (AdvanceMeasurement advanceMeasurement : advanceMeasurements) { if (advanceMeasurement.getDate().compareTo(date) <= 0) { return advanceMeasurement; } } return null; } public BigDecimal getAdvancePercentage() { return getAdvancePercentage(null); } public BigDecimal getAdvancePercentage(LocalDate date) { if (maxValue.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } AdvanceMeasurement advanceMeasurement = (date != null) ? getAdvanceMeasurementAtDateOrPrevious(date) : getLastAdvanceMeasurement(); if (advanceMeasurement == null || advanceMeasurement.getValue() == null) { return BigDecimal.ZERO; } return advanceMeasurement.getValue().divide(maxValue, 4, RoundingMode.DOWN); } public boolean addAdvanceMeasurements(AdvanceMeasurement advanceMeasurement) { boolean result = this.advanceMeasurements.add(advanceMeasurement); if (result) { advanceMeasurement.setAdvanceAssignment(this); if (getOrderElement() != null) { getOrderElement() .markAsDirtyLastAdvanceMeasurementForSpreading(); } } return result; } public void removeAdvanceMeasurement(AdvanceMeasurement advanceMeasurement) { this.advanceMeasurements.remove(advanceMeasurement); advanceMeasurement.setAdvanceAssignment(null); getOrderElement().markAsDirtyLastAdvanceMeasurementForSpreading(); } public void removeAdvanceMeasurements( Set<AdvanceMeasurement> advanceMeasurements) { for (AdvanceMeasurement each: advanceMeasurements) { each.setAdvanceAssignment(null); } this.advanceMeasurements.removeAll(advanceMeasurements); getOrderElement().markAsDirtyLastAdvanceMeasurementForSpreading(); } public void clearAdvanceMeasurements() { this.advanceMeasurements.clear(); if (getOrderElement() != null) { getOrderElement().markAsDirtyLastAdvanceMeasurementForSpreading(); } } public AdvanceMeasurement getAdvanceMeasurementAtExactDate(LocalDate date) { if (advanceMeasurements.isEmpty()) { return null; } for (AdvanceMeasurement advanceMeasurement : advanceMeasurements) { if (advanceMeasurement.getDate().equals(date)) { return advanceMeasurement; } } return null; } @AssertTrue(message = "Progress measurements must have a value lower than their following progress measurements.") public boolean isValidAdvanceMeasurementsConstraint() { if (advanceMeasurements.isEmpty()) { return true; } Iterator<AdvanceMeasurement> iterator = advanceMeasurements.iterator(); AdvanceMeasurement currentAdvance = iterator.next(); while (iterator.hasNext()) { AdvanceMeasurement nextAdvance = iterator.next(); if ((currentAdvance.getValue() != null) && (nextAdvance.getValue() != null) && (currentAdvance.getDate() != null) && (nextAdvance.getDate() != null) && (currentAdvance.getValue().compareTo( nextAdvance.getValue()) < 0)) { return false; } currentAdvance = nextAdvance; } return true; } public void setFake(boolean fake) { this.fake = fake; } public boolean isFake() { return fake; } @AssertTrue(message = "maxixum value of percentage progress type must be 100") public boolean isMaxValueMustBe100ForPercentageConstraint() { AdvanceType advanceType = getAdvanceType(); if ((advanceType != null) && (advanceType.getPercentage())) { if (maxValue.compareTo(new BigDecimal(100)) != 0) { return false; } } return true; } @AssertTrue(message = "maximum value must be greater than zero") public boolean isMaxValueMustBeGreaterThanZeroConstraint() { return maxValue.compareTo(BigDecimal.ZERO) > 0; } public void setNonCalculatedConsolidation( Set<NonCalculatedConsolidation> nonCalculatedConsolidation) { this.nonCalculatedConsolidations = nonCalculatedConsolidation; } public Set<NonCalculatedConsolidation> getNonCalculatedConsolidation() { return nonCalculatedConsolidations; } public static DirectAdvanceAssignment copy( DirectAdvanceAssignment origin, OrderElement orderElement) { DirectAdvanceAssignment copy = DirectAdvanceAssignment.create(origin .getReportGlobalAdvance(), origin.getMaxValue()); copy.setAdvanceType(origin.getAdvanceType()); copy.setAdvanceMeasurements(origin.getAdvanceMeasurements()); copy.setOrderElement(orderElement); return copy; } public boolean hasAnyConsolidationValue() { return !nonCalculatedConsolidations.isEmpty(); } public void resetAdvanceMeasurements(AdvanceMeasurement advanceMeasurement) { advanceMeasurements.clear(); addAdvanceMeasurements(advanceMeasurement); } }