/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 Adempiere, 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. *
*****************************************************************************/
package org.compiere.pos;
import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.ParseException;
import java.util.logging.Level;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import net.miginfocom.swing.MigLayout;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.apps.ADialog;
import org.compiere.grid.ed.VPAttributeDialog;
import org.compiere.minigrid.ColumnInfo;
import org.compiere.minigrid.IDColumn;
import org.compiere.model.MOrderLine;
import org.compiere.model.MProduct;
import org.compiere.model.MWarehousePrice;
import org.compiere.model.PO;
import org.compiere.swing.CButton;
import org.compiere.swing.CLabel;
import org.compiere.swing.CScrollPane;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Trx;
import org.compiere.util.TrxRunnable;
/**
* Current Line Sub Panel
*
* @author OpenXpertya
* Based on Modified Original Code, Revised and Optimized
* *Copyright Jorg Janke
* red1 - [2093355 ] Small bugs in OpenXpertya POS
*/
public class SubCurrentLine extends PosSubPanel implements ActionListener, FocusListener, ListSelectionListener {
/**
*
*/
private static final long serialVersionUID = -4023538043556457231L;
private String trxName;
/**
* Constructor
*
* @param posPanel POS Panel
*/
public SubCurrentLine(PosBasePanel posPanel) {
super(posPanel);
trxName = posPanel.getTrxName();
}
private CButton f_up;
private CButton f_delete;
private CButton f_down;
private CButton f_productAttr;
private CButton f_plus;
private CButton f_minus;
private PosTextField f_price;
private PosTextField f_quantity;
protected PosTextField f_productName;
private CButton f_bSearch;
private int orderLineId = 0;
/*
* @emmie - Botón como variable de instancia privada
* para evitar efectos laterales indeseados
*/
private CButton f_cashPayment;
/** The Product */
private MProduct m_product = null;
/** Warehouse */
private int m_M_Warehouse_ID;
/** PLV */
private int m_M_PriceList_Version_ID;
/** Logger */
private static CLogger log = CLogger.getCLogger(SubCurrentLine.class);
/** The Table */
PosTable m_table;
/** The Query SQL */
private String m_sql;
/** Logger */
/** Table Column Layout Info */
private static ColumnInfo[] s_layout = new ColumnInfo[]
{
new ColumnInfo(" ", "C_OrderLine_ID", IDColumn.class),
new ColumnInfo(Msg.translate(Env.getCtx(), "Name"), "Name", String.class),
new ColumnInfo(Msg.translate(Env.getCtx(), "Qty"), "QtyOrdered", Double.class),
new ColumnInfo(Msg.translate(Env.getCtx(), "C_UOM_ID"), "UOMSymbol", String.class),
new ColumnInfo(Msg.translate(Env.getCtx(), "PriceActual"), "PriceActual", BigDecimal.class),
new ColumnInfo(Msg.translate(Env.getCtx(), "LineNetAmt"), "LineNetAmt", BigDecimal.class),
new ColumnInfo(Msg.translate(Env.getCtx(), "C_Tax_ID"), "TaxIndicator", String.class),
};
/** From Clause */
private static String s_sqlFrom = "C_Order_LineTax_v";
/** Where Clause */
private static String s_sqlWhere = "C_Order_ID=? AND LineNetAmt <> 0";
/**
* Initialize
*/
public void init() {
// Content
setLayout(new MigLayout("fill, ins 0 0"));
String buttonSize = "w 50!, h 50!,";
//
f_bSearch = createButtonAction ("Product", KeyStroke.getKeyStroke(KeyEvent.VK_I, Event.CTRL_MASK));
f_bSearch.setName("ProductSearch");
add (f_bSearch, buttonSize );
CLabel productLabel = new CLabel(Msg.translate(Env.getCtx(), "M_Product_ID"));
add(productLabel, ", flowy, h 15");
f_productName = new PosTextField(Msg.translate(Env.getCtx(), "M_Product_ID"), p_posPanel, p_pos.getOSK_KeyLayout_ID());
f_productName.setName("ProductInput");
f_productName.addActionListener(this);
f_productName.addFocusListener(this);
f_productName.requestFocusInWindow();
add (f_productName, "spanx 4, growx, pushx, h 25!");
// PAYMENT
add (new CLabel(),"");
f_cashPayment = createButtonAction("Payment", null);
f_cashPayment.setActionCommand("Payment");
add (f_cashPayment, "w 75!, h 50!, pushx, wrap");
f_cashPayment.setEnabled(false);
m_table = new PosTable();
CScrollPane scroll = new CScrollPane(m_table);
m_sql = m_table.prepareTable (s_layout, s_sqlFrom,
s_sqlWhere, false, "C_Order_LineTax_v")
+ " ORDER BY Line";
// m_table.addMouseListener(this);
m_table.getSelectionModel().addListSelectionListener(this);
m_table.setColumnVisibility(m_table.getColumn(0), false);
m_table.getColumn(1).setPreferredWidth(220);
m_table.getColumn(2).setPreferredWidth(75);
m_table.getColumn(3).setPreferredWidth(35);
m_table.getColumn(4).setPreferredWidth(80);
m_table.getColumn(5).setPreferredWidth(80);
m_table.getColumn(6).setPreferredWidth(30);
m_table.setFocusable(false);
m_table.setFillsViewportHeight( true ); //@Trifon
m_table.growScrollbars();
add (scroll, "growx, spanx, growy, pushy, h 200:300:");
f_up = createButtonAction("Previous", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0));
add (f_up, buttonSize);
f_down = createButtonAction("Next", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0));
add (f_down, buttonSize);
// Product Attributes
f_productAttr = createButtonAction("PAttribute", KeyStroke.getKeyStroke(KeyEvent.VK_F6, 0));
add (f_productAttr, buttonSize);
f_delete = createButtonAction("Cancel", KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, Event.SHIFT_MASK));
add (f_delete, buttonSize);
//
f_minus = createButtonAction("Minus", null);
add(f_minus, buttonSize);
CLabel qtyLabel = new CLabel(Msg.translate(Env.getCtx(), "QtyOrdered"));
add(qtyLabel, "split 2, flowy, h 15");
//
f_quantity = new PosTextField(Msg.translate(Env.getCtx(), "QtyOrdered"),
p_posPanel,p_pos.getOSNP_KeyLayout_ID(), DisplayType.getNumberFormat(DisplayType.Quantity));
f_quantity.setHorizontalAlignment(JTextField.TRAILING);
f_quantity.addActionListener(this);
add(f_quantity, "h 30:30:, w 100");
setQty(Env.ONE);
//
f_plus = createButtonAction("Plus", null);
add(f_plus, buttonSize);
CLabel priceLabel = new CLabel(Msg.translate(Env.getCtx(), "PriceActual"));
add(priceLabel, "split 2, flowy, h 15");
//
f_price = new PosTextField(Msg.translate(Env.getCtx(), "PriceActual"),
p_posPanel,p_pos.getOSNP_KeyLayout_ID(), DisplayType.getNumberFormat(DisplayType.Amount));
f_price.addActionListener(this);
f_price.addFocusListener(this);
f_price.setHorizontalAlignment(JTextField.TRAILING);
add(f_price, "h 30, w 100, wrap");
setPrice(Env.ZERO);
enableButtons();
} //init
/**
* Dispose - Free Resources
*/
public void dispose() {
super.dispose();
} // dispose
/**
* Action Listener
*
* @param e event
*/
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
if (action == null || action.length() == 0)
return;
log.info( "actionPerformed: " + action);
// Plus
if (action.equals("Plus"))
{
if ( orderLineId > 0 )
{
MOrderLine line = new MOrderLine(p_ctx, orderLineId, null);
BigDecimal newQty = line.getQtyOrdered().add(Env.ONE);
if (line != null && hasStock(line.getProduct(), newQty) && hasCredit(line.getProduct(), newQty))
{
line.setQty(newQty);
line.saveEx();
}
}
}
// Minus
else if (action.equals("Minus"))
{
if ( orderLineId > 0 )
{
MOrderLine line = new MOrderLine(p_ctx, orderLineId, null);
if ( line != null )
{
if (line.getQtyOrdered().compareTo(BigDecimal.ONE) > 0)
{
line.setQty(line.getQtyOrdered().subtract(Env.ONE));
line.saveEx();
}
}
}
}
// Product Attribute
else if (action.equals("PAttribute"))
{
if (orderLineId > 0)
{
MOrderLine line = new MOrderLine(p_ctx, orderLineId, null);
if (line != null)
{
requestProductAttributes(line);
}
}
return;
}
else if (action.equals("Payment"))
{
payOrder();
return;
}
else if (e.getSource() == f_price && orderLineId > 0)
{
MOrderLine line = new MOrderLine(p_ctx, orderLineId, null);
if ( line != null )
{
line.setPrice(new BigDecimal(f_price.getValue().toString()));
line.saveEx();
}
}
else if (e.getSource() == f_quantity && orderLineId > 0 )
{
MOrderLine line = new MOrderLine(p_ctx, orderLineId, null);
BigDecimal newQty = new BigDecimal(f_quantity.getValue().toString());
if (line != null && hasStock(line.getProduct(), newQty))
{
line.setQty(newQty);
line.saveEx();
}
}
// Product
else if (action.equals("Product"))
{
setParameter();
QueryProduct qt = new QueryProduct(p_posPanel);
qt.setQueryData(m_M_PriceList_Version_ID, m_M_Warehouse_ID);
qt.setVisible(true);
/* @emmie - perform unneeded second search
if (findProduct()) {
int row = m_table.getSelectedRow();
if (row < 0) row = 0;
//m_table.getSelectionModel().setSelectionInterval(row, row); --red1 - use product window first will gives out of bound error
//https://sourceforge.net/tracker/?func=detail&atid=879332&aid=3121975&group_id=176962
m_table.scrollRectToVisible(m_table.getCellRect(row, 1, true)); //@Trifon - BF[3121975]
}
*/
// @emmie - avoid clean BP when no product is selected
if (orderLineId <= 0)
return;
}
// ProductName
else if (e.getSource() == f_productName)
{
try {
if (findProduct()) {
p_posPanel.updateInfo();
}
} catch (AdempiereException ex) {
ADialog.error(p_posPanel.getWindowNo(), this, ex.getMessage());
}
return;
}
else if ("Previous".equalsIgnoreCase(e.getActionCommand()))
{
int rows = m_table.getRowCount();
if (rows == 0)
return;
int row = m_table.getSelectedRow();
row--;
if (row < 0)
row = 0;
m_table.getSelectionModel().setSelectionInterval(row, row);
// https://sourceforge.net/tracker/?func=detail&atid=879332&aid=3121975&group_id=176962
m_table.scrollRectToVisible(m_table.getCellRect(row, 1, true)); //@Trifon - BF[3121975]
return;
}
else if ("Next".equalsIgnoreCase(e.getActionCommand()))
{
int rows = m_table.getRowCount();
if (rows == 0)
return;
int row = m_table.getSelectedRow();
row++;
if (row >= rows)
row = rows - 1;
m_table.getSelectionModel().setSelectionInterval(row, row);
// https://sourceforge.net/tracker/?func=detail&atid=879332&aid=3121975&group_id=176962
m_table.scrollRectToVisible(m_table.getCellRect(row, 1, true)); //@Trifon - BF[3121975]
return;
}
// Delete
else if (action.equals("Cancel"))
{
int rows = m_table.getRowCount();
if (rows != 0)
{
int row = m_table.getSelectedRow();
if (row != -1)
{
if ( p_posPanel.m_order != null )
p_posPanel.m_order.deleteLine(m_table.getSelectedRowKey());
setQty(null);
setPrice(null);
orderLineId = 0;
}
}
}
p_posPanel.updateInfo();
} // actionPerformed
/**
*
*/
private void payOrder() {
//Check if order is completed, if so, print and open drawer, create an empty order and set cashGiven to zero
if( p_posPanel.m_order != null ) //red1 wrong action flow below
{
// Create a transaction thread
final TrxRunnable trxRunnable = new TrxRunnable()
{
@Override
public void run(final String trxName)
{
// set the proper trx name to order
p_posPanel.m_order.set_TrxName(trxName);
// Si se procesa un remito por el POS no es necesario
// definir medio de pago ni crear los mismos
if (!p_pos.get_ValueAsBoolean("IsShipment"))
{
if (!PosPayment.pay(p_posPanel)) {
String msg = Msg.translate(p_ctx, "PosPaymentCancel");
throw new AdempierePOSException(msg);
}
if (!p_posPanel.m_order.processPayments()) {
String msg = Msg.translate(p_ctx, "FailProcessPaymentHeader");
throw new AdempierePOSException(msg);
}
}
if (!p_posPanel.m_order.isProcessed() && !p_posPanel.m_order.processOrder()) {
String msg = Msg.translate(p_ctx, p_posPanel.m_order.getProcessMsg());
throw new AdempierePOSException(msg);
}
// set trx name to null again
p_posPanel.m_order.set_TrxName(null);
}
};
// Execute the transaction
p_posPanel.startGlassPane("PrintingTicket");
try {
Trx.run(trxRunnable);
} catch (Exception e) {
// set trx name to null again
p_posPanel.m_order.set_TrxName(null);
ADialog.warn(0, p_posPanel, e.getLocalizedMessage());
p_posPanel.stopGlassPane();
return;
}
// Actions out of transaction
printTicket();
p_posPanel.setOrder(0);
}
}
/**
* Update Table
* @param order order
*/
public void updateTable (PosOrderModel order)
{
int C_Order_ID = 0;
if (order != null)
C_Order_ID = order.getC_Order_ID();
if (C_Order_ID == 0)
{
p_posPanel.f_curLine.m_table.loadTable(new PO[0]);
p_posPanel.f_order.setSums(null);
}
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
pstmt = DB.prepareStatement (m_sql, null);
pstmt.setInt (1, C_Order_ID);
rs = pstmt.executeQuery ();
m_table.loadTable(rs);
}
catch (Exception e)
{
log.log(Level.SEVERE, m_sql, e);
}
finally
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
}
for ( int i = 0; i < m_table.getRowCount(); i ++ )
{
IDColumn key = (IDColumn) m_table.getModel().getValueAt(i, 0);
if ( key != null && orderLineId > 0 && key.getRecord_ID() == orderLineId )
{
m_table.getSelectionModel().setSelectionInterval(i, i);
break;
}
}
enableButtons();
p_posPanel.f_order.setSums(order);
} // updateTable
private void enableButtons()
{
boolean enabled = true;
if ( m_table == null || m_table.getRowCount() == 0 || m_table.getSelectedRowKey() == null )
{
enabled = false;
}
f_down.setEnabled(enabled);
f_up.setEnabled(enabled);
f_delete.setEnabled(enabled);
f_minus.setEnabled(enabled);
f_plus.setEnabled(enabled);
f_quantity.setEnabled(enabled);
f_price.setEnabled(enabled);
f_productAttr.setEnabled(enabled);
}
/**
* Set Query Parameter
*/
//TODO - Review this method, I think that is unuseful
private void setParameter()
{
// What PriceList ?
m_M_Warehouse_ID = p_pos.getM_Warehouse_ID();
m_M_PriceList_Version_ID = p_posPanel.f_order.getM_PriceList_Version_ID();
} // setParameter
/**
* Set Price
*
* @param price
*/
public void setPrice(BigDecimal price) {
if (price == null)
price = Env.ZERO;
f_price.setValue(price);
boolean rw = Env.ZERO.compareTo(price) == 0 || p_pos.isModifyPrice();
f_price.setEditable(rw);
} // setPrice
/**
* Get Price
*
* @return price
*/
public BigDecimal getPrice() {
return (BigDecimal) f_price.getValue();
} // getPrice
/**
* Set Qty
*
* @param qty
*/
public void setQty(BigDecimal qty) {
f_quantity.setValue(qty);
} // setQty
/**
* Get Qty
*
* @return qty
*/
public BigDecimal getQty() {
return (BigDecimal) f_quantity.getValue();
} // getQty
/***************************************************************************
* New Line
*/
public void newLine() {
setM_Product_ID(0);
setQty(Env.ONE);
setPrice(Env.ZERO);
orderLineId = 0;
f_productName.requestFocusInWindow();
} // newLine
/**
* Save Line
*
* @return true if saved
*/
public boolean saveLine() {
MProduct product = getProduct();
if (product == null)
return false;
BigDecimal qtyOrdered = (BigDecimal) f_quantity.getValue();
BigDecimal priceActual = (BigDecimal) f_price.getValue();
if ( p_posPanel.m_order == null )
{
p_posPanel.m_order = PosOrderModel.createOrder(p_posPanel.p_pos, p_posPanel.f_order.getBPartner(),
p_posPanel.f_order.getC_BPartner_Location_ID(), trxName);
}
MOrderLine line = null;
if ( p_posPanel.m_order != null )
{
line = p_posPanel.m_order.createLine(product, qtyOrdered, priceActual, p_posPanel.getWindowNo());
if (line == null)
return false;
if (!line.save())
return false;
}
orderLineId = line.getC_OrderLine_ID();
setM_Product_ID(0);
//
return true;
} // saveLine
/**
* Get Product
* @return product
*/
public MProduct getProduct()
{
return m_product;
} // getProduct
/**
* Set Price for defined product
*/
public void setPrice()
{
if (m_product == null)
return;
//
setParameter();
MWarehousePrice result = MWarehousePrice.get (m_product,
m_M_PriceList_Version_ID, m_M_Warehouse_ID, null);
if (result != null)
p_posPanel.f_curLine.setPrice(result.getPriceStd());
else
p_posPanel.f_curLine.setPrice(Env.ZERO);
} // setPrice
/**************************************************************************
* Find/Set Product & Price
*/
private boolean findProduct()
{
String query = f_productName.getText();
if (query == null || query.length() == 0)
return false;
query = query.toUpperCase();
// Test Number
boolean allNumber = true;
try
{
Integer.getInteger(query);
}
catch (Exception e)
{
allNumber = false;
}
String Value = query;
String Name = query;
String UPC = (allNumber ? query : null);
String SKU = (allNumber ? query : null);
MWarehousePrice[] results = null;
setParameter();
//
results = MWarehousePrice.find (p_ctx, m_M_PriceList_Version_ID, m_M_Warehouse_ID, Value,
Name, UPC, SKU, null);
// Set Result
if (results.length == 0)
{
String message = Msg.translate(p_ctx, "search.product.notfound");
ADialog.warn(0, p_posPanel, message + query);
setM_Product_ID(0);
p_posPanel.f_curLine.setPrice(Env.ZERO);
return false;
}
else if (results.length == 1)
{
setM_Product_ID(results[0].getM_Product_ID());
setQty(Env.ONE);
f_productName.setText(results[0].getName());
p_posPanel.f_curLine.setPrice(results[0].getPriceStd());
return saveLine();
}
else // more than one
{
QueryProduct qt = new QueryProduct(p_posPanel);
qt.setResults(results);
qt.setQueryData(m_M_PriceList_Version_ID, m_M_Warehouse_ID);
qt.setVisible(true);
return orderLineId > 0; // @emmie
}
} // findProduct
/**************************************************************************
* Set Product
* @param M_Product_ID id
*/
public void setM_Product_ID (int M_Product_ID)
{
log.info("M_Product_ID=" + M_Product_ID);
if (M_Product_ID <= 0)
m_product = null;
else
{
m_product = MProduct.get(p_ctx, M_Product_ID);
if (m_product.get_ID() == 0)
m_product = null;
}
// Set String Info
if (m_product != null)
{
f_productName.setText(m_product.getName());
f_productName.setToolTipText(m_product.getDescription());
}
else
{
f_productName.setText(null);
f_productName.setToolTipText(null);
}
} // setM_Product_ID
/**
* Focus Gained
* @param e
*/
public void focusGained (FocusEvent e) {}
/**
* Focus Lost
* @param e
*/
public void focusLost (FocusEvent e)
{
if (e.isTemporary())
return;
log.info( "PosSubProduct - focusLost");
// Product Name
if (e.getSource() == f_productName)
{
if (!findProduct())
return;
}
// Price
else if (e.getSource() == f_price && orderLineId > 0)
{
MOrderLine line = new MOrderLine(p_ctx, orderLineId, null);
if (line != null) {
// force commit edited value of f_price
try {
f_price.commitEdit();
} catch (ParseException ex) {
log.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
return;
}
line.setPrice(new BigDecimal(f_price.getValue().toString()));
line.saveEx();
}
}
p_posPanel.updateInfo();
} // focusLost
public void valueChanged(ListSelectionEvent e) {
if ( e.getValueIsAdjusting() )
return;
int row = m_table.getSelectedRow();
if (row != -1 )
{
Object data = m_table.getModel().getValueAt(row, 0);
if ( data != null )
{
Integer id = (Integer) ((IDColumn)data).getRecord_ID();
orderLineId = id;
loadLine(id);
}
}
enableButtons();
}
private void loadLine(int lineId)
{
if ( lineId <= 0 )
return;
log.fine("loading line " + lineId);
MOrderLine ol = new MOrderLine(p_ctx, lineId, null);
if ( ol != null )
{
setPrice(ol.getPriceActual());
setQty(ol.getQtyOrdered());
}
}
/**
* Recupera el botón de pago
* @return botón de pago
*/
CButton getPaymentButton()
{
return f_cashPayment;
}
/**
* Check stock available
*
* @author Emiliano Pereyra
*/
private boolean hasStock(final MProduct product, final BigDecimal newQty)
{
String stockMsg = p_posPanel.m_order.checkStockAvailable(product, newQty, p_posPanel.getWindowNo());
if (stockMsg != null) {
ADialog.error(0, this, stockMsg);
return false;
}
return true;
} // hasStock
/**
* Check credit available
*
* @author Emiliano Pereyra
*/
private boolean hasCredit(final MProduct product, final BigDecimal qty)
{
String creditMsg = p_posPanel.m_order.checkCreditAvailable(product, qty);
if (creditMsg != null) {
ADialog.error(0, this, creditMsg);
return false;
}
return true;
} // hasCredit
/**
* Shows the product attribute instance dialog in order to set the attributes
* defined for each product (if product has any)
*
* @param product
*/
private void requestProductAttributes(final MOrderLine line)
{
MProduct product = line.getProduct();
int m_AttributeSet_ID = product.getM_AttributeSet_ID();
int m_AttributeSetInstance_ID = line.getM_AttributeSetInstance_ID();
String logMsg = String.format("Product=%s - M_AttributeSet_ID=%d - M_AttributeSetInstance_ID=%d",product, m_AttributeSet_ID
, m_AttributeSetInstance_ID);
log.info(logMsg);
String msg;
if (m_AttributeSet_ID != 0) {
VPAttributeDialog vad = new VPAttributeDialog(Env.getFrame(this), m_AttributeSetInstance_ID,
product.get_ID(), 0, false, 0, p_posPanel.getWindowNo());
if (vad.isChanged()) {
line.setM_AttributeSetInstance_ID(vad.getM_AttributeSetInstance_ID());
if (line.save()) {
msg = Msg.translate(p_ctx, "AttributeSetInstanceSaved");
ADialog.info(p_posPanel.getWindowNo(), this, msg);
} else {
msg = Msg.translate(p_ctx, "AttributeSetInstanceSavedError");
ADialog.error(p_posPanel.getWindowNo(), this, msg);
}
}
} else {
msg = Msg.translate(p_ctx, "ProductWithoutAttributSet");
ADialog.warn(p_posPanel.getWindowNo(), this, msg);
}
} // requestProductAttributes
} // PosSubCurrentLine