diff --git a/migration/i2.0/oracle/201312051535_IDEMPIERE-337.sql b/migration/i2.0/oracle/201312051535_IDEMPIERE-337.sql new file mode 100644 index 0000000000..dd8d9a52f7 --- /dev/null +++ b/migration/i2.0/oracle/201312051535_IDEMPIERE-337.sql @@ -0,0 +1,18 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- IDEMPIERE-337 zkwebui - Improve Info Product window +UPDATE M_Product_PO po +SET IsCurrentVendor='N' +WHERE po.IsActive='Y' +AND po.IsCurrentVendor='Y' +AND po.C_BPartner_ID NOT IN ( + SELECT MAX(ppo.C_BPartner_ID) + FROM M_Product_PO ppo + WHERE ppo.IsActive='Y' + AND ppo.IsCurrentVendor='Y' + AND ppo.M_Product_ID = po.M_Product_ID +); + +SELECT register_migration_script('201312051535_IDEMPIERE-337') FROM dual +; \ No newline at end of file diff --git a/migration/i2.0/postgresql/201312051535_IDEMPIERE-337.sql b/migration/i2.0/postgresql/201312051535_IDEMPIERE-337.sql new file mode 100644 index 0000000000..fd2829156a --- /dev/null +++ b/migration/i2.0/postgresql/201312051535_IDEMPIERE-337.sql @@ -0,0 +1,15 @@ +-- IDEMPIERE-337 zkwebui - Improve Info Product window +UPDATE M_Product_PO po +SET IsCurrentVendor='N' +WHERE po.IsActive='Y' +AND po.IsCurrentVendor='Y' +AND po.C_BPartner_ID NOT IN ( + SELECT MAX(ppo.C_BPartner_ID) + FROM M_Product_PO ppo + WHERE ppo.IsActive='Y' + AND ppo.IsCurrentVendor='Y' + AND ppo.M_Product_ID = po.M_Product_ID +); + +SELECT register_migration_script('201312051535_IDEMPIERE-337') FROM dual +; \ No newline at end of file diff --git a/org.adempiere.base.callout/src/org/compiere/model/CalloutInvoice.java b/org.adempiere.base.callout/src/org/compiere/model/CalloutInvoice.java index 0adede9787..b3e36dc703 100644 --- a/org.adempiere.base.callout/src/org/compiere/model/CalloutInvoice.java +++ b/org.adempiere.base.callout/src/org/compiere/model/CalloutInvoice.java @@ -510,6 +510,8 @@ public class CalloutInvoice extends CalloutEngine int M_Product_ID = Env.getContextAsInt(ctx, WindowNo, "M_Product_ID"); int M_PriceList_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID"); int StdPrecision = MPriceList.getStandardPrecision(ctx, M_PriceList_ID); + MPriceList pl = new MPriceList(ctx, M_PriceList_ID, null); + boolean isEnforcePriceLimit = pl.isEnforcePriceLimit(); BigDecimal QtyEntered, QtyInvoiced, PriceEntered, PriceActual, PriceLimit, Discount, PriceList; // get values QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); @@ -630,7 +632,7 @@ public class CalloutInvoice extends CalloutEngine // Check PriceLimit String epl = Env.getContext(ctx, WindowNo, "EnforcePriceLimit"); - boolean enforce = Env.isSOTrx(ctx, WindowNo) && epl != null && epl.equals("Y"); + boolean enforce = Env.isSOTrx(ctx, WindowNo) && epl != null && !epl.equals("") ? epl.equals("Y") : isEnforcePriceLimit; if (enforce && MRole.getDefault().isOverwritePriceLimit()) enforce = false; // Check Price Limit? diff --git a/org.adempiere.base.callout/src/org/compiere/model/CalloutOrder.java b/org.adempiere.base.callout/src/org/compiere/model/CalloutOrder.java index 8a5c2359e6..09331f172a 100644 --- a/org.adempiere.base.callout/src/org/compiere/model/CalloutOrder.java +++ b/org.adempiere.base.callout/src/org/compiere/model/CalloutOrder.java @@ -1038,6 +1038,8 @@ public class CalloutOrder extends CalloutEngine int M_Product_ID = Env.getContextAsInt(ctx, WindowNo, "M_Product_ID"); int M_PriceList_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID"); int StdPrecision = MPriceList.getStandardPrecision(ctx, M_PriceList_ID); + MPriceList pl = new MPriceList(ctx, M_PriceList_ID, null); + boolean isEnforcePriceLimit = pl.isEnforcePriceLimit(); BigDecimal QtyEntered, QtyOrdered, PriceEntered, PriceActual, PriceLimit, Discount, PriceList; // get values QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); @@ -1158,7 +1160,7 @@ public class CalloutOrder extends CalloutEngine // Check PriceLimit String epl = Env.getContext(ctx, WindowNo, "EnforcePriceLimit"); - boolean enforce = Env.isSOTrx(ctx, WindowNo) && epl != null && epl.equals("Y"); + boolean enforce = Env.isSOTrx(ctx, WindowNo) && epl != null && !epl.equals("") ? epl.equals("Y") : isEnforcePriceLimit; if (enforce && MRole.getDefault().isOverwritePriceLimit()) enforce = false; // Check Price Limit? diff --git a/org.adempiere.base.process/src/org/compiere/process/ImportAccount.java b/org.adempiere.base.process/src/org/compiere/process/ImportAccount.java index 66060a4a68..efe60aee52 100644 --- a/org.adempiere.base.process/src/org/compiere/process/ImportAccount.java +++ b/org.adempiere.base.process/src/org/compiere/process/ImportAccount.java @@ -25,6 +25,7 @@ import java.util.logging.Level; import org.compiere.model.MAccount; import org.compiere.model.MAcctSchema; +import org.compiere.model.MColumn; import org.compiere.model.MElementValue; import org.compiere.model.X_I_ElementValue; import org.compiere.util.DB; @@ -656,8 +657,14 @@ public class ImportAccount extends SvrProcess } // replace combination } // need to update } // for all default accounts - else - log.log(Level.SEVERE, "Account not found " + sql); + else { + // check if column is active before logging on SEVERE level + int columnID = MColumn.getColumn_ID(TableName, ColumnName); + if (new MColumn(getCtx(), columnID, get_TrxName()).isActive()) + log.log(Level.SEVERE, "Account not found " + sql); + else + log.log(Level.WARNING, "The account " + ColumnName + " is deprecated, you should consider removing it from your import file"); + } } catch (SQLException e) { diff --git a/org.adempiere.base/src/org/compiere/model/DataStatusEvent.java b/org.adempiere.base/src/org/compiere/model/DataStatusEvent.java index 18251591d4..0327477f1a 100644 --- a/org.adempiere.base/src/org/compiere/model/DataStatusEvent.java +++ b/org.adempiere.base/src/org/compiere/model/DataStatusEvent.java @@ -20,6 +20,8 @@ import java.io.Serializable; import java.sql.Timestamp; import java.util.EventObject; +import org.idempiere.fa.util.Util; + /** * Data Status Event *

@@ -337,4 +339,17 @@ public final class DataStatusEvent extends EventObject implements Serializable return m_confirmed; } // isConfirmed + public boolean isEqual(DataStatusEvent e) { + if (e == null) return false; + + return e.m_changed == m_changed && + e.m_inserting == m_inserting && + e.m_isError == m_isError && + e.m_isWarning == m_isWarning && + Util.equals(e.m_AD_Message, m_AD_Message) && + e.m_changedColumn == m_changedColumn && + Util.equals(e.m_columnName, m_columnName) && + e.m_currentRow == m_currentRow; + } + } // DataStatusEvent diff --git a/org.adempiere.base/src/org/compiere/model/GridTab.java b/org.adempiere.base/src/org/compiere/model/GridTab.java index c0d28b9e3b..18d4331f46 100644 --- a/org.adempiere.base/src/org/compiere/model/GridTab.java +++ b/org.adempiere.base/src/org/compiere/model/GridTab.java @@ -2251,7 +2251,7 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable * @param e event */ public void dataStatusChanged (DataStatusEvent e) - { + { if (log.isLoggable(Level.FINE)) log.fine("#" + m_vo.TabNo + " - " + e.toString()); int oldCurrentRow = e.getCurrentRow(); m_DataStatusEvent = e; // save it @@ -2262,6 +2262,7 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable // set current row m_DataStatusEvent = e; // setCurrentRow clear it, need to save again m_DataStatusEvent.setCurrentRow(m_currentRow); + // Same row - update value if (oldCurrentRow == m_currentRow) { @@ -2272,8 +2273,25 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable field.setValue(value, m_mTable.isInserting()); } } - else // Redistribute Info with current row info - fireDataStatusChanged(m_DataStatusEvent); + else + { + // Redistribute Info with current row info + // Avoid firing of duplicate event + boolean fire = true; + if (m_lastDataStatusEvent != null) + { + if (System.currentTimeMillis() - m_lastDataStatusEventTime < 200) + { + if (m_lastDataStatusEvent.isEqual(m_DataStatusEvent)) + { + fire = false; + } + } + } + + if (fire) + fireDataStatusChanged(m_DataStatusEvent); + } //reset m_lastDataStatusEventTime = System.currentTimeMillis(); diff --git a/org.adempiere.base/src/org/compiere/model/MInvoiceLine.java b/org.adempiere.base/src/org/compiere/model/MInvoiceLine.java index 7951b446cd..c32cbc48c4 100644 --- a/org.adempiere.base/src/org/compiere/model/MInvoiceLine.java +++ b/org.adempiere.base/src/org/compiere/model/MInvoiceLine.java @@ -860,6 +860,19 @@ public class MInvoiceLine extends X_C_InvoiceLine && Env.ZERO.compareTo(getPriceActual()) == 0 && Env.ZERO.compareTo(getPriceList()) == 0) setPrice(); + // IDEMPIERE-1574 Sales Order Line lets Price under the Price Limit when updating + // Check PriceLimit + boolean enforce = m_IsSOTrx && m_parent.getM_PriceList().isEnforcePriceLimit(); + if (enforce && MRole.getDefault().isOverwritePriceLimit()) + enforce = false; + // Check Price Limit? + if (enforce && getPriceLimit() != Env.ZERO + && getPriceActual().compareTo(getPriceLimit()) < 0) + { + log.saveError("UnderLimitPrice", "PriceEntered=" + getPriceEntered() + ", PriceLimit=" + getPriceLimit()); + return false; + } + // } // Set Tax diff --git a/org.adempiere.base/src/org/compiere/model/MMailText.java b/org.adempiere.base/src/org/compiere/model/MMailText.java index 8acec867b3..53ac18a862 100644 --- a/org.adempiere.base/src/org/compiere/model/MMailText.java +++ b/org.adempiere.base/src/org/compiere/model/MMailText.java @@ -18,12 +18,15 @@ package org.compiere.model; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.text.SimpleDateFormat; import java.util.Properties; import java.util.logging.Level; import org.compiere.util.CCache; import org.compiere.util.DB; +import org.compiere.util.DisplayType; import org.compiere.util.Env; +import org.compiere.util.Msg; /** * Request Mail Template Model. @@ -221,6 +224,14 @@ public class MMailText extends X_R_MailText Object value = null; if (col != null && col.isSecure()) { value = "********"; + } else if (col.getAD_Reference_ID() == DisplayType.Date || col.getAD_Reference_ID() == DisplayType.DateTime || col.getAD_Reference_ID() == DisplayType.Time) { + SimpleDateFormat sdf = DisplayType.getDateFormat(col.getAD_Reference_ID()); + value = sdf.format (po.get_Value(index)); + } else if (col.getAD_Reference_ID() == DisplayType.YesNo) { + if (po.get_ValueAsBoolean(variable)) + value = Msg.getMsg(Env.getCtx(), "Yes"); + else + value = Msg.getMsg(Env.getCtx(), "No"); } else { value = po.get_Value(index); } diff --git a/org.adempiere.base/src/org/compiere/model/MOrderLine.java b/org.adempiere.base/src/org/compiere/model/MOrderLine.java index bc1df9dad5..dae5610880 100644 --- a/org.adempiere.base/src/org/compiere/model/MOrderLine.java +++ b/org.adempiere.base/src/org/compiere/model/MOrderLine.java @@ -870,6 +870,19 @@ public class MOrderLine extends X_C_OrderLine // Check if on Price list if (m_productPrice == null) getProductPricing(m_M_PriceList_ID); + // IDEMPIERE-1574 Sales Order Line lets Price under the Price Limit when updating + // Check PriceLimit + boolean enforce = m_IsSOTrx && m_parent.getM_PriceList().isEnforcePriceLimit(); + if (enforce && MRole.getDefault().isOverwritePriceLimit()) + enforce = false; + // Check Price Limit? + if (enforce && getPriceLimit() != Env.ZERO + && getPriceActual().compareTo(getPriceLimit()) < 0) + { + log.saveError("UnderLimitPrice", "PriceEntered=" + getPriceEntered() + ", PriceLimit=" + getPriceLimit()); + return false; + } + // if (!m_productPrice.isCalculated()) { throw new ProductNotOnPriceListException(m_productPrice, getLine()); diff --git a/org.adempiere.base/src/org/compiere/model/MProductPO.java b/org.adempiere.base/src/org/compiere/model/MProductPO.java index dde9a5356b..b04471a1c9 100644 --- a/org.adempiere.base/src/org/compiere/model/MProductPO.java +++ b/org.adempiere.base/src/org/compiere/model/MProductPO.java @@ -19,6 +19,9 @@ package org.compiere.model; import java.sql.ResultSet; import java.util.List; import java.util.Properties; +import java.util.logging.Level; + +import org.compiere.util.DB; /** * Product PO Model @@ -31,8 +34,7 @@ public class MProductPO extends X_M_Product_PO /** * */ - private static final long serialVersionUID = -747761340543484440L; - + private static final long serialVersionUID = -1883198806060209516L; /** * Get current PO of Product @@ -84,4 +86,34 @@ public class MProductPO extends X_M_Product_PO super(ctx, rs, trxName); } // MProductPO + /** + * Before Save + * @param newRecord new + * @return true + */ + @Override + protected boolean beforeSave(boolean newRecord) + { + if ((newRecord && isActive() && isCurrentVendor()) || + (!newRecord && + ( + (is_ValueChanged("IsActive") && isActive()) // now active + || (is_ValueChanged("IsCurrentVendor") && isCurrentVendor()) // now current vendor + || is_ValueChanged("C_BPartner_ID") + || is_ValueChanged("M_Product_ID") + ) + ) + ) + { + if (isActive() && isCurrentVendor()) + { + String sql = "UPDATE M_Product_PO SET IsCurrentVendor='N' WHERE IsActive='Y' AND IsCurrentVendor='Y' AND C_BPartner_ID!=? AND M_Product_ID=?"; + int no = DB.executeUpdate(sql, new Object[] {getC_BPartner_ID(), getM_Product_ID()}, false, get_TrxName()); + if (log.isLoggable(Level.FINEST)) log.finest("Updated M_Product_PO.IsCurrentVendor #" + no); + } + } + + return true; + } + } // MProductPO diff --git a/org.adempiere.pipo/src/org/adempiere/pipo2/PoExporter.java b/org.adempiere.pipo/src/org/adempiere/pipo2/PoExporter.java index a1530e29c4..ea01ee7c68 100644 --- a/org.adempiere.pipo/src/org/adempiere/pipo2/PoExporter.java +++ b/org.adempiere.pipo/src/org/adempiere/pipo2/PoExporter.java @@ -29,6 +29,11 @@ public class PoExporter { private void addTextElement(String qName, String text, AttributesImpl atts) { try { + //default trim to false for print item label since trailing space is commonly use + //for formatting purpose + if (qName.equalsIgnoreCase("PrintName")) { + atts.addAttribute("", "", "trim", "CDATA", "false"); + } transformerHandler.startElement("", "", qName, atts); append(text); transformerHandler.endElement("", "", qName); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Messagebox.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Messagebox.java index be306888f9..b81cdbfc93 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Messagebox.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Messagebox.java @@ -28,6 +28,7 @@ import org.compiere.util.Env; import org.compiere.util.Msg; import org.compiere.util.Util; import org.zkoss.zhtml.Text; +import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Page; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; @@ -244,7 +245,20 @@ public class Messagebox extends Window implements EventListener this.setSizable(true); this.setVisible(true); - this.setId("MessageBox_"+AdempiereIdGenerator.escapeId(title)); + String id = "MessageBox_"+AdempiereIdGenerator.escapeId(title); + //make sure id is unique + Page page = AEnv.getDesktop().getFirstPage(); + Component fellow = page.getFellowIfAny(id); + if (fellow != null) { + int count = 0; + String newId = null; + while (fellow != null) { + newId = id + "_" + ++count; + fellow = page.getFellowIfAny(newId); + } + id = newId; + } + this.setId(id); AEnv.showCenterScreen(this); return returnValue; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/GridTabDataBinder.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/GridTabDataBinder.java index f9da63ba1c..19a2a6b905 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/GridTabDataBinder.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/GridTabDataBinder.java @@ -195,9 +195,9 @@ public class GridTabDataBinder implements ValueChangeListener { for (int i = 0; i < values.length; i++) { - if (!gridTab.dataNew(true)) + if (!gridTab.dataNew(false)) { - throw new IllegalStateException("Could not clone tab"); + throw new IllegalStateException("Could not create new row"); } gridTab.setValue(columnName, values[i]); @@ -209,10 +209,9 @@ public class GridTabDataBinder implements ValueChangeListener { if (!gridTab.dataSave(false)) { - throw new IllegalStateException("Could not update tab"); - } - - gridTab.setCurrentRow(oldRow); + throw new IllegalStateException("Could not update row"); + } } + gridTab.setCurrentRow(oldRow); } -} +} \ No newline at end of file diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FDialog.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FDialog.java index 232a8a7130..5e5073affa 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FDialog.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FDialog.java @@ -62,7 +62,7 @@ public class FDialog if (message != null && message.length() > 0) { - out.append("\n").append(message); + out.append("
").append(message); } return out; diff --git a/org.adempiere.ui/src/org/compiere/apps/form/Allocation.java b/org.adempiere.ui/src/org/compiere/apps/form/Allocation.java index 7bb72f5ae4..7ef931b896 100644 --- a/org.adempiere.ui/src/org/compiere/apps/form/Allocation.java +++ b/org.adempiere.ui/src/org/compiere/apps/form/Allocation.java @@ -30,6 +30,7 @@ import org.compiere.model.MAllocationLine; import org.compiere.model.MInvoice; import org.compiere.model.MPayment; import org.compiere.model.MRole; +import org.compiere.model.MSysConfig; import org.compiere.process.DocAction; import org.compiere.util.CLogger; import org.compiere.util.DB; @@ -422,8 +423,9 @@ public class Allocation { if ( applied.signum() == -open.signum() ) applied = applied.negate(); - if ( open.abs().compareTo( applied.abs() ) < 0 ) - applied = open; + if (! MSysConfig.getBooleanValue("ALLOW_OVER_APPLIED_PAYMENT", false, Env.getAD_Client_ID(Env.getCtx()))) + if ( open.abs().compareTo( applied.abs() ) < 0 ) + applied = open; } payment.setValueAt(applied, row, i_payment);