ItEr24S08CUAsignacionGrupoRecursosAPlanificacionItEr23S10: Revamped ResourceAllocation

Error on loading Task after deleting one ResourceAllocation and Cancel
This commit is contained in:
Diego Pino Garcia 2009-09-07 01:06:17 +02:00 committed by Óscar González Fernández
parent 47c4e73845
commit e62f1f51bd
9 changed files with 585 additions and 264 deletions

View file

@ -79,6 +79,10 @@ public class Task extends TaskElement {
resourceAllocations.remove(resourceAllocation);
}
public Boolean getFixedDuration() {
return fixedDuration;
}
public void setFixedDuration(Boolean fixed_duration) {
this.fixedDuration = fixed_duration;
}
@ -207,4 +211,41 @@ public class Task extends TaskElement {
}
return result;
}
public Set<GenericResourceAllocation> getGenericResourceAllocations() {
Set<GenericResourceAllocation> result = new HashSet<GenericResourceAllocation>();
Set<ResourceAllocation> resourceAllocations = getResourceAllocations();
for (ResourceAllocation resourceAllocation : resourceAllocations) {
if (resourceAllocation instanceof GenericResourceAllocation) {
result.add((GenericResourceAllocation) resourceAllocation);
}
}
return result;
}
public Set<SpecificResourceAllocation> getSpecificResourceAllocations() {
Set<SpecificResourceAllocation> result = new HashSet<SpecificResourceAllocation>();
Set<ResourceAllocation> resourceAllocations = getResourceAllocations();
for (ResourceAllocation resourceAllocation : resourceAllocations) {
if (resourceAllocation instanceof SpecificResourceAllocation) {
result.add((SpecificResourceAllocation) resourceAllocation);
}
}
return result;
}
public BigDecimal getSumPercentage(
List<ResourceAllocation> resourceAllocations) {
BigDecimal result = new BigDecimal(0);
for (ResourceAllocation resourceAllocation : resourceAllocations) {
result = result.add(resourceAllocation.getPercentage());
}
return result;
}
}

View file

@ -1,15 +1,25 @@
package org.navalplanner.business.resources.daos;
import java.util.List;
import java.util.Set;
import org.navalplanner.business.common.daos.IGenericDAO;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker;
/**
* DAO interface for the <code>Resource</code> entity.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
* @author Diego Pino Garcia <dpino@igalia.com>
*/
public interface IResourceDAO extends IGenericDAO<Resource, Long> {
public List<Worker> getWorkers();
/**
* Returns all {@link Resource} which satisfy a set of {@link Criterion}
*/
List<Resource> getAllByCriterions(Set<Criterion> criterions);
}

View file

@ -1,8 +1,11 @@
package org.navalplanner.business.resources.daos;
import java.util.List;
import java.util.Set;
import org.hibernate.Query;
import org.navalplanner.business.common.daos.GenericDAOHibernate;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker;
import org.springframework.beans.factory.config.BeanDefinition;
@ -11,7 +14,9 @@ import org.springframework.stereotype.Repository;
/**
* Hibernate DAO for the <code>Resource</code> entity.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
* @author Diego Pino Garcia <dpino@udc.es>
*/
@Repository
@Scope(BeanDefinition.SCOPE_SINGLETON)
@ -21,4 +26,17 @@ public class ResourceDAO extends GenericDAOHibernate<Resource, Long> implements
public List<Worker> getWorkers() {
return list(Worker.class);
}
@Override
public List<Resource> getAllByCriterions(Set<Criterion> criterions) {
String strQuery = "SELECT resource "
+ "FROM Resource resource "
+ "LEFT OUTER JOIN resource.criterionSatisfactions criterionSatisfactions "
+ "LEFT OUTER JOIN criterionSatisfactions.criterion criterion "
+ "WHERE criterion IN (:criterions)";
Query query = getSession().createQuery(strQuery);
query.setParameterList("criterions", criterions);
return (List<Resource>) query.list();
}
}

View file

