/****************************************************************************** * Product: Adempiere ERP & CRM Smart Business Solution * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * Copyright (C) 2003-2007 e-Evolution,SC. All Rights Reserved. * * Contributor(s): Victor Perez www.e-evolution.com * *****************************************************************************/ package org.compiere.apps.form; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Collections; import java.util.List; import java.util.Properties; import java.util.Vector; import java.util.function.Function; import org.compiere.minigrid.IMiniTable; import org.compiere.model.MProduct; import org.compiere.model.MUOM; import org.compiere.util.CLogger; import org.compiere.util.Env; import org.compiere.util.KeyNamePair; import org.compiere.util.Msg; import org.eevolution.model.MPPProductBOM; import org.eevolution.model.MPPProductBOMLine; /** * Form to view BOM tree. * @param Tree Node type */ public class TreeBOM { public static final CLogger log = CLogger.getCLogger(TreeBOM.class); /** Child components of current selected product */ protected Vector> dataBOM = new Vector>(); /** M_Product_ID of selected tree node */ protected int m_selectedId = 0; public Properties getCtx() { return Env.getCtx(); } /** * Get Product Summary * @param product Product * @param isLeaf is Leaf * @return Product Summary (Value_Name[UOM]) */ public String productSummary(MProduct product, boolean isLeaf) { MUOM uom = MUOM.get(getCtx(), product.getC_UOM_ID()); String value = product.getValue(); String name = product.get_Translation(MProduct.COLUMNNAME_Name); // StringBuilder sb = new StringBuilder(value); if (name != null && !value.equals(name)) sb.append("_").append(product.getName()); sb.append(" [").append(uom.get_Translation(MUOM.COLUMNNAME_UOMSymbol)).append("]"); // return sb.toString(); } /** * Get BOM Summary * @param bom Product BOM * @return BOM Summary (Value_Name) */ public String productSummary(MPPProductBOM bom) { String value = bom.getValue(); String name = bom.get_Translation(MPPProductBOM.COLUMNNAME_Name); // StringBuilder sb = new StringBuilder(value); if (name != null && !name.equals(value)) sb.append("_").append(name); // return sb.toString(); } /** * Set class type for table * @param table * @see TreeBOM#getColumnNames() */ public void setColumnClass(IMiniTable table) { table.setColumnClass( 0, Boolean.class, true); // 0 IsActive table.setColumnClass( 1, String.class,true); // 1 Line table.setColumnClass( 2, KeyNamePair.class,true); // 2 M_Product_ID table.setColumnClass( 3, KeyNamePair.class,true); // 3 C_UOM_ID table.setColumnClass( 4, BigDecimal.class,true); // 4 QtyBOM } /** * Get column names for {@link #dataBOM} * @return column names */ public Vector getColumnNames() { // Header Info Vector columnNames = new Vector(); columnNames.add(Msg.translate(Env.getCtx(), "IsActive")); // 0 columnNames.add(Msg.getElement(Env.getCtx(), "Line")); // 1 columnNames.add(Msg.getElement(Env.getCtx(), "M_Product_ID")); // 2 columnNames.add(Msg.getElement(Env.getCtx(), "C_UOM_ID")); // 3 columnNames.add(Msg.getElement(Env.getCtx(), "QtyBOM")); // 4 return columnNames; } /** * New product line * @param product * @param lineNo * @return product line */ protected Vector newProductLine(MProduct product, int lineNo, BigDecimal qty) { Vector line = new Vector(5); line.add( Boolean.valueOf(product.isActive())); // 0 IsActive line.add( Integer.valueOf(lineNo).toString()); // 1 Line KeyNamePair pp = new KeyNamePair(product.getM_Product_ID(),product.getValue().concat("_").concat(product.getName())); line.add(pp); // 2 M_Product_ID MUOM u = new MUOM(product.getCtx(), product.getC_UOM_ID(), product.get_TrxName()); KeyNamePair uom = new KeyNamePair(u.get_ID(),u.getUOMSymbol()); line.add(uom); // 3 C_UOM_ID line.add(qty.setScale(4, RoundingMode.HALF_UP).stripTrailingZeros()); // 4 QtyBOM return line; } /** * Load BOM * @param product * @param parent parent node * @param createNewNodeFunction * @param implosion * @param reload */ public void loadBOM(MProduct product, T parent, Function, T> createNewNodeFunction, boolean implosion, boolean reload) { int M_Product_ID = product.getM_Product_ID(); m_selectedId = M_Product_ID; dataBOM.clear(); if (implosion) { for (MPPProductBOMLine bomline : MPPProductBOMLine.getByProduct(product)) { addParent(bomline, parent, createNewNodeFunction, reload); } } else { for (MPPProductBOMLine bom : MPPProductBOMLine.getBOMLines(product)) { addChild(bom, parent, createNewNodeFunction, reload); } } } /** * Add BOM line that is using selected product as component * @param bomline * @param parent parent tree node * @param createNewNodeFunction * @param reload */ protected void addParent(MPPProductBOMLine bomline, T parent, Function, T> createNewNodeFunction, boolean reload) { MPPProductBOM bom = new MPPProductBOM(getCtx(), bomline.getPP_Product_BOM_ID(), null); MProduct product = MProduct.get(getCtx(), bom.getM_Product_ID()); Vector line = newProductLine(product, bomline.getLine(), bomline.getQtyBOM()!=null ? bomline.getQtyBOM() : Env.ZERO); if (m_selectedId == bomline.getM_Product_ID()) dataBOM.add(line); T child = null; if (!reload) { List bomLines = MPPProductBOMLine.getByProduct(product); child = createNewNodeFunction.apply(new NewNodeArguments(line, parent, bomLines.isEmpty())); for (MPPProductBOMLine bl : bomLines) { addParent(bl, child, createNewNodeFunction, reload); } } else { return; } } /** * Add child BOM line of selected product * @param bomline * @param parent parent tree node * @param createNewNodeFunction * @param reload */ protected void addChild(MPPProductBOMLine bomline, T parent, Function, T> createNewNodeFunction, boolean reload) { MProduct product = MProduct.get(getCtx(), bomline.getM_Product_ID()); Vector line = newProductLine(product, bomline.getLine(), bomline.getQtyBOM()!=null ? bomline.getQtyBOM() : Env.ZERO); if (m_selectedId == bomline.getParent().getM_Product_ID()) dataBOM.add(line); T child = null; if (!reload) { MPPProductBOMLine[] bomLines = MPPProductBOMLine.getBOMLines(product); child = createNewNodeFunction.apply(new NewNodeArguments(line, parent, bomLines.length == 0)); for (MPPProductBOMLine bom : bomLines) { addChild(bom, child, createNewNodeFunction, reload); } } else { return; } } /** * Get immutable BOM lines of current selected product * @return bom lines */ public List> getDataBOM() { return Collections.unmodifiableList(dataBOM); } public record NewNodeArguments(List dataLine, T parentNode, boolean isLeafNode) {} }