/****************************************************************************** * 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 * *****************************************************************************/ package org.adempiere.webui.window; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Timestamp; import java.util.logging.Level; import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.component.Checkbox; import org.adempiere.webui.component.ConfirmPanel; import org.adempiere.webui.component.Panel; import org.adempiere.webui.component.WListbox; import org.adempiere.webui.component.Window; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.util.ZKUpdateUtil; import org.compiere.minigrid.ColumnInfo; import org.compiere.minigrid.IDColumn; import org.compiere.model.MSysConfig; 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.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; import org.zkoss.zul.Borderlayout; import org.zkoss.zul.Center; import org.zkoss.zul.North; import org.zkoss.zul.South; import org.zkoss.zul.Hbox; /** * Product Attribute Set Instance (for instance attributes) view and selection dialog. * * @see WPAttributeDialog * @author Jorg Janke */ public class WPAttributeInstance extends Window implements EventListener { /** * generated serial id */ private static final long serialVersionUID = -4052029122256207113L; /** * Constructor * @param title title * @param M_Warehouse_ID warehouse key name pair * @param M_Locator_ID locator * @param M_Product_ID product key name pair * @param C_BPartner_ID bp */ public WPAttributeInstance(String title, int M_Warehouse_ID, int M_Locator_ID, int M_Product_ID, int C_BPartner_ID) { super (); this.setTitle(Msg.getMsg(Env.getCtx(), "PAttributeInstance") + title); this.setBorder("normal"); this.setSizable(true); this.setMaximizable(true); if (!ThemeManager.isUseCSSForWindowSize()) { ZKUpdateUtil.setWindowWidthX(this, 1000); ZKUpdateUtil.setWindowHeightX(this, 550); } else { addCallback(AFTER_PAGE_ATTACHED, t-> { ZKUpdateUtil.setCSSHeight(this); ZKUpdateUtil.setCSSWidth(this); }); } this.setSclass("pattribute-instance-dialog"); init (M_Warehouse_ID, M_Locator_ID, M_Product_ID, C_BPartner_ID); AEnv.showCenterScreen(this); } // WPAttributeInstance /** * Initialization * @param M_Warehouse_ID wh * @param M_Locator_ID loc * @param M_Product_ID product * @param C_BPartner_ID partner */ private void init (int M_Warehouse_ID, int M_Locator_ID, int M_Product_ID, int C_BPartner_ID) { log.info("M_Warehouse_ID=" + M_Warehouse_ID + ", M_Locator_ID=" + M_Locator_ID + ", M_Product_ID=" + M_Product_ID); m_M_Warehouse_ID = M_Warehouse_ID; m_M_Locator_ID = M_Locator_ID; m_M_Product_ID = M_Product_ID; try { init(); dynInit(C_BPartner_ID); } catch (Exception e) { log.log(Level.SEVERE, "", e); } } // init private Borderlayout mainLayout = new Borderlayout(); private Panel northPanel = new Panel(); private ConfirmPanel confirmPanel = new ConfirmPanel (true); private Checkbox showAll = new Checkbox(); // private WListbox m_table = new WListbox(); // Parameter private int m_M_Warehouse_ID; private int m_M_Locator_ID; private int m_M_Product_ID; // private int m_M_AttributeSetInstance_ID = -1; private String m_M_AttributeSetInstanceName = null; private String m_sql; /* SysConfig USE_ESC_FOR_TAB_CLOSING */ private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); /** Logger */ private static final CLogger log = CLogger.getCLogger(WPAttributeInstance.class); /** * Layout dialog * @throws Exception */ private void init() throws Exception { showAll.setLabel(Msg.getMsg(Env.getCtx(), "ShowAll")); this.appendChild(mainLayout); // North Hbox box = new Hbox(); box.setParent(northPanel); box.setPack("end"); box.appendChild(showAll); showAll.addEventListener(Events.ON_CHECK, this); North north = new North(); north.setParent(mainLayout); north.appendChild(northPanel); // Center Center center = new Center(); center.setParent(mainLayout); ZKUpdateUtil.setHflex(m_table, "true"); ZKUpdateUtil.setVflex(m_table, "true"); center.appendChild(m_table); // South South south = new South(); south.setParent(mainLayout); south.appendChild(confirmPanel); confirmPanel.addActionListener(this); addEventListener(Events.ON_CANCEL, e -> onCancel()); } // jbInit /** Column Layout Info for {@link #m_table} */ private static ColumnInfo[] s_layout = new ColumnInfo[] { new ColumnInfo(" ", "s.M_AttributeSetInstance_ID", IDColumn.class), new ColumnInfo(Msg.translate(Env.getCtx(), "Description"), "asi.Description", String.class), new ColumnInfo(Msg.translate(Env.getCtx(), "Lot"), "asi.Lot", String.class), new ColumnInfo(Msg.translate(Env.getCtx(), "SerNo"), "asi.SerNo", String.class), new ColumnInfo(Msg.translate(Env.getCtx(), "GuaranteeDate"), "asi.GuaranteeDate", Timestamp.class), new ColumnInfo(Msg.translate(Env.getCtx(), "M_Locator_ID"), "l.Value", KeyNamePair.class, "s.M_Locator_ID"), new ColumnInfo(Msg.translate(Env.getCtx(), "QtyAvailable"), "SUM(s.QtyOnHand - s.QtyReserved)", Double.class), new ColumnInfo(Msg.translate(Env.getCtx(), "QtyOnHand"), "SUM(s.QtyOnHand)", Double.class), new ColumnInfo(Msg.translate(Env.getCtx(), "QtyReserved"), "SUM(s.QtyReserved)", Double.class), new ColumnInfo(Msg.translate(Env.getCtx(), "QtyOrdered"), "SUM(s.QtyOrdered)", Double.class), // See RV_Storage new ColumnInfo(Msg.translate(Env.getCtx(), "GoodForDays"), "(daysbetween(asi.GuaranteeDate, getDate()))-p.GuaranteeDaysMin", Integer.class, true, true, null), new ColumnInfo(Msg.translate(Env.getCtx(), "ShelfLifeDays"), "daysbetween(asi.GuaranteeDate, getDate())", Integer.class), new ColumnInfo(Msg.translate(Env.getCtx(), "ShelfLifeRemainingPct"), "CASE WHEN p.GuaranteeDays > 0 THEN TRUNC(((daysbetween(asi.GuaranteeDate, getDate()))/p.GuaranteeDays)*100) ELSE 0 END", Integer.class), }; /** From Clause */ private static String s_sqlFrom = "M_Storage s" + " INNER JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)" + " INNER JOIN M_Product p ON (s.M_Product_ID=p.M_Product_ID)" + " LEFT OUTER JOIN M_AttributeSetInstance asi ON (s.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID)"; /** Where Clause */ private static String s_sqlWhere = "s.M_Product_ID=? AND l.M_Warehouse_ID=?"; private static String s_sqlWhereWithoutWarehouse = " s.M_Product_ID=?"; private String m_sqlNonZero = " AND (s.QtyOnHand<>0 OR s.QtyReserved<>0 OR s.QtyOrdered<>0)"; private String m_sqlMinLife = ""; /** * Init components and variables * @param C_BPartner_ID BP */ private void dynInit(int C_BPartner_ID) { if (log.isLoggable(Level.CONFIG)) log.config("C_BPartner_ID=" + C_BPartner_ID); if (C_BPartner_ID != 0) { int ShelfLifeMinPct = 0; int ShelfLifeMinDays = 0; String sql = "SELECT bp.ShelfLifeMinPct, bpp.ShelfLifeMinPct, bpp.ShelfLifeMinDays " + "FROM C_BPartner bp " + " LEFT OUTER JOIN C_BPartner_Product bpp" + " ON (bp.C_BPartner_ID=bpp.C_BPartner_ID AND bpp.M_Product_ID=?) " + "WHERE bp.C_BPartner_ID=?"; PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement(sql, null); pstmt.setInt(1, m_M_Product_ID); pstmt.setInt(2, C_BPartner_ID); rs = pstmt.executeQuery(); if (rs.next()) { ShelfLifeMinPct = rs.getInt(1); // BP int pct = rs.getInt(2); // BP_P if (pct > 0) // overwrite ShelfLifeMinDays = pct; ShelfLifeMinDays = rs.getInt(3); } } catch (Exception e) { log.log(Level.SEVERE, sql, e); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } if (ShelfLifeMinPct > 0) { m_sqlMinLife = " AND COALESCE(TRUNC(((daysbetween(asi.GuaranteeDate, getDate()))/p.GuaranteeDays)*100),0)>=" + ShelfLifeMinPct; if (log.isLoggable(Level.CONFIG)) log.config( "PAttributeInstance.dynInit - ShelfLifeMinPct=" + ShelfLifeMinPct); } if (ShelfLifeMinDays > 0) { m_sqlMinLife += " AND COALESCE((daysbetween(asi.GuaranteeDate, getDate())),0)>=" + ShelfLifeMinDays; if (log.isLoggable(Level.CONFIG)) log.config( "PAttributeInstance.dynInit - ShelfLifeMinDays=" + ShelfLifeMinDays); } } // BPartner != 0 m_sql = m_table.prepareTable (s_layout, s_sqlFrom, m_M_Warehouse_ID == 0 ? s_sqlWhereWithoutWarehouse : s_sqlWhere, false, "s") + " GROUP BY s.M_AttributeSetInstance_ID,asi.Description,asi.Lot,asi.SerNo,asi.GuaranteeDate,l.Value,s.M_Locator_ID,p.GuaranteeDaysMin,p.GuaranteeDays" + " ORDER BY asi.GuaranteeDate, SUM(s.QtyOnHand)"; // oldest, smallest first // m_table.addEventListener(Events.ON_SELECT, this); // refresh(); } // dynInit /** * Refresh Query */ private void refresh() { String sql = m_sql; int pos = m_sql.lastIndexOf(" GROUP BY "); if (!showAll.isChecked()) { sql = m_sql.substring(0, pos) + m_sqlNonZero; if (m_sqlMinLife.length() > 0) sql += m_sqlMinLife; sql += m_sql.substring(pos); } // log.finest(sql); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement(sql, null); pstmt.setInt(1, m_M_Product_ID); if (m_M_Warehouse_ID != 0) pstmt.setInt(2, m_M_Warehouse_ID); rs = pstmt.executeQuery(); m_table.loadTable(rs); } catch (Exception e) { log.log(Level.SEVERE, sql, e); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } enableButtons(); } // refresh @Override public void onEvent(Event e) throws Exception { if (e.getTarget().getId().equals("Ok")) detach(); else if (e.getTarget().getId().equals("Cancel")) { onCancel(); } else if (e.getTarget() == showAll) { refresh(); } else if (e.getTarget() == m_table) { enableButtons(); } } // actionPerformed /** * Handle onCancel event */ private void onCancel() { // do not allow to close tab for Events.ON_CTRL_KEY event if(isUseEscForTabClosing) SessionManager.getAppDesktop().setCloseTabWithShortcut(false); m_M_AttributeSetInstance_ID = -1; m_M_AttributeSetInstanceName = null; detach(); } /** * Enable/Set Buttons and set ID */ private void enableButtons() { m_M_AttributeSetInstance_ID = -1; m_M_AttributeSetInstanceName = null; m_M_Locator_ID = 0; int row = m_table.getSelectedRow(); boolean enabled = row != -1; if (enabled) { Integer ID = m_table.getSelectedRowKey(); if (ID != null) { m_M_AttributeSetInstance_ID = ID.intValue(); m_M_AttributeSetInstanceName = (String)m_table.getValueAt(row, 1); // Object oo = m_table.getValueAt(row, 5); if (oo instanceof KeyNamePair) { KeyNamePair pp = (KeyNamePair)oo; m_M_Locator_ID = pp.getKey(); } } } confirmPanel.getButton("Ok").setEnabled(enabled); if (log.isLoggable(Level.FINE)) log.fine("M_AttributeSetInstance_ID=" + m_M_AttributeSetInstance_ID + " - " + m_M_AttributeSetInstanceName + "; M_Locator_ID=" + m_M_Locator_ID); } // enableButtons /** * Get Attribute Set Instance * @return M_AttributeSetInstance_ID or -1 */ public int getM_AttributeSetInstance_ID() { return m_M_AttributeSetInstance_ID; } // getM_AttributeSetInstance_ID /** * Get Instance Name * @return Instance Name */ public String getM_AttributeSetInstanceName() { return m_M_AttributeSetInstanceName; } // getM_AttributeSetInstanceName /** * Get Locator * @return M_Locator_ID or 0 */ public int getM_Locator_ID() { return m_M_Locator_ID; } // getM_Locator_ID } // WPAttributeInstance