@ -34,6 +34,10 @@ public abstract class Resource extends BaseEntity{
private Set<CriterionSatisfaction> criterionSatisfactions = new HashSet<CriterionSatisfaction>();
public Set<CriterionSatisfaction> getCriterionSatisfactions() {
return criterionSatisfactions;
}
public abstract String getDescription();
private interface IPredicate {

View file

@ -1,5 +1,8 @@
package org.navalplanner.business.resources.entities;
import java.util.ArrayList;
import java.util.Set;
import org.hibernate.validator.Min;
import org.hibernate.validator.NotEmpty;
@ -94,4 +97,10 @@ public class Worker extends Resource {
return dailyHours;
}
public boolean satisfiesCriterions(Set<Criterion> criterions) {
ICriterion compositedCriterion = CriterionCompounder.buildAnd(
new ArrayList<ICriterion>(criterions)).getResult();
return compositedCriterion.isSatisfiedBy(this);
}
}

View file

@ -1,7 +1,9 @@
package org.navalplanner.web.planner;
import java.math.BigDecimal;
import java.util.Set;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation;
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
import org.navalplanner.business.planner.entities.Task;
@ -12,9 +14,72 @@ import org.navalplanner.business.resources.entities.Worker;
* Contract for {@link Task}.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Diego Pino García <dpino@igalia.com>
*/
public interface IResourceAllocationModel {
/**
* Adds a new {@link GenericResourceAllocation} to the current {@link Task}.
*/
void addGenericResourceAllocation();
/**
* Adds {@link SpecificResourceAllocation} to {@link Task}
* {@link ResourceAllocation} list
*
* If a {@link SpecificResourceAllocation} satisfies {@link Task} criterions
* one of the {@link GenericResourceAllocation} assigned to
* {@link ResourceAllocation} is removed (in case any exists)
*
*/
void addSpecificResourceAllocation(Worker worker) throws Exception;
/**
* Returns {@link Set} of {@link Criterion} of the current {@link Task}
*
* @return
*/
Set<Criterion> getCriterions();
/**
* Returns {@link Set} of {@link GenericResourceAllocation} of current
*
* @return
*/
Set<GenericResourceAllocation> getGenericResourceAllocations();
/**
* Returns number of {@link ResourceAllocation} which are candidate to add
* as {@link GenericResourceAllocation}
*
* @return
*/
int getNumberUnassignedResources();
/**
* Returns the {@link Set} of {@link ResourceAllocation} of the current
* {@link Task}.
*
* @return A {@link Set} of {@link ResourceAllocation}
*/
Set<ResourceAllocation> getResourceAllocations();
/**
* Return sum of percentages for current {@link Task}
* {@link ResourceAllocation}
*
* @return
*/
BigDecimal getSumPercentageResourceAllocations();
/**
* Return sum of percentages for current {@link Task}
* {@link SpecificResourceAllocation}
*
* @return
*/
BigDecimal getSumPercentageSpecificResourceAllocations();
/**
* Gets the current {@link Task} object.
*
@ -22,11 +87,6 @@ public interface IResourceAllocationModel {
*/
Task getTask();
/**
* Adds a new {@link ResourceAllocation} to the current {@link Task}.
*/
void addResourceAllocation();
/**
* Removes the {@link ResourceAllocation} from the current {@link Task}.
*
@ -36,72 +96,13 @@ public interface IResourceAllocationModel {
void removeResourceAllocation(ResourceAllocation resourceAllocation);
/**
* Tries to find a {@link Worker} with the specified NIF.
*
* @param nif
* The NIF to search the {@link Worker}
* @return The {@link Worker} with this NIF or <code>null</code> if it's not
* found
*/
Worker findWorkerByNif(String nif);
/**
* Relates a {@link Worker} and a {@link Task} through a
* {@link SpecificResourceAllocation}.
* Removes {@link SpecificResourceAllocation} from current {@link Task}
* {@link ResourceAllocation} list
*
* @param resourceAllocation
* A {@link SpecificResourceAllocation} to set the {@link Worker}
* @param worker
* A {@link Worker} for the {@link SpecificResourceAllocation}
*/
void setWorker(SpecificResourceAllocation resourceAllocation, Worker worker);
/**
* Sets the current {@link Task}, where the user is allocating resources.
*
* @param task
* A {@link Task}
*/
void setTask(Task task);
/**
* Gets the {@link Set} of {@link Criterion} of the current task.
*
* @return A {@link Set} of {@link Criterion}
*/
Set<Criterion> getCriterions();
/**
* Gets the {@link Set} of {@link ResourceAllocation} of the current task.
*
* @return A {@link Set} of {@link ResourceAllocation}
*/
Set<ResourceAllocation> getResourceAllocations();
/**
* Sets the current {@link ResourceAllocation} to be rendered.
*
* @param resourceAllocation
* The current {@link ResourceAllocation}
*/
void setResourceAllocation(ResourceAllocation resourceAllocation);
/**
* Gets the {@link Worker} of the current {@link ResourceAllocation}.
*
* @return A {@link Worker}
*/
Worker getWorker();
/**
* Checks if the {@link Worker} of the current {@link ResourceAllocation}
* satisfies the {@link Criterion} of the current {@link Task}.
*
* @return True if the {@link Worker} satisfies the {@link Criterion}
* required. Or if the current {@link Worker} is <code>null</code>.
* Or if the {@link Criterion} list is empty.
*/
boolean workerSatisfiesCriterions();
void removeSpecificResourceAllocation(
SpecificResourceAllocation resourceAllocation);
/**
* Sets the current Gantt {@link org.zkoss.ganttz.data.Task ganttTask},
@ -111,6 +112,14 @@ public interface IResourceAllocationModel {
*/
void setGanttTask(org.zkoss.ganttz.data.Task ganttTask);
/**
* Sets the current {@link Task}, where the user is allocating resources.
*
* @param task
* A {@link Task}
*/
void setTask(Task task);
/**
* Update the duration of the current Gantt
* {@link org.zkoss.ganttz.data.Task ganttTask}, depending on the resources
@ -121,10 +130,11 @@ public interface IResourceAllocationModel {
void updateGanttTaskDuration();
/**
* Adds {@link SpecificResourceAllocation} to {@link Task}
* Updates {@link GenericResourceAllocation} percentages of current
* {@link Task}
*
* @param worker
* @param totalPercentage
*/
void addSpecificResourceAllocation(Worker worker);
void updateGenericPercentages(BigDecimal totalPercentage);
}

View file

@ -3,24 +3,29 @@ package org.navalplanner.web.planner;
import static org.navalplanner.web.I18nHelper._;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation;
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.Worker;
import org.navalplanner.web.common.IMessagesForUser;
import org.navalplanner.web.common.Level;
import org.navalplanner.web.common.MessagesForUser;
import org.navalplanner.web.common.Util;
import org.navalplanner.web.common.components.WorkerSearch;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.SuspendNotAllowedException;
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.util.Clients;
import org.zkoss.zk.ui.event.InputEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Button;
import org.zkoss.zul.Decimalbox;
@ -35,6 +40,7 @@ import org.zkoss.zul.api.Window;
* Controller for {@link ResourceAllocation} view.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Diego Pino Garcia <dpino@igalia.com>
*/
@org.springframework.stereotype.Component("resourceAllocationController")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -44,56 +50,36 @@ public class ResourceAllocationController extends GenericForwardComposer {
private ResourceAllocationRenderer resourceAllocationRenderer = new ResourceAllocationRenderer();
private Component messagesContainer;
private IMessagesForUser messagesForUser;
private Listbox resourcesList;
private Decimalbox genericResourceAllocationPercentage;
private Window window;
public Set<Criterion> getCriterions() {
Set<Criterion> criterions = resourceAllocationModel.getCriterions();
if (criterions.isEmpty()) {
window.getFellow("requiredCriterions").setVisible(false);
window.getFellow("requiredCriterionsEmpty").setVisible(true);
} else {
window.getFellow("requiredCriterionsEmpty").setVisible(false);
window.getFellow("requiredCriterions").setVisible(true);
}
return criterions;
}
public Set<ResourceAllocation> getResourceAllocations() {
return resourceAllocationModel.getResourceAllocations();
}
public ResourceAllocationRenderer getResourceAllocationRenderer() {
return resourceAllocationRenderer;
}
public void addResourceAllocation() {
resourceAllocationModel.addResourceAllocation();
Util.reloadBindings(resourcesList);
}
public void removeResourceAllocation() {
Set<Listitem> selectedItems = resourcesList.getSelectedItems();
for (Listitem listitem : selectedItems) {
ResourceAllocation resourceAllocation = (ResourceAllocation) listitem
.getValue();
resourceAllocationModel.removeResourceAllocation(resourceAllocation);
}
Util.reloadBindings(resourcesList);
}
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
messagesForUser = new MessagesForUser(messagesContainer);
this.window = (Window) comp;
}
/**
* Shows Resource Allocation window
*
* @param task
* @param ganttTask
*/
public void showWindow(Task task, org.zkoss.ganttz.data.Task ganttTask) {
resourceAllocationModel.setTask(task);
resourceAllocationModel.setGanttTask(ganttTask);
// Add generic resources to resources list
addGenericResources();
Util.reloadBindings(window);
try {
window.doModal();
@ -104,30 +90,24 @@ public class ResourceAllocationController extends GenericForwardComposer {
}
}
public void back() {
Set<ResourceAllocation> resourceAllocations = resourceAllocationModel.getResourceAllocations();
for (ResourceAllocation resourceAllocation : resourceAllocations) {
if (((SpecificResourceAllocation) resourceAllocation).getWorker() == null) {
throw new WrongValueException(
window.getFellow("resourcesList"),
_("Worker not valid in some resource allocation"));
}
/**
* Check how many {@link ResourceAllocation} object can be assigned to this
* {@link Task} and add them to {@link ResourceAllocation} list
*/
private void addGenericResources() {
int n = resourceAllocationModel.getNumberUnassignedResources();
for (int i = 0; i < n; i++) {
resourceAllocationModel.addGenericResourceAllocation();
}
if (!resourceAllocationModel.getTask()
.isValidResourceAllocationWorkers()) {
throw new WrongValueException(window.getFellow("resourcesList"),
_("There is some Worker assigned twice (or more)"));
}
Clients.closeErrorBox(window.getFellow("resourcesList"));
resourceAllocationModel.updateGanttTaskDuration();
window.setVisible(false);
}
public void showSearchResources(Event e) {
/**
* Shows WorkerSearch window, add picked workers as
* {@link SpecificResourceAllocation} to {@link ResourceAllocation} list
*
* @return
*/
public void showSearchResources() {
WorkerSearch workerSearch = new WorkerSearch();
workerSearch.setParent(self.getParent());
workerSearch.afterCompose();
@ -143,15 +123,99 @@ public class ResourceAllocationController extends GenericForwardComposer {
return;
}
// Get selected workers and add specificResourceAllocations
List<Worker> workers = workerSearch.getWorkers();
for (Worker worker : workers) {
resourceAllocationModel.addSpecificResourceAllocation(worker);
}
addSpecificResourceAllocations(workerSearch.getWorkers());
Util.reloadBindings(resourcesList);
}
/**
* Adds a list of {@link Worker} to {@link ResourceAllocation} list
*
* @param workers
*/
private void addSpecificResourceAllocations(List<Worker> workers) {
for (Worker worker : workers) {
addSpecificResourceAllocation(worker);
}
updateGenericPercentages();
}
/**
* Update percentages of {@link GenericResourceAllocation} items when
* genericResourceAllocationPercentage box is changed
*
* @param e
*/
public void updateGenericPercentages(InputEvent e) {
updateGenericPercentages(new BigDecimal((String) e.getValue()));
}
public void updateGenericPercentages() {
updateGenericPercentages(genericResourceAllocationPercentage.getValue());
}
private void updateGenericPercentages(BigDecimal genericPercentage) {
if (genericPercentage != null) {
resourceAllocationModel.updateGenericPercentages(genericPercentage
.divide(new BigDecimal(100)));
}
Util.reloadBindings(resourcesList);
}
private void addSpecificResourceAllocation(Worker worker) {
try {
resourceAllocationModel.addSpecificResourceAllocation(worker);
} catch (Exception e1) {
messagesForUser.showMessage(Level.ERROR, e1.getMessage());
}
}
/**
* Returns list of {@link Criterion} separated by comma
*
* @return
*/
public String getTaskCriterions() {
Set<String> criterionNames = new HashSet<String>();
Set<Criterion> criterions = resourceAllocationModel.getCriterions();
for (Criterion criterion : criterions) {
criterionNames.add(criterion.getName());
}
return StringUtils.join(criterionNames, ",");
}
/**
* Returns hours of {@link Task}
*
* @return
*/
public String getTaskHours() {
Task task = resourceAllocationModel.getTask();
return (task != null && task.getHours() != null) ? task.getHours()
.toString() : "";
}
/**
* Returns type of {@link Task} based on value of fixedDuration attribute
*
* @return
*/
public String getTaskType() {
Task task = resourceAllocationModel.getTask();
return (task != null && task.getFixedDuration()) ? _("Fixed duration")
: _("Variable duration");
}
public Set<ResourceAllocation> getResourceAllocations() {
return resourceAllocationModel.getResourceAllocations();
}
public ResourceAllocationRenderer getResourceAllocationRenderer() {
return resourceAllocationRenderer;
}
/**
*
* Renders a {@link SpecificResourceAllocation} item
@ -163,14 +227,25 @@ public class ResourceAllocationController extends GenericForwardComposer {
@Override
public void render(Listitem item, Object data) throws Exception {
final SpecificResourceAllocation resourceAllocation = (SpecificResourceAllocation) data;
if (data instanceof SpecificResourceAllocation) {
renderSpecificResourceAllocation(item,
(SpecificResourceAllocation) data);
}
if (data instanceof GenericResourceAllocation) {
renderGenericResourceAllocation(item,
(GenericResourceAllocation) data);
}
}
private void renderSpecificResourceAllocation(Listitem item,
final SpecificResourceAllocation resourceAllocation)
throws Exception {
item.setValue(resourceAllocation);
// Label fields are fixed, can only be viewed
appendLabel(item, resourceAllocation.getWorker().getName());
appendLabel(item, resourceAllocation.getWorker().getNif());
// Pecentage field is editable
// appendLabel(item, resourceAllocation.getWorker().getNif());
// Percentage field is editable
bindPercentage(appendDecimalbox(item), resourceAllocation);
// On click delete button
appendButton(item, _("Delete")).addEventListener("onClick",
@ -178,18 +253,43 @@ public class ResourceAllocationController extends GenericForwardComposer {
@Override
public void onEvent(Event event) throws Exception {
resourceAllocationModel
.removeResourceAllocation(resourceAllocation);
Util.reloadBindings(resourcesList);
removeSpecificResourceAllocation(resourceAllocation);
}
});
}
private void removeSpecificResourceAllocation(
SpecificResourceAllocation resourceAllocation) {
resourceAllocationModel
.removeSpecificResourceAllocation(resourceAllocation);
updateGenericPercentages();
Util.reloadBindings(resourcesList);
}
private void renderGenericResourceAllocation(Listitem item,
final GenericResourceAllocation resourceAllocation)
throws Exception {
item.setValue(resourceAllocation);
// Set name
appendLabel(item, _("Generic"));
// Set percentage
BigDecimal percentage = resourceAllocation.getPercentage();
if (!new BigDecimal(0).equals(resourceAllocation.getPercentage())) {
percentage = percentage.scaleByPowerOfTen(2).setScale(2,
BigDecimal.ROUND_CEILING);
}
appendLabel(item, percentage.toString());
// No buttons
appendLabel(item, "");
}
/**
* Appends {@link Label} to {@link Listitem}
*
* @param listitem
* @param name value for {@link Label}
* @param name
* value for {@link Label}
*/
private void appendLabel(Listitem listitem, String name) {
Label label = new Label(name);
@ -203,7 +303,8 @@ public class ResourceAllocationController extends GenericForwardComposer {
* Appends {@link Button} to {@link Listitem}
*
* @param listitem
* @param label value for {@link Button}
* @param label
* value for {@link Button}
* @return
*/
private Button appendButton(Listitem listitem, String label) {
@ -245,16 +346,21 @@ public class ResourceAllocationController extends GenericForwardComposer {
@Override
public BigDecimal get() {
return resourceAllocation.getPercentage().scaleByPowerOfTen(2);
return (resourceAllocation.getPercentage() != null) ? resourceAllocation
.getPercentage().scaleByPowerOfTen(2)
: new BigDecimal(0);
}
}, new Util.Setter<BigDecimal>() {
@Override
public void set(BigDecimal value) {
resourceAllocation
.setPercentage(value.setScale(2).divide(
new BigDecimal(100), BigDecimal.ROUND_DOWN));
if (value != null) {
value = value.setScale(2).divide(new BigDecimal(100),
BigDecimal.ROUND_DOWN);
updateGenericPercentages();
decimalbox.setValue(value);
}
}
});
}

View file

@ -1,25 +1,28 @@
package org.navalplanner.web.planner;
import static org.navalplanner.web.I18nHelper._;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.hibernate.LockMode;
import org.hibernate.SessionFactory;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.orders.daos.IHoursGroupDAO;
import org.navalplanner.business.orders.entities.HoursGroup;
import org.navalplanner.business.planner.daos.IResourceAllocationDAO;
import org.navalplanner.business.planner.daos.ITaskElementDAO;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation;
import org.navalplanner.business.planner.entities.SpecificResourceAllocation;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.resources.daos.IResourceDAO;
import org.navalplanner.business.resources.daos.IWorkerDAO;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionCompounder;
import org.navalplanner.business.resources.entities.CriterionSatisfaction;
import org.navalplanner.business.resources.entities.ICriterion;
import org.navalplanner.business.resources.entities.CriterionType;
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
@ -31,6 +34,7 @@ import org.springframework.transaction.annotation.Transactional;
* Model for UI operations related to {@link Task}
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Diego Pino García <dpino@igalia.com>
*/
@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -43,10 +47,10 @@ public class ResourceAllocationModel implements IResourceAllocationModel {
private IWorkerDAO workerDAO;
@Autowired
private SessionFactory sessionFactory;
private IHoursGroupDAO hoursGroupDAO;
@Autowired
private IHoursGroupDAO hoursGroupDAO;
private IResourceDAO resourceDAO;
@Autowired
private IResourceAllocationDAO resourceAllocationDAO;
@ -55,30 +59,110 @@ public class ResourceAllocationModel implements IResourceAllocationModel {
private org.zkoss.ganttz.data.Task ganttTask;
private ResourceAllocation resourceAllocation;
@Override
@Transactional(readOnly = true)
public void setTask(Task task) {
taskElementDAO.save(task);
task.getResourceAllocations().size();
HoursGroup hoursGroup = task.getHoursGroup();
hoursGroupDAO.save(hoursGroup);
hoursGroup.getCriterions().size();
this.task = task;
}
@Override
public Task getTask() {
return task;
}
@Override
public void addResourceAllocation() {
ResourceAllocation resourceAllocation = SpecificResourceAllocation.create(task);
@Transactional(readOnly = true)
public void setTask(Task task) {
try {
task = (Task) taskElementDAO.find(task.getId());
reattachResourceAllocations(task.getResourceAllocations());
hoursGroupDAO.save(task.getHoursGroup());
reattachHoursGroup(task.getHoursGroup());
reattachCriterions(task.getHoursGroup().getCriterions());
this.task = task;
} catch (InstanceNotFoundException e) {
}
}
private void reattachResourceAllocations(
Set<ResourceAllocation> resourceAllocations) {
resourceAllocations.size();
for (ResourceAllocation resourceAllocation : resourceAllocations) {
resourceAllocation.getPercentage();
if (resourceAllocation instanceof SpecificResourceAllocation) {
reattachSpecificResourceAllocation((SpecificResourceAllocation) resourceAllocation);
}
resourceAllocationDAO.save(resourceAllocation);
}
}
private void reattachSpecificResourceAllocation(
SpecificResourceAllocation resourceAllocation) {
resourceAllocation.getWorker().getName();
reattachCriterionSatisfactions(resourceAllocation.getWorker()
.getCriterionSatisfactions());
}
private void reattachHoursGroup(HoursGroup hoursGroup) {
hoursGroup.getPercentage();
}
private void reattachCriterions(Set<Criterion> criterions) {
for (Criterion criterion : criterions) {
reattachCriterion(criterion);
}
}
private void reattachCriterion(Criterion criterion) {
criterion.getName();
reattachCriterionType(criterion.getType());
}
private void reattachCriterionType(CriterionType criterionType) {
criterionType.getName();
}
@Override
@Transactional(readOnly = true)
public void addGenericResourceAllocation() {
GenericResourceAllocation resourceAllocation = GenericResourceAllocation
.create(task);
resourceAllocation.setPercentage(new BigDecimal(0));
task.addResourceAllocation(resourceAllocation);
taskElementDAO.save(task);
}
@Override
@Transactional(readOnly = true)
public void addSpecificResourceAllocation(Worker worker) throws Exception {
// ResourceAllocation already exists
if (findSpecificResourceAllocationByWorker(worker) != null) {
throw new IllegalArgumentException(_(
"{0} already assigned to resource allocation list", worker
.getName()));
}
// Prepare resourceAllocation
SpecificResourceAllocation resourceAllocation = SpecificResourceAllocation
.create(task);
resourceAllocation.setWorker(worker);
resourceAllocation.setPercentage((new BigDecimal(1)));
reattachWorker(worker);
// Check if worker was itself a generic resource
if (worker.satisfiesCriterions(getCriterions())) {
Set<GenericResourceAllocation> genericResourceAllocations = getGenericResourceAllocations();
// Generic resources always match criterions, so we need to remove
// one generic resource to leave room for a specific resource
if (genericResourceAllocations.size() > 0) {
removeResourceAllocation(genericResourceAllocations.iterator()
.next());
}
}
task.addResourceAllocation(resourceAllocation);
}
@Override
@Transactional(readOnly = true)
public Set<GenericResourceAllocation> getGenericResourceAllocations() {
return task.getGenericResourceAllocations();
}
@Override
@ -86,92 +170,122 @@ public class ResourceAllocationModel implements IResourceAllocationModel {
task.removeResourceAllocation(resourceAllocation);
}
@Override
@Transactional(readOnly = true)
public Worker findWorkerByNif(String nif) {
try {
return workerDAO.findUniqueByNif(nif);
} catch (InstanceNotFoundException e) {
return null;
}
}
@Override
public void setWorker(SpecificResourceAllocation resourceAllocation,
Worker worker) {
resourceAllocation.setWorker(worker);
}
@Override
public Set<Criterion> getCriterions() {
if (task == null) {
return new HashSet<Criterion>();
}
return task.getHoursGroup().getCriterions();
return (task != null) ? task.getHoursGroup().getCriterions()
: new HashSet<Criterion>();
}
@Override
public Set<ResourceAllocation> getResourceAllocations() {
if (task == null) {
return new HashSet<ResourceAllocation>();
}
return task.getResourceAllocations();
return (task != null) ? task.getResourceAllocations()
: new HashSet<ResourceAllocation>();
}
@Override
@Transactional(readOnly = true)
public void setResourceAllocation(ResourceAllocation resourceAllocation) {
resourceAllocationDAO.save(resourceAllocation);
public void removeSpecificResourceAllocation(
SpecificResourceAllocation resourceAllocation) {
boolean addGenericResourceAllocation = false;
Worker worker = ((SpecificResourceAllocation) resourceAllocation)
.getWorker();
if (worker != null) {
workerDAO.save(worker);
Set<CriterionSatisfaction> criterionSatisfactions = worker
.getAllSatisfactions();
for (CriterionSatisfaction criterionSatisfaction : criterionSatisfactions) {
criterionSatisfaction.getCriterion().getName();
criterionSatisfaction.getCriterion().getType().getName();
// On removing this resourceAllocation, it may be room for a new generic
// resource allocation
Worker worker = resourceAllocation.getWorker();
if (worker.satisfiesCriterions(getCriterions())) {
addGenericResourceAllocation = true;
}
resourceAllocationDAO.save(resourceAllocation);
task.removeResourceAllocation(resourceAllocation);
// Add new generic resource
if (addGenericResourceAllocation) {
addGenericResourceAllocation();
}
}
@Override
@Transactional(readOnly = true)
public void updateGenericPercentages(BigDecimal totalPercentage) {
Set<GenericResourceAllocation> genericResourceAllocations = getGenericResourceAllocations();
BigDecimal percentagePerResource = totalPercentage;
percentagePerResource = percentagePerResource
.subtract(getSumPercentageSpecificResourceAllocations());
if (genericResourceAllocations.size() > 0) {
percentagePerResource = percentagePerResource.setScale(8).divide(
new BigDecimal(genericResourceAllocations.size()),
BigDecimal.ROUND_DOWN);
// Percentage cannot be negative
if (percentagePerResource.compareTo(new BigDecimal(0)) < 0) {
percentagePerResource = new BigDecimal(0);
}
for (ResourceAllocation resourceAllocation : genericResourceAllocations) {
resourceAllocation.setPercentage(percentagePerResource);
}
}
this.resourceAllocation = resourceAllocation;
}
@Override
@Transactional(readOnly = true)
public Worker getWorker() {
if (resourceAllocation == null) {
return null;
public BigDecimal getSumPercentageSpecificResourceAllocations() {
return getSumPercentage(task.getSpecificResourceAllocations());
}
@SuppressWarnings("unchecked")
private BigDecimal getSumPercentage(Set resourceAllocations) {
BigDecimal result = new BigDecimal(0);
for (Iterator i = resourceAllocations.iterator(); i.hasNext();) {
ResourceAllocation resourceAllocation = (ResourceAllocation) i
.next();
result = result.add(resourceAllocation.getPercentage());
}
Worker worker = ((SpecificResourceAllocation) resourceAllocation)
.getWorker();
if (worker == null) {
return null;
return result;
}
private SpecificResourceAllocation findSpecificResourceAllocationByWorker(Worker worker) {
for (SpecificResourceAllocation resourceAllocation : task
.getSpecificResourceAllocations()) {
if (resourceAllocation.getWorker().getId().equals(worker.getId())) {
return resourceAllocation;
}
}
try {
return workerDAO.find(worker.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
return null;
}
@Transactional(readOnly = true)
private void reattachWorker(Worker worker) {
workerDAO.save(worker);
reattachCriterionSatisfactions(worker.getCriterionSatisfactions());
}
private void reattachCriterionSatisfactions(
Set<CriterionSatisfaction> criterionSatisfactions) {
for (CriterionSatisfaction criterionSatisfaction : criterionSatisfactions) {
criterionSatisfaction.getStartDate();
reattachCriterion(criterionSatisfaction.getCriterion());
}
}
@Override
@Transactional(readOnly = true)
public boolean workerSatisfiesCriterions() {
public BigDecimal getSumPercentageResourceAllocations() {
return getSumPercentage(task.getResourceAllocations());
}
for (Criterion criterion : getCriterions()) {
sessionFactory.getCurrentSession().lock(criterion, LockMode.NONE);
}
@Override
@Transactional(readOnly = true)
public int getNumberUnassignedResources() {
List<Resource> resources = resourceDAO
.getAllByCriterions(getCriterions());
Set<ResourceAllocation> resourceAllocations = task
.getResourceAllocations();
Worker worker = getWorker();
if (worker == null) {
return true;
}
ICriterion compositedCriterion = CriterionCompounder.buildAnd(
new ArrayList<ICriterion>(getCriterions())).getResult();
return compositedCriterion.isSatisfiedBy(worker);
return (resources.size() - resourceAllocations.size() > 0) ? resources
.size()
- resourceAllocations.size() : 0;
}
@Override
@ -187,13 +301,4 @@ public class ResourceAllocationModel implements IResourceAllocationModel {
ganttTask.setEndDate(task.getEndDate());
}
@Override
public void addSpecificResourceAllocation(Worker worker) {
SpecificResourceAllocation resourceAllocation = SpecificResourceAllocation
.create(task);
resourceAllocation.setWorker(worker);
resourceAllocation.setPercentage(new BigDecimal(1));
task.addResourceAllocation(resourceAllocation);
}
}
}

View file

@ -64,34 +64,52 @@
apply="${allocationController}"
title="${i18n:_('Resource allocation')}" width="600px"
closable="true" visible="false">
<tabbox>
<tabs>
<tab
label="${i18n:_('Specific resource allocation')}">
</tab>
</tabs>
<tabpanels>
<tabpanel>
<listbox id="resourcesList"
model="@{allocationController.resourceAllocations}"
itemRenderer="@{allocationController.resourceAllocationRenderer}">
<listhead>
<listheader label="${i18n:_('Name')}" />
<listheader label="${i18n:_('NIF')}" />
<listheader label="${i18n:_('Percentage')}" />
<listheader label="" />
</listhead>
</listbox>
</tabpanel>
</tabpanels>
</tabbox>
<panel title="Generic resource allocation" border="normal" style="margin-bottom: 5px">
<panelchildren>
<hbox>
<label value="${i18n:_('Task type')}:"
style="font-weight:bold" />
<label value="@{allocationController.taskType}" />
</hbox>
<hbox>
<label value="${i18n:_('Criterions')}:"
style="font-weight:bold" />
<label
value="@{allocationController.taskCriterions}" />
</hbox>
<hbox>
<label value="${i18n:_('Hours')}:"
style="font-weight:bold" />
<label value="@{allocationController.taskHours}" />
</hbox>
<hbox>
<label value="${i18n:_('Generic allocation')}:"
style="font-weight:bold" />
<decimalbox id="genericResourceAllocationPercentage" width="48px"
onChange="allocationController.updateGenericPercentages(event)" />
</hbox>
</panelchildren>
</panel>
<vbox id="messagesContainer"></vbox>
<listbox id="resourcesList"
model="@{allocationController.resourceAllocations}"
itemRenderer="@{allocationController.resourceAllocationRenderer}"
style="margin-bottom: 5px">
<listhead>
<listheader label="${i18n:_('Name')}" />
<listheader label="${i18n:_('Percentage')}" />
<listheader label="" />
</listhead>
</listbox>
<hbox>
<button label="${i18n:_('Save')}" />
<button label="${i18n:_('Cancel')}" />
<button label="${i18n:_('Search resources...')}"
onClick="allocationController.showSearchResources(event)" />
onClick="allocationController.showSearchResources()" />
<button label="${i18n:_('Advance allocation')}" />
</hbox>
</window>