/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* 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 *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
/**
* 2007, Modified by Posterita Ltd.
*/
package org.adempiere.webui.apps.form;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.logging.Level;
import org.adempiere.webui.component.Checkbox;
import org.adempiere.webui.component.ConfirmPanel;
import org.adempiere.webui.component.Grid;
import org.adempiere.webui.component.GridFactory;
import org.adempiere.webui.component.Label;
import org.adempiere.webui.component.ListItem;
import org.adempiere.webui.component.Listbox;
import org.adempiere.webui.component.Row;
import org.adempiere.webui.component.Rows;
import org.adempiere.webui.panel.ADForm;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.window.FDialog;
import org.compiere.model.MInvoice;
import org.compiere.model.MInvoiceLine;
import org.compiere.model.MOrder;
import org.compiere.model.MOrderLine;
import org.compiere.model.MProduct;
import org.compiere.model.MProductBOM;
import org.compiere.model.MProject;
import org.compiere.model.MProjectLine;
import org.compiere.model.MRole;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.KeyNamePair;
import org.compiere.util.Msg;
import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Caption;
import org.zkoss.zul.Decimalbox;
import org.zkoss.zul.Groupbox;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Radio;
import org.zkoss.zul.Radiogroup;
import org.zkoss.zul.Separator;
import org.zkoss.zul.Space;
public class WBOMDrop extends ADForm implements EventListener
{
/**
*
*/
private static final long serialVersionUID = -5065364554398280623L;
/** Product to create BOMs from */
private MProduct m_product;
/** BOM Qty */
private BigDecimal m_qty = Env.ONE;
/** Line Counter */
private int m_bomLine = 0;
/** Logger */
private static CLogger log = CLogger.getCLogger(WBOMDrop.class);
/** List of all selectors */
private ArrayList<org.zkoss.zul.Checkbox> m_selectionList = new ArrayList<org.zkoss.zul.Checkbox>();
/** List of all quantities */
private ArrayList<Decimalbox> m_qtyList = new ArrayList<Decimalbox>();
/** List of all products */
private ArrayList<Integer> m_productList = new ArrayList<Integer>();
/** Alternative Group Lists */
private HashMap<String, Radiogroup> m_buttonGroups = new HashMap<String,Radiogroup>();
private static final int WINDOW_WIDTH = 600; // width of the window
private ConfirmPanel confirmPanel = new ConfirmPanel(true);
private Grid selectionPanel = GridFactory.newGridLayout();
private Listbox productField = new Listbox();
private Decimalbox productQty = new Decimalbox();
private Listbox orderField = new Listbox();
private Listbox invoiceField = new Listbox();
private Listbox projectField = new Listbox();
private Groupbox grpSelectionPanel = new Groupbox();
private Groupbox grpSelectProd = new Groupbox();
public WBOMDrop()
{}
/**
* Initialize Panel
* @param WindowNo window
* @param frame parent frame
*/
protected void initForm()
{
log.info("");
try
{
confirmPanel = new ConfirmPanel(true);
// Top Selection Panel
createSelectionPanel(true, true, true);
// Center
createMainPanel();
confirmPanel.addActionListener(Events.ON_CLICK, this);
}
catch(Exception e)
{
log.log(Level.SEVERE, "", e);
}
//sizeIt();
} // init
/**
* Dispose
*/
public void dispose()
{
if (selectionPanel != null)
selectionPanel.getChildren().clear();
selectionPanel = null;
if (m_selectionList != null)
m_selectionList.clear();
m_selectionList = null;
if (m_productList != null)
m_productList.clear();
m_productList = null;
if (m_qtyList != null)
m_qtyList.clear();
m_qtyList = null;
if (m_buttonGroups != null)
m_buttonGroups.clear();
m_buttonGroups = null;
} // dispose
/**************************************************************************
* Create Selection Panel
* @param order
* @param invoice
* @param project
*/
private void createSelectionPanel (boolean order, boolean invoice, boolean project)
{
Caption caption = new Caption(Msg.translate(Env.getCtx(), "Selection"));
// grpSelectionPanel.setWidth("100%");
grpSelectionPanel.appendChild(caption);
grpSelectionPanel.appendChild(selectionPanel);
productField.setRows(1);
productField.setMold("select");
KeyNamePair[] keyNamePair = getProducts();
for (int i = 0; i < keyNamePair.length; i++)
{
productField.addItem(keyNamePair[i]);
}
Rows rows = selectionPanel.newRows();
Row boxProductQty = rows.newRow();
Label lblProduct = new Label(Msg.translate(Env.getCtx(), "M_Product_ID"));
Label lblQty = new Label(Msg.translate(Env.getCtx(), "Qty"));
productQty.setValue(new BigDecimal(1));
productField.addEventListener(Events.ON_SELECT, this);
productQty.addEventListener(Events.ON_CHANGE, this);
productField.setWidth("99%");
boxProductQty.appendChild(lblProduct.rightAlign());
boxProductQty.appendChild(productField);
boxProductQty.appendChild(lblQty.rightAlign());
boxProductQty.appendChild(productQty);
if (order)
{
keyNamePair = getOrders();
orderField.setRows(1);
orderField.setMold("select");
orderField.setWidth("99%");
for (int i = 0; i < keyNamePair.length; i++)
{
orderField.addItem(keyNamePair[i]);
}
Label lblOrder = new Label(Msg.translate(Env.getCtx(), "C_Order_ID"));
Row boxOrder = rows.newRow();
orderField.addEventListener(Events.ON_CLICK, this);
boxOrder.appendChild(lblOrder.rightAlign());
boxOrder.appendChild(orderField);
boxOrder.appendChild(new Space());
boxOrder.appendChild(new Space());
}
if (invoice)
{
invoiceField.setRows(1);
invoiceField.setMold("select");
invoiceField.setWidth("99%");
keyNamePair = getInvoices();
for (int i = 0; i < keyNamePair.length; i++)
{
invoiceField.addItem(keyNamePair[i]);
}
Label lblInvoice = new Label(Msg.translate(Env.getCtx(), "C_Invoice_ID"));
Row boxInvoices = rows.newRow();
invoiceField.addEventListener(Events.ON_SELECT, this);
boxInvoices.appendChild(lblInvoice.rightAlign());
boxInvoices.appendChild(invoiceField);
boxInvoices.appendChild(new Space());
boxInvoices.appendChild(new Space());
}
if (project)
{
projectField.setRows(1);
projectField.setMold("select");
projectField.setWidth("99%");
keyNamePair = getProjects();
for (int i = 0; i < keyNamePair.length; i++)
{
projectField.addItem(keyNamePair[i]);
}
Label lblProject = new Label(Msg.translate(Env.getCtx(), "C_Project_ID"));
Row boxProject = rows.newRow();
projectField.addEventListener(Events.ON_SELECT, this);
boxProject.appendChild(lblProject.rightAlign());
boxProject.appendChild(projectField);
boxProject.appendChild(new Space());
boxProject.appendChild(new Space());
}
// Enabled in ActionPerformed
confirmPanel.setEnabled("Ok", false);
} // createSelectionPanel
/**
* Get Array of BOM Products
* @return products
*/
private KeyNamePair[] getProducts()
{
String sql = "SELECT M_Product_ID, Name "
+ "FROM M_Product "
+ "WHERE IsBOM='Y' AND IsVerified='Y' AND IsActive='Y' "
+ "ORDER BY Name";
return DB.getKeyNamePairs(MRole.getDefault().addAccessSQL(
sql, "M_Product", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO), true);
} // getProducts
/**
* Get Array of open Orders
* @return orders
*/
private KeyNamePair[] getOrders()
{
String sql = "SELECT C_Order_ID, DocumentNo || '_' || GrandTotal "
+ "FROM C_Order "
+ "WHERE Processed='N' AND DocStatus='DR' "
+ "ORDER BY DocumentNo";
return DB.getKeyNamePairs(MRole.getDefault().addAccessSQL(
sql, "C_Order", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO), true);
} // getOrders
/**
* Get Array of open non service Projects
* @return orders
*/
private KeyNamePair[] getProjects()
{
String sql = "SELECT C_Project_ID, Name "
+ "FROM C_Project "
+ "WHERE Processed='N' AND IsSummary='N' AND IsActive='Y'"
+ " AND ProjectCategory<>'S' "
+ "ORDER BY Name";
return DB.getKeyNamePairs(MRole.getDefault().addAccessSQL(
sql, "C_Project", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO), true);
} // getProjects
/**
* Get Array of open Invoices
* @return invoices
*/
private KeyNamePair[] getInvoices()
{
String sql = "SELECT C_Invoice_ID, DocumentNo || '_' || GrandTotal "
+ "FROM C_Invoice "
+ "WHERE Processed='N' AND DocStatus='DR' "
+ "ORDER BY DocumentNo";
return DB.getKeyNamePairs(MRole.getDefault().addAccessSQL(
sql, "C_Invoice", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO), true);
} // getInvoices
/**************************************************************************
* Create Main Panel.
* Called when changing Product
*/
private void createMainPanel ()
{
log.config(": " + m_product);
this.getChildren().clear();
//this.invalidate();
//this.setBorder(null);
m_selectionList.clear();
m_productList.clear();
m_qtyList.clear();
m_buttonGroups.clear();
this.appendChild(new Separator());
this.appendChild(grpSelectionPanel);
this.appendChild(new Separator());
this.appendChild(grpSelectProd);
this.appendChild(new Separator());
this.appendChild(confirmPanel);
this.appendChild(new Separator());
this.setBorder("normal");
Caption title = new Caption(Msg.getMsg(Env.getCtx(), "SelectProduct"));
grpSelectProd.getChildren().clear();
grpSelectProd.appendChild(title);
if (m_product != null && m_product.get_ID() > 0)
{
title.setLabel(m_product.getName());
if (m_product.getDescription() != null && m_product.getDescription().length() > 0)
;//this.setsetToolTipText(m_product.getDescription());
m_bomLine = 0;
addBOMLines(m_product, m_qty);
}
} // createMainPanel
/**
* Add BOM Lines to this.
* Called recursively
* @param product product
* @param qty quantity
*/
private void addBOMLines (MProduct product, BigDecimal qty)
{
MProductBOM[] bomLines = MProductBOM.getBOMLines(product);
for (int i = 0; i < bomLines.length; i++)
{
grpSelectProd.appendChild(new Separator());
addBOMLine (bomLines[i], qty);
grpSelectProd.appendChild(new Separator());
}
log.fine("#" + bomLines.length);
} // addBOMLines
/**
* Add BOM Line to this.
* Calls addBOMLines if added product is a BOM
* @param line BOM Line
* @param qty quantity
*/
private void addBOMLine (MProductBOM line, BigDecimal qty)
{
log.fine(line.toString());
String bomType = line.getBOMType();
if (bomType == null)
bomType = MProductBOM.BOMTYPE_StandardPart;
//
BigDecimal lineQty = line.getBOMQty().multiply(qty);
MProduct product = line.getProduct();
if (product == null)
return;
if (product.isBOM() && product.isVerified())
addBOMLines (product, lineQty); // recursive
else
addDisplay (line.getM_Product_ID(),
product.getM_Product_ID(), bomType, product.getName(), lineQty);
} // addBOMLine
/**
* Add Line to Display
* @param parentM_Product_ID parent product
* @param M_Product_ID product
* @param bomType bom type
* @param name name
* @param lineQty qty
*/
private void addDisplay (int parentM_Product_ID,
int M_Product_ID, String bomType, String name, BigDecimal lineQty)
{
log.fine("M_Product_ID=" + M_Product_ID + ",Type=" + bomType + ",Name=" + name + ",Qty=" + lineQty);
boolean selected = true;
Hbox boxQty = new Hbox();
boxQty.setWidth("100%");
boxQty.setWidths("10%, 40%, 50%");
if (MProductBOM.BOMTYPE_StandardPart.equals(bomType))
{
String title = "";
Checkbox cb = new Checkbox();
cb.setLabel(title);
cb.setChecked(true);
cb.setEnabled(false);
m_selectionList.add(cb);
boxQty.appendChild(cb);
}
else if (MProductBOM.BOMTYPE_OptionalPart.equals(bomType))
{
String title = Msg.getMsg(Env.getCtx(), "Optional");
Checkbox cb = new Checkbox();
cb.setLabel(title);
cb.setChecked(false);
selected = false;
cb.addEventListener(Events.ON_CHECK, this);
m_selectionList.add(cb);
boxQty.appendChild(cb);
}
else // Alternative
{
String title = Msg.getMsg(Env.getCtx(), "Alternative") + " " + bomType;
Radio b = new Radio();
b.setLabel(title);
String groupName = String.valueOf(parentM_Product_ID) + "_" + bomType;
Radiogroup group = m_buttonGroups.get(groupName);
if (group == null)
{
log.fine("ButtonGroup=" + groupName);
group = new Radiogroup();
m_buttonGroups.put(groupName, group);
group.appendChild(b);
b.setSelected(true); // select first one
}
else
{
group.appendChild(b);
b.setSelected(false);
selected = false;
}
b.addEventListener(Events.ON_CLICK, this);
m_selectionList.add(b);
boxQty.appendChild(b);
}
// Add to List & display
m_productList.add (new Integer(M_Product_ID));
Decimalbox qty = new Decimalbox();
qty.setValue(lineQty);
qty.setReadonly(!selected);
m_qtyList.add(qty);
Label label = new Label(name);
HtmlBasedComponent c = (HtmlBasedComponent) label.rightAlign();
c.setStyle(c.getStyle() + ";margin-right: 5px");
boxQty.appendChild(c);
boxQty.appendChild(qty);
grpSelectProd.appendChild(boxQty);
} // addDisplay
/**************************************************************************
* Action Listener
* @param e event
*/
public void onEvent (Event e) throws Exception
{
log.config(e.getName());
Object source = e.getTarget();
// Toggle Qty Enabled
if (source instanceof Checkbox || source instanceof Radio)
{
cmd_selection (source);
// need to de-select the others in group
if (source instanceof Radio)
{
// find Button Group
Iterator<Radiogroup> it = m_buttonGroups.values().iterator();
while (it.hasNext())
{
Radiogroup group = it.next();
Enumeration en = (Enumeration) group.getChildren();
while (en.hasMoreElements())
{
// We found the group
if (source == en.nextElement())
{
Enumeration info = (Enumeration) group.getChildren();
while (info.hasMoreElements())
{
Object infoObj = info.nextElement();
if (source != infoObj)
cmd_selection(infoObj);
}
}
}
}
}
} // JCheckBox or JRadioButton
// Product / Qty
else if (source == productField || source == productQty)
{
m_qty = productQty.getValue();
ListItem listitem = productField.getSelectedItem();
KeyNamePair pp = null;
if (listitem != null)
pp = listitem.toKeyNamePair();
m_product = MProduct.get (Env.getCtx(), pp.getKey());
createMainPanel();
//sizeIt();
}
// Order
else if (source == orderField)
{
ListItem listitem = orderField.getSelectedItem();
KeyNamePair pp = null;
if (listitem != null)
pp = listitem.toKeyNamePair();
boolean valid = (pp != null && pp.getKey() > 0);
if (invoiceField != null)
invoiceField.setEnabled(!valid);
if (projectField != null)
projectField.setEnabled(!valid);
}
// Invoice
else if (source == invoiceField)
{
ListItem listitem = invoiceField.getSelectedItem();
KeyNamePair pp = null;
if (listitem != null)
pp = listitem.toKeyNamePair();
boolean valid = (pp != null && pp.getKey() > 0);
if (orderField != null)
orderField.setEnabled(!valid);
if (projectField != null)
projectField.setEnabled(!valid);
}
// Project
else if (source == projectField)
{
ListItem listitem = projectField.getSelectedItem();
KeyNamePair pp = null;
if (listitem != null)
pp = listitem.toKeyNamePair();
boolean valid = (pp != null && pp.getKey() > 0);
//
if (orderField != null)
orderField.setEnabled(!valid);
if (invoiceField != null)
invoiceField.setEnabled(!valid);
}
// OK
else if (confirmPanel.getButton("Ok").equals(e.getTarget()))
{
if (cmd_save())
SessionManager.getAppDesktop().closeActiveWindow();
}
else if (confirmPanel.getButton("Cancel").equals(e.getTarget()))
SessionManager.getAppDesktop().closeActiveWindow();
// Enable OK
boolean OK = m_product != null;
if (OK)
{
KeyNamePair pp = null;
if (orderField != null)
{
ListItem listitem = orderField.getSelectedItem();
if (listitem != null)
pp = listitem.toKeyNamePair();
}
if ((pp == null || pp.getKey() <= 0) && invoiceField != null)
{
ListItem listitem = invoiceField.getSelectedItem();
if (listitem != null)
pp = listitem.toKeyNamePair();
}
if ((pp == null || pp.getKey() <= 0) && projectField != null)
{
ListItem listitem = projectField.getSelectedItem();
if (listitem != null)
pp = listitem.toKeyNamePair();
}
OK = (pp != null && pp.getKey() > 0);
}
confirmPanel.setEnabled("Ok", OK);
} // actionPerformed
/**
* Enable/disable qty based on selection
* @param source JCheckBox or JRadioButton
*/
private void cmd_selection (Object source)
{
for (int i = 0; i < m_selectionList.size(); i++)
{
if (source == m_selectionList.get(i))
{
boolean selected = isSelectionSelected(source);
Decimalbox qty = m_qtyList.get(i);
qty.setReadonly(!selected);
return;
}
}
log.log(Level.SEVERE, "not found - " + source);
} // cmd_selection
/**
* Is Selection Selected
* @param source CheckBox or RadioButton
* @return true if selected
*/
private boolean isSelectionSelected (Object source)
{
boolean retValue = false;
if (source instanceof Checkbox)
retValue = ((Checkbox)source).isChecked();
else if (source instanceof Radio)
retValue = ((Radio)source).isChecked();
else
log.log(Level.SEVERE, "Not valid - " + source);
return retValue;
} // isSelected
/**************************************************************************
* Save Selection
* @return true if saved
*/
private boolean cmd_save()
{
ListItem listitem = orderField.getSelectedItem();
KeyNamePair pp = null;
if (listitem != null)
pp = listitem.toKeyNamePair();
if (pp != null && pp.getKey() > 0)
return cmd_saveOrder (pp.getKey());
listitem = invoiceField.getSelectedItem();
pp = null;
if (listitem != null)
pp = listitem.toKeyNamePair();
if (pp != null && pp.getKey() > 0)
return cmd_saveInvoice (pp.getKey());
listitem = projectField.getSelectedItem();
pp = null;
if (listitem != null)
pp = listitem.toKeyNamePair();
if (pp != null && pp.getKey() > 0)
return cmd_saveProject (pp.getKey());
log.log(Level.SEVERE, "Nothing selected");
return false;
} // cmd_save
/**
* Save to Order
* @param C_Order_ID id
* @return true if saved
*/
private boolean cmd_saveOrder (int C_Order_ID)
{
log.config("C_Order_ID=" + C_Order_ID);
MOrder order = new MOrder (Env.getCtx(), C_Order_ID, null);
if (order.get_ID() == 0)
{
log.log(Level.SEVERE, "Not found - C_Order_ID=" + C_Order_ID);
return false;
}
int lineCount = 0;
// for all bom lines
for (int i = 0; i < m_selectionList.size(); i++)
{
if (isSelectionSelected(m_selectionList.get(i)))
{
BigDecimal qty = m_qtyList.get(i).getValue();
int M_Product_ID = m_productList.get(i).intValue();
// Create Line
MOrderLine ol = new MOrderLine (order);
ol.setM_Product_ID(M_Product_ID, true);
ol.setQty(qty);
ol.setPrice();
ol.setTax();
if (ol.save())
lineCount++;
else
log.log(Level.SEVERE, "Line not saved");
} // line selected
} // for all bom lines
FDialog.info(-1, this, order.getDocumentInfo() + " " + Msg.translate(Env.getCtx(), "Inserted") + "=" + lineCount);
log.config("#" + lineCount);
return true;
} // cmd_saveOrder
/**
* Save to Invoice
* @param C_Invoice_ID id
* @return true if saved
*/
private boolean cmd_saveInvoice (int C_Invoice_ID)
{
log.config("C_Invoice_ID=" + C_Invoice_ID);
MInvoice invoice = new MInvoice (Env.getCtx(), C_Invoice_ID, null);
if (invoice.get_ID() == 0)
{
log.log(Level.SEVERE, "Not found - C_Invoice_ID=" + C_Invoice_ID);
return false;
}
int lineCount = 0;
// for all bom lines
for (int i = 0; i < m_selectionList.size(); i++)
{
if (isSelectionSelected(m_selectionList.get(i)))
{
BigDecimal qty = m_qtyList.get(i).getValue();
int M_Product_ID = m_productList.get(i).intValue();
// Create Line
MInvoiceLine il = new MInvoiceLine (invoice);
il.setM_Product_ID(M_Product_ID, true);
il.setQty(qty);
il.setPrice();
il.setTax();
if (il.save())
lineCount++;
else
log.log(Level.SEVERE, "Line not saved");
} // line selected
} // for all bom lines
FDialog.info(-1, this, invoice.getDocumentInfo() + " " + Msg.translate(Env.getCtx(), "Inserted") + "=" + lineCount);
log.config("#" + lineCount);
return true;
} // cmd_saveInvoice
/**
* Save to Project
* @param C_Project_ID id
* @return true if saved
*/
private boolean cmd_saveProject (int C_Project_ID)
{
log.config("C_Project_ID=" + C_Project_ID);
MProject project = new MProject (Env.getCtx(), C_Project_ID, null);
if (project.get_ID() == 0)
{
log.log(Level.SEVERE, "Not found - C_Project_ID=" + C_Project_ID);
return false;
}
int lineCount = 0;
// for all bom lines
for (int i = 0; i < m_selectionList.size(); i++)
{
if (isSelectionSelected(m_selectionList.get(i)))
{
BigDecimal qty = m_qtyList.get(i).getValue();
int M_Product_ID = m_productList.get(i).intValue();
// Create Line
MProjectLine pl = new MProjectLine (project);
pl.setM_Product_ID(M_Product_ID);
pl.setPlannedQty(qty);
if (pl.save())
lineCount++;
else
log.log(Level.SEVERE, "Line not saved");
} // line selected
} // for all bom lines
FDialog.info(-1, this, project.getName() + " " + Msg.translate(Env.getCtx(), "Inserted") + "=" + lineCount);
log.config("#" + lineCount);
return true;
} // cmd_saveProject
}