diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/ValidationException.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/ValidationException.java index ba470e723..b5e1b1671 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/ValidationException.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/ValidationException.java @@ -28,6 +28,7 @@ import org.navalplanner.business.common.BaseEntity; /** * Encapsulates some validation failure
* @author Óscar González Fernández + * @author Diego Pino García */ 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() { diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/CostCategory.java b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/CostCategory.java index 3089e1c52..8f18bab12 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/CostCategory.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/CostCategory.java @@ -45,6 +45,7 @@ import org.navalplanner.business.costcategories.daos.ICostCategoryDAO; /** * @author Jacobo Aragunde Perez + * @author Diego Pino García */ 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 hoursCosts) + throws ValidationException { + List listHourCosts = new ArrayList(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 listHourCosts = new ArrayList(); - listHourCosts.addAll(getHourCosts()); - for(int i=0; i=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 diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryCRUDController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryCRUDController.java index bc9040cd9..cbf0a051a 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryCRUDController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryCRUDController.java @@ -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 + * @author Diego Pino García */ @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(); } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryModel.java index 657677a32..57150a9a7 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryModel.java @@ -47,6 +47,7 @@ import org.springframework.transaction.annotation.Transactional; * Model for UI operations related to {@link CostCategory} * * @author Jacobo Aragunde Perez + * @author Diego Pino García */ @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()); + } +} \ No newline at end of file diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/ICostCategoryModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/ICostCategoryModel.java index d35b60db5..cacef385d 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/ICostCategoryModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/ICostCategoryModel.java @@ -34,6 +34,7 @@ import org.navalplanner.web.common.IIntegrationEntityModel; * Model for UI operations related to {@link CostCategory} * * @author Jacobo Aragunde Perez + * @author Diego Pino García */ public interface ICostCategoryModel extends IIntegrationEntityModel { @@ -62,4 +63,7 @@ public interface ICostCategoryModel extends IIntegrationEntityModel { throws InstanceNotFoundException; boolean canRemoveCostCategory(CostCategory category); -} + + void validateHourCostsOverlap() throws ValidationException; + +} \ No newline at end of file