ItEr34S07CUObtencionRequisitosEnProxectoTraballoItEr33S07 : Refactoring data hoursGroups.

This commit is contained in:
Susana Montes Pedreira 2009-11-16 13:11:34 +01:00 committed by Javier Moran Rua
parent ed100d903c
commit 406e9044e4
12 changed files with 214 additions and 757 deletions

View file

@ -89,8 +89,12 @@ public class HoursGroup extends BaseEntity implements Cloneable {
*/
public void setPercentage(BigDecimal proportion)
throws IllegalArgumentException {
if (proportion.compareTo(new BigDecimal(1).setScale(2)) > 0) {
this.percentage = new BigDecimal(0).setScale(2);
BigDecimal oldPercentage = this.percentage;
this.percentage = proportion;
if (!parentOrderLine.isPercentageValid()) {
this.percentage = oldPercentage;
throw new IllegalArgumentException(
"Total percentage should be less than 100%");
}

View file

@ -139,6 +139,10 @@ public class OrderLine extends OrderElement {
*/
public void setWorkHours(Integer workHours) throws IllegalArgumentException {
if (workHours == null) {
workHours = new Integer(0);
}
if (workHours < 0) {
throw new IllegalArgumentException(
"workHours should be greater or equals to 0");
@ -270,6 +274,10 @@ public class OrderLine extends OrderElement {
*/
public boolean isTotalHoursValid(Integer total) {
if (total == null) {
return false;
}
Integer newTotal = 0;
for (HoursGroup hoursGroup : hoursGroups) {
@ -384,6 +392,7 @@ public class OrderLine extends OrderElement {
if (newTotal.compareTo(total) < 0) {
// Add a new HourGroup with the remaining hours
HoursGroup hoursGroup = HoursGroup.create(this);
hoursGroup.updateMyCriterionRequirements();
hoursGroup.setWorkingHours(total - newTotal);
hoursGroups.add(hoursGroup);
}

View file

@ -30,8 +30,6 @@ import org.navalplanner.business.orders.entities.OrderElement;
import org.navalplanner.business.orders.entities.OrderLine;
import org.navalplanner.business.resources.entities.CriterionWithItsType;
import org.navalplanner.business.workreports.entities.WorkReportLine;
import org.navalplanner.web.common.IMessagesForUser;
import org.navalplanner.web.common.MessagesForUser;
import org.navalplanner.web.common.Util;
import org.navalplanner.web.common.components.NewDataSortableGrid;
import org.zkoss.zk.ui.Component;
@ -39,9 +37,9 @@ import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Bandbox;
import org.zkoss.zul.Constraint;
import org.zkoss.zul.Detail;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Intbox;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Panel;
@ -67,18 +65,11 @@ public class AssignedCriterionRequirementToOrderElementController extends
private Grid listHoursGroups;
private IMessagesForUser messages;
private Component messagesContainer;
private Detail detail;
private Intbox orderElementTotalHours;
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
if (containerHoursGroup == null)
throw new RuntimeException(_("MessagesContainer is needed"));
messages = new MessagesForUser(containerHoursGroup);
comp.setVariable("assignedCriterionRequirementController", this, true);
vbox = (Vbox) comp;
}
@ -164,19 +155,41 @@ setValidCriterionRequirementWrapper(requirement, true);
private void reload() {
Util.reloadBindings(listingRequirements);
Util.reloadBindings(orderElementTotalHours);
Util.reloadBindings(listHoursGroups);
}
private boolean showInvalidValues() {
CriterionRequirementWrapper invalidWrapper = this.assignedCriterionRequirementToOrderElementModel
.validateWrappers();
CriterionRequirementWrapper invalidWrapper = assignedCriterionRequirementToOrderElementModel
.validateWrappers(criterionRequirementWrappers());
if (invalidWrapper != null) {
showInvalidValues(invalidWrapper);
return true;
}
CriterionRequirementWrapper invalidHoursGroupWrapper = assignedCriterionRequirementToOrderElementModel
.validateHoursGroupWrappers();
if (invalidHoursGroupWrapper != null) {
showInvalidValuesInHoursGroups(invalidHoursGroupWrapper);
return true;
}
return false;
}
// Show invalid values inside listhoursGroup.
private void showInvalidValuesInHoursGroups(
CriterionRequirementWrapper requirementWrapper) {
if (listHoursGroups != null) {
List<Row> listRows = (List<Row>) ((Rows) listHoursGroups.getRows())
.getChildren();
for (Row row : listRows) {
Rows listRequirementRows = getRequirementRows(row);
Row requirementRow = findRowOfCriterionRequirementWrapper(
listRequirementRows, requirementWrapper);
showInvalidValue(requirementRow, requirementWrapper);
}
}
}
/**
* Validates {@link CriterionRequirementWrapper} data constraints
* @param invalidValue
@ -187,12 +200,17 @@ setValidCriterionRequirementWrapper(requirement, true);
// Find which listItem contains CriterionSatisfaction inside listBox
Row row = findRowOfCriterionRequirementWrapper(listingRequirements
.getRows(), requirementWrapper);
if (row != null) {
Bandbox bandType = getBandType(requirementWrapper, row);
bandType.setValue(null);
throw new WrongValueException(bandType,
_("The criterion and its type cannot be null"));
}
showInvalidValue(row, requirementWrapper);
}
}
private void showInvalidValue(Row row,
CriterionRequirementWrapper requirementWrapper) {
if (row != null) {
Bandbox bandType = getBandType(requirementWrapper, row);
bandType.setValue(null);
throw new WrongValueException(bandType,
_("The criterion and its type cannot be null"));
}
}
@ -316,7 +334,6 @@ setValidCriterionRequirementWrapper(requirement, true);
public void removeCriterionToHoursGroup(Component self){
try {
System.out.println("remove in Controller");
Row row = (Row) self.getParent().getParent();
CriterionRequirementWrapper requirementWrapper = (CriterionRequirementWrapper) row.getValue();
HoursGroupWrapper hoursGroupWrapper = getHoursGroupOfRequirementWrapper(row);
@ -378,6 +395,31 @@ setValidCriterionRequirementWrapper(requirement, true);
* percentage and its number of hours or set the fixed percentage
*/
public void changeTotalHours() {
recalculateHoursGroup();
}
public Constraint validateTotalHours() {
return new Constraint() {
@Override
public void validate(Component comp, Object value)
throws WrongValueException {
if (value == null) {
value = new Integer(0);
orderElementTotalHours.setValue((Integer) value);
}
try {
if (getOrderElement() instanceof OrderLine) {
((OrderLine) getOrderElement())
.setWorkHours((Integer) value);
}
} catch (IllegalArgumentException e) {
throw new WrongValueException(comp, _(e.getMessage()));
}
}
};
}
public Constraint validatePercentage() {
return new Constraint() {
@Override
@ -385,12 +427,21 @@ setValidCriterionRequirementWrapper(requirement, true);
throws WrongValueException {
HoursGroupWrapper hoursGroupWrapper = (HoursGroupWrapper) ((Row) comp
.getParent()).getValue();
hoursGroupWrapper.setPercentage((BigDecimal) value);
if (!assignedCriterionRequirementToOrderElementModel.isPercentageValid()) {
throw new WrongValueException(
comp,_("Total percentage should be less than 100%"));
try {
hoursGroupWrapper.setPercentage((BigDecimal) value);
} catch (IllegalArgumentException e) {
throw new WrongValueException(comp, _(e.getMessage()));
}
}
};
}
public void recalculateHoursGroup() {
((OrderLine) assignedCriterionRequirementToOrderElementModel
.getOrderElement()).recalculateHoursGroups();
assignedCriterionRequirementToOrderElementModel.updateHoursGroup();
Util.reloadBindings(listHoursGroups);
Util.reloadBindings(orderElementTotalHours);
}
}

View file

@ -20,7 +20,6 @@
package org.navalplanner.web.orders;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -149,6 +148,13 @@ public class AssignedCriterionRequirementToOrderElementModel implements
return criterionWithItsTypes;
}
public Integer getTotalHours() {
if (getOrderElement() != null) {
return getOrderElement().getWorkHours();
}
return 0;
}
@Override
@Transactional(readOnly = true)
public void assignCriterionRequirementWrapper() {
@ -225,8 +231,9 @@ public class AssignedCriterionRequirementToOrderElementModel implements
}
}
public CriterionRequirementWrapper validateWrappers() {
for (CriterionRequirementWrapper requirementWrapper : criterionRequirementWrappers) {
public CriterionRequirementWrapper validateWrappers(
List<CriterionRequirementWrapper> list) {
for (CriterionRequirementWrapper requirementWrapper : list) {
if (requirementWrapper.getCriterionWithItsType() == null) {
return requirementWrapper;
}
@ -234,6 +241,16 @@ public class AssignedCriterionRequirementToOrderElementModel implements
return null;
}
public CriterionRequirementWrapper validateHoursGroupWrappers() {
for (HoursGroupWrapper hoursGroupWrapper : hoursGroupsWrappers) {
CriterionRequirementWrapper requirementWrapper = validateWrappers(hoursGroupWrapper
.getCriterionRequirementWrappersView());
if (requirementWrapper != null) {
return requirementWrapper;
}
}
return null;
}
/*
* Operations to manage the hours groups (add new hours group, delete a
@ -245,7 +262,7 @@ public class AssignedCriterionRequirementToOrderElementModel implements
if (getOrderElement() instanceof OrderLine) {
return (OrderLine) getOrderElement();
} else {
return new OrderLine();
return null;
}
}
@ -270,10 +287,12 @@ public class AssignedCriterionRequirementToOrderElementModel implements
}
private HoursGroup createNewHoursGroup() {
HoursGroup newHoursGroup = HoursGroup
.create(asOrderLine());
(asOrderLine()).addHoursGroup(newHoursGroup);
return newHoursGroup;
if (asOrderLine() != null) {
HoursGroup newHoursGroup = HoursGroup.create(asOrderLine());
(asOrderLine()).addHoursGroup(newHoursGroup);
return newHoursGroup;
}
return null;
}
public List<HoursGroupWrapper> getHoursGroupsWrappers() {
@ -284,9 +303,11 @@ public class AssignedCriterionRequirementToOrderElementModel implements
}
public void deleteHoursGroupWrapper(HoursGroupWrapper hoursGroupWrapper) {
HoursGroup hoursGroup = hoursGroupWrapper.getHoursGroup();
asOrderLine().deleteHoursGroup(hoursGroup);
hoursGroupsWrappers.remove(hoursGroupWrapper);
if (asOrderLine() != null) {
HoursGroup hoursGroup = hoursGroupWrapper.getHoursGroup();
asOrderLine().deleteHoursGroup(hoursGroup);
hoursGroupsWrappers.remove(hoursGroupWrapper);
}
}
/*
@ -407,21 +428,22 @@ public class AssignedCriterionRequirementToOrderElementModel implements
exception.setValid(false);
}
/* Operations to control the data hoursGroup */
public boolean isPercentageValid() {
BigDecimal newPercentage = new BigDecimal(0).setScale(2);
for (HoursGroupWrapper hoursGroupWrapper : hoursGroupsWrappers) {
if (hoursGroupWrapper.getFixedPercentage()) {
BigDecimal percentage = hoursGroupWrapper.getPercentage();
percentage = percentage.divide(new BigDecimal(100),
BigDecimal.ROUND_DOWN);
newPercentage = newPercentage.add(percentage);
/* Operations to control and validate the data hoursGroup */
public void updateHoursGroup() {
for (HoursGroup hoursGroup : orderElement.getHoursGroups()) {
if (!existIntohoursGroupsWrappers(hoursGroup)) {
addNewHoursGroupWrapper(hoursGroup);
}
}
if (newPercentage.compareTo(new BigDecimal(1).setScale(2)) > 0) {
return false;
}
return true;
}
private boolean existIntohoursGroupsWrappers(HoursGroup hoursGroup) {
for (HoursGroupWrapper hoursGroupWrapper : hoursGroupsWrappers) {
if (hoursGroupWrapper.getHoursGroup().equals(hoursGroup)) {
return true;
}
}
return false;
}
}

View file

@ -20,47 +20,10 @@
package org.navalplanner.web.orders;
import static org.navalplanner.web.I18nHelper._;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.navalplanner.business.orders.entities.HoursGroup;
import org.navalplanner.business.orders.entities.Order;
import org.navalplanner.business.orders.entities.OrderElement;
import org.navalplanner.business.orders.entities.OrderLine;
import org.navalplanner.business.orders.entities.OrderLineGroup;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionType;
import org.navalplanner.web.common.Util;
import org.zkoss.zk.ui.Component;
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.event.Events;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Button;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Constraint;
import org.zkoss.zul.Decimalbox;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Intbox;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listheader;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Panel;
import org.zkoss.zul.RendererCtrl;
import org.zkoss.zul.Vbox;
import org.zkoss.zul.api.Listhead;
/**
* Controller for {@link OrderElement} details
@ -73,8 +36,6 @@ public class DetailsOrderElementController extends
private IOrderElementModel orderElementModel;
private Listbox hoursGroupsListbox;
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
@ -89,584 +50,8 @@ public class DetailsOrderElementController extends
return orderElementModel.getOrderElement();
}
/**
* Returns a {@link List} of {@link HoursGroup}.
*
* If the current element is an {@link OrderLine} this method just returns
* the {@link HoursGroup} of this {@link OrderLine}.
*
* Otherwise, this method gets all the {@link HoursGroup} of all the
* children {@link OrderElement}, and aggregates them if they have the same
* {@link Criterion}.
*
* @return The {@link HoursGroup} list of the current {@link OrderElement}
*/
public List<HoursGroup> getHoursGroups() {
if (orderElementModel == null || getOrderElement() == null) {
return new ArrayList<HoursGroup>();
}
// It's an OrderLine
if (orderElementModel.getOrderElement() instanceof OrderLine) {
return getOrderElement().getHoursGroups();
}
// If it's an OrderLineGroup
Set<CriterionType> criterionTypes = getSelectedCriterionTypes();
// If there isn't any CriterionType selected
if (criterionTypes.isEmpty()) {
return getOrderElement().getHoursGroups();
}
// Creates a map in order to join HoursGroup with the same
// Criterions.
Map<Set<Criterion>, HoursGroup> map = new HashMap<Set<Criterion>, HoursGroup>();
List<HoursGroup> hoursGroups = getOrderElement().getHoursGroups();
for (HoursGroup hoursGroup : hoursGroups) {
Set<Criterion> key = getKeyFor(hoursGroup, criterionTypes);
HoursGroup hoursGroupAggregation = map.get(key);
if (hoursGroupAggregation == null) {
// This is not a real HoursGroup element, it's just an
// aggregation that join HoursGroup with the same Criterions
hoursGroupAggregation = new HoursGroup();
hoursGroupAggregation.setWorkingHours(hoursGroup.getWorkingHours());
hoursGroupAggregation.setCriterionRequirements(
hoursGroup.getCriterionRequirements());
} else {
Integer newHours = hoursGroupAggregation.getWorkingHours() + hoursGroup.getWorkingHours();
hoursGroupAggregation.setWorkingHours(newHours);
}
map.put(key, hoursGroupAggregation);
}
return new ArrayList<HoursGroup>(map.values());
}
private Set<Criterion> getKeyFor(HoursGroup hoursGroup,
Set<CriterionType> criterionTypes) {
Set<Criterion> key = new HashSet<Criterion>();
for (CriterionType criterionType : criterionTypes) {
for (Criterion criterion : criterionType.getCriterions()) {
if(hoursGroup.getDirectCriterion(criterion) != null){
key.add(criterion);
}
}
}
return key;
}
/**
* Adds a new {@link HoursGroup} to the current {@link OrderElement}
*
* The {@link OrderElement} should be a {@link OrderLine}
*/
public void addHoursGroup() {
OrderLine orderLine = (OrderLine) getOrderElement();
HoursGroup hoursGroup = HoursGroup.create(orderLine);
orderLine.addHoursGroup(hoursGroup);
Util.reloadBindings(self);
}
/**
* Deletes the selected {@link HoursGroup} for the current
* {@link OrderElement}
*
* The {@link OrderElement} should be a {@link OrderLine}
*/
public void deleteHoursGroups() {
Set<Listitem> selectedItems = hoursGroupsListbox.getSelectedItems();
OrderElement orderElement = getOrderElement();
for (Listitem item : selectedItems) {
((OrderLine) orderElement).deleteHoursGroup((HoursGroup) item
.getValue());
}
Util.reloadBindings(self);
}
private transient ListitemRenderer renderer = new HoursGroupListitemRender();
public ListitemRenderer getRenderer() {
return renderer;
}
/**
* Represents every {@link HoursGroup} with an edition form if needed
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
*/
public class HoursGroupListitemRender implements ListitemRenderer, RendererCtrl{
@Override
public void render(Listitem item, Object data) throws Exception {
final HoursGroup hoursGroup = (HoursGroup) data;
hoursGroup.getCriterions();
item.setValue(hoursGroup);
Listcell cellWorkingHours = new Listcell();
cellWorkingHours.setParent(item);
Listcell cellPercentage = new Listcell();
cellPercentage.setParent(item);
final Decimalbox decimalBox = new Decimalbox();
decimalBox.setScale(2);
// If is a container
if (getOrderElement() instanceof OrderLineGroup) {
// Just getters are needed
// Working hours
cellWorkingHours.appendChild(Util.bind(new Intbox(),
new Util.Getter<Integer>() {
@Override
public Integer get() {
return hoursGroup.getWorkingHours();
}
}));
// Percentage
cellPercentage.appendChild(Util.bind(decimalBox,
new Util.Getter<BigDecimal>() {
@Override
public BigDecimal get() {
BigDecimal workingHours = new BigDecimal(hoursGroup
.getWorkingHours()).setScale(2);
BigDecimal total = new BigDecimal(getOrderElement().
getWorkHours()).setScale(2);
if (total.equals(new BigDecimal(0).setScale(2))) {
return new BigDecimal(0).setScale(2);
}
return workingHours.divide(total,
BigDecimal.ROUND_DOWN).scaleByPowerOfTen(2);
}
}));
// For each CriterionType selected
for (CriterionType criterionType : getSelectedCriterionTypes()) {
Listcell cellCriterion = new Listcell();
cellCriterion.setParent(item);
// Add a new Listbox for each CriterionType
final Listbox criterionListbox = new Listbox();
criterionListbox.setRows(1);
criterionListbox.setMold("select");
criterionListbox.setDisabled(true);
// Add an empty option to remove a Criterion
Listitem emptyListitem = new Listitem();
emptyListitem.setParent(criterionListbox);
// For each possible Criterion of the current type
for (Criterion criterion : orderElementModel
.getCriterionsFor(criterionType)) {
// Add the Criterion option
Listitem listitem = new Listitem();
listitem.setValue(criterion);
listitem.setLabel(criterion.getName());
listitem.setParent(criterionListbox);
}
cellCriterion.appendChild(criterionListbox);
}
} else { // If is a leaf
Intbox workingHours = Util.bind(new Intbox(),
new Util.Getter<Integer>() {
@Override
public Integer get() {
return hoursGroup.getWorkingHours();
}
}, new Util.Setter<Integer>() {
@Override
public void set(Integer value) {
hoursGroup.setWorkingHours(value);
}
});
// Add EventListener to reload the window when the value change
workingHours.addEventListener(Events.ON_CHANGE,
new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
((OrderLine) getOrderElement())
.recalculateHoursGroups();
Util.reloadBindings(self);
}
});
Decimalbox percentage = Util.bind(decimalBox,
new Util.Getter<BigDecimal>() {
@Override
public BigDecimal get() {
return hoursGroup.getPercentage().scaleByPowerOfTen(2);
}
}, new Util.Setter<BigDecimal>() {
@Override
public void set(BigDecimal value) {
value = value.divide(new BigDecimal(100),BigDecimal.ROUND_DOWN);
try {
hoursGroup.setPercentage(value);
} catch (IllegalArgumentException e) {
throw new WrongValueException(decimalBox, e.getMessage());
}
}
});
// Add EventListener to reload the window when the value change
percentage.addEventListener(Events.ON_CHANGE,
new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
((OrderLine) getOrderElement())
.recalculateHoursGroups();
Util.reloadBindings(self);
}
});
// Fixed percentage
Listcell cellFixedPercentage = new Listcell();
cellFixedPercentage.setParent(item);
Checkbox fixedPercentage = Util.bind(new Checkbox(),
new Util.Getter<Boolean>() {
@Override
public Boolean get() {
return hoursGroup.isFixedPercentage();
}
}, new Util.Setter<Boolean>() {
@Override
public void set(Boolean value) {
hoursGroup.setFixedPercentage(value);
}
});
fixedPercentage.addEventListener(Events.ON_CHECK,
new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
((OrderLine) getOrderElement())
.recalculateHoursGroups();
Util.reloadBindings(self);
}
});
// Disable components depending on the policy
disableComponents(workingHours, percentage,
fixedPercentage.isChecked());
cellWorkingHours.appendChild(workingHours);
cellPercentage.appendChild(percentage);
cellFixedPercentage.appendChild(fixedPercentage);
// For each CriterionType selected
for (CriterionType criterionType : getSelectedCriterionTypes()) {
Listcell cellCriterion = new Listcell();
cellCriterion.setParent(item);
// Add a new Listbox for each CriterionType
final Listbox criterionListbox = new Listbox();
criterionListbox.setRows(1);
criterionListbox.setMold("select");
// Add an empty option to remove a Criterion
Listitem emptyListitem = new Listitem();
emptyListitem.setParent(criterionListbox);
// For each possible Criterion of the current type
for (Criterion criterion : orderElementModel
.getCriterionsFor(criterionType)) {
// Add the Criterion option
Listitem listitem = new Listitem();
listitem.setValue(criterion);
listitem.setLabel(criterion.getName());
listitem.setParent(criterionListbox);
}
// Add operation for Criterion selection
criterionListbox.addEventListener(Events.ON_SELECT,
new EventListener() {
@Override
public void onEvent(Event event)
throws Exception {
Criterion criterion = (Criterion) criterionListbox
.getSelectedItem().getValue();
try {
hoursGroup.addDirectRequirementCriterion(criterion);
} catch (Exception e) {
// At moment it do nothing -- change
// with new interface.
}
}
});
cellCriterion.appendChild(criterionListbox);
}
}
}
/**
* Disable workingHours and percentage components depending on the
* policy selected by the user.
*
* @param workingHours
* An {@link Intbox} for the workingHours
* @param percentage
* A {@link Decimalbox} for the percentage
* @param fixedPercentage
* If FIXED_PERCENTAGE policy is set or not
*/
public void disableComponents(Intbox workingHours,
Decimalbox percentage, Boolean fixedPercentage) {
if (fixedPercentage) {
// Working hours not editable
workingHours.setDisabled(true);
// Percentage editable
percentage.setDisabled(false);
} else {
// Working hours editable
workingHours.setDisabled(false);
// Percentage not editable
percentage.setDisabled(true);
}
}
@Override
public void doCatch(Throwable ex) throws Throwable {
}
@Override
public void doFinally() {
}
@Override
public void doTry() {
generateListhead();
}
/**
* Generates the {@link Listhead} of the {@link HoursGroup} {@link Listbox}
* depending on the {@link CriterionType} selected.
*/
private void generateListhead() {
Listhead listhead = hoursGroupsListbox.getListheadApi();
// Remove the current header
listhead.getChildren().clear();
// Generate basic headers
Listheader hours = new Listheader(_("Hours"));
listhead.appendChild(hours);
Listheader percentage = new Listheader(_("%"));
listhead.appendChild(percentage);
// If it's a leaf add Fixed percentage column
if (getOrderElement() instanceof OrderLine) {
Listheader headerFixedPercentage = new Listheader(
_("Fixed percentage"));
listhead.appendChild(headerFixedPercentage);
}
// For each CriterionType selected
for (CriterionType criterionType : getSelectedCriterionTypes()) {
// Add a new column on the HoursGroup table
Listheader headerCriterion = new Listheader();
headerCriterion.setLabel(criterionType.getName());
listhead.appendChild(headerCriterion);
}
}
}
public void clear() {
}
private Intbox totalHours;
private Button btnAddHoursGroup;
private Button btnDeleteHoursGroup;
private Vbox selectCriterions;
private Grid details;
private Panel panelCriterions;
public void openWindow(IOrderElementModel model) {
setOrderElementModel(model);
final OrderElement orderElement = getOrderElement();
// Hide details and panelCriterion for Order
final boolean isOrder = orderElement != null && orderElement instanceof Order;
details.setVisible(!isOrder);
panelCriterions.setVisible(!isOrder);
// If is a container
if (orderElement instanceof OrderLineGroup) {
// Disable fields just used in the OrderLine
totalHours.setDisabled(true);
// Hide not needed buttons
btnAddHoursGroup.setVisible(false);
btnDeleteHoursGroup.setVisible(false);
} else {
// Enable fields just used in the OrderLine
totalHours.setDisabled(false);
// Show needed buttons
btnAddHoursGroup.setVisible(true);
btnDeleteHoursGroup.setVisible(true);
// Add EventListener to reload the window when the value change
totalHours.addEventListener(Events.ON_CHANGE, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
Util.reloadBindings(self);
}
});
totalHours.setConstraint(new Constraint() {
@Override
public void validate(Component comp, Object value)
throws WrongValueException {
if (!((OrderLine) orderElement)
.isTotalHoursValid((Integer) value)) {
throw new WrongValueException(comp,
_("Value is not valid, taking into account the current list of HoursGroup"));
}
}
});
}
reloadSelectedCriterionTypes();
selectCriterions.setVisible(true);
hoursGroupsListbox.invalidate();
Util.reloadBindings(self);
}
/**
* Toggle visibility of the selectCriterions {@link Vbox}
*/
public void manageCriterions() {
if (selectCriterions.isVisible()) {
selectCriterions.setVisible(false);
} else {
reloadSelectedCriterionTypes();
selectCriterions.setVisible(true);
}
Util.reloadBindings(selectCriterions);
}
/**
* Gets the set of possible {@link CriterionType}.
*
* @return A {@link Set} of {@link CriterionType}
*/
public Set<CriterionType> getCriterionTypes() {
if (orderElementModel == null) {
return new HashSet<CriterionType>();
}
List<CriterionType> list = orderElementModel.getCriterionTypes();
list.removeAll(getSelectedCriterionTypes());
return new HashSet<CriterionType>(list);
}
/**
* List of selected {@link CriterionType} just used in the controller
*/
private Set<CriterionType> selectedCriterionTypes = new LinkedHashSet<CriterionType>();
/**
* Returns the selected {@link CriterionType}.
*
* @return A {@link List} of {@link CriterionType}
*/
public Set<CriterionType> getSelectedCriterionTypes() {
return new HashSet<CriterionType>(selectedCriterionTypes);
}
public void setSelectedCriterionTypes(
Set<CriterionType> selectedCriterionTypes) {
this.selectedCriterionTypes = selectedCriterionTypes;
Util.reloadBindings(self);
}
/**
* Reloads the selected {@link CriterionType}, depending on the
* {@link Criterion} related with the {@link HoursGroup}
*/
private void reloadSelectedCriterionTypes() {
OrderElement orderElement = getOrderElement();
if (orderElement == null) {
selectedCriterionTypes = new LinkedHashSet<CriterionType>();
} else {
Set<CriterionType> criterionTypes = new LinkedHashSet<CriterionType>();
for (HoursGroup hoursGroup : orderElement.getHoursGroups()) {
Set<Criterion> criterions = orderElementModel
.getCriterionsHoursGroup(hoursGroup);
for (Criterion criterion : criterions) {
CriterionType type = orderElementModel.getCriterionType(criterion);
CriterionType criterionTypeByName = orderElementModel
.getCriterionTypeByName(type.getName());
criterionTypes.add(criterionTypeByName);
}
}
selectedCriterionTypes = criterionTypes;
}
}
/**
* Removes the {@link Criterion} which matches with this type for all the
* {@link HoursGroup}
*
* @param type
* The type of the {@link Criterion} that should be removed
*/
private void removeCriterionsFromHoursGroup(CriterionType type) {
OrderElement orderElement = getOrderElement();
for (HoursGroup hoursGroup : orderElement.getHoursGroups()) {
for (Criterion criterion : type.getCriterions()) {
hoursGroup.removeDirectCriterionRequirement(criterion);
}
}
}
public void close() {
validate();
Clients.closeErrorBox(hoursGroupsListbox);
}
public void validate() {
if (!getOrderElement().checkAtLeastOneHoursGroup()) {
throw new WrongValueException(hoursGroupsListbox, _("At least one HoursGroup is needed"));
}
for (CriterionType criterionType : getCriterionTypes()) {
removeCriterionsFromHoursGroup(criterionType);
}
}
}

View file

@ -24,7 +24,6 @@ import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.validator.NotNull;
import org.navalplanner.business.INewObject;
import org.navalplanner.business.orders.entities.HoursGroup;
import org.navalplanner.business.orders.entities.OrderElement;
@ -44,17 +43,16 @@ public class HoursGroupWrapper implements INewObject {
private Boolean newObject = false;
private Integer workingHours = 0;
private BigDecimal percentage = new BigDecimal(0);
private Boolean fixedPercentage = false;
private List<CriterionRequirementWrapper> directRequirementWrappers = new ArrayList<CriterionRequirementWrapper>();
private List<CriterionRequirementWrapper> exceptionRequirementWrappers = new ArrayList<CriterionRequirementWrapper>();
@NotNull
private Integer workingHours = 0;
private BigDecimal percentage = new BigDecimal(0).setScale(2);
private Boolean fixedPercentage = false;
private OrderElement orderElement;
private HoursGroup hoursGroup;
@ -68,14 +66,6 @@ public class HoursGroupWrapper implements INewObject {
initRequirementWrappers(hoursGroup);
}
// public HoursGroupWrapper(OrderElement orderElement,
// List<CriterionRequirementWrapper> list) {
// this.orderElement = orderElement;
// this.newObject = true;
// initRequirementWrappers(list);
// initExceptions();
// }
private void initRequirementWrappers(HoursGroup hoursGroup) {
directRequirementWrappers = new ArrayList<CriterionRequirementWrapper>();
for (CriterionRequirement requirement : hoursGroup
@ -115,18 +105,18 @@ public class HoursGroupWrapper implements INewObject {
}
public Integer getWorkingHours() {
return workingHours;
return hoursGroup.getWorkingHours();
}
public void setWorkingHours(Integer workingHours) {
this.workingHours = workingHours;
hoursGroup.setWorkingHours(workingHours);
}
public BigDecimal getPercentage() {
if (orderElement instanceof OrderLineGroup) {
return getPercentageInOrderLineGroup();
}
return percentage.scaleByPowerOfTen(2);
return hoursGroup.getPercentage().scaleByPowerOfTen(2);
}
private BigDecimal getPercentageInOrderLineGroup() {
@ -143,20 +133,21 @@ public class HoursGroupWrapper implements INewObject {
public void setPercentage(BigDecimal percentage) {
if (percentage != null) {
this.percentage = percentage.divide(new BigDecimal(100),
BigDecimal.ROUND_DOWN);
BigDecimal proportion = percentage.divide(
new BigDecimal(100), BigDecimal.ROUND_DOWN);
hoursGroup.setPercentage(proportion);
} else {
this.percentage = new BigDecimal(0).setScale(2);
hoursGroup.setPercentage(new BigDecimal(0).setScale(2));
}
}
public Boolean getFixedPercentage() {
return fixedPercentage;
return hoursGroup.isFixedPercentage();
}
public void setFixedPercentage(Boolean fixedPercentage) {
this.fixedPercentage = fixedPercentage;
hoursGroup.setFixedPercentage(fixedPercentage);
}
public HoursGroup getHoursGroup() {
@ -167,6 +158,16 @@ public class HoursGroupWrapper implements INewObject {
this.hoursGroup = hoursGroup;
}
public boolean isPercentageReadOnly() {
return (!hoursGroup.isFixedPercentage())
|| ((orderElement instanceof OrderLineGroup));
}
public boolean isWorkingHoursReadOnly() {
return (hoursGroup.isFixedPercentage())
|| ((orderElement instanceof OrderLineGroup));
}
/* Operations to manage the criterions requirements */
public void assignCriterionRequirementWrapper(
CriterionRequirementWrapper newRequirementWrapper) {

View file

@ -32,13 +32,17 @@ public interface IAssignedCriterionRequirementToOrderElementModel {
void setOrderModel(IOrderModel orderModel);
List<CriterionRequirementWrapper> getCriterionRequirementWrappers();
List<CriterionWithItsType> getCriterionWithItsTypes();
boolean canSetCriterionWithItsType(
CriterionRequirementWrapper requirementWrapper,
CriterionWithItsType criterionAndType);
CriterionRequirementWrapper validateWrappers();
CriterionRequirementWrapper validateWrappers(
List<CriterionRequirementWrapper> list);
CriterionRequirementWrapper validateHoursGroupWrappers();
void setValidCriterionRequirementWrapper(
CriterionRequirementWrapper requirement, boolean valid);
@ -64,5 +68,6 @@ public interface IAssignedCriterionRequirementToOrderElementModel {
void deleteCriterionToHoursGroup(HoursGroupWrapper hoursGroupWrapper,
CriterionRequirementWrapper requirementWrapper);
boolean isPercentageValid();
void updateHoursGroup();
}

View file

@ -139,7 +139,6 @@ public class OrderElementController extends GenericForwardComposer {
private void clearAll() {
clear();
detailsController.clear();
assignedLabelsController.clear();
}
@ -163,7 +162,6 @@ public class OrderElementController extends GenericForwardComposer {
}
private void closeAll() {
detailsController.close();
if (!manageOrderElementAdvancesController.close()) {
selectTab("tabAdvances");
return;

View file

@ -48,7 +48,7 @@
<tabpanel>
<listOrderElementLabels id="orderElementLabels" />
</tabpanel>
<tabpanel>
<tabpanel style="overflow:auto">
<listOrderElementCriterionRequirements id="orderElementCriterionRequirements"/>
</tabpanel>
</tabpanels>

View file

@ -20,12 +20,12 @@
<panel title="${i18n:_('Criterions Requirement')}" border="normal">
<panelchildren >
<newdatasortablegrid mold="paging" pageSize="10" fixedLayout="true"
<newdatasortablegrid mold="paging" pageSize="5" fixedLayout="true"
model="@{hoursGroupWrapper.criterionRequirementWrappersView}">
<columns>
<newdatasortablecolumn label="${i18n:_('Criterion name')}" sort="auto(criterionAndType)" sortDirection="ascending"/>
<newdatasortablecolumn label="${i18n:_('Type')}" sort="auto(type)" width="70px" align="center"/>
<newdatasortablecolumn label="${i18n:_('Operations')}" width="70px" align="center"/>
<newdatasortablecolumn label="${i18n:_('Type')}" sort="auto(type)" width="120px" align="center"/>
<newdatasortablecolumn label="${i18n:_('Operations')}" width="90px" align="center"/>
</columns>
<rows>
<row self="@{each='criterionRequirementWrapper'}" value="@{criterionRequirementWrapper}">

View file

@ -21,7 +21,8 @@
<?component name="listHoursGroupCriterionRequirements" inline="true" macroURI="_listHoursGroupCriterionRequirement.zul"?>
<vbox id="${arg.id}"
apply="org.navalplanner.web.orders.AssignedCriterionRequirementToOrderElementController">
<panel title="${i18n:_('Assigned Criterions Requirement')}" border="normal">
<panel title="${i18n:_('Assigned Criterions Requirement')}" border="normal"
style="overflow:auto" width="99%">
<panelchildren>
<hbox align="center">
<separator bar="false" spacing="40px" orient="horizontal"/>
@ -30,17 +31,18 @@
label="${i18n:_('Add criterion requirement')}" />
<separator bar="false" spacing="40px" orient="vertical"/>
</hbox>
<newdatasortablegrid id="listingRequirements" mold="paging" pageSize="10" fixedLayout="true"
<newdatasortablegrid id="listingRequirements" mold="paging"
pageSize="4" fixedLayout="true"
model="@{assignedCriterionRequirementController.criterionRequirementWrappers}">
<columns>
<newdatasortablecolumn label="${i18n:_('Criterion name')}" sort="auto(criterionAndType)" sortDirection="ascending"/>
<newdatasortablecolumn label="${i18n:_('Type')}" sort="auto(type)" width="70px" align="center"/>
<newdatasortablecolumn label="${i18n:_('Operations')}" width="70px" align="center"/>
<newdatasortablecolumn label="${i18n:_('Type')}" sort="auto(type)" width="100px" align="center"/>
<newdatasortablecolumn label="${i18n:_('Operations')}" width="150px" align="center"/>
</columns>
<rows>
<row self="@{each='criterionRequirementWrapper'}" value="@{criterionRequirementWrapper}">
<hbox>
<bandbox width="500px"
<bandbox width="500px"
visible ="@{criterionRequirementWrapper.updatable}"
value = "@{criterionRequirementWrapper.criterionAndType}">
<bandpopup>
@ -84,32 +86,49 @@
</row>
</rows>
</newdatasortablegrid>
<separator bar="false" spacing="40px" orient="vertical"/>
</panelchildren>
</panel>
<separator bar="false" spacing="80px" orient="vertical"/>
<vbox id= "containerHoursGroup">
</vbox>
<!--Manage Hours Groups-->
<panel title="${i18n:_('Hours Group')}" border="normal">
<panel title="${i18n:_('Total Hours OrderElement')}" border="normal"
width="200px">
<panelchildren>
<hbox visible = "@{assignedCriterionRequirementController.editableHoursGroup}">
<hbox align="center">
<separator bar="false" spacing="40px" orient="horizontal"/>
<separator bar="false" spacing="20px" orient="vertical"/>
<intbox id="orderElementTotalHours"
value = "@{assignedCriterionRequirementController.orderElement.workHours}"
onChange="assignedCriterionRequirementController.changeTotalHours();"
readonly = "@{assignedCriterionRequirementController.readOnly}"
constraint = "@{assignedCriterionRequirementController.validateTotalHours}"/>
<separator bar="false" spacing="20px" orient="vertical"/>
</hbox>
</panelchildren>
</panel>
<separator bar="false" spacing="80px" orient="vertical"/>
<!--Manage Hours Groups-->
<panel title="${i18n:_('Hours Group')}" border="normal" width="99%">
<panelchildren>
<hbox align="center"
visible = "@{assignedCriterionRequirementController.editableHoursGroup}">
<separator bar="false" spacing="40px" orient="horizontal"/>
<separator bar="false" spacing="20px" orient="vertical"/>
<button id="buttonAddHoursGroup"
label="${i18n:_('Add new hours group')}"
onClick="assignedCriterionRequirementController.addHoursGroup()" />
<separator bar="false" spacing="40px" orient="vertical"/>
<separator bar="false" spacing="20px" orient="vertical"/>
</hbox>
<grid id = "listHoursGroups" fixedLayout="true"
<grid id = "listHoursGroups" mold="paging" pageSize="4" fixedLayout="true"
model="@{assignedCriterionRequirementController.hoursGroupWrappers}">
<columns>
<column width="25px" />
<column label="Hours"/>
<column label="%"/>
<column label="Fixed %"/>
<column label="Operations" visible = "@{assignedCriterionRequirementController.editableHoursGroup}"/>
<column label="Hours" width="200px" align="center"/>
<column label="%" width="200px" align="center"/>
<column label="Fixed %" width="100px" align="center"/>
<column label="Operations" align="center"
visible = "@{assignedCriterionRequirementController.editableHoursGroup}"/>
</columns>
<rows>
<row self="@{each='hoursGroupWrapper'}" value="@{hoursGroupWrapper}">
@ -117,12 +136,15 @@
<listHoursGroupCriterionRequirements/>
</detail>
<intbox value="@{hoursGroupWrapper.workingHours}"
readonly ="@{assignedCriterionRequirementController.readOnly}"/>
readonly ="@{hoursGroupWrapper.workingHoursReadOnly}"
onChange = "assignedCriterionRequirementController.recalculateHoursGroup()"/>
<decimalbox scale = "2" value="@{hoursGroupWrapper.percentage}"
constraint = "@{assignedCriterionRequirementController.validatePercentage}"
readonly ="@{assignedCriterionRequirementController.readOnly}"/>
readonly ="@{hoursGroupWrapper.percentageReadOnly}"
onChange = "assignedCriterionRequirementController.recalculateHoursGroup()"/>
<checkbox checked="@{hoursGroupWrapper.fixedPercentage}"
disabled ="@{assignedCriterionRequirementController.readOnly}"/>
disabled ="@{assignedCriterionRequirementController.readOnly}"
onCheck = "assignedCriterionRequirementController.recalculateHoursGroup()"/>
<hbox
visible = "@{assignedCriterionRequirementController.editableHoursGroup}">
<button id="buttonDeleteHoursGroup"

View file

@ -39,11 +39,6 @@
<label value="${i18n:_('Mandatory')}" />
</hbox>
</row>
<row>
<label value="${i18n:_('Total hours')}" />
<intbox id="totalHours"
value="@{detailsController.orderElement.workHours}" />
</row>
<row>
<label value="${i18n:_('Description')}" />
<textbox id="description" rows="3"
@ -52,39 +47,4 @@
</row>
</rows>
</grid>
<!-- Hours group -->
<panel title="${i18n:_('Hours group')}">
<panelchildren>
<hbox>
<button id="btnAddHoursGroup"
label="${i18n:_('Add new hours group')}"
onClick="detailsController.addHoursGroup()" />
<button id="btnDeleteHoursGroup"
label="${i18n:_('Delete hours group')}"
onClick="detailsController.deleteHoursGroups()" />
</hbox>
<listbox id="hoursGroupsListbox" multiple="true"
model="@{detailsController.hoursGroups}"
itemRenderer="@{detailsController.renderer}" rows="3">
<listhead sizable="false">
<listheader label="${i18n:_('Hours')}" />
<listheader label="${i18n:_('%')}" />
</listhead>
</listbox>
</panelchildren>
</panel>
<!-- Manage criteria -->
<panel id="panelCriterions" title="${i18n:_('Manage criteria')}">
<panelchildren>
<vbox id="selectCriterions">
<twowayselector
assignedObjects="@{detailsController.selectedCriterionTypes, access='both'}"
assignedTitle="Selected types"
unassignedObjects="@{detailsController.criterionTypes}"
unassignedTitle="Criterion types" columns="name" />
</vbox>
</panelchildren>
</panel>
</vbox>