ItEr35S09CUConfiguracionMaquinasItEr34S09: Select assigned workers and required criterion in machine configuration tab

This commit is contained in:
Lorenzo Tilve 2009-11-21 00:34:17 +01:00 committed by Javier Moran Rua
parent 6ae02ce6a1
commit 12bbcbdd88
8 changed files with 279 additions and 60 deletions

View file

@ -144,6 +144,10 @@ public class Criterion extends BaseEntity implements ICriterion {
this.type = type;
}
public String getCompleteName() {
return type.getName() + " :: " + name;
}
public boolean isActive() {
return active;
}

View file

@ -6,6 +6,7 @@ import java.util.HashSet;
import java.util.Set;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.Valid;
public class Machine extends Resource {
@ -20,6 +21,7 @@ public class Machine extends Resource {
private Set<MachineWorkersConfigurationUnit> configurationUnits = new HashSet<MachineWorkersConfigurationUnit>();
@Valid
public Set<MachineWorkersConfigurationUnit> getConfigurationUnits() {
return Collections.unmodifiableSet(configurationUnits);
}

View file

@ -22,9 +22,11 @@ package org.navalplanner.business.resources.entities;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.validator.AssertTrue;
import org.navalplanner.business.common.BaseEntity;
/**
@ -96,6 +98,7 @@ public class MachineWorkersConfigurationUnit extends BaseEntity {
public void addNewWorkerAssignment(Worker worker) {
MachineWorkerAssignment assigment = MachineWorkerAssignment.create(
this, worker);
assigment.setStartDate(new Date());
workerAssignments.add(assigment);
}
@ -120,4 +123,76 @@ public class MachineWorkersConfigurationUnit extends BaseEntity {
requiredCriterions.remove(criterion);
}
public boolean existsWorkerAssignmentWithSameWorker(
MachineWorkerAssignment assignment) {
boolean assigned = false;
for (MachineWorkerAssignment each : workerAssignments) {
if (!(each.getId().equals(assignment.getId()))
&& ((each.getWorker().getId().equals(assignment.getWorker()
.getId())))) {
assigned = true;
}
}
return assigned;
}
public boolean existsWorkerAssignmentWithSameWorker(
MachineWorkerAssignment assignment,
Interval interval) {
boolean assigned = false;
Worker worker = assignment.getWorker();
Interval range = null;
for (MachineWorkerAssignment each : workerAssignments) {
if ((each.getWorker().getId().equals(worker.getId()))
&& (each.getId() != assignment.getId())) {
if (each.getFinishDate() != null) {
range = Interval.range(each.getStartDate(), each
.getFinishDate());
} else {
range = Interval.from(each.getStartDate());
}
if ((range == null) || (interval.overlapsWith(range))) {
assigned = true;
}
}
}
return assigned;
}
@AssertTrue(message = "All Machine worker assignments must have a start date earlier than the finish date")
public boolean checkWorkerAssignmentsIntervalsProperlyDefined() {
boolean correctIntervals = true;
for (MachineWorkerAssignment each : workerAssignments) {
if (each.getStartDate() == null) {
correctIntervals = false;
} else if ((each.getFinishDate() != null)
&& (each.getStartDate().compareTo(each.getFinishDate()) > 0)) {
correctIntervals = false;
}
}
return correctIntervals;
}
@AssertTrue(message = "The same resource is assigned twice inside an interval")
public boolean checkConstraintUniqueWorkerAssignmentInInterval() {
boolean unique = true;
Interval range = null;
for (MachineWorkerAssignment each : workerAssignments) {
if (each.getStartDate() != null) {
if (each.getFinishDate() != null) {
range = Interval.range(each.getStartDate(), each
.getFinishDate());
} else {
range = Interval.from(each.getStartDate());
}
if (((range == null)
&& existsWorkerAssignmentWithSameWorker(each) || (existsWorkerAssignmentWithSameWorker(
each, range)))) {
unique = false;
}
}
}
return unique;
}
}

View file

@ -21,12 +21,15 @@
package org.navalplanner.web.resources.machine;
import java.util.List;
import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.navalplanner.business.calendars.entities.ResourceCalendar;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.Machine;
import org.navalplanner.business.resources.entities.MachineWorkersConfigurationUnit;
import org.navalplanner.business.resources.entities.Worker;
/*
* This interface contains the operations to create/edit a machine.
@ -69,9 +72,13 @@ public interface IMachineModel {
List<MachineWorkersConfigurationUnit> getConfigurationUnitsOfMachine();
void setCalendarOfMachine(ResourceCalendar resourceCalendar);
void addWorkerAssigmentToConfigurationUnit(MachineWorkersConfigurationUnit
machineWorkersConfigurationUnit);
machineWorkersConfigurationUnit,
Worker worker);
void addCriterionRequirementToConfigurationUnit(
MachineWorkersConfigurationUnit criterion);
MachineWorkersConfigurationUnit unit, Criterion criterion);
MachineWorkersConfigurationUnit getConfigurationUnitById(Long id)
throws InstanceNotFoundException;
// Final conversational step
void confirmSave() throws ValidationException;
@ -79,4 +86,6 @@ public interface IMachineModel {
// Non conversational methods
List<Machine> getMachines();
List<BaseCalendar> getBaseCalendars();
void removeConfigurationUnit(MachineWorkersConfigurationUnit unit);
}

View file

@ -27,6 +27,7 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.validator.InvalidValue;
import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.navalplanner.business.calendars.entities.ResourceCalendar;
import org.navalplanner.business.common.exceptions.ValidationException;
@ -193,11 +194,19 @@ public class MachineCRUDController extends GenericForwardComposer {
goToList();
messagesForUser.showMessage(Level.INFO, _("Machine saved"));
} catch (ValidationException e) {
messagesForUser.showMessage(Level.ERROR, _("Could not save Machine"));
messagesForUser.showMessage(Level.ERROR,
_("Could not save Machine") + " " + showInvalidValues(e));
LOG.error(e);
}
}
private String showInvalidValues(ValidationException e) {
String result = "";
for (InvalidValue each : e.getInvalidValues())
result = result + each.getMessage();
return result;
}
private void saveCalendar() throws ValidationException {
if (baseCalendarEditionController != null) {
baseCalendarEditionController.save();

View file

@ -19,25 +19,39 @@
*/
package org.navalplanner.web.resources.machine;
import static org.navalplanner.web.I18nHelper._;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.resources.daos.ICriterionDAO;
import org.navalplanner.business.resources.daos.IWorkerDAO;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionWithItsType;
import org.navalplanner.business.resources.entities.MachineWorkerAssignment;
import org.navalplanner.business.resources.entities.MachineWorkersConfigurationUnit;
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.Autocomplete;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Constraint;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Row;
import org.zkoss.zul.Rows;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.api.Bandbox;
/**
@ -119,21 +133,103 @@ public class MachineConfigurationController extends GenericForwardComposer {
public void addWorkerAssignment(MachineWorkersConfigurationUnit unit,
Component c) {
machineModel.addWorkerAssigmentToConfigurationUnit(unit);
Util.reloadBindings(c.getNextSibling());
Autocomplete a = (Autocomplete) c.getPreviousSibling();
Worker worker = (Worker) a.getItemByText(a.getValue());
if (worker == null) {
messages.showMessage(Level.ERROR, _("No worker selected"));
} else {
machineModel.addWorkerAssigmentToConfigurationUnit(unit, worker);
Util.reloadBindings(c.getNextSibling());
}
}
public void addCriterionRequirement(MachineWorkersConfigurationUnit unit,
Component c) {
machineModel.addCriterionRequirementToConfigurationUnit(unit);
Util.reloadBindings(c.getNextSibling());
public boolean checkExistingCriterion(MachineWorkersConfigurationUnit unit,
Criterion criterion) {
boolean repeated = false;
for (Criterion each : unit.getRequiredCriterions()) {
if (each.getId().equals(criterion.getId())) {
repeated = true;
}
}
return repeated;
}
public void deleteWorkerAssignment(MachineWorkerAssignment assignment) {
public void addCriterionRequirement(Listitem item, Bandbox bandbox) {
MachineWorkersConfigurationUnit unit = null;
String unitString = ((Textbox) bandbox.getPreviousSibling()).getValue();
try {
unit = machineModel.getConfigurationUnitById(Long
.valueOf(unitString));
} catch (InstanceNotFoundException e) {
LOG.error("Configuration unit not found", e);
}
if (item != null) {
CriterionWithItsType criterionAndType = (CriterionWithItsType) item
.getValue();
bandbox.setValue(criterionAndType.getNameAndType());
if (checkExistingCriterion(unit, criterionAndType.getCriterion())) {
messages.showMessage(Level.ERROR,
_("Criterion previously selected"));
} else {
machineModel.addCriterionRequirementToConfigurationUnit(unit,
criterionAndType.getCriterion());
}
} else {
bandbox.setValue("");
}
bandbox.close();
Util.reloadBindings(bandbox.getNextSibling().getNextSibling());
}
public void deleteConfigurationUnit(MachineWorkersConfigurationUnit unit) {
machineModel.removeConfigurationUnit(unit);
Util.reloadBindings(configurationUnitsGrid);
}
public void deleteWorkerAssignment(Component component) {
MachineWorkerAssignment assignment = (MachineWorkerAssignment) ((Row) component)
.getValue();
MachineWorkersConfigurationUnit conf = assignment
.getMachineWorkersConfigurationUnit();
conf.removeMachineWorkersConfigurationUnit(assignment);
Util.reloadBindings(component.getParent().getParent());
}
public void deleteRequiredCriterion(Criterion criterion, Rows component) {
String unitString = ((Textbox) component.getParent()
.getPreviousSibling()).getValue();
try {
MachineWorkersConfigurationUnit unit = machineModel
.getConfigurationUnitById(Long.valueOf(unitString));
unit.removeRequiredCriterion(criterion);
} catch (InstanceNotFoundException e) {
LOG.error("Configuration unit not found", e);
}
Util.reloadBindings(component.getParent().getParent());
}
public Constraint validateEndDate() {
return new Constraint() {
@Override
public void validate(Component comp, Object value)
throws WrongValueException {
validateEndDate(comp, value);
}
};
}
private void validateEndDate(Component comp, Object value) {
Datebox startDateBox = (Datebox) comp.getPreviousSibling();
if (startDateBox != null) {
if ((startDateBox.getValue() != null)
&& (startDateBox.getValue().compareTo((Date) value) > 0)) {
throw new WrongValueException(
comp,
_("End date is not valid, the new end date must be greater than the start date"));
}
}
}
}

View file

@ -25,14 +25,11 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
import org.hsqldb.lib.Collection;
import org.navalplanner.business.calendars.daos.IBaseCalendarDAO;
import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.navalplanner.business.calendars.entities.ResourceCalendar;
@ -45,7 +42,6 @@ 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.CriterionSatisfaction;
import org.navalplanner.business.resources.entities.CriterionType;
import org.navalplanner.business.resources.entities.Machine;
import org.navalplanner.business.resources.entities.MachineWorkerAssignment;
import org.navalplanner.business.resources.entities.MachineWorkersConfigurationUnit;
@ -155,7 +151,7 @@ public class MachineModel implements IMachineModel {
private void loadCriterionSatisfactions() {
for (CriterionSatisfaction each: machine.getCriterionSatisfactions()) {
each.getStartDate();
each.getCriterion().getName();
each.getCriterion().getCompleteName();
insertInCriterionsCacheIfNotExist(each.getCriterion());
}
}
@ -170,7 +166,7 @@ public class MachineModel implements IMachineModel {
private void loadRequiredCriterionsOf(MachineWorkersConfigurationUnit configurationUnit) {
for (Criterion each: configurationUnit.getRequiredCriterions()) {
each.getName();
each.getCompleteName();
insertInCriterionsCacheIfNotExist(each);
}
}
@ -212,10 +208,7 @@ public class MachineModel implements IMachineModel {
@Transactional(readOnly=true)
@Override
public void addWorkerAssigmentToConfigurationUnit(
MachineWorkersConfigurationUnit unit) {
// TODO: Modify method to add the WorkerAssigment to add
Worker worker = workerDAO.getWorkers().iterator().next();
MachineWorkersConfigurationUnit unit, Worker worker) {
for (MachineWorkersConfigurationUnit each:
machine.getConfigurationUnits()) {
if (each == unit) {
@ -227,22 +220,12 @@ public class MachineModel implements IMachineModel {
@Transactional(readOnly=true)
@Override
public void addCriterionRequirementToConfigurationUnit(
MachineWorkersConfigurationUnit unit) {
// TODO: Modify method to add the criterion to add as parameter
MachineWorkersConfigurationUnit unit, Criterion criterion) {
HashSet<ResourceEnum> appliableToMachine =
new HashSet<ResourceEnum>();
appliableToMachine.add(ResourceEnum.MACHINE);
appliableToMachine.add(ResourceEnum.RESOURCE);
boolean stop = false;
for (CriterionType each:
criterionTypeDAO.getCriterionTypesByResources(appliableToMachine)) {
for (Criterion eachCriterion: each.getCriterions()) {
unit.addRequiredCriterion(eachCriterion);
stop = true;
break;
}
if (stop) break;
}
unit.addRequiredCriterion(criterion);
}
@Override
@ -251,10 +234,6 @@ public class MachineModel implements IMachineModel {
if (machine.getCalendar() != null) {
baseCalendarModel.checkInvalidValuesCalendar(machine.getCalendar());
}
InvalidValue[] invalidValues = validator.getInvalidValues(getMachine());
if (invalidValues.length > 0) {
throw new ValidationException(invalidValues);
}
resourceDAO.save(machine);
}
@ -269,4 +248,24 @@ public class MachineModel implements IMachineModel {
public List<Machine> getMachines() {
return machineDAO.getAll();
}
public MachineWorkersConfigurationUnit getConfigurationUnitById(Long id)
throws InstanceNotFoundException {
MachineWorkersConfigurationUnit unit = null;
for (MachineWorkersConfigurationUnit each : getConfigurationUnitsOfMachine()) {
if (each.getId().equals(id)) {
unit = each;
}
}
if (unit == null) {
throw new InstanceNotFoundException(id, MachineModel.class
.getName());
}
return unit;
}
@Override
public void removeConfigurationUnit(MachineWorkersConfigurationUnit unit) {
machine.removeMachineWorkersConfigurationUnit(unit);
}
}

View file

@ -32,28 +32,27 @@
width="400px" sort="auto(name)" />
<column label="${i18n:_('Alpha')}"
tooltiptext="${i18n:_('Human hours per machine working hour within configuration unit')}" />
<column label="${i18n:_('Operations')}" />
</columns>
<rows>
<!-- To iterate on workersConfiguration Units -->
<row self="@{each='configurationUnit'}" value="@{configurationUnit}">
<!--
detail open="false"
fulfill="onOpen=_workersConfigurationUnit.zul" /
-->
<detail>
<!-- Assigned resources -->
<button label="${i18n:_('Add new worker assignment')}"
onClick="configurationController.addWorkerAssignment(self.parent.parent.value,self)" />
<autocomplete finder="WorkerFinder" buttonVisible="true" value="" width="300px" style="margin-left:10px;margin-top:10px;"/>
<panel title="${i18n:_('Worker assignments')}">
<button label="${i18n:_('Add new worker assignment')}"
onClick="configurationController.addWorkerAssignment(self.parent.parent.value,self)"/>
<panel title="${i18n:_('Worker assignments')}" border="normal">
<panelchildren>
<grid fixedLayout="true"
model="@{configurationUnit.workerAssignments}">
<columns sizable="true">
<column label="Name" sort="auto" />
<column label="Start date" />
<column label="End date" />
<column label="Operations" />
<column label="${i18n:_('Name')}" sort="auto" />
<column label="${i18n:_('Start date')}" />
<column label="${i18n:_('End date')}" />
<column label="${i18n:_('Operations')}" />
</columns>
<rows>
<row self="@{each='workerAssignment'}"
@ -61,14 +60,14 @@
<label
value="@{workerAssignment.worker.name}" />
<datebox
value="@{workerAssignment.startDate}" />
value="@{workerAssignment.startDate}" constraint="no empty"/>
<datebox
value="@{workerAssignment.finishDate}" />
value="@{workerAssignment.finishDate}" constraint="@{configurationController.validateEndDate}" />
<button sclass="icono"
image="/common/img/ico_borrar1.png"
hoverImage="/common/img/ico_borrar.png"
tooltiptext="${i18n:_('Delete')}"
onClick="configurationController.deleteWorkerAssignment(self.parent.value)">
onClick="configurationController.deleteWorkerAssignment(self.parent)">
</button>
</row>
@ -76,26 +75,48 @@
</grid>
</panelchildren>
</panel>
<!-- Assigned criterions -->
<button label="${i18n:_('Add new criterion requirement')}"
onClick="configurationController.addCriterionRequirement(self.parent.parent.value,self)" />
<panel title="${i18n:_('Criterion requirements')}">
<!-- Assigned criteria -->
<textbox value="@{configurationUnit.id}" visible="false" />
<bandbox value = "@{criterionSatisfactionDTO.criterionAndType}" width="300px" style="margin-left:10px;margin-top:100px;">
<bandpopup>
<listbox width="500px" height="150px" fixedLayout="true"
model="@{assignedCriterionsController.criterionWithItsTypes}"
onSelect="configurationController.addCriterionRequirement(self.selectedItem,self.parent.parent)">
<listhead>
<listheader label="Type" />
<listheader label="Criterion" />
</listhead>
<listitem self="@{each='criterionWithItsType'}" value="@{criterionWithItsType}">
<listcell label="@{criterionWithItsType.type.name}" />
<listcell label="@{criterionWithItsType.nameHierarchy}" />
</listitem>
</listbox>
</bandpopup>
</bandbox>
<button label="${i18n:_('Add new criterion requirement')}"
onClick="configurationController.addCriterionRequirement(self.parent.parent.value,self)" disabled="true" />
<panel title="${i18n:_('Criterion requirements')}" border="normal">
<panelchildren>
<textbox value="@{configurationUnit.id}" visible="false" />
<grid fixedLayout="true"
model="@{configurationUnit.requiredCriterions}">
<columns sizable="true">
<column label="Name" sort="auto" />
<column label="Operations" />
<column label="${i18n:_('Name')}" sort="auto" />
<column label="${i18n:_('Operations')}" />
</columns>
<rows>
<row self="@{each='requirement'}"
value="@{requirement}">
<textbox value="@{requirement.name}" />
<textbox value="@{requirement.completeName}" width="300px"/>
<button sclass="icono"
image="/common/img/ico_borrar1.png"
hoverImage="/common/img/ico_borrar.png"
tooltiptext="${i18n:_('Delete')}"
onClick="configurationController.deleteCriterion(self.parent.value)"></button>
onClick="configurationController.deleteRequiredCriterion(self.parent.value, self.parent.parent)">
</button>
</row>
</rows>
</grid>
@ -107,6 +128,10 @@
constraint="no empty:${i18n:_('cannot be null or empty')}" />
<textbox value="@{configurationUnit.alpha}"
constraint="no negative,no zero,no empty:${i18n:_('cannot be null or empty')}" />
<button sclass="icono" image="/common/img/ico_borrar1.png"
hoverImage="/common/img/ico_borrar.png" tooltiptext="${i18n:_('Delete')}"
onClick="configurationController.deleteConfigurationUnit(self.parent.value)">
</button>
</row>
</rows>
</grid>