ItEr42S12CUImportacionRecursosProductivosItEr41S15: Calendar-specification support for resources being imported.
Resources to be imported can now specify a calendar name. Each resource will have a derived calendar of the specified one. Furthermore, test cases have been implemented for the most common cases (calendar not specified -> use default calendar, calendar specified, and non-existent calendar).
This commit is contained in:
parent
1a12344ce5
commit
3f67d4aad5
7 changed files with 246 additions and 16 deletions
|
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.navalplanner.business.calendars.entities.BaseCalendar;
|
||||
|
|
@ -39,6 +40,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
* DAO for {@link BaseCalendar}
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
* @author Fernando Bellas Permuy <fbellas@udc.es>
|
||||
*/
|
||||
@Repository
|
||||
@Scope(BeanDefinition.SCOPE_SINGLETON)
|
||||
|
|
@ -88,8 +90,13 @@ public class BaseCalendarDAO extends GenericDAOHibernate<BaseCalendar, Long>
|
|||
|
||||
@Override
|
||||
public List<BaseCalendar> findByName(String name) {
|
||||
|
||||
if (StringUtils.isBlank(name)) {
|
||||
return new ArrayList<BaseCalendar>();
|
||||
}
|
||||
|
||||
Criteria c = getSession().createCriteria(BaseCalendar.class);
|
||||
c.add(Restrictions.eq("name", name));
|
||||
c.add(Restrictions.eq("name", name).ignoreCase());
|
||||
|
||||
List<BaseCalendar> list = (List<BaseCalendar>) c.list();
|
||||
removeResourceCalendarInstances(list);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* This file is part of ###PROJECT_NAME###
|
||||
*
|
||||
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
|
||||
* Desenvolvemento Tecnolóxico de Galicia
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.navalplanner.business.common.exceptions;
|
||||
|
||||
/**
|
||||
* An exception for specifying that there exist multiple persistent instances
|
||||
* with the same "logic" identifier (e.g. a name).
|
||||
*
|
||||
* @author Fernando Bellas Permuy <fbellas@udc.es>
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MultipleInstancesException extends InstanceException {
|
||||
|
||||
public MultipleInstancesException(String logicId, String className) {
|
||||
super("Multiple instances with the same logic identifier",
|
||||
logicId, className);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ import java.util.ListIterator;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.hibernate.validator.AssertFalse;
|
||||
import org.hibernate.validator.AssertTrue;
|
||||
|
|
@ -38,10 +39,14 @@ import org.hibernate.validator.InvalidValue;
|
|||
import org.hibernate.validator.Valid;
|
||||
import org.joda.time.Days;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.calendars.entities.BaseCalendar;
|
||||
import org.navalplanner.business.calendars.entities.IWorkHours;
|
||||
import org.navalplanner.business.calendars.entities.ResourceCalendar;
|
||||
import org.navalplanner.business.calendars.entities.SameWorkHoursEveryDay;
|
||||
import org.navalplanner.business.common.BaseEntity;
|
||||
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.ResourcesCostCategoryAssignment;
|
||||
import org.navalplanner.business.planner.entities.DayAssignment;
|
||||
|
|
@ -659,6 +664,37 @@ public abstract class Resource extends BaseEntity{
|
|||
return calendar;
|
||||
}
|
||||
|
||||
public void setResourceCalendar(String calendarName)
|
||||
throws InstanceNotFoundException, MultipleInstancesException {
|
||||
|
||||
ResourceCalendar calendar;
|
||||
|
||||
if (StringUtils.isBlank(calendarName)) {
|
||||
|
||||
calendar = Registry.getConfigurationDAO().getConfiguration().
|
||||
getDefaultCalendar().newDerivedResourceCalendar();
|
||||
|
||||
} else {
|
||||
|
||||
List<BaseCalendar> baseCalendars = Registry.getBaseCalendarDAO().
|
||||
findByName(StringUtils.trim(calendarName));
|
||||
|
||||
if (baseCalendars.isEmpty()) {
|
||||
throw new InstanceNotFoundException(calendarName,
|
||||
BaseCalendar.class.getName());
|
||||
} if (baseCalendars.size() > 1) {
|
||||
throw new MultipleInstancesException(calendarName,
|
||||
BaseCalendar.class.getName());
|
||||
} else {
|
||||
calendar = baseCalendars.get(0).newDerivedResourceCalendar();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setCalendar(calendar);
|
||||
|
||||
}
|
||||
|
||||
public int getAssignedHours(LocalDate localDate) {
|
||||
int sum = 0;
|
||||
for (DayAssignment dayAssignment : getAssignmentsForDay(localDate)) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ package org.navalplanner.ws.resources.api;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
|
||||
|
|
@ -33,6 +34,9 @@ import javax.xml.bind.annotation.XmlElementWrapper;
|
|||
*/
|
||||
public abstract class ResourceDTO {
|
||||
|
||||
@XmlAttribute(name="calendar-name")
|
||||
public String calendarName;
|
||||
|
||||
@XmlElementWrapper(name="criterion-satisfaction-list")
|
||||
@XmlElement(name="criterion-satisfaction")
|
||||
public List<CriterionSatisfactionDTO> criterionSatisfactions =
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import java.util.List;
|
|||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.navalplanner.business.common.exceptions.CreateUnvalidatedException;
|
||||
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.navalplanner.business.common.exceptions.MultipleInstancesException;
|
||||
import org.navalplanner.business.resources.entities.CriterionSatisfaction;
|
||||
import org.navalplanner.business.resources.entities.Machine;
|
||||
import org.navalplanner.business.resources.entities.Resource;
|
||||
|
|
@ -56,12 +58,13 @@ public class ResourceConverter {
|
|||
resource = createResourceWithBasicData((WorkerDTO) resourceDTO);
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
_("Service does not manages resource of type: {0}",
|
||||
_("Service does not manage resource of type: {0}",
|
||||
resourceDTO.getClass().getName()));
|
||||
}
|
||||
|
||||
addCriterionSatisfactions(resource,
|
||||
resourceDTO.criterionSatisfactions);
|
||||
setResourceCalendar(resource, resourceDTO.calendarName);
|
||||
|
||||
return resource;
|
||||
|
||||
|
|
@ -110,4 +113,20 @@ public class ResourceConverter {
|
|||
|
||||
}
|
||||
|
||||
private static void setResourceCalendar(Resource resource,
|
||||
String calendarName) throws CreateUnvalidatedException {
|
||||
|
||||
try {
|
||||
resource.setResourceCalendar(calendarName);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new CreateUnvalidatedException(
|
||||
_("{0}: calendar not found", calendarName));
|
||||
} catch (MultipleInstancesException e) {
|
||||
throw new CreateUnvalidatedException(
|
||||
_("there exist multiple calendars with name {0}",
|
||||
calendarName));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
package org.navalplanner.web.test.ws.resources.api;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
|
@ -32,10 +33,15 @@ import java.util.Calendar;
|
|||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.navalplanner.business.calendars.daos.IBaseCalendarDAO;
|
||||
import org.navalplanner.business.calendars.entities.BaseCalendar;
|
||||
import org.navalplanner.business.common.IAdHocTransactionService;
|
||||
import org.navalplanner.business.common.IOnTransaction;
|
||||
import org.navalplanner.business.common.daos.IConfigurationDAO;
|
||||
import org.navalplanner.business.common.entities.IConfigurationBootstrap;
|
||||
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.navalplanner.business.resources.daos.ICriterionTypeDAO;
|
||||
import org.navalplanner.business.resources.daos.IMachineDAO;
|
||||
|
|
@ -88,9 +94,23 @@ public class ResourceServiceTest {
|
|||
@Autowired
|
||||
private ICriterionTypeDAO criterionTypeDAO;
|
||||
|
||||
@Autowired
|
||||
private IConfigurationDAO configurationDAO;
|
||||
|
||||
@Autowired
|
||||
private IBaseCalendarDAO baseCalendarDAO;
|
||||
|
||||
@Autowired
|
||||
private IConfigurationBootstrap configurationBootstrap;
|
||||
|
||||
@Autowired
|
||||
private IAdHocTransactionService transactionService;
|
||||
|
||||
@Before
|
||||
public void loadConfiguration() {
|
||||
configurationBootstrap.loadRequiredData();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddResourcesWithBasicContraintViolations()
|
||||
throws InstanceNotFoundException {
|
||||
|
|
@ -342,6 +362,62 @@ public class ResourceServiceTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
@NotTransactional
|
||||
public void testAddResourceWithDefaultCalendar()
|
||||
throws InstanceNotFoundException {
|
||||
|
||||
/* Create a machine DTO. */
|
||||
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
|
||||
|
||||
/* Test. */
|
||||
assertNoConstraintViolations(resourceService.
|
||||
addResources(createResourceListDTO(machineDTO)));
|
||||
Machine machine = findUniqueMachineByCodeInitialized(machineDTO.code);
|
||||
assertEquals(getDefaultCalendar().getId(),
|
||||
machine.getCalendar().getParent().getId());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@NotTransactional
|
||||
public void testAddResourceWithSpecificCalendar()
|
||||
throws InstanceNotFoundException {
|
||||
|
||||
/* Create a base calendar. */
|
||||
BaseCalendar baseCalendar = createBaseCalendar();
|
||||
|
||||
/* Create a machine DTO. */
|
||||
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
|
||||
machineDTO.calendarName =
|
||||
' ' + baseCalendar.getName().toUpperCase() + ' ';
|
||||
|
||||
/* Test. */
|
||||
assertNoConstraintViolations(resourceService.
|
||||
addResources(createResourceListDTO(machineDTO)));
|
||||
Machine machine = findUniqueMachineByCodeInitialized(machineDTO.code);
|
||||
assertEquals(baseCalendar.getId(),
|
||||
machine.getCalendar().getParent().getId());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@NotTransactional
|
||||
public void testAddResourceWithNonExistentCalendar()
|
||||
throws InstanceNotFoundException {
|
||||
|
||||
/* Create a machine DTO. */
|
||||
MachineDTO machineDTO = new MachineDTO(getUniqueName(), "name", "desc");
|
||||
machineDTO.calendarName = getUniqueName();
|
||||
|
||||
/* Test. */
|
||||
assertOneConstraintViolation(resourceService.
|
||||
addResources(createResourceListDTO(machineDTO)));
|
||||
assertFalse(machineDAO.existsMachineWithCodeInAnotherTransaction(
|
||||
machineDTO.code));
|
||||
|
||||
}
|
||||
|
||||
private CriterionType createCriterionType() {
|
||||
return createCriterionType(ResourceEnum.RESOURCE);
|
||||
}
|
||||
|
|
@ -398,6 +474,18 @@ public class ResourceServiceTest {
|
|||
|
||||
}
|
||||
|
||||
private Resource initializeResource(Resource resource) {
|
||||
|
||||
for (CriterionSatisfaction cs : resource.getCriterionSatisfactions()) {
|
||||
cs.getCriterion().getType().getName();
|
||||
}
|
||||
|
||||
resource.getCalendar().getParent();
|
||||
|
||||
return resource;
|
||||
|
||||
}
|
||||
|
||||
private void saveResource(final Resource resource) {
|
||||
|
||||
IOnTransaction<Void> save = new IOnTransaction<Void>() {
|
||||
|
|
@ -413,13 +501,35 @@ public class ResourceServiceTest {
|
|||
|
||||
}
|
||||
|
||||
private Resource initializeResource(Resource resource) {
|
||||
public BaseCalendar getDefaultCalendar() {
|
||||
|
||||
for (CriterionSatisfaction cs : resource.getCriterionSatisfactions()) {
|
||||
cs.getCriterion().getType().getName();
|
||||
}
|
||||
IOnTransaction<BaseCalendar> find = new IOnTransaction<BaseCalendar>() {
|
||||
|
||||
return resource;
|
||||
@Override
|
||||
public BaseCalendar execute() {
|
||||
return configurationDAO.getConfiguration().getDefaultCalendar();
|
||||
}
|
||||
};
|
||||
|
||||
return transactionService.runOnTransaction(find);
|
||||
|
||||
}
|
||||
|
||||
private BaseCalendar createBaseCalendar() {
|
||||
|
||||
IOnTransaction<BaseCalendar> create =
|
||||
new IOnTransaction<BaseCalendar>() {
|
||||
|
||||
@Override
|
||||
public BaseCalendar execute() {
|
||||
BaseCalendar baseCalendar = BaseCalendar.create();
|
||||
baseCalendar.setName(getUniqueName());
|
||||
baseCalendarDAO.save(baseCalendar);
|
||||
return baseCalendar;
|
||||
}
|
||||
};
|
||||
|
||||
return transactionService.runOnTransaction(create);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -436,6 +546,15 @@ public class ResourceServiceTest {
|
|||
|
||||
}
|
||||
|
||||
private void assertNoConstraintViolations(
|
||||
InstanceConstraintViolationsListDTO
|
||||
instanceConstraintViolationsListDTO) {
|
||||
|
||||
assertTrue(instanceConstraintViolationsListDTO.
|
||||
instanceConstraintViolationsList.size() == 0);
|
||||
|
||||
}
|
||||
|
||||
private void assertOneConstraintViolation(
|
||||
InstanceConstraintViolationsListDTO
|
||||
instanceConstraintViolationsListDTO) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<!-- *** Machines *** -->
|
||||
|
||||
<!-- OK -->
|
||||
<machine code=" m1 " name="m1-name" description="m1-desc"/>
|
||||
<machine code="m1" name="m1-name" description="m1-desc"/>
|
||||
|
||||
<!-- Missing code and name (description is optional). -->
|
||||
<machine code="" description=""/>
|
||||
|
|
@ -24,14 +24,18 @@
|
|||
<!-- Another machine is being imported with the same code. -->
|
||||
<machine code="m1" name="m3-name" description="m3-desc"/>
|
||||
|
||||
<!-- OK or not OK depending on the existence of "CalendarTest". -->
|
||||
<machine code="m4" name="m4-name" description="m4-desc"
|
||||
calendar-name="CalendarTest"/>
|
||||
|
||||
<!-- *** Workers *** -->
|
||||
|
||||
<!-- OK -->
|
||||
<worker first-name="w1-firstName" surname="w1-surname" nif=" w1-nif ">
|
||||
<worker first-name="w1-firstName" surname="w1-surname" nif="w1-nif">
|
||||
<criterion-satisfaction-list>
|
||||
<criterion-satisfaction
|
||||
criterion-type-name=" WORK_RELATIONSHIP "
|
||||
criterion-name=" hiredResourceWorkingRelationship "
|
||||
criterion-type-name="WORK_RELATIONSHIP"
|
||||
criterion-name="hiredResourceWorkingRelationship"
|
||||
start-date="2009-01-01"
|
||||
finish-date=""/>
|
||||
<criterion-satisfaction
|
||||
|
|
@ -46,7 +50,7 @@
|
|||
<worker first-name="" nif=""/>
|
||||
|
||||
<!-- Missing start date in criterion satisfaction. -->
|
||||
<worker first-name="w2-firstName" surname="w2-surname" nif=" w2-nif ">
|
||||
<worker first-name="w2-firstName" surname="w2-surname" nif="w2-nif">
|
||||
<criterion-satisfaction-list>
|
||||
<criterion-satisfaction
|
||||
criterion-type-name="LEAVE"
|
||||
|
|
@ -56,7 +60,7 @@
|
|||
</worker>
|
||||
|
||||
<!-- Non-existent criterion type. -->
|
||||
<worker first-name="w3-firstName" surname="w3-surname" nif=" w3-nif ">
|
||||
<worker first-name="w3-firstName" surname="w3-surname" nif="w3-nif">
|
||||
<criterion-satisfaction-list>
|
||||
<criterion-satisfaction
|
||||
criterion-type-name="WORK_RELATIONSHIP_XXX"
|
||||
|
|
@ -67,7 +71,7 @@
|
|||
</worker>
|
||||
|
||||
<!-- Non-existent criterion. -->
|
||||
<worker first-name="w4-firstName" surname="w4-surname" nif=" w4-nif ">
|
||||
<worker first-name="w4-firstName" surname="w4-surname" nif="w4-nif">
|
||||
<criterion-satisfaction-list>
|
||||
<criterion-satisfaction
|
||||
criterion-type-name="WORK_RELATIONSHIP"
|
||||
|
|
@ -78,7 +82,7 @@
|
|||
</worker>
|
||||
|
||||
<!-- Criterion not specified. -->
|
||||
<worker first-name="w5-firstName" surname="w5-surname" nif=" w5-nif ">
|
||||
<worker first-name="w5-firstName" surname="w5-surname" nif="w5-nif">
|
||||
<criterion-satisfaction-list>
|
||||
<criterion-satisfaction
|
||||
criterion-type-name="WORK_RELATIONSHIP"
|
||||
|
|
@ -88,7 +92,7 @@
|
|||
</worker>
|
||||
|
||||
<!-- Criterion type not specified. -->
|
||||
<worker first-name="w6-firstName" surname="w6-surname" nif=" w6-nif ">
|
||||
<worker first-name="w6-firstName" surname="w6-surname" nif="w6-nif">
|
||||
<criterion-satisfaction-list>
|
||||
<criterion-satisfaction
|
||||
criterion-name="hiredResourceWorkingRelationship"
|
||||
|
|
@ -101,4 +105,8 @@
|
|||
and nif. -->
|
||||
<worker first-name="w1-firstName" surname="w1-surname" nif="w1-nif"/>
|
||||
|
||||
<!-- OK or not OK depending on the existence of "CalendarTest". -->
|
||||
<worker first-name="w8-firstName" surname="w8-surname" nif="w8-nif"
|
||||
calendar-name="CalendarTest" />
|
||||
|
||||
</resource-list>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue