diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/orders/daos/IOrderElementDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/orders/daos/IOrderElementDAO.java index 0f97a6cb1..ddea45057 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/orders/daos/IOrderElementDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/orders/daos/IOrderElementDAO.java @@ -28,6 +28,7 @@ import org.navalplanner.business.common.daos.IIntegrationEntityDAO; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.orders.entities.Order; import org.navalplanner.business.orders.entities.OrderElement; +import org.navalplanner.business.orders.entities.OrderLineGroup; import org.navalplanner.business.templates.entities.OrderElementTemplate; import org.navalplanner.business.workreports.entities.WorkReportLine; @@ -152,6 +153,6 @@ public interface IOrderElementDAO extends IIntegrationEntityDAO { * @param order * @return */ - OrderElement findRepeatedOrderCodeInDB(Order order); + OrderElement findRepeatedOrderCodeInDB(OrderLineGroup order); } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/orders/daos/OrderElementDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/orders/daos/OrderElementDAO.java index 46794445d..0be52853d 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/orders/daos/OrderElementDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/orders/daos/OrderElementDAO.java @@ -41,6 +41,7 @@ import org.navalplanner.business.common.daos.IntegrationEntityDAO; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; import org.navalplanner.business.orders.entities.Order; import org.navalplanner.business.orders.entities.OrderElement; +import org.navalplanner.business.orders.entities.OrderLineGroup; import org.navalplanner.business.orders.entities.SchedulingDataForVersion; import org.navalplanner.business.orders.entities.TaskSource; import org.navalplanner.business.planner.daos.ITaskSourceDAO; @@ -603,7 +604,7 @@ public class OrderElementDAO extends IntegrationEntityDAO @Override @Transactional(readOnly= true, propagation = Propagation.REQUIRES_NEW) - public OrderElement findRepeatedOrderCodeInDB(Order order) { + public OrderElement findRepeatedOrderCodeInDB(OrderLineGroup order) { final Map orderElements = createMapByCode(getOrderAndAllChildren(order)); final Map orderElementsInDB = createMapByCode(getAll()); @@ -621,7 +622,7 @@ public class OrderElementDAO extends IntegrationEntityDAO return null; } - private List getOrderAndAllChildren(Order order) { + private List getOrderAndAllChildren(OrderLineGroup order) { List result = new ArrayList(); result.add(order); result.addAll(order.getAllChildren()); diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/Order.java b/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/Order.java index 9c1bbef59..c582f608d 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/Order.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/Order.java @@ -20,6 +20,8 @@ package org.navalplanner.business.orders.entities; +import static org.navalplanner.business.i18n.I18nHelper._; + import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; @@ -33,7 +35,9 @@ import org.apache.commons.lang.Validate; import org.hibernate.validator.AssertTrue; import org.hibernate.validator.NotNull; import org.navalplanner.business.calendars.entities.BaseCalendar; +import org.navalplanner.business.common.Registry; import org.navalplanner.business.common.entities.OrderSequence; +import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.externalcompanies.entities.ExternalCompany; import org.navalplanner.business.planner.entities.DayAssignment; import org.navalplanner.business.planner.entities.Task; @@ -329,16 +333,6 @@ public class Order extends OrderLineGroup { return dayAssignments; } - public List getAllOrderElements() { - List result = new ArrayList( - this - .getChildren()); - for (OrderElement orderElement : this.getChildren()) { - result.addAll(orderElement.getAllChildren()); - } - return result; - } - public Set getResources() { Set resources = new HashSet(); for (DayAssignment dayAssignment : getDayAssignments()) { @@ -391,23 +385,6 @@ public class Order extends OrderLineGroup { return lastOrderElementSequenceCode; } - public OrderElement findRepeatedOrderCode() { - Set codes = new HashSet(); - codes.add(getCode()); - - for (OrderElement each : getAllOrderElements()) { - String code = each.getCode(); - if (code != null) { - if (codes.contains(code)) { - return each; - } - codes.add(code); - } - } - - return null; - } - @Override public Order getOrder() { return this; @@ -537,4 +514,32 @@ public class Order extends OrderLineGroup { } return false; } + + public static void checkConstraintOrderUniqueCode(OrderElement orderElement) { + if (orderElement instanceof OrderLineGroup) { + checkConstraintOrderUniqueCode((OrderLineGroup) orderElement); + } + } + + public static void checkConstraintOrderUniqueCode(OrderLineGroup order) { + OrderElement repeatedOrder; + + // Check no code is repeated in this order + repeatedOrder = order.findRepeatedOrderCode(); + if (repeatedOrder != null) { + throw new ValidationException(_( + "Repeated Order code {0} in Order {1}", + repeatedOrder.getCode(), repeatedOrder.getName())); + } + + // Check no code is repeated within the DB + repeatedOrder = Registry.getOrderElementDAO() + .findRepeatedOrderCodeInDB(order); + if (repeatedOrder != null) { + throw new ValidationException(_( + "Repeated Order code {0} in Order {1}", + repeatedOrder.getCode(), repeatedOrder.getName())); + } + } + } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/OrderLineGroup.java b/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/OrderLineGroup.java index cb34579b5..2001e950a 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/OrderLineGroup.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/orders/entities/OrderLineGroup.java @@ -1013,4 +1013,30 @@ public class OrderLineGroup extends OrderElement implements return getCurrentSchedulingData().getOriginOrderVersion(); } + public OrderElement findRepeatedOrderCode() { + Set codes = new HashSet(); + codes.add(getCode()); + + for (OrderElement each : getAllOrderElements()) { + String code = each.getCode(); + if (code != null) { + if (codes.contains(code)) { + return each; + } + codes.add(code); + } + } + + return null; + } + + public List getAllOrderElements() { + List result = new ArrayList( + this.getChildren()); + for (OrderElement orderElement : this.getChildren()) { + result.addAll(orderElement.getAllChildren()); + } + return result; + } + } \ No newline at end of file diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderModel.java index f5fcc1dfb..d2440b776 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/orders/OrderModel.java @@ -510,7 +510,7 @@ public class OrderModel implements IOrderModel { } private void saveOnTransaction(boolean newOrderVersionNeeded) { - checkConstraintOrderUniqueCode(); + Order.checkConstraintOrderUniqueCode(order); checkConstraintHoursGroupUniqueCode(); reattachCriterions(); @@ -563,25 +563,6 @@ public class OrderModel implements IOrderModel { } } - private void checkConstraintOrderUniqueCode() { - OrderElement repeatedOrder; - - // Check no code is repeated in this order - repeatedOrder = order.findRepeatedOrderCode(); - if (repeatedOrder != null) { - throw new ValidationException(_( - "Repeated Order code {0} in Order {1}", - repeatedOrder.getCode(), repeatedOrder.getName())); - } - - repeatedOrder = orderElementDAO.findRepeatedOrderCodeInDB(order); - if (repeatedOrder != null) { - throw new ValidationException(_( - "Repeated Order code {0} in Order {1}", - repeatedOrder.getCode(), repeatedOrder.getName())); - } - } - private void calculateAdvancePercentageIncludingChildren(OrderElement order) { calculateAdvancePercentage(order); for (OrderElement orderElement : order.getAllChildren()) { diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/OrderLineGroupDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/OrderLineGroupDTO.java index 255225b4f..3c16ee00f 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/OrderLineGroupDTO.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/api/OrderLineGroupDTO.java @@ -21,6 +21,7 @@ package org.navalplanner.ws.common.api; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -63,4 +64,40 @@ public class OrderLineGroupDTO extends OrderElementDTO { this.children = children; } + public OrderElementDTO findRepeatedOrderCode() { + Set codes = new HashSet(); + codes.add(code); + + for (OrderElementDTO each : getAllOrderElements()) { + String code = each.code; + if (code != null) { + if (codes.contains(code)) { + return each; + } + codes.add(code); + } + } + + return null; + } + + private List getAllOrderElements() { + List result = new ArrayList(); + for (OrderElementDTO each: children) { + result.add(each); + if (isOrderLineGroupDTO(each)) { + result.addAll(toOrderLineGroupDTO(each).getAllOrderElements()); + } + } + return result; + } + + private boolean isOrderLineGroupDTO(OrderElementDTO orderElement) { + return orderElement instanceof OrderLineGroupDTO; + } + + private OrderLineGroupDTO toOrderLineGroupDTO(OrderElementDTO orderElement) { + return (OrderLineGroupDTO) orderElement; + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/OrderElementConverter.java b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/OrderElementConverter.java index f70f5b155..0825f1785 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/OrderElementConverter.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/ws/common/impl/OrderElementConverter.java @@ -244,6 +244,7 @@ public final class OrderElementConverter { public final static OrderElement toEntity(OrderVersion orderVersion, OrderElementDTO orderElementDTO, ConfigurationOrderElementConverter configuration) { + if (orderVersion == null) { Scenario current = Registry.getScenarioManager().getCurrent(); orderVersion = OrderVersion.createInitialVersion(current); @@ -441,6 +442,9 @@ public final class OrderElementConverter { addAdvanceMeasurements(orderElement, orderElementDTO); } + // Validate code must be unique + Order.checkConstraintOrderUniqueCode(orderElement); + return orderElement; } @@ -597,8 +601,21 @@ public final class OrderElementConverter { update(orderElement.getOrderElement(childDTO.code), childDTO, configuration); } else { - ((OrderLineGroup) orderElement).add(toEntity(childDTO, - configuration)); + // Check there's not other OrderElement with the same code in DB + try { + OrderElement existsByCode = Registry.getOrderElementDAO().findByCode(childDTO.code); + if (existsByCode != null) { + throw new ValidationException(_( + "Order element {0} : Duplicate code in DB" + + orderElement.getCode())); + } else { + ((OrderLineGroup) orderElement).add(toEntity(childDTO, + configuration)); + } + } catch (InstanceNotFoundException e) { + e.printStackTrace(); + } + } } diff --git a/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/orders/OrderElementServiceTest.java b/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/orders/OrderElementServiceTest.java index 57fadba85..4ef8efd2a 100644 --- a/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/orders/OrderElementServiceTest.java +++ b/navalplanner-webapp/src/test/java/org/navalplanner/web/test/ws/orders/OrderElementServiceTest.java @@ -1259,4 +1259,28 @@ public class OrderElementServiceTest { return new OrderListDTO(orderList); } + + @Test + public void testCannotExistTwoOrderElementsWithTheSameCode() { + final String code = "code1"; + + OrderLineDTO orderLineDTO = new OrderLineDTO(); + orderLineDTO.initDate = DateConverter.toXMLGregorianCalendar(new Date()); + orderLineDTO.code = code; + orderLineDTO.name = UUID.randomUUID().toString(); + + OrderDTO orderDTO = new OrderDTO(); + orderDTO.initDate = DateConverter.toXMLGregorianCalendar(new Date()); + orderDTO.code = code; + orderDTO.name = UUID.randomUUID().toString(); + orderDTO.children.add(orderLineDTO); + + OrderListDTO orderListDTO = createOrderListDTO(orderDTO); + List instanceConstraintViolationsList = orderElementService + .addOrders(orderListDTO).instanceConstraintViolationsList; + + assertTrue(instanceConstraintViolationsList.toString(), + instanceConstraintViolationsList.size() == 1); + } + }