[Bug #931] Added explicit check hour cost in 'Cost category' don't overlap for the same type of hours
FEA: ItEr74S04BugFixing
This commit is contained in:
parent
145b6b70f9
commit
e281fab21b
5 changed files with 100 additions and 40 deletions
|
|
@ -28,6 +28,7 @@ import org.navalplanner.business.common.BaseEntity;
|
|||
/**
|
||||
* Encapsulates some validation failure <br />
|
||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
* @author Diego Pino García <dpino@igalia.com>
|
||||
*/
|
||||
public class ValidationException extends RuntimeException {
|
||||
|
||||
|
|
@ -63,6 +64,12 @@ public class ValidationException extends RuntimeException {
|
|||
return bean.toString();
|
||||
}
|
||||
|
||||
public static ValidationException invalidValue(String message, Object value) {
|
||||
InvalidValue invalidValue = new InvalidValue(message, null, "", value,
|
||||
null);
|
||||
return new ValidationException(invalidValue);
|
||||
}
|
||||
|
||||
private InvalidValue[] invalidValues;
|
||||
|
||||
public InvalidValue[] getInvalidValues() {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import org.navalplanner.business.costcategories.daos.ICostCategoryDAO;
|
|||
|
||||
/**
|
||||
* @author Jacobo Aragunde Perez <jaragunde@igalia.com>
|
||||
* @author Diego Pino García <dpino@igalia.com>
|
||||
*/
|
||||
public class CostCategory extends IntegrationEntity {
|
||||
|
||||
|
|
@ -91,6 +92,58 @@ public class CostCategory extends IntegrationEntity {
|
|||
return (CostCategory) create(new CostCategory(name));
|
||||
}
|
||||
|
||||
public static void validateHourCostsOverlap(Set<HourCost> hoursCosts)
|
||||
throws ValidationException {
|
||||
List<HourCost> listHourCosts = new ArrayList<HourCost>(hoursCosts);
|
||||
for (int i = 0; i < listHourCosts.size(); i++) {
|
||||
LocalDate initDate = listHourCosts.get(i).getInitDate();
|
||||
LocalDate endDate = listHourCosts.get(i).getEndDate();
|
||||
for (int j = i + 1; j < listHourCosts.size(); j++) {
|
||||
HourCost listElement = listHourCosts.get(j);
|
||||
if (listElement.getType() == null
|
||||
|| listHourCosts.get(i).getType() == null) {
|
||||
// this is not exactly an overlapping but a
|
||||
// problem with missing compulsory fields
|
||||
throw ValidationException.invalidValue(
|
||||
_("Hours cost type cannot be empty or null"),
|
||||
listElement);
|
||||
}
|
||||
if (listElement.getType().getId()
|
||||
.equals(listHourCosts.get(i).getType().getId())) {
|
||||
if (initDate == null || listElement.getInitDate() == null) {
|
||||
// this is not exactly an overlapping but a
|
||||
// problem with missing compulsory fields
|
||||
throw ValidationException.invalidValue(
|
||||
_("Init date cannot be empty or null"),
|
||||
listElement);
|
||||
}
|
||||
if (endDate == null && listElement.getEndDate() == null) {
|
||||
throw ValidationException.invalidValue(
|
||||
_("End date cannot be empty or null"),
|
||||
listElement);
|
||||
} else if ((endDate == null && listElement.getEndDate()
|
||||
.compareTo(initDate) >= 0)
|
||||
|| (listElement.getEndDate() == null && listElement
|
||||
.getInitDate().compareTo(endDate) <= 0)) {
|
||||
throw ValidationException
|
||||
.invalidValue(
|
||||
_("Two hour costs with the same type overlap in time"),
|
||||
listElement);
|
||||
} else if ((endDate != null && listElement.getEndDate() != null)
|
||||
&& ((listElement.getEndDate().compareTo(initDate) >= 0 && listElement
|
||||
.getEndDate().compareTo(endDate) <= 0) || (listElement
|
||||
.getInitDate().compareTo(initDate) >= 0 && listElement
|
||||
.getInitDate().compareTo(endDate) <= 0))) {
|
||||
throw ValidationException
|
||||
.invalidValue(
|
||||
_("Two hour costs with the same type overlap in time"),
|
||||
listElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected CostCategory(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
|
@ -173,42 +226,12 @@ public class CostCategory extends IntegrationEntity {
|
|||
|
||||
@AssertFalse(message="Two hour costs with the same type overlap in time")
|
||||
public boolean checkHourCostsOverlap() {
|
||||
List<HourCost> listHourCosts = new ArrayList<HourCost>();
|
||||
listHourCosts.addAll(getHourCosts());
|
||||
for(int i=0; i<listHourCosts.size(); i++) {
|
||||
LocalDate initDate = listHourCosts.get(i).getInitDate();
|
||||
LocalDate endDate = listHourCosts.get(i).getEndDate();
|
||||
for(int j=i+1; j<listHourCosts.size(); j++) {
|
||||
HourCost listElement = listHourCosts.get(j);
|
||||
if (listElement.getType() == null || listHourCosts.get(i).getType() == null) {
|
||||
//this is not exactly an overlapping but a
|
||||
//problem with missing compulsory fields
|
||||
return true;
|
||||
}
|
||||
if(listElement.getType().getId().equals(listHourCosts.get(i).getType().getId())) {
|
||||
if (initDate == null || listElement.getInitDate() == null) {
|
||||
//this is not exactly an overlapping but a
|
||||
//problem with missing compulsory fields
|
||||
return true;
|
||||
}
|
||||
if (endDate == null && listElement.getEndDate() == null) {
|
||||
return true;
|
||||
}
|
||||
else if((endDate == null && listElement.getEndDate().compareTo(initDate)>=0) ||
|
||||
(listElement.getEndDate() == null && listElement.getInitDate().compareTo(endDate)<=0)) {
|
||||
return true;
|
||||
}
|
||||
else if((endDate != null && listElement.getEndDate() != null) &&
|
||||
((listElement.getEndDate().compareTo(initDate)>=0 &&
|
||||
listElement.getEndDate().compareTo(endDate)<=0) ||
|
||||
(listElement.getInitDate().compareTo(initDate)>=0 &&
|
||||
listElement.getInitDate().compareTo(endDate)<=0))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
validateHourCostsOverlap(getHourCosts());
|
||||
return false;
|
||||
} catch (ValidationException e) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.validator.InvalidValue;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.navalplanner.business.common.exceptions.ValidationException;
|
||||
|
|
@ -45,7 +46,9 @@ import org.navalplanner.web.common.OnlyOneVisible;
|
|||
import org.navalplanner.web.common.Util;
|
||||
import org.navalplanner.web.common.components.Autocomplete;
|
||||
import org.navalplanner.web.workreports.WorkReportCRUDController;
|
||||
import org.zkoss.ganttz.util.ComponentsFinder;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.WrongValueException;
|
||||
import org.zkoss.zk.ui.event.CheckEvent;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
|
|
@ -68,6 +71,7 @@ import org.zkoss.zul.api.Window;
|
|||
* Controller for CRUD actions over a {@link CostCategory}
|
||||
*
|
||||
* @author Jacobo Aragunde Perez <jaragunde@igalia.com>
|
||||
* @author Diego Pino García <dpino@igalia.com>
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class CostCategoryCRUDController extends GenericForwardComposer
|
||||
|
|
@ -164,20 +168,36 @@ public class CostCategoryCRUDController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
public boolean save() {
|
||||
if(!ConstraintChecker.isValid(createWindow)) {
|
||||
if (!ConstraintChecker.isValid(createWindow)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
costCategoryModel.validateHourCostsOverlap();
|
||||
} catch (ValidationException e) {
|
||||
showHoursCostsOverlapValidationException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
costCategoryModel.confirmSave();
|
||||
messagesForUser.showMessage(Level.INFO,
|
||||
_("Cost category saved"));
|
||||
messagesForUser.showMessage(Level.INFO, _("Cost category saved"));
|
||||
return true;
|
||||
} catch (ValidationException e) {
|
||||
e.getInvalidValue().getValue();
|
||||
messagesForUser.showInvalidValues(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void showHoursCostsOverlapValidationException(ValidationException e) {
|
||||
InvalidValue invalid = e.getInvalidValue();
|
||||
Row comp = ComponentsFinder.findRowByValue(listHourCosts,
|
||||
invalid.getValue());
|
||||
if (comp != null) {
|
||||
throw new WrongValueException(comp, invalid.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public CostCategory getCostCategory() {
|
||||
return costCategoryModel.getCostCategory();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
* Model for UI operations related to {@link CostCategory}
|
||||
*
|
||||
* @author Jacobo Aragunde Perez <jaragunde@igalia.com>
|
||||
* @author Diego Pino García <dpino@igalia.com>
|
||||
*/
|
||||
@Service
|
||||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||
|
|
@ -181,4 +182,9 @@ public class CostCategoryModel extends IntegrationEntityModel implements
|
|||
public IntegrationEntity getCurrentEntity() {
|
||||
return this.costCategory;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateHourCostsOverlap() throws ValidationException {
|
||||
CostCategory.validateHourCostsOverlap(getCostCategory().getHourCosts());
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,7 @@ import org.navalplanner.web.common.IIntegrationEntityModel;
|
|||
* Model for UI operations related to {@link CostCategory}
|
||||
*
|
||||
* @author Jacobo Aragunde Perez <jaragunde@igalia.com>
|
||||
* @author Diego Pino García <dpino@igalia.com>
|
||||
*/
|
||||
public interface ICostCategoryModel extends IIntegrationEntityModel {
|
||||
|
||||
|
|
@ -62,4 +63,7 @@ public interface ICostCategoryModel extends IIntegrationEntityModel {
|
|||
throws InstanceNotFoundException;
|
||||
|
||||
boolean canRemoveCostCategory(CostCategory category);
|
||||
}
|
||||
|
||||
void validateHourCostsOverlap() throws ValidationException;
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue