Bug #1553, #1554: Remove unique constraint in DB for OrderElement codes

In order to allow switch tasks codes and avoid the issues changing the code
while creating a child, the unique constraint in DB for field code in
order_element table has been removed.

Instead two new constraints methods have been added:
* OrderElement.checkConstraintUniqueCode()
* Order.checkConstraintUniqueCodeInsideOrder()

FEA: ItEr77S04BugFixing
This commit is contained in:
Manuel Rego Casasnovas 2012-11-19 18:35:25 +01:00
parent e05678e946
commit a6ef3f34d2
6 changed files with 68 additions and 23 deletions

View file

@ -87,10 +87,6 @@ public interface IOrderElementDAO extends IIntegrationEntityDAO<OrderElement> {
OrderElement findUniqueByCodeAnotherTransaction(String code) OrderElement findUniqueByCodeAnotherTransaction(String code)
throws InstanceNotFoundException; throws InstanceNotFoundException;
boolean existsOtherOrderElementByCode(OrderElement orderElement);
boolean existsByCodeAnotherTransaction(OrderElement orderElement);
List<OrderElement> getAll(); List<OrderElement> getAll();
public List<OrderElement> findOrderElementsWithExternalCode(); public List<OrderElement> findOrderElementsWithExternalCode();
@ -139,4 +135,7 @@ public interface IOrderElementDAO extends IIntegrationEntityDAO<OrderElement> {
public List<OrderElement> findByLabelsAndCriteria(Set<Label> labels, public List<OrderElement> findByLabelsAndCriteria(Set<Label> labels,
Set<Criterion> criteria); Set<Criterion> criteria);
boolean existsByCodeInAnotherOrderAnotherTransaction(
OrderElement orderElement);
} }

View file

@ -43,6 +43,7 @@ import org.libreplan.business.common.daos.IntegrationEntityDAO;
import org.libreplan.business.common.exceptions.InstanceNotFoundException; import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.expensesheet.daos.IExpenseSheetLineDAO; import org.libreplan.business.expensesheet.daos.IExpenseSheetLineDAO;
import org.libreplan.business.labels.entities.Label; import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement; import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.SchedulingDataForVersion; import org.libreplan.business.orders.entities.SchedulingDataForVersion;
import org.libreplan.business.orders.entities.TaskSource; import org.libreplan.business.orders.entities.TaskSource;
@ -257,22 +258,6 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement>
return findUniqueByCode(code); return findUniqueByCode(code);
} }
@Override
public boolean existsOtherOrderElementByCode(OrderElement orderElement) {
try {
OrderElement t = findUniqueByCode(orderElement.getCode());
return t != null && t != orderElement;
} catch (InstanceNotFoundException e) {
return false;
}
}
@Override
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
public boolean existsByCodeAnotherTransaction(OrderElement orderElement) {
return existsOtherOrderElementByCode(orderElement);
}
@Override @Override
public List<OrderElement> getAll() { public List<OrderElement> getAll() {
return list(OrderElement.class); return list(OrderElement.class);
@ -493,9 +478,11 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement>
OrderElement orderElementInDB = orderElementsInDB.get(code); OrderElement orderElementInDB = orderElementsInDB.get(code);
// There's an element in the DB with the same code and it's a // There's an element in the DB with the same code and it's a
// different element // different element in a different order
if (orderElementInDB != null if (orderElementInDB != null
&& !orderElementInDB.getId().equals(orderElement.getId())) { && !orderElementInDB.getId().equals(orderElement.getId())
&& !orderElementInDB.getOrder().getId()
.equals(orderElement.getOrder().getId())) {
return orderElement; return orderElement;
} }
} }
@ -590,4 +577,30 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement>
.setParameterList("ids", orderElementsIds).list(); .setParameterList("ids", orderElementsIds).list();
} }
@Override
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
public boolean existsByCodeInAnotherOrderAnotherTransaction(
OrderElement orderElement) {
return existsByCodeInAnotherOrder(orderElement);
}
private boolean existsByCodeInAnotherOrder(OrderElement orderElement) {
try {
OrderElement found = findUniqueByCode(orderElement.getCode());
return !areInTheSameOrder(orderElement, found);
} catch (InstanceNotFoundException e) {
return false;
}
}
private boolean areInTheSameOrder(OrderElement orderElement1,
OrderElement orderElement2) {
Order order1 = orderElement1.getOrder();
Order order2 = orderElement2.getOrder();
if (order1.getId() == null || order2.getId() == null) {
return false;
}
return order1.getId().equals(order2.getId());
}
} }

View file

@ -675,4 +675,20 @@ public class Order extends OrderLineGroup implements Comparable {
return true; return true;
} }
@AssertTrue(message = "task code is repeated inside the project")
public boolean checkConstraintUniqueCodeInsideOrder() {
List<String> codes = new ArrayList<String>();
codes.add(getCode());
for (OrderElement child : getAllChildren()) {
String childCode = child.getCode();
if (codes.contains(childCode)) {
return false;
}
codes.add(childCode);
}
return true;
}
} }

View file

@ -34,6 +34,7 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.hibernate.validator.AssertTrue; import org.hibernate.validator.AssertTrue;
import org.hibernate.validator.InvalidValue; import org.hibernate.validator.InvalidValue;
@ -1167,6 +1168,16 @@ public abstract class OrderElement extends IntegrationEntity implements
return true; return true;
} }
@AssertTrue(message = "code is already used in another project")
public boolean checkConstraintCodeRepeatedInAnotherOrder() {
if (StringUtils.isBlank(getCode())) {
return true;
}
return !Registry.getOrderElementDAO()
.existsByCodeInAnotherOrderAnotherTransaction(this);
}
@AssertTrue(message = "a label can not be assigned twice in the same branch") @AssertTrue(message = "a label can not be assigned twice in the same branch")
public boolean checkConstraintLabelNotRepeatedInTheSameBranch() { public boolean checkConstraintLabelNotRepeatedInTheSameBranch() {
return checkConstraintLabelNotRepeatedInTheSameBranch(new HashSet<Label>()); return checkConstraintLabelNotRepeatedInTheSameBranch(new HashSet<Label>());

View file

@ -187,4 +187,10 @@
</update> </update>
</changeSet> </changeSet>
<changeSet id="drop-unique-constraint-code-in-order_element" author="mrego">
<comment>Drop unique constraint for code in order_element table</comment>
<dropUniqueConstraint tableName="order_element"
constraintName="order_element_code_key" />
</changeSet>
</databaseChangeLog> </databaseChangeLog>

View file

@ -11,7 +11,7 @@
<component name="infoComponent" class="org.libreplan.business.orders.entities.InfoComponentWithCode"> <component name="infoComponent" class="org.libreplan.business.orders.entities.InfoComponentWithCode">
<property name="name" access="field" /> <property name="name" access="field" />
<property name="description" access="field" type="text" /> <property name="description" access="field" type="text" />
<property name="code" access="field" unique="true" /> <property name="code" access="field" />
</component> </component>
<property name="initDate" access="field" column="init_date" /> <property name="initDate" access="field" column="init_date" />
<property name="deadline" access="field" /> <property name="deadline" access="field" />