[Bug #932] Check there are not overlapped category assignments, and if there are mark failing criterio assignment in form
I refactored the code that does the checking in the business layer. Instead of putting it directly in a method executed by HibernateValidator I put it in a static method in the business layer. This way it can be reused easily from the view layer. The validation returns a ValidationException pointing to the object that caused the error. Its corresponding component is localized in the view and the error is shown as a WrongValidationException. FEA: ItEr73S04BugFixing
This commit is contained in:
parent
363a56126b
commit
24edef10ec
6 changed files with 115 additions and 30 deletions
|
|
@ -25,6 +25,9 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zul.Grid;
|
||||
import org.zkoss.zul.Row;
|
||||
import org.zkoss.zul.api.Rows;
|
||||
|
||||
/**
|
||||
* Utility methods to find components
|
||||
|
|
@ -56,4 +59,18 @@ public class ComponentsFinder {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static Row findRowByValue(Grid grid, Object needle) {
|
||||
Rows rows = grid.getRows();
|
||||
for (Object each : rows.getChildren()) {
|
||||
if (each instanceof Row) {
|
||||
Row row = (Row) each;
|
||||
Object value = row.getValue();
|
||||
if (needle.equals(value)) {
|
||||
return row;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,10 @@ public class ValidationException extends RuntimeException {
|
|||
return invalidValues.clone();
|
||||
}
|
||||
|
||||
public InvalidValue getInvalidValue() {
|
||||
return (invalidValues.length > 0) ? invalidValues.clone()[0] : null;
|
||||
}
|
||||
|
||||
public ValidationException(InvalidValue invalidValue) {
|
||||
super(getValidationErrorSummary(invalidValue));
|
||||
storeInvalidValues(toArray(invalidValue));
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
package org.navalplanner.business.costcategories.entities;
|
||||
|
||||
import static org.navalplanner.business.i18n.I18nHelper._;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
|
@ -29,6 +31,7 @@ import java.util.Set;
|
|||
import org.apache.commons.lang.StringUtils;
|
||||
import org.hibernate.validator.AssertFalse;
|
||||
import org.hibernate.validator.AssertTrue;
|
||||
import org.hibernate.validator.InvalidValue;
|
||||
import org.hibernate.validator.NotEmpty;
|
||||
import org.hibernate.validator.NotNull;
|
||||
import org.hibernate.validator.Valid;
|
||||
|
|
@ -37,6 +40,7 @@ import org.navalplanner.business.common.IntegrationEntity;
|
|||
import org.navalplanner.business.common.Registry;
|
||||
import org.navalplanner.business.common.entities.EntitySequence;
|
||||
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.navalplanner.business.common.exceptions.ValidationException;
|
||||
import org.navalplanner.business.costcategories.daos.ICostCategoryDAO;
|
||||
|
||||
/**
|
||||
|
|
@ -243,4 +247,50 @@ public class CostCategory extends IntegrationEntity {
|
|||
public Integer getLastHourCostSequenceCode() {
|
||||
return lastHourCostSequenceCode;
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkOverlapping(
|
||||
List<ResourcesCostCategoryAssignment> costCategoryAssignments) {
|
||||
|
||||
for (int i = 0; i < costCategoryAssignments.size(); i++) {
|
||||
LocalDate initDate = costCategoryAssignments.get(i).getInitDate();
|
||||
LocalDate endDate = costCategoryAssignments.get(i).getEndDate();
|
||||
for (int j = i + 1; j < costCategoryAssignments.size(); j++) {
|
||||
ResourcesCostCategoryAssignment costCategory = costCategoryAssignments
|
||||
.get(j);
|
||||
if (endDate == null && costCategory.getEndDate() == null) {
|
||||
throw new ValidationException(invalidValue(_("Some cost category assignments overlap in time"), costCategory));
|
||||
} else if ((endDate == null && costCategory.getEndDate()
|
||||
.compareTo(initDate) >= 0)
|
||||
|| (costCategory.getEndDate() == null && costCategory
|
||||
.getInitDate().compareTo(endDate) <= 0)) {
|
||||
throw new ValidationException(invalidValue(_("Some cost category assignments overlap in time"), costCategory));
|
||||
} else if ((endDate != null && costCategory.getEndDate() != null)
|
||||
&& ((costCategory.getEndDate().compareTo(initDate) >= 0 && // (1)
|
||||
// listElement.getEndDate()
|
||||
// inside
|
||||
// [initDate,
|
||||
// endDate]
|
||||
costCategory.getEndDate().compareTo(endDate) <= 0)
|
||||
|| (costCategory.getInitDate().compareTo(
|
||||
initDate) >= 0 && // (2)
|
||||
// listElement.getInitDate()
|
||||
// inside [initDate,
|
||||
// endDate]
|
||||
costCategory.getInitDate().compareTo(endDate) <= 0) || (costCategory
|
||||
.getInitDate().compareTo(initDate) <= 0 && // (3)
|
||||
// [listElement.getInitDate(),
|
||||
// listElement.getEndDate()]
|
||||
costCategory.getEndDate().compareTo(endDate) >= 0))) { // contains
|
||||
// [initDate,
|
||||
// endDate]
|
||||
throw new ValidationException(invalidValue(_("Some cost category assignments overlap in time"), costCategory));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static InvalidValue invalidValue(String message, ResourcesCostCategoryAssignment each) {
|
||||
return new InvalidValue(message, null, "", each, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -52,6 +52,7 @@ import org.navalplanner.business.common.Registry;
|
|||
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.navalplanner.business.common.exceptions.MultipleInstancesException;
|
||||
import org.navalplanner.business.common.exceptions.ValidationException;
|
||||
import org.navalplanner.business.costcategories.entities.CostCategory;
|
||||
import org.navalplanner.business.costcategories.entities.ResourcesCostCategoryAssignment;
|
||||
import org.navalplanner.business.planner.entities.AvailabilityCalculator;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
|
|
@ -1079,14 +1080,11 @@ public abstract class Resource extends IntegrationEntity {
|
|||
* Check if time intervals in cost assignments are correct in isolation.
|
||||
* If not, it does not make sense to check assignment overlapping.
|
||||
*/
|
||||
for (ResourcesCostCategoryAssignment i :
|
||||
getResourcesCostCategoryAssignments()) {
|
||||
|
||||
if (!(i.isInitDateSpecified() &&
|
||||
i.checkConstraintPositiveTimeInterval())) {
|
||||
for (ResourcesCostCategoryAssignment each : getResourcesCostCategoryAssignments()) {
|
||||
if (!(each.isInitDateSpecified() && each
|
||||
.checkConstraintPositiveTimeInterval())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1095,28 +1093,11 @@ public abstract class Resource extends IntegrationEntity {
|
|||
List<ResourcesCostCategoryAssignment> assignmentsList =
|
||||
new ArrayList<ResourcesCostCategoryAssignment>();
|
||||
assignmentsList.addAll(getResourcesCostCategoryAssignments());
|
||||
for(int i=0; i<assignmentsList.size(); i++) {
|
||||
LocalDate initDate = assignmentsList.get(i).getInitDate();
|
||||
LocalDate endDate = assignmentsList.get(i).getEndDate();
|
||||
for(int j=i+1; j<assignmentsList.size(); j++) {
|
||||
ResourcesCostCategoryAssignment listElement = assignmentsList.get(j);
|
||||
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 && // (1) listElement.getEndDate() inside [initDate, endDate]
|
||||
listElement.getEndDate().compareTo(endDate)<=0) ||
|
||||
(listElement.getInitDate().compareTo(initDate)>=0 && // (2) listElement.getInitDate() inside [initDate, endDate]
|
||||
listElement.getInitDate().compareTo(endDate)<=0) ||
|
||||
(listElement.getInitDate().compareTo(initDate)<=0 && // (3) [listElement.getInitDate(), listElement.getEndDate()]
|
||||
listElement.getEndDate().compareTo(endDate)>=0))) { // contains [initDate, endDate]
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
CostCategory.checkOverlapping(assignmentsList);
|
||||
} catch (ValidationException e) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.validator.InvalidValue;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.common.exceptions.ValidationException;
|
||||
import org.navalplanner.business.costcategories.entities.CostCategory;
|
||||
import org.navalplanner.business.costcategories.entities.ResourcesCostCategoryAssignment;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
|
|
@ -38,7 +40,9 @@ import org.navalplanner.web.common.MessagesForUser;
|
|||
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.Event;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
|
|
@ -318,4 +322,25 @@ public class ResourcesCostCategoryAssignmentController extends GenericForwardCom
|
|||
public void validateConstraints() {
|
||||
ConstraintChecker.isValid(self);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check there are not category assignment overlaps
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean validate() {
|
||||
List<ResourcesCostCategoryAssignment> costCategoryAssignments = resourcesCostCategoryAssignmentModel
|
||||
.getCostCategoryAssignments();
|
||||
try {
|
||||
CostCategory.checkOverlapping(costCategoryAssignments);
|
||||
} catch (ValidationException e) {
|
||||
InvalidValue invalidValue = e.getInvalidValue();
|
||||
Component comp = ComponentsFinder.findRowByValue(
|
||||
listResourcesCostCategoryAssignments,
|
||||
invalidValue.getValue());
|
||||
throw new WrongValueException(comp, invalidValue.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,11 +196,19 @@ public class WorkerCRUDController extends GenericForwardComposer implements
|
|||
|
||||
public boolean save() {
|
||||
validateConstraints();
|
||||
|
||||
// Validate 'Cost category assignment' tab is correct
|
||||
if (resourcesCostCategoryAssignmentController != null) {
|
||||
if (!resourcesCostCategoryAssignmentController.validate()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (baseCalendarEditionController != null) {
|
||||
baseCalendarEditionController.save();
|
||||
}
|
||||
if(criterionsController != null){
|
||||
if (criterionsController != null){
|
||||
if(!criterionsController.validate()){
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue