ItEr37S13CUAsignacionMateriaisAPedidoItEr36S15: Assign Materials to Order

This commit is contained in:
Diego Pino Garcia 2009-11-30 13:56:51 +01:00 committed by Javier Moran Rua
parent b4e81de660
commit 01249ee2a9
19 changed files with 1457 additions and 4 deletions

View file

@ -328,4 +328,33 @@ public class MutableTreeModel<T> extends AbstractTreeModel {
return getChildCount(node) > 0;
}
public boolean contains(T parent, T child) {
Node<T> parentNode = find(parent);
Node<T> childNode = find(child);
if (parentNode != null && (childNode != null && childNode.getParent() != null)) {
return childNode.getParent().equals(parentNode);
}
return false;
}
public List<T> asList() {
List<T> result = new ArrayList<T>();
asList(getRoot(), result);
return result;
}
private void asList(T root, List<T> result) {
List<T> list = new ArrayList<T>();
for (int i = 0; i < getChildCount(root); i++) {
final T child = getChild(root, i);
list.add(child);
result.add(child);
}
for (T each: list) {
asList(each, result);
}
}
}

View file

@ -440,6 +440,29 @@ public class MutableTreeModelTest {
assertThat(model.getChild(model.getRoot(), 1), equalTo(prueba2));
}
@Test
public void treeParentContainsChild() {
final MutableTreeModel<Prueba> model = MutableTreeModel
.create(Prueba.class);
Prueba parent = new Prueba();
model.addToRoot(parent);
Prueba child = new Prueba();
model.add(parent, child);
assertTrue(model.contains(parent, child));
}
@Test
public void treeParentDoesNotContainChild() {
final MutableTreeModel<Prueba> model = MutableTreeModel
.create(Prueba.class);
Prueba parent = new Prueba();
model.addToRoot(parent);
Prueba child = new Prueba();
assertFalse(model.contains(parent, child));
}
private void checkIsValid(TreeDataEvent event, int type,
Prueba expectedParent, int expectedPosition) {
checkIsValid(event, type, expectedParent, expectedPosition,
@ -461,4 +484,5 @@ public class MutableTreeModelTest {
}
return list.get(list.size() - 1);
}
}

View file

@ -21,17 +21,50 @@
package org.navalplanner.business.materials.daos;
import java.util.List;
import java.util.Set;
import org.navalplanner.business.common.daos.IGenericDAO;
import org.navalplanner.business.materials.entities.Material;
import org.navalplanner.business.materials.entities.MaterialCategory;
/**
* Interface IMaterialDAO
*
* @author Jacobo Aragunde Perez <jaragunde@igalia.com>
* @author Diego Pino Garcia <dpino@igalia.com>
*/
public interface IMaterialDAO extends IGenericDAO<Material, Long> {
/**
* Searches {@link Material} by code and description (ilike matching) within
* categories
*
* @param text
* @param categories
* @return
*/
List<Material> findMaterialsInCategories(String text,
Set<MaterialCategory> categories);
/**
* Searches {@link Material} by code and description (ilike matching) within
* category and its subcategories
*
* @param text
* @param materialCategory
* @return
*/
List<Material> findMaterialsInCategoryAndSubCategories(String text,
MaterialCategory materialCategory);
List<Material> getAll();
/**
* Returns all subcategories for materialCategory
*
* @param materialCategory
* @return
*/
Set<MaterialCategory> getAllSubcategories(MaterialCategory materialCategory);
}

View file

@ -20,10 +20,15 @@
package org.navalplanner.business.materials.daos;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.navalplanner.business.common.daos.GenericDAOHibernate;
import org.navalplanner.business.materials.entities.Material;
import org.navalplanner.business.materials.entities.MaterialCategory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
@ -32,6 +37,7 @@ import org.springframework.stereotype.Repository;
* DAO for {@link Material}
*
* @author Jacobo Aragunde Perez <jaragunde@igalia.com>
* @author Diego Pino Garcia <dpino@igalia.com>
*/
@Repository
@Scope(BeanDefinition.SCOPE_SINGLETON)
@ -43,4 +49,44 @@ public class MaterialDAO extends GenericDAOHibernate<Material, Long> implements
return list(Material.class);
}
@Override
public List<Material> findMaterialsInCategoryAndSubCategories(String text,
MaterialCategory materialCategory) {
Set<MaterialCategory> materialCategories = new HashSet<MaterialCategory>();
if (materialCategory != null) {
materialCategories.add(materialCategory);
materialCategories.addAll(getAllSubcategories(materialCategory));
}
return findMaterialsInCategories(text, materialCategories);
}
@Override
public Set<MaterialCategory> getAllSubcategories(MaterialCategory materialCategory) {
Set<MaterialCategory> result = new HashSet<MaterialCategory>();
getAllSubcategories(result, materialCategory.getSubcategories());
return result;
}
private void getAllSubcategories(Set<MaterialCategory> materialCategories, Set<MaterialCategory> subcategories) {
for (MaterialCategory each: subcategories) {
materialCategories.add(each);
getAllSubcategories(materialCategories, each.getSubcategories());
}
}
@SuppressWarnings("unchecked")
@Override
public List<Material> findMaterialsInCategories(String text,
Set<MaterialCategory> categories) {
Criteria criteria = this.getSession().createCriteria(Material.class);
text = "%" + text + "%";
criteria.add(Restrictions.or(Restrictions.ilike("code", text), Restrictions.eq("description", text)));
criteria.add(Restrictions.eq("disabled", false));
if (categories != null && !categories.isEmpty()) {
criteria.add(Restrictions.in("category", categories));
}
return criteria.list();
}
}

View file

@ -40,7 +40,7 @@ public class Material extends BaseEntity implements Comparable {
private String description;
private BigDecimal defaultUnitPrice;
private BigDecimal defaultUnitPrice = new BigDecimal(0);
private UnitTypeEnum unitType;
@ -113,7 +113,6 @@ public class Material extends BaseEntity implements Comparable {
@Override
public int compareTo(Object arg0) {
final Material material = (Material) arg0;
return code.compareTo(material.getCode());
}

View file

@ -0,0 +1,139 @@
/*
* This file is part of ###PROJECT_NAME###
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.business.materials.entities;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import org.navalplanner.business.common.BaseEntity;
import org.navalplanner.business.orders.entities.OrderElement;
/**
*
* @author Diego Pino Garcia <dpino@igalia.com>
*
*/
public class MaterialAssignment extends BaseEntity implements Comparable {
Material material;
double units = 0;
BigDecimal unitPrice = new BigDecimal(0);
Date estimatedAvailability;
MaterialStatusEnum status = MaterialStatusEnum.PENDING;
OrderElement orderElement;
public static MaterialAssignment create() {
return BaseEntity.create(new MaterialAssignment());
}
protected MaterialAssignment() {
}
public static MaterialAssignment create(Material material) {
MaterialAssignment materialAssignment = create();
materialAssignment.setUnitPrice(material.getDefaultUnitPrice());
materialAssignment.setMaterial(material);
return materialAssignment;
}
public static MaterialAssignment create(MaterialAssignment materialAssignment) {
MaterialAssignment result = create();
result.setMaterial(materialAssignment.getMaterial());
result.setUnits(materialAssignment.getUnits());
result.setUnitPrice(materialAssignment.getUnitPrice());
result.setEstimatedAvailability(materialAssignment.getEstimatedAvailability());
result.setStatus(materialAssignment.getStatus());
return result;
}
public Material getMaterial() {
return material;
}
public void setMaterial(Material material) {
this.material = material;
}
public double getUnits() {
return units;
}
public void setUnits(double units) {
this.units = units;
}
public BigDecimal getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(BigDecimal unitPrice) {
this.unitPrice = unitPrice;
}
public BigDecimal getTotalPrice() {
BigDecimal result = new BigDecimal(getUnits());
return result.multiply(getUnitPrice());
}
public void setTotalPrice(BigDecimal totalPrice) {
BigDecimal unitPrice = totalPrice;
unitPrice = unitPrice.divide(new BigDecimal(units), 3, RoundingMode.HALF_UP);
setUnitPrice(unitPrice);
}
public Date getEstimatedAvailability() {
return estimatedAvailability;
}
public void setEstimatedAvailability(Date estimatedAvailability) {
this.estimatedAvailability = estimatedAvailability;
}
public MaterialStatusEnum getStatus() {
return status;
}
public void setStatus(MaterialStatusEnum status) {
this.status = status;
}
public OrderElement getOrderElement() {
return orderElement;
}
public void setOrderElement(OrderElement orderElement) {
this.orderElement = orderElement;
}
@Override
public int compareTo(Object arg0) {
final MaterialAssignment materialAssignment = (MaterialAssignment) arg0;
return materialAssignment.getMaterial().compareTo(getMaterial());
}
}

View file

@ -0,0 +1,34 @@
/*
* This file is part of ###PROJECT_NAME###
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.business.materials.entities;
/**
*
* @author Diego Pino Garcia <dpino@igalia.com>
*
*/
public enum MaterialStatusEnum {
RECEIVED,
PENDING,
ORDERED,
PROCESSING,
CANCELED
}

View file

@ -42,6 +42,7 @@ import org.navalplanner.business.advance.exceptions.DuplicateAdvanceAssignmentFo
import org.navalplanner.business.advance.exceptions.DuplicateValueTrueReportGlobalAdvanceException;
import org.navalplanner.business.common.BaseEntity;
import org.navalplanner.business.labels.entities.Label;
import org.navalplanner.business.materials.entities.MaterialAssignment;
import org.navalplanner.business.orders.entities.SchedulingState.ITypeChangedListener;
import org.navalplanner.business.orders.entities.SchedulingState.Type;
import org.navalplanner.business.orders.entities.TaskSource.TaskSourceSynchronization;
@ -68,6 +69,8 @@ public abstract class OrderElement extends BaseEntity {
protected Set<DirectAdvanceAssignment> directAdvanceAssignments = new HashSet<DirectAdvanceAssignment>();
protected Set<MaterialAssignment> materialAssignments = new HashSet<MaterialAssignment>();
private Set<Label> labels = new HashSet<Label>();
private String code;
@ -262,6 +265,13 @@ public abstract class OrderElement extends BaseEntity {
public void setInitDate(Date initDate) {
this.initDate = initDate;
updateMaterialAssigmentsEstimatedAvailability(this.initDate);
}
private void updateMaterialAssigmentsEstimatedAvailability(Date estimatedAvailability) {
for (MaterialAssignment each: materialAssignments) {
each.setEstimatedAvailability(estimatedAvailability);
}
}
public Date getDeadline() {
@ -644,4 +654,38 @@ public abstract class OrderElement extends BaseEntity {
result.add(taskSource);
}
}
public Set<MaterialAssignment> getMaterialAssignments() {
return Collections.unmodifiableSet(materialAssignments);
}
public void addMaterialAssignment(MaterialAssignment materialAssignment) {
materialAssignments.add(materialAssignment);
materialAssignment.setOrderElement(this);
}
public void removeMaterialAssignment(MaterialAssignment materialAssignment) {
materialAssignments.remove(materialAssignment);
}
public double getTotalMaterialAssigmentUnits() {
double result = 0;
final Set<MaterialAssignment> materialAssigments = getMaterialAssignments();
for (MaterialAssignment each: materialAssigments) {
result += each.getUnits();
}
return result;
}
public BigDecimal getTotalMaterialAssigmentPrice() {
BigDecimal result = new BigDecimal(0);
final Set<MaterialAssignment> materialAssigments = getMaterialAssignments();
for (MaterialAssignment each: materialAssigments) {
result = result.add(each.getTotalPrice());
}
return result;
}
}

View file

@ -54,4 +54,31 @@
</class>
<!-- MaterialAssignment -->
<class name="MaterialAssignment" table="MATERIAL_ASSIGMENT">
<id name="id" type="long" access="property">
<generator class="hilo">
<param name="max_lo">100</param>
</generator>
</id>
<version name="version" access="property" type="long" />
<property name="units" />
<property name="unitPrice" column="UNIT_PRICE" />
<property name="estimatedAvailability" column="ESTIMATED_AVAILABILITY" />
<property name="status">
<type name="org.hibernate.type.EnumType">
<param name="enumClass">org.navalplanner.business.materials.entities.MaterialStatusEnum</param>
</type>
</property>
<many-to-one name="orderElement" class="org.navalplanner.business.orders.entities.OrderElement" column="ORDER_ELEMENT_ID" />
<many-to-one name="material" class="Material" column="MATERIAL_ID" />
</class>
</hibernate-mapping>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.navalplanner.business.orders.entities">
<hibernate-mapping package="org.navalplanner.business.orders.entities" default-access="field">
<class name="OrderElement" abstract="true">
<id name="id" access="property" type="long">
<generator class="hilo" >
@ -37,6 +37,11 @@
<one-to-many class="org.navalplanner.business.requirements.entities.CriterionRequirement"/>
</set>
<set name="materialAssignments" cascade="all-delete-orphan" inverse="true">
<key column="ORDER_ELEMENT_ID" not-null="true" />
<one-to-many class="org.navalplanner.business.materials.entities.MaterialAssignment" />
</set>
<!-- Inverse navigation from OrderElement to OrderLineGroup -->
<many-to-one name="parent" access="field" cascade="all"/>

View file

@ -0,0 +1,463 @@
/*
* This file is part of ###PROJECT_NAME###
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.web.orders;
import static org.navalplanner.web.I18nHelper._;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.LogFactory;
import org.navalplanner.business.materials.entities.Material;
import org.navalplanner.business.materials.entities.MaterialAssignment;
import org.navalplanner.business.materials.entities.MaterialCategory;
import org.navalplanner.business.orders.entities.OrderElement;
import org.navalplanner.web.common.Util;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.SuspendNotAllowedException;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Doublebox;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Label;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Row;
import org.zkoss.zul.SimpleListModel;
import org.zkoss.zul.Tab;
import org.zkoss.zul.Tree;
import org.zkoss.zul.TreeModel;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.TreeitemRenderer;
import org.zkoss.zul.Treerow;
import org.zkoss.zul.api.Textbox;
import org.zkoss.zul.impl.MessageboxDlg;
/**
* Controller for showing {@link OrderElement} assigned {@link Material}
*
* @author Diego Pino García <dpino@igalia.com>
*
*/
public class AssignedMaterialsToOrderElementController extends
GenericForwardComposer {
private static final org.apache.commons.logging.Log LOG = LogFactory.getLog(AssignedMaterialsToOrderElementController.class);
private IAssignedMaterialsToOrderElementModel assignedMaterialsToOrderElementModel;
private Tree categoriesTree;
private Tree allCategoriesTree;
private Grid gridMaterials;
private Listbox lbFoundMaterials;
private Textbox txtSearchMaterial;
private Tab tbAssignedMaterials;
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
comp.setVariable("assignedMaterialsController", this, true);
}
public void openWindow(IOrderElementModel orderElementModel) {
assignedMaterialsToOrderElementModel.initEdit(orderElementModel);
prepareCategoriesTree();
prepareAllCategoriesTree();
}
/**
* Delay initialization of categories tree till user clicks on Materials tab
*
* Initializing model and renderer properties directly in ZUL resulted in calling the renderer
* more times than actually needed, resulting in noticeable lack of performance
*/
private void prepareCategoriesTree() {
if (categoriesTree.getTreeitemRenderer() == null) {
categoriesTree.setTreeitemRenderer(getMaterialCategoryWithUnitsAndPriceRenderer());
}
categoriesTree.setModel(getMaterialCategories());
}
public TreeModel getMaterialCategories() {
return assignedMaterialsToOrderElementModel.getMaterialCategories();
}
private void prepareAllCategoriesTree() {
if (allCategoriesTree.getTreeitemRenderer() == null) {
allCategoriesTree.setTreeitemRenderer(getMaterialCategoryRenderer());
}
allCategoriesTree.setModel(getAllMaterialCategories());
}
public TreeModel getAllMaterialCategories() {
return assignedMaterialsToOrderElementModel.getAllMaterialCategories();
}
public double getTotalUnits() {
double result = 0;
final OrderElement orderElement = getOrderElement();
if (orderElement != null) {
result = orderElement.getTotalMaterialAssigmentUnits();
}
return result;
}
public BigDecimal getTotalPrice() {
BigDecimal result = new BigDecimal(0);
final OrderElement orderElement = getOrderElement();
if (orderElement != null) {
result = orderElement.getTotalMaterialAssigmentPrice();
}
return result.setScale(2, RoundingMode.HALF_UP);
}
private OrderElement getOrderElement() {
return assignedMaterialsToOrderElementModel.getOrderElement();
}
/**
* On selecting category, refresh {@link MaterialAssignment} associated with
* selected {@link MaterialCategory}
*/
public void refreshMaterialAssigments() {
final List<MaterialAssignment> materials = getAssignedMaterials();
gridMaterials.setModel(new SimpleListModel(materials));
Util.reloadBindings(gridMaterials);
}
public List<MaterialAssignment> getAssignedMaterials() {
final Treeitem treeitem = categoriesTree.getSelectedItem();
return getAssignedMaterials(treeitem);
}
private List<MaterialAssignment> getAssignedMaterials(Treeitem treeitem) {
final MaterialCategory materialCategory = (treeitem != null) ? (MaterialCategory) treeitem.getValue() : null;
return getAssignedMaterials(materialCategory);
}
private List<MaterialAssignment> getAssignedMaterials(MaterialCategory materialCategory) {
return assignedMaterialsToOrderElementModel.getAssignedMaterials(materialCategory);
}
/**
* On changing total price, recalculate unit price and refresh categories tree
*
* @param row
*/
public void updateTotalPrice(Row row) {
final MaterialAssignment materialAssignment = (MaterialAssignment) row
.getValue();
Doublebox totalPrice = (Doublebox) row.getChildren().get(5);
totalPrice.setValue(materialAssignment.getTotalPrice().doubleValue());
refreshTotalPriceAndTotalUnits(materialAssignment);
}
/**
* Refresh categoriesTree since it shows totalUnits and totalPrice as well
*/
private void refreshTotalPriceAndTotalUnits(MaterialAssignment materialAssignment) {
final Treeitem item = findMaterialCategoryInTree(materialAssignment
.getMaterial().getCategory(), categoriesTree);
if (item != null) {
// Reload categoriesTree
categoriesTree.setModel(getMaterialCategories());
}
}
/**
* On changing unit price, recalculate total price and refresh categories tree
*
* @param row
*/
public void updateUnitPrice(Row row) {
final MaterialAssignment materialAssignment = (MaterialAssignment) row.getValue();
Doublebox unitPrice = (Doublebox) row.getChildren().get(4);
unitPrice.setValue(materialAssignment.getUnitPrice().doubleValue());
refreshTotalPriceAndTotalUnits(materialAssignment);
}
/**
* Finds which {@link Treeitem} in tree is associated with category
*
* @param category
* @param tree
* @return
*/
private Treeitem findMaterialCategoryInTree(MaterialCategory category, Tree tree) {
for (Iterator i = tree.getItems().iterator(); i.hasNext(); ) {
Treeitem treeitem = (Treeitem) i.next();
final MaterialCategory materialCategory = (MaterialCategory) treeitem.getValue();
if (category.equals(materialCategory)) {
return treeitem;
}
}
return null;
}
/**
* Search materials on pressing search button
*/
public void searchMaterials() {
final String text = txtSearchMaterial.getValue();
final MaterialCategory materialCategory = getSelectedCategory(allCategoriesTree);
assignedMaterialsToOrderElementModel.searchMaterials(text, materialCategory);
Util.reloadBindings(lbFoundMaterials);
}
/**
* Returns {@link MaterialCategory} associated with selected {@link Treeitem} in {@link Tree}
*
* @param tree
* @return
*/
private MaterialCategory getSelectedCategory(Tree tree) {
final Treeitem treeitem = tree.getSelectedItem();
return (treeitem != null) ? (MaterialCategory) treeitem.getValue() : null;
}
/**
* Get materials found on latest search
*
* @return
*/
public List<Material> getMatchingMaterials() {
return assignedMaterialsToOrderElementModel.getMatchingMaterials();
}
/**
* Assigns a list of selected {@link Material} to current {@link OrderElement}
*/
public void assignSelectedMaterials() {
Set<Material> materials = getSelectedMaterials();
if (materials.isEmpty()) {
return;
}
for(Material each: materials) {
assignedMaterialsToOrderElementModel.addMaterialAssignment(each);
}
categoriesTree.clearSelection();
tbAssignedMaterials.setSelected(true);
lbFoundMaterials.clearSelection();
Util.reloadBindings(categoriesTree);
Util.reloadBindings(gridMaterials);
}
private Set<Material> getSelectedMaterials() {
Set<Material> result = new HashSet<Material>();
final Set<Listitem> listitems = lbFoundMaterials.getSelectedItems();
for (Listitem each: listitems) {
final Material material = (Material) each.getValue();
result.add(material);
}
return result;
}
public MaterialCategoryRenderer getMaterialCategoryRenderer() {
return new MaterialCategoryRenderer();
}
private class MaterialCategoryRenderer implements TreeitemRenderer {
/**
* Copied verbatim from org.zkoss.zul.Tree;
*/
@Override
public void render(Treeitem ti, Object node) throws Exception {
final MaterialCategory materialCategory = (MaterialCategory) node;
Label lblName = new Label(materialCategory.getName());
Treerow tr = null;
ti.setValue(node);
if (ti.getTreerow() == null) {
tr = new Treerow();
tr.setParent(ti);
ti.setOpen(true); // Expand node
} else {
tr = ti.getTreerow();
tr.getChildren().clear();
}
// Add category name
Treecell cellName = new Treecell();
lblName.setParent(cellName);
cellName.setParent(tr);
}
}
public MaterialCategoryWithUnitsAndPriceRenderer getMaterialCategoryWithUnitsAndPriceRenderer() {
return new MaterialCategoryWithUnitsAndPriceRenderer();
}
private class MaterialCategoryWithUnitsAndPriceRenderer implements TreeitemRenderer {
/**
* Copied verbatim from org.zkoss.zul.Tree;
*/
@Override
public void render(Treeitem ti, Object node) throws Exception {
final MaterialCategory materialCategory = (MaterialCategory) node;
Label lblName = new Label(materialCategory.getName());
Label lblUnits = new Label(new Double(getUnits(materialCategory)).toString());
Label lblPrice = new Label(getPrice(materialCategory).toString());
Treerow tr = null;
ti.setValue(node);
if (ti.getTreerow() == null) {
tr = new Treerow();
tr.setParent(ti);
ti.setOpen(true); // Expand node
} else {
tr = ti.getTreerow();
tr.getChildren().clear();
}
// Add category name
Treecell cellName = new Treecell();
lblName.setParent(cellName);
cellName.setParent(tr);
// Add total assigned material units in category
Treecell cellUnits = new Treecell();
lblUnits.setParent(cellUnits);
cellUnits.setParent(tr);
// Add total price for assigned materials in category
Treecell cellPrice = new Treecell();
lblPrice.setParent(cellPrice);
cellPrice.setParent(tr);
}
private double getUnits(MaterialCategory materialCategory) {
return assignedMaterialsToOrderElementModel.getUnits(materialCategory);
}
private BigDecimal getPrice(MaterialCategory materialCategory) {
return assignedMaterialsToOrderElementModel.getPrice(materialCategory);
}
}
/**
* On clicking remove {@link MaterialAssignment}, shows dialog for
* confirming removing selected element
*
* @param materialAssignment
*/
public void showRemoveMaterialAssignmentDlg(MaterialAssignment materialAssignment) {
try {
int status = Messagebox.show(_("Delete item {0}. Are you sure?", materialAssignment.getMaterial().getCode()),
_("Delete"), Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION);
if (Messagebox.OK == status) {
removeMaterialAssignment(materialAssignment);
}
} catch (InterruptedException e) {
LOG.error(_("Error on showing delete materialAssignment: ", materialAssignment.getId()), e);
}
}
private void removeMaterialAssignment(MaterialAssignment materialAssignment) {
assignedMaterialsToOrderElementModel.removeMaterialAssignment(materialAssignment);
Util.reloadBindings(gridMaterials);
// Reload categoriesTree
categoriesTree.setModel(getMaterialCategories());
}
/**
* On clicking Split button, shows dialog for splitting selected
* {@link MaterialAssignment} into two
*
* @param materialAssignment
*/
@SuppressWarnings("unchecked")
public void showSplitMaterialAssignmentDlg(MaterialAssignment materialAssignment) {
MessageboxDlg dialogSplitAssignment;
final String message = _("Create new material assignment out of material assignment {0}. Are you sure?",
materialAssignment.getMaterial().getCode());
Map args = new HashMap();
args.put("message", message);
args.put("title", _("Split new assignment"));
args.put("OK", Messagebox.OK);
args.put("CANCEL", Messagebox.CANCEL);
args.put("icon", Messagebox.QUESTION);
dialogSplitAssignment = (MessageboxDlg) Executions
.createComponents("/orders/_splitMaterialAssignmentDlg.zul",
self, args);
Doublebox dbUnits = (Doublebox) dialogSplitAssignment.getFellowIfAny("dbUnits");
dbUnits.setValue(materialAssignment.getUnits());
try {
dialogSplitAssignment.doModal();
int status = dialogSplitAssignment.getResult();
if (Messagebox.OK == status) {
splitMaterialAssignment(materialAssignment, dbUnits.getValue());
}
} catch (SuspendNotAllowedException e) {
LOG.error(_("Error on splitting element: ", materialAssignment.getId()), e);
} catch (InterruptedException e) {
LOG.error(_("Error on splitting element: ", materialAssignment.getId()), e);
}
}
/**
* Creates a new {@link MaterialAssignment} out of materialAssignment, but
* setting its units attribute to units.
*
* materialAssignment passed as parameter decreases its units attribute in units
*
* @param materialAssignment
* @param units
*/
private void splitMaterialAssignment(MaterialAssignment materialAssignment, double units) {
MaterialAssignment newMaterialAssignment = MaterialAssignment.create(materialAssignment);
double currentUnits = materialAssignment.getUnits();
if (units > currentUnits) {
units = currentUnits;
currentUnits = 0;
} else {
currentUnits -= units;
}
newMaterialAssignment.setUnits(units);
materialAssignment.setUnits(currentUnits);
assignedMaterialsToOrderElementModel.addMaterialAssignment(newMaterialAssignment);
Util.reloadBindings(gridMaterials);
}
}

View file

@ -0,0 +1,268 @@
/*
* This file is part of ###PROJECT_NAME###
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.web.orders;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.navalplanner.business.materials.daos.IMaterialCategoryDAO;
import org.navalplanner.business.materials.daos.IMaterialDAO;
import org.navalplanner.business.materials.entities.Material;
import org.navalplanner.business.materials.entities.MaterialAssignment;
import org.navalplanner.business.materials.entities.MaterialCategory;
import org.navalplanner.business.orders.daos.IOrderElementDAO;
import org.navalplanner.business.orders.entities.OrderElement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zkoss.ganttz.util.MutableTreeModel;
import org.zkoss.zul.TreeModel;
/**
* @author Diego Pino Garcia <dpino@igalia.com>
*/
@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class AssignedMaterialsToOrderElementModel implements
IAssignedMaterialsToOrderElementModel {
@Autowired
private IMaterialCategoryDAO categoryDAO;
@Autowired
private IMaterialDAO materialDAO;
@Autowired
private IOrderElementDAO orderElementDAO;
private IOrderElementModel orderElementModel;
private OrderElement orderElement;
private MutableTreeModel<MaterialCategory> materialCategories = MutableTreeModel
.create(MaterialCategory.class);
private MutableTreeModel<MaterialCategory> allMaterialCategories = MutableTreeModel
.create(MaterialCategory.class);
private List<Material> matchingMaterials = new ArrayList<Material>();
@Override
@Transactional(readOnly = true)
public void initEdit(IOrderElementModel orderElementModel) {
this.orderElementModel = orderElementModel;
this.orderElement = this.orderElementModel.getOrderElement();
orderElementDAO.reattach(this.orderElement);
materialCategories = MutableTreeModel.create(MaterialCategory.class);
initializeMaterialAssigments(this.orderElement.getMaterialAssignments());
// Initialize matching materials
matchingMaterials.clear();
matchingMaterials.addAll(materialDAO.getAll());
initializeMaterials(matchingMaterials);
}
private void initializeMaterialAssigments(
Set<MaterialAssignment> materialAssignments) {
for (MaterialAssignment each : materialAssignments) {
each.getStatus();
initializeMaterialCategory(each.getMaterial().getCategory());
}
}
@Transactional(readOnly = true)
private void initializeMaterialCategories(
Collection<MaterialCategory> materialCategories) {
for (MaterialCategory each : materialCategories) {
initializeMaterialCategory(each);
}
}
private void initializeMaterialCategory(MaterialCategory materialCategory) {
materialCategory.getName();
initializeMaterials(materialCategory.getMaterials());
initializeMaterialCategories(materialCategory.getSubcategories());
}
private void initializeMaterials(Collection<Material> materials) {
for (Material each : materials) {
initializeMaterial(each);
}
}
private void initializeMaterial(Material material) {
material.getDescription();
material.getCategory().getName();
}
@Override
public OrderElement getOrderElement() {
return orderElement;
}
@Override
@Transactional(readOnly = true)
public MutableTreeModel<MaterialCategory> getMaterialCategories() {
if (orderElement != null && materialCategories.isEmpty()) {
feedTree(materialCategories, orderElement.getMaterialAssignments());
initializeMaterialCategories(materialCategories.asList());
}
return materialCategories;
}
private void feedTree(MutableTreeModel<MaterialCategory> tree,
Set<MaterialAssignment> materialAssignments) {
for (MaterialAssignment each : materialAssignments) {
final Material material = (Material) each.getMaterial();
addCategory(tree, material.getCategory());
}
}
/**
* Adds category to treeModel
*
* If category.parent is not in treeModel add it to treeModel recursively.
*
*/
private void addCategory(
MutableTreeModel<MaterialCategory> materialCategories,
MaterialCategory materialCategory) {
categoryDAO.reattach(materialCategory);
final MaterialCategory parent = materialCategory.getParent();
if (parent == null) {
if (!materialCategories.contains(parent, materialCategory)) {
materialCategories.addToRoot(materialCategory);
}
} else {
if (!materialCategories.contains(parent, materialCategory)) {
addCategory(materialCategories, parent);
materialCategories.add(parent, materialCategory);
}
}
}
@Override
@Transactional(readOnly = true)
public TreeModel getAllMaterialCategories() {
if (allMaterialCategories.isEmpty()) {
feedTree(allMaterialCategories, categoryDAO.getAll());
initializeMaterialCategories(allMaterialCategories.asList());
}
return allMaterialCategories;
}
private void feedTree(MutableTreeModel<MaterialCategory> tree,
List<MaterialCategory> materialCategories) {
for (MaterialCategory each : materialCategories) {
addCategory(tree, each);
}
}
@Override
public List<MaterialAssignment> getAssignedMaterials(
MaterialCategory materialCategory) {
List<MaterialAssignment> result = new ArrayList<MaterialAssignment>();
if (orderElement != null) {
for (MaterialAssignment materialAssigment : orderElement
.getMaterialAssignments()) {
final Material material = materialAssigment.getMaterial();
if (materialCategory == null
|| materialCategory.equals(material.getCategory())) {
result.add(materialAssigment);
}
}
}
return result;
}
@Override
@Transactional(readOnly = true)
public void searchMaterials(String text, MaterialCategory materialCategory) {
matchingMaterials = materialDAO
.findMaterialsInCategoryAndSubCategories(text, materialCategory);
initializeMaterials(matchingMaterials);
}
@Override
public List<Material> getMatchingMaterials() {
return matchingMaterials;
}
@Override
@Transactional(readOnly = true)
public void addMaterialAssignment(Material material) {
MaterialAssignment materialAssigment = MaterialAssignment
.create(material);
materialAssigment.setEstimatedAvailability(orderElement.getInitDate());
addMaterialAssignment(materialAssigment);
}
@Override
@Transactional(readOnly = true)
public void addMaterialAssignment(MaterialAssignment materialAssignment) {
orderElement.addMaterialAssignment(materialAssignment);
// Add material category to materialCategories tree
final MaterialCategory materialCategory = materialAssignment.getMaterial().getCategory();
addCategory(materialCategories, materialCategory);
}
@Override
public void removeMaterialAssignment(MaterialAssignment materialAssignment) {
orderElement.removeMaterialAssignment(materialAssignment);
}
@Override
public double getUnits(MaterialCategory materialCategory) {
double result = 0;
if (orderElement != null) {
for (MaterialAssignment materialAssignment : orderElement
.getMaterialAssignments()) {
final Material material = materialAssignment.getMaterial();
if (materialCategory.equals(material.getCategory())) {
result += materialAssignment.getUnits();
}
}
}
return result;
}
@Override
public BigDecimal getPrice(MaterialCategory materialCategory) {
BigDecimal result = new BigDecimal(0);
if (orderElement != null) {
for (MaterialAssignment materialAssignment : orderElement
.getMaterialAssignments()) {
final Material material = materialAssignment.getMaterial();
if (materialCategory.equals(material.getCategory())) {
result = result.add(materialAssignment.getTotalPrice());
}
}
}
return result;
}
}

View file

@ -0,0 +1,102 @@
/*
* This file is part of ###PROJECT_NAME###
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.web.orders;
import java.math.BigDecimal;
import java.util.List;
import org.navalplanner.business.materials.entities.Material;
import org.navalplanner.business.materials.entities.MaterialAssignment;
import org.navalplanner.business.materials.entities.MaterialCategory;
import org.navalplanner.business.orders.entities.OrderElement;
import org.zkoss.zul.TreeModel;
/**
* @author Diego Pino Garcia <dpino@igalia.com>
*/
public interface IAssignedMaterialsToOrderElementModel {
/**
* Add a new {@link MaterialAssignment} out of {@link Material}
*
* @param each
*/
void addMaterialAssignment(Material material);
/**
* Add a new {@link MaterialAssignment} out of existing {@link MaterialAssignment}
*
* @param materialAssignment
*/
void addMaterialAssignment(MaterialAssignment materialAssignment);
TreeModel getAllMaterialCategories();
List<MaterialAssignment> getAssignedMaterials(MaterialCategory materialCategory);
/**
* Returns list of {@link Material} found after executing latest search
*
* @return
*/
List<Material> getMatchingMaterials();
/**
* Get list of {@link MaterialCategory} assigned to current {@link OrderElement}
*
* @return
*/
TreeModel getMaterialCategories();
OrderElement getOrderElement();
/**
* Calculates sum of price for all {@link MaterialAssignment} which belong
* to {@link MaterialCategory}
*
* @param materialCategory
* @return
*/
BigDecimal getPrice(MaterialCategory materialCategory);
/**
* Calculates sum of units for all {@link MaterialAssignment} which belong
* to {@link MaterialCategory}
*
* @param materialCategory
* @return
*/
double getUnits(MaterialCategory materialCategory);
void initEdit(IOrderElementModel orderElementModel);
void removeMaterialAssignment(MaterialAssignment materialAssignment);
/**
* Searches materials in categories and its subcategories by code and
* description
*
* @param code
* @param materialCategory
*/
void searchMaterials(String text, MaterialCategory materialCategory);
}

View file

@ -115,12 +115,14 @@ public class OrderCRUDController extends GenericForwardComposer {
OrderElementController orderElementController = new OrderElementController();
orderElementController.doAfterCompose(comp
.getFellow("editOrderElement"));
setupOrderElementTreeController(comp, orderElementController);
setupDetailsOrderElementController(comp);
setupAsignedHoursToOrderElementController(comp);
setupManageOrderElementAdvancesController(comp);
setupAssignedLabelsToOrderElementController(comp);
setupAssignedCriterionRequirementsToOrderElementController(comp);
setupAssignedMaterialsToOrderElementController(comp);
}
private void setupOrderElementTreeController(Component comp,
@ -178,6 +180,16 @@ public class OrderCRUDController extends GenericForwardComposer {
.getVariable("assignedCriterionRequirementController", true);
}
private AssignedMaterialsToOrderElementController assignedMaterialsController;
private void setupAssignedMaterialsToOrderElementController(
Component comp) throws Exception {
Component orderElementMaterials = editWindow
.getFellowIfAny("orderElementMaterials");
assignedMaterialsController = (AssignedMaterialsToOrderElementController) orderElementMaterials
.getVariable("assignedMaterialsController", true);
}
public List<Order> getOrders() {
return orderModel.getOrders();
}
@ -315,6 +327,7 @@ public class OrderCRUDController extends GenericForwardComposer {
manageOrderElementAdvancesController.openWindow(orderElementModel);
assignedLabelsController.openWindow(orderElementModel);
assignedCriterionRequirementController.openWindow(orderElementModel);
assignedMaterialsController.openWindow(orderElementModel);
}
private void clearEditWindow() {

View file

@ -40,7 +40,7 @@
<component-class>org.navalplanner.web.common.components.NewDataSortableColumn</component-class>
<extends>column</extends>
</component>
<component>
<component-name>schedulingStateToggler</component-name>
<component-class>org.navalplanner.web.orders.SchedulingStateToggler</component-class>
@ -61,4 +61,13 @@
</annotation>
</component>
<component>
<component-name>doublebox</component-name>
<extends>doublebox</extends>
<property>
<property-name>format</property-name>
<property-value>###,##0.00####</property-value>
</property>
</component>
</language-addon>

View file

@ -24,6 +24,8 @@
<?component name="listOrderElementAdvances" inline="true" macroURI="_listOrderElementAdvances.zul"?>
<?component name="listOrderElementLabels" inline="true" macroURI="_listOrderElementLabels.zul"?>
<?component name="listOrderElementCriterionRequirements" inline="true" macroURI="_listOrderElementCriterionRequirements.zul"?>
<?component name="listOrderElementMaterials" inline="true" macroURI="_listOrderElementMaterials.zul"?>
<window id="${arg.top_id}">
<tabbox>
<tabs>
@ -35,6 +37,7 @@
<tab label="${i18n:_('Label')}" />
<tab id="tabRequirements" label="${i18n:_('Criterion Requirement')}"
onClick = "controller.reloadHoursGroupOrder();"/>
<tab label="${i18n:_('Materials')}" />
</tabs>
<tabpanels>
<tabpanel>
@ -111,6 +114,9 @@
<tabpanel>
<listOrderElementCriterionRequirements id="orderElementCriterionRequirements"/>
</tabpanel>
<tabpanel>
<listOrderElementMaterials id="orderElementMaterials"/>
</tabpanel>
</tabpanels>
</tabbox>
<hbox>

View file

@ -0,0 +1,180 @@
<!--
This file is part of ###PROJECT_NAME###
Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
Desenvolvemento Tecnolóxico de Galicia
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<vbox id="${arg.id}"
apply="org.navalplanner.web.orders.AssignedMaterialsToOrderElementController" >
<zscript>
Object[] unitTypes = org.navalplanner.business.materials.entities.UnitTypeEnum
.values();
Object[] materialStatus = org.navalplanner.business.materials.entities.MaterialStatusEnum
.values();
</zscript>
<tabbox mold="accordion-lite">
<tabs>
<tab id="tbAssignedMaterials" label="${i18n:_('Materials')}" image="common/img/ico_bajar.png"/>
<tab label="${i18n:_('Material search')}" image="common/img/ico_bajar.png"/>
</tabs>
<tabpanels>
<tabpanel>
<hbox>
<!-- Categories -->
<vbox>
<panel title="${i18n:_('Categories')}" border="normal">
<panelchildren>
<toolbarbutton style="text-decoration: none" label="${i18n:_('Unselect')}" onClick="categoriesTree.clearSelection()" />
<tree id="categoriesTree"
fixedLayout="false"
width="280px" rows="10" vflex="true" multiple="false"
onSelect="assignedMaterialsController.refreshMaterialAssigments()">
<treecols>
<treecol label="Name" />
<treecol label="Units" width="50px" />
<treecol label="Price" width="50px" />
</treecols>
</tree>
</panelchildren>
</panel>
</vbox>
<!-- Materials -->
<vbox>
<panel title="${i18n:_('Materials')}"
border="normal">
<panelchildren>
<newdatasortablegrid id="gridMaterials"
fixedLayout="false"
model="@{assignedMaterialsController.assignedMaterials}">
<columns>
<newdatasortablecolumn label="${i18n:_('Code')}" />
<newdatasortablecolumn label="${i18n:_('Date')}" />
<newdatasortablecolumn label="${i18n:_('Units')}" />
<newdatasortablecolumn label="${i18n:_('Unit type')}" />
<newdatasortablecolumn label="${i18n:_('Unit price')}" />
<newdatasortablecolumn label="${i18n:_('Total price')}" />
<newdatasortablecolumn label="${i18n:_('Category')}" />
<newdatasortablecolumn label="${i18n:_('Status')}" />
<newdatasortablecolumn label="" />
</columns>
<rows>
<row self="@{each='assignedMaterial'}" value="@{assignedMaterial}">
<textbox value="@{assignedMaterial.material.code}"
constraint="no empty:${i18n:_('cannot be null or empty')}"
readonly="true" />
<datebox value="@{assignedMaterial.estimatedAvailability}" />
<doublebox value="@{assignedMaterial.units}"
onChange="assignedMaterialsController.updateTotalPrice(self.parent)" />
<listbox mold="select" model="@{unitTypes}"
selectedItem="@{assignedMaterial.material.unitType}" disabled="true" />
<doublebox value="@{assignedMaterial.unitPrice}"
onChange="assignedMaterialsController.updateTotalPrice(self.parent)" />
<doublebox value="@{assignedMaterial.totalPrice}"
onChange="assignedMaterialsController.updateUnitPrice(self.parent)" />
<listbox mold="select" model="@{materialStatus}"
selectedItem="@{assignedMaterial.status}"/>
<label value="@{assignedMaterial.material.category.name}" width="150px" />
<hbox>
<button sclass="icono"
image="/common/img/ico_borrar1.png"
hoverImage="/common/img/ico_borrar.png"
tooltiptext="${i18n:_('Delete')}"
onClick="assignedMaterialsController.showRemoveMaterialAssignmentDlg(self.parent.parent.value)">
</button>
<button label="${i18n:_('Split')}"
tooltiptext="${i18n:_('Split assignment')}"
onClick="assignedMaterialsController.showSplitMaterialAssignmentDlg(self.parent.parent.value)">
</button>
</hbox>
</row>
</rows>
</newdatasortablegrid>
</panelchildren>
</panel>
</vbox>
</hbox>
</tabpanel>
<tabpanel>
<!-- Material search -->
<hbox>
<!-- Categories -->
<vbox>
<panel title="${i18n:_('Categories')}" border="normal">
<panelchildren>
<toolbarbutton style="text-decoration: none" label="${i18n:_('Unselect')}" onClick="allCategoriesTree.clearSelection()" />
<tree id="allCategoriesTree"
width="280px" rows="10" vflex="true" multiple="false">
<treecols>
<treecol label="Name" />
</treecols>
</tree>
</panelchildren>
</panel>
</vbox>
<vbox>
<!-- Found materials -->
<panel title="${i18n:_('Materials')}" border="normal">
<panelchildren>
<!-- Search textbox -->
<hbox>
<textbox id="txtSearchMaterial" width="250px" style="margin-top: 5px" />
<button label="${i18n:_('Search')}" style="margin-bottom: 5px"
onClick="assignedMaterialsController.searchMaterials()"/>
<button label="${i18n:_('Assign')}"
onClick="assignedMaterialsController.assignSelectedMaterials()" />
</hbox>
<listbox id="lbFoundMaterials"
fixedLayout="true"
model="@{assignedMaterialsController.matchingMaterials}">
<listhead sizable="true">
<listheader label="${i18n:_('Code')}" />
<listheader label="${i18n:_('Name')}" />
<listheader label="${i18n:_('Unit type')}" />
<listheader label="${i18n:_('Unit price')}" />
<listheader label="${i18n:_('Category')}" />
</listhead>
<listitem self="@{each='material'}" value="@{material}">
<listcell label="@{material.code}" />
<listcell label="@{material.description}" />
<listcell>
<listbox mold="select"
model="@{unitTypes}"
selectedItem="@{material.unitType}"
disabled="true" />
</listcell>
<listcell label="@{material.defaultUnitPrice}" />
<listcell label="@{material.category.name}" />
</listitem>
</listbox>
</panelchildren>
</panel>
</vbox>
</hbox>
</tabpanel>
</tabpanels>
</tabbox>
</vbox>

View file

@ -0,0 +1,29 @@
<window title="${arg.title}" border="normal" width="250pt" closable="true"
use="org.zkoss.zul.impl.MessageboxDlg">
<hbox>
<div class="${arg.icon}"/>
<div sclass="z-messagebox" width="210pt">
<label value="${arg.message}" multiline="true"/>
</div>
</hbox>
<separator spacing="20px"/>
<grid>
<columns>
<column />
<column />
</columns>
<rows>
<row>
<label style="font-weight: bold" value="${i18n:_('Units')}:" width="150px" />
<doublebox id="dbUnits" width="200px" />
</row>
</rows>
</grid>
<separator bar="true"/>
<hbox style="margin-left:auto; margin-right:auto">
<button id="btnOk" identity="${arg.OK}" sclass="z-messagebox-btn"
use="org.zkoss.zul.impl.MessageboxDlg$Button" />
<button id="btnCancel" identity="${arg.CANCEL}" sclass="z-messagebox-btn"
use="org.zkoss.zul.impl.MessageboxDlg$Button" />
</hbox>
</window>

View file

@ -60,6 +60,9 @@
<value>
org/navalplanner/business/common/entities/Configuration.hbm.xml
</value>
<value>
org/navalplanner/business/materials/entities/Materials.hbm.xml
</value>
</list>
</property>