diff --git a/migration/i6.2/oracle/201902121250_IDEMPIERE-3896.sql b/migration/i6.2/oracle/201902121250_IDEMPIERE-3896.sql new file mode 100644 index 0000000000..8655b9c9ec --- /dev/null +++ b/migration/i6.2/oracle/201902121250_IDEMPIERE-3896.sql @@ -0,0 +1,42 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Feb 11, 2019 4:36:05 PM CET +-- IDEMPIERE-3896 Process that fixes M_StorageReservation when wrong reservations are found +INSERT INTO AD_Process (CopyFromProcess,AD_Process_ID,Help,IsDirectPrint,IsReport,AD_Process_UU,AccessLevel,IsBetaFunctionality,IsServerProcess,Statistic_Seconds,Statistic_Count,ShowHelp,Updated,IsActive,UpdatedBy,Name,Created,CreatedBy,Classname,AD_Client_ID,EntityType,Value,AD_Org_ID,AllowMultipleExecution) VALUES ('N',200107,'The process checks if there are errors in storage reservartion (storageqtyReserved <> orderqtyreserved), if there are, it recreates all the reservation records for the offending products.','N','N','c4409eac-e5a8-4eac-b34a-1ac73319aa03','3','N','N',0,0,'Y',TO_DATE('2019-02-11 16:36:04','YYYY-MM-DD HH24:MI:SS'),'Y',100,'Recreate Storage Reservation',TO_DATE('2019-02-11 16:36:04','YYYY-MM-DD HH24:MI:SS'),100,'org.adempiere.process.RecreateStorageReservation',0,'D','RecreateStorageReservation',0,'N') +; + +-- Feb 11, 2019 4:37:49 PM CET +INSERT INTO AD_Menu (AD_Menu_ID,IsSummary,AD_Menu_UU,IsSOTrx,IsReadOnly,AD_Process_ID,IsCentrallyMaintained,Name,Action,IsActive,CreatedBy,AD_Client_ID,Created,Updated,UpdatedBy,EntityType,AD_Org_ID) VALUES (200166,'N','cac979ac-f9b3-4756-a367-1f2f5941ad41','N','N',200107,'Y','Recreate Storage Reservation','P','Y',100,0,TO_DATE('2019-02-11 16:37:48','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2019-02-11 16:37:48','YYYY-MM-DD HH24:MI:SS'),100,'D',0) +; + +-- Feb 11, 2019 4:37:49 PM CET +INSERT INTO AD_TreeNode (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, AD_Tree_ID, Node_ID, Parent_ID, SeqNo, AD_TreeNode_UU) SELECT t.AD_Client_ID, 0, 'Y', SysDate, 100, SysDate, 100,t.AD_Tree_ID, 200166, 0, 999, Generate_UUID() FROM AD_Tree t WHERE t.AD_Client_ID=0 AND t.IsActive='Y' AND t.IsAllNodes='Y' AND t.TreeType='TL' AND t.AD_Table_ID=116 AND NOT EXISTS (SELECT * FROM AD_TreeNode e WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=200166) +; + +-- Feb 11, 2019 4:37:49 PM CET +INSERT INTO AD_TreeNodeMM (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, AD_Tree_ID, Node_ID, Parent_ID, SeqNo, AD_TreeNodeMM_UU) SELECT t.AD_Client_ID, 0, 'Y', SysDate, 100, SysDate, 100,t.AD_Tree_ID, 200166, 0, 999, Generate_UUID() FROM AD_Tree t WHERE t.AD_Client_ID=0 AND t.IsActive='Y' AND t.IsAllNodes='Y' AND t.TreeType='MM' AND NOT EXISTS (SELECT * FROM AD_TreeNodeMM e WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=200166) +; + +-- Feb 17, 2019, 11:22:47 AM CET +UPDATE AD_TreeNodeMM SET Parent_ID=183, SeqNo=20, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=200166 +; + +-- Feb 17, 2019, 11:22:47 AM CET +UPDATE AD_TreeNodeMM SET Parent_ID=183, SeqNo=21, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=311 +; + +-- Feb 17, 2019, 11:22:47 AM CET +UPDATE AD_TreeNodeMM SET Parent_ID=183, SeqNo=22, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=292 +; + +-- Feb 17, 2019, 11:22:47 AM CET +UPDATE AD_TreeNodeMM SET Parent_ID=183, SeqNo=23, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=504 +; + +-- Feb 17, 2019, 11:22:47 AM CET +UPDATE AD_TreeNodeMM SET Parent_ID=183, SeqNo=24, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=515 +; + +SELECT register_migration_script('201902121250_IDEMPIERE-3896.sql') FROM dual +; diff --git a/migration/i6.2/oracle/201902141541_IDEMPIERE-1887.sql b/migration/i6.2/oracle/201902141541_IDEMPIERE-1887.sql new file mode 100644 index 0000000000..782124cdac --- /dev/null +++ b/migration/i6.2/oracle/201902141541_IDEMPIERE-1887.sql @@ -0,0 +1,11 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- IDEMPIERE-1887 can make inconsistent data from physical inventory window +-- Feb 14, 2019, 3:40:50 PM CET +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','Warehouse cannot be changed because there are lines.',0,0,'Y',TO_DATE('2019-02-14 15:40:49','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-02-14 15:40:49','YYYY-MM-DD HH24:MI:SS'),100,200487,'CannotChangeWarehouse','D','2a9c7a1b-35b2-464c-a2ba-0aa60be3d81d') +; + +SELECT register_migration_script('201902141541_IDEMPIERE-1887.sql') FROM dual +; + diff --git a/migration/i6.2/oracle/201902141651_IDEMPIERE-1615.sql b/migration/i6.2/oracle/201902141651_IDEMPIERE-1615.sql new file mode 100644 index 0000000000..c5cc814729 --- /dev/null +++ b/migration/i6.2/oracle/201902141651_IDEMPIERE-1615.sql @@ -0,0 +1,11 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- IDEMPIERE-1615 Multiple key columns lead to data corruption or data loss +-- Feb 14, 2019, 4:51:33 PM CET +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','The table has already a key column, there can be just one key.',0,0,'Y',TO_DATE('2019-02-14 16:51:32','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-02-14 16:51:32','YYYY-MM-DD HH24:MI:SS'),100,200488,'KeyColumnAlreadyDefined','D','c5011666-1371-4620-a5bc-aa29265f5d90') +; + +SELECT register_migration_script('201902141651_IDEMPIERE-1615.sql') FROM dual +; + diff --git a/migration/i6.2/postgresql/201902121250_IDEMPIERE-3896.sql b/migration/i6.2/postgresql/201902121250_IDEMPIERE-3896.sql new file mode 100644 index 0000000000..9acbc90322 --- /dev/null +++ b/migration/i6.2/postgresql/201902121250_IDEMPIERE-3896.sql @@ -0,0 +1,39 @@ +-- Feb 11, 2019 4:36:05 PM CET +-- IDEMPIERE-3896 Process that fixes M_StorageReservation when wrong reservations are found +INSERT INTO AD_Process (CopyFromProcess,AD_Process_ID,Help,IsDirectPrint,IsReport,AD_Process_UU,AccessLevel,IsBetaFunctionality,IsServerProcess,Statistic_Seconds,Statistic_Count,ShowHelp,Updated,IsActive,UpdatedBy,Name,Created,CreatedBy,Classname,AD_Client_ID,EntityType,Value,AD_Org_ID,AllowMultipleExecution) VALUES ('N',200107,'The process checks if there are errors in storage reservartion (storageqtyReserved <> orderqtyreserved), if there are, it recreates all the reservation records for the offending products.','N','N','c4409eac-e5a8-4eac-b34a-1ac73319aa03','3','N','N',0,0,'Y',TO_TIMESTAMP('2019-02-11 16:36:04','YYYY-MM-DD HH24:MI:SS'),'Y',100,'Recreate Storage Reservation',TO_TIMESTAMP('2019-02-11 16:36:04','YYYY-MM-DD HH24:MI:SS'),100,'org.adempiere.process.RecreateStorageReservation',0,'D','RecreateStorageReservation',0,'N') +; + +-- Feb 11, 2019 4:37:49 PM CET +INSERT INTO AD_Menu (AD_Menu_ID,IsSummary,AD_Menu_UU,IsSOTrx,IsReadOnly,AD_Process_ID,IsCentrallyMaintained,Name,"action",IsActive,CreatedBy,AD_Client_ID,Created,Updated,UpdatedBy,EntityType,AD_Org_ID) VALUES (200166,'N','cac979ac-f9b3-4756-a367-1f2f5941ad41','N','N',200107,'Y','Recreate Storage Reservation','P','Y',100,0,TO_TIMESTAMP('2019-02-11 16:37:48','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2019-02-11 16:37:48','YYYY-MM-DD HH24:MI:SS'),100,'D',0) +; + +-- Feb 11, 2019 4:37:49 PM CET +INSERT INTO AD_TreeNode (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, AD_Tree_ID, Node_ID, Parent_ID, SeqNo, AD_TreeNode_UU) SELECT t.AD_Client_ID, 0, 'Y', statement_timestamp(), 100, statement_timestamp(), 100,t.AD_Tree_ID, 200166, 0, 999, Generate_UUID() FROM AD_Tree t WHERE t.AD_Client_ID=0 AND t.IsActive='Y' AND t.IsAllNodes='Y' AND t.TreeType='TL' AND t.AD_Table_ID=116 AND NOT EXISTS (SELECT * FROM AD_TreeNode e WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=200166) +; + +-- Feb 11, 2019 4:37:49 PM CET +INSERT INTO AD_TreeNodeMM (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, AD_Tree_ID, Node_ID, Parent_ID, SeqNo, AD_TreeNodeMM_UU) SELECT t.AD_Client_ID, 0, 'Y', statement_timestamp(), 100, statement_timestamp(), 100,t.AD_Tree_ID, 200166, 0, 999, Generate_UUID() FROM AD_Tree t WHERE t.AD_Client_ID=0 AND t.IsActive='Y' AND t.IsAllNodes='Y' AND t.TreeType='MM' AND NOT EXISTS (SELECT * FROM AD_TreeNodeMM e WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=200166) +; + +-- Feb 17, 2019, 11:22:47 AM CET +UPDATE AD_TreeNodeMM SET Parent_ID=183, SeqNo=20, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=200166 +; + +-- Feb 17, 2019, 11:22:47 AM CET +UPDATE AD_TreeNodeMM SET Parent_ID=183, SeqNo=21, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=311 +; + +-- Feb 17, 2019, 11:22:47 AM CET +UPDATE AD_TreeNodeMM SET Parent_ID=183, SeqNo=22, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=292 +; + +-- Feb 17, 2019, 11:22:47 AM CET +UPDATE AD_TreeNodeMM SET Parent_ID=183, SeqNo=23, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=504 +; + +-- Feb 17, 2019, 11:22:47 AM CET +UPDATE AD_TreeNodeMM SET Parent_ID=183, SeqNo=24, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=515 +; + +SELECT register_migration_script('201902121250_IDEMPIERE-3896.sql') FROM dual +; diff --git a/migration/i6.2/postgresql/201902141541_IDEMPIERE-1887.sql b/migration/i6.2/postgresql/201902141541_IDEMPIERE-1887.sql new file mode 100644 index 0000000000..8c3d6c846b --- /dev/null +++ b/migration/i6.2/postgresql/201902141541_IDEMPIERE-1887.sql @@ -0,0 +1,8 @@ +-- IDEMPIERE-1887 can make inconsistent data from physical inventory window +-- Feb 14, 2019, 3:40:50 PM CET +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','Warehouse cannot be changed because there are lines.',0,0,'Y',TO_TIMESTAMP('2019-02-14 15:40:49','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-02-14 15:40:49','YYYY-MM-DD HH24:MI:SS'),100,200487,'CannotChangeWarehouse','D','2a9c7a1b-35b2-464c-a2ba-0aa60be3d81d') +; + +SELECT register_migration_script('201902141541_IDEMPIERE-1887.sql') FROM dual +; + diff --git a/migration/i6.2/postgresql/201902141651_IDEMPIERE-1615.sql b/migration/i6.2/postgresql/201902141651_IDEMPIERE-1615.sql new file mode 100644 index 0000000000..ef2a62b7ac --- /dev/null +++ b/migration/i6.2/postgresql/201902141651_IDEMPIERE-1615.sql @@ -0,0 +1,8 @@ +-- IDEMPIERE-1615 Multiple key columns lead to data corruption or data loss +-- Feb 14, 2019, 4:51:33 PM CET +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','The table has already a key column, there can be just one key.',0,0,'Y',TO_TIMESTAMP('2019-02-14 16:51:32','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-02-14 16:51:32','YYYY-MM-DD HH24:MI:SS'),100,200488,'KeyColumnAlreadyDefined','D','c5011666-1371-4620-a5bc-aa29265f5d90') +; + +SELECT register_migration_script('201902141651_IDEMPIERE-1615.sql') FROM dual +; + diff --git a/org.adempiere.base.callout/src/org/adempiere/base/callout/CostAdjustmentCalloutFactory.java b/org.adempiere.base.callout/src/org/adempiere/base/callout/CostAdjustmentCalloutFactory.java index 322ddcc852..37f4daf7e2 100644 --- a/org.adempiere.base.callout/src/org/adempiere/base/callout/CostAdjustmentCalloutFactory.java +++ b/org.adempiere.base.callout/src/org/adempiere/base/callout/CostAdjustmentCalloutFactory.java @@ -20,6 +20,7 @@ import org.adempiere.base.IColumnCallout; import org.adempiere.base.IColumnCalloutFactory; import org.compiere.model.GridField; import org.compiere.model.GridTab; +import org.compiere.model.GridTable; import org.compiere.model.I_M_InventoryLine; import org.compiere.model.MAcctSchema; import org.compiere.model.MClient; @@ -66,7 +67,15 @@ public class CostAdjustmentCalloutFactory implements IColumnCalloutFactory { @Override public String start(Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value, Object oldValue) { - MInventory inventory = MInventory.get(ctx, (Integer) mTab.getValue("M_Inventory_ID")); + String trxName = null; + if ( mTab != null + && mTab.getTableModel() != null) { + GridTable gt = mTab.getTableModel(); + if (gt.isImporting()) { + trxName = gt.get_TrxName(); + } + } + MInventory inventory = new MInventory(ctx, (Integer) mTab.getValue("M_Inventory_ID"), trxName); if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(inventory.getC_DocType().getDocSubTypeInv())) { String costingMethod = inventory.getCostingMethod(); if (value == null) { @@ -121,7 +130,15 @@ public class CostAdjustmentCalloutFactory implements IColumnCalloutFactory { @Override public String start(Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value, Object oldValue) { - MInventory inventory = MInventory.get(ctx, (Integer) mTab.getValue("M_Inventory_ID")); + String trxName = null; + if ( mTab != null + && mTab.getTableModel() != null) { + GridTable gt = mTab.getTableModel(); + if (gt.isImporting()) { + trxName = gt.get_TrxName(); + } + } + MInventory inventory = new MInventory(ctx, (Integer) mTab.getValue("M_Inventory_ID"), trxName); if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(inventory.getC_DocType().getDocSubTypeInv())) { String costingMethod = inventory.getCostingMethod(); Object productValue = mTab.getValue(I_M_InventoryLine.COLUMNNAME_M_Product_ID); diff --git a/org.adempiere.base/src/org/adempiere/process/RecreateStorageReservation.java b/org.adempiere.base/src/org/adempiere/process/RecreateStorageReservation.java new file mode 100644 index 0000000000..883451a6b2 --- /dev/null +++ b/org.adempiere.base/src/org/adempiere/process/RecreateStorageReservation.java @@ -0,0 +1,135 @@ +/****************************************************************************** + * Project: Trek Global ERP * + * Copyright (C) 2009-2018 Trek Global Corporation * + * 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.adempiere.process; + +import org.compiere.process.SvrProcess; +import org.compiere.util.DB; +import org.compiere.util.Env; + +public class RecreateStorageReservation extends SvrProcess { + + private int m_AD_Client_ID = 0; + + @Override + protected void prepare() { + m_AD_Client_ID = Env.getAD_Client_ID(getCtx()); + } + + @Override + protected String doIt() throws Exception { + + final String sql = "" + + "SELECT COUNT(*) " + + "FROM " + + "( " + + "SELECT SUM(ol.QtyReserved) AS OrderQtyReserved, " + + " ol.M_Warehouse_ID, " + + " ol.M_Product_ID, " + + " COALESCE(M_AttributeSetInstance_ID, 0) AS M_AttributeSetInstance_ID, " + + " o.IsSOTrx, " + + " w.AD_Client_ID, " + + " w.AD_Org_ID " + + "FROM C_OrderLine ol " + + " JOIN C_Order o ON ( ol.C_Order_ID = o.C_Order_ID ) " + + " JOIN M_Warehouse w ON ( w.M_Warehouse_ID = o.M_Warehouse_ID ) " + + "WHERE ol.m_product_ID > 0 " + + " AND ol.ad_client_ID = ? " + + " AND ol.qtyreserved != 0 " + + " AND o.docstatus NOT IN ( 'VO', 'RE' ) " + + "GROUP BY ol.M_Warehouse_ID, " + + " ol.M_Product_ID, " + + " COALESCE(M_AttributeSetInstance_ID, 0), " + + " o.IsSOTrx, " + + " w.AD_Client_ID, " + + " w.AD_Org_ID " + + ") y " + + "FULL OUTER JOIN " + + "( " + + "SELECT Qty AS StorageQtyreserved, " + + " M_Warehouse_ID, " + + " M_Product_ID, " + + " M_AttributeSetInstance_ID, " + + " IsSOTrx, " + + " AD_Client_ID " + + "FROM M_StorageReservation " + + "WHERE AD_Client_ID = ? " + + " AND Qty != 0 " + + ") x " + + " ON y.M_Warehouse_ID = x.M_Warehouse_ID " + + " AND x.M_Product_ID = y.M_Product_ID " + + " AND x.M_AttributeSetInstance_ID = y.M_AttributeSetInstance_ID " + + " AND x.IsSOTrx = y.IsSOTrx " + + "WHERE COALESCE(x.StorageQtyReserved, 0) <> COALESCE(y.OrderQtyReserved, 0)"; + + int wrongReservations = DB.getSQLValueEx(get_TrxName(), sql, m_AD_Client_ID, m_AD_Client_ID); + + int noInserted = 0; + if (wrongReservations > 0) { + + log.warning(wrongReservations + " wrong reservation records found"); + + final String deleteSql = "DELETE FROM M_StorageReservation WHERE AD_Client_ID=?"; + int no = DB.executeUpdateEx(deleteSql, new Object[]{m_AD_Client_ID}, get_TrxName()); + log.warning(no + " reservation records deleted"); + + final String ins = "" + + "INSERT INTO M_StorageReservation " + + " (Qty, " + + " M_Warehouse_ID, " + + " M_Product_ID, " + + " M_AttributeSetInstance_ID, " + + " IsSOTrx, " + + " AD_Client_ID, " + + " AD_Org_ID, " + + " Created, " + + " CreatedBy, " + + " Updated, " + + " UpdatedBy, " + + " IsActive, " + + " M_StorageReservation_UU) " + + "SELECT SUM(ol.QtyReserved) AS OrderQtyReserved, " + + " ol.M_Warehouse_ID, " + + " ol.M_Product_ID, " + + " COALESCE(M_AttributeSetInstance_ID, 0), " + + " o.IsSOTrx, " + + " w.AD_Client_ID, " + + " w.AD_Org_ID, " + + " SysDate, " + + " ?, " + + " SysDate, " + + " ?, " + + " 'Y', " + + " generate_uuid() " + + "FROM C_OrderLine ol " + + " JOIN C_Order o ON ( ol.C_Order_ID = o.C_Order_ID ) " + + " JOIN M_Warehouse w ON ( w.M_Warehouse_ID = o.M_Warehouse_ID ) " + + "WHERE ol.M_Product_ID > 0 " + + " AND ol.QtyReserved != 0 " + + " AND o.DocStatus NOT IN ( 'VO', 'RE' ) " + + " AND o.AD_Client_ID = ? " + + "GROUP BY ol.M_Warehouse_ID, " + + " ol.M_Product_ID, " + + " COALESCE(M_AttributeSetInstance_ID, 0), " + + " o.IsSOTrx, " + + " w.AD_Client_ID, " + + " w.AD_Org_ID"; + + noInserted = DB.executeUpdateEx(ins, new Object[]{Env.getAD_User_ID(getCtx()), Env.getAD_User_ID(getCtx()), m_AD_Client_ID}, get_TrxName()); + log.warning(noInserted + " reservation records inserted"); + } + + return noInserted + " @Inserted@"; + } + +} diff --git a/org.adempiere.base/src/org/compiere/acct/Doc_AllocationHdr.java b/org.adempiere.base/src/org/compiere/acct/Doc_AllocationHdr.java index f159087158..dfc0a20f73 100644 --- a/org.adempiere.base/src/org/compiere/acct/Doc_AllocationHdr.java +++ b/org.adempiere.base/src/org/compiere/acct/Doc_AllocationHdr.java @@ -1047,12 +1047,14 @@ class Doc_AllocationTax for (int i = 0; i < m_facts.size(); i++) { MFactAcct factAcct = (MFactAcct)m_facts.get(i); - if (factAcct.getAmtSourceDr().compareTo(total) > 0) + if ( (factAcct.getAmtSourceDr().signum() > 0 && factAcct.getAmtSourceDr().compareTo(total) > 0) + || (factAcct.getAmtSourceDr().signum() < 0 && factAcct.getAmtSourceDr().compareTo(total) < 0)) { total = factAcct.getAmtSourceDr(); m_totalIndex = i; } - if (factAcct.getAmtSourceCr().compareTo(total) > 0) + if ( (factAcct.getAmtSourceCr().signum() > 0 && factAcct.getAmtSourceCr().compareTo(total) > 0) + || (factAcct.getAmtSourceCr().signum() < 0 && factAcct.getAmtSourceCr().compareTo(total) < 0)) { total = factAcct.getAmtSourceCr(); m_totalIndex = i; diff --git a/org.adempiere.base/src/org/compiere/model/GridTable.java b/org.adempiere.base/src/org/compiere/model/GridTable.java index cc11e1a1e8..46b1314b1f 100644 --- a/org.adempiere.base/src/org/compiere/model/GridTable.java +++ b/org.adempiere.base/src/org/compiere/model/GridTable.java @@ -3628,12 +3628,12 @@ public class GridTable extends AbstractTableModel } // run private void doRun() { - openResultSet(); - if (m_rs == null) - return; - try { + openResultSet(); + if (m_rs == null) + return; + while (m_rs.next()) { if (Thread.interrupted()) diff --git a/org.adempiere.base/src/org/compiere/model/Lookup.java b/org.adempiere.base/src/org/compiere/model/Lookup.java index cfe6264717..f2171c64e7 100644 --- a/org.adempiere.base/src/org/compiere/model/Lookup.java +++ b/org.adempiere.base/src/org/compiere/model/Lookup.java @@ -43,7 +43,7 @@ public abstract class Lookup extends AbstractListModel /** * */ - private static final long serialVersionUID = -28200392264647953L; + private static final long serialVersionUID = -2500275921218601088L; /** * Lookup @@ -468,8 +468,14 @@ public abstract class Lookup extends AbstractListModel * @param key key * @param saveInCache save in cache for r/w * @param cacheLocal cache locally for r/o + * @param trxName the transaction name * @return value */ + public NamePair getDirect (Object key, boolean saveInCache, boolean cacheLocal, String trxName) + { + return get (key); + } // getDirect + public NamePair getDirect (Object key, boolean saveInCache, boolean cacheLocal) { return get (key); diff --git a/org.adempiere.base/src/org/compiere/model/MColumn.java b/org.adempiere.base/src/org/compiere/model/MColumn.java index 7c12a848ec..b5f6574179 100644 --- a/org.adempiere.base/src/org/compiere/model/MColumn.java +++ b/org.adempiere.base/src/org/compiere/model/MColumn.java @@ -413,6 +413,17 @@ public class MColumn extends X_AD_Column } } + // IDEMPIERE-1615 Multiple key columns lead to data corruption or data loss + if ((is_ValueChanged(COLUMNNAME_IsKey) || is_ValueChanged(COLUMNNAME_IsActive)) && isKey() && isActive()) { + int cnt = DB.getSQLValueEx(get_TrxName(), + "SELECT COUNT(*) FROM AD_Column WHERE AD_Table_ID=? AND IsActive='Y' AND AD_Column_ID!=? AND IsKey='Y'", + getAD_Table_ID(), getAD_Column_ID()); + if (cnt > 0) { + log.saveError("Error", Msg.getMsg(getCtx(), "KeyColumnAlreadyDefined")); + return false; + } + } + return true; } // beforeSave diff --git a/org.adempiere.base/src/org/compiere/model/MInventory.java b/org.adempiere.base/src/org/compiere/model/MInventory.java index 586f8661ce..35cb14bbbb 100644 --- a/org.adempiere.base/src/org/compiere/model/MInventory.java +++ b/org.adempiere.base/src/org/compiere/model/MInventory.java @@ -255,6 +255,14 @@ public class MInventory extends X_M_Inventory implements DocAction log.saveError("FillMandatory", Msg.getElement(getCtx(), COLUMNNAME_C_DocType_ID)); return false; } + // IDEMPIERE-1887 can make inconsistent data from physical inventory window + if (!newRecord && is_ValueChanged(COLUMNNAME_M_Warehouse_ID)) { + int cnt = DB.getSQLValueEx(get_TrxName(), "SELECT COUNT(*) FROM M_InventoryLine WHERE M_Inventory_ID=?", getM_Inventory_ID()); + if (cnt > 0) { + log.saveError("Error", Msg.getMsg(getCtx(), "CannotChangeWarehouse")); + return false; + } + } return true; } // beforeSave diff --git a/org.adempiere.base/src/org/compiere/model/MLookup.java b/org.adempiere.base/src/org/compiere/model/MLookup.java index fbf48b26cc..e8ba95e710 100644 --- a/org.adempiere.base/src/org/compiere/model/MLookup.java +++ b/org.adempiere.base/src/org/compiere/model/MLookup.java @@ -56,7 +56,7 @@ public final class MLookup extends Lookup implements Serializable /** * */ - private static final long serialVersionUID = 2228200000988048623L; + private static final long serialVersionUID = 2288661955135689187L; /** * MLookup Constructor @@ -488,6 +488,11 @@ public final class MLookup extends Lookup implements Serializable private Object m_directNullKey = null; private Future m_loaderFuture; + public NamePair getDirect (Object key, boolean saveInCache, boolean cacheLocal) + { + return getDirect(key, saveInCache, cacheLocal, null); + } // getDirect + /** * Get Data Direct from Table. * @param key key @@ -495,7 +500,7 @@ public final class MLookup extends Lookup implements Serializable * @param cacheLocal cache locally for r/o * @return value */ - public NamePair getDirect (Object key, boolean saveInCache, boolean cacheLocal) + public NamePair getDirect (Object key, boolean saveInCache, boolean cacheLocal, String trxName) { // Nothing to query if (key == null || m_info.QueryDirect == null || m_info.QueryDirect.length() == 0) @@ -520,7 +525,7 @@ public final class MLookup extends Lookup implements Serializable try { // SELECT Key, Value, Name FROM ... - pstmt = DB.prepareStatement(m_info.QueryDirect, null); + pstmt = DB.prepareStatement(m_info.QueryDirect, trxName); if (isNumber) pstmt.setInt(1, Integer.parseInt(key.toString())); else diff --git a/org.adempiere.base/src/org/compiere/model/MMovement.java b/org.adempiere.base/src/org/compiere/model/MMovement.java index 1a9d7fe67a..06a75714e9 100644 --- a/org.adempiere.base/src/org/compiere/model/MMovement.java +++ b/org.adempiere.base/src/org/compiere/model/MMovement.java @@ -466,7 +466,7 @@ public class MMovement extends X_M_Movement implements DocAction ma.getMovementQty().negate(),ma.getDateMaterialPolicy(), get_TrxName())) { String lastError = CLogger.retrieveErrorString(""); - m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError; + m_processMsg = "Cannot correct Inventory OnHand (MA) [" + product.getValue() + "] - " + lastError; return DocAction.STATUS_Invalid; } @@ -485,7 +485,7 @@ public class MMovement extends X_M_Movement implements DocAction ma.getMovementQty(),ma.getDateMaterialPolicy(), get_TrxName())) { String lastError = CLogger.retrieveErrorString(""); - m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError; + m_processMsg = "Cannot correct Inventory OnHand (MA) [" + product.getValue() + "] - " + lastError; return DocAction.STATUS_Invalid; } @@ -497,7 +497,7 @@ public class MMovement extends X_M_Movement implements DocAction trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID()); if (!trxFrom.save()) { - m_processMsg = "Transaction From not inserted (MA)"; + m_processMsg = "Transaction From not inserted (MA) [" + product.getValue() + "] - "; return DocAction.STATUS_Invalid; } // @@ -508,7 +508,7 @@ public class MMovement extends X_M_Movement implements DocAction trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID()); if (!trxTo.save()) { - m_processMsg = "Transaction To not inserted (MA)"; + m_processMsg = "Transaction To not inserted (MA) [" + product.getValue() + "] - "; return DocAction.STATUS_Invalid; } } @@ -553,7 +553,7 @@ public class MMovement extends X_M_Movement implements DocAction line.getMovementQty().negate(),effDateMPolicy, get_TrxName())) { String lastError = CLogger.retrieveErrorString(""); - m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError; + m_processMsg = "Cannot correct Inventory OnHand (MA) [" + product.getValue() + "] - " + lastError; return DocAction.STATUS_Invalid; } @@ -569,7 +569,7 @@ public class MMovement extends X_M_Movement implements DocAction line.getMovementQty(),effDateMPolicy, get_TrxName())) { String lastError = CLogger.retrieveErrorString(""); - m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError; + m_processMsg = "Cannot correct Inventory OnHand (MA) [" + product.getValue() + "] - " + lastError; return DocAction.STATUS_Invalid; } @@ -581,7 +581,7 @@ public class MMovement extends X_M_Movement implements DocAction trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID()); if (!trxFrom.save()) { - m_processMsg = "Transaction From not inserted"; + m_processMsg = "Transaction From not inserted (MA) [" + product.getValue() + "] - "; return DocAction.STATUS_Invalid; } // @@ -592,7 +592,7 @@ public class MMovement extends X_M_Movement implements DocAction trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID()); if (!trxTo.save()) { - m_processMsg = "Transaction To not inserted"; + m_processMsg = "Transaction To not inserted [" + product.getValue() + "] - "; return DocAction.STATUS_Invalid; } } // Fallback @@ -878,7 +878,7 @@ public class MMovement extends X_M_Movement implements DocAction rLine.setProcessed(false); if (!rLine.save()) { - m_processMsg = "Could not create Movement Reversal Line"; + m_processMsg = "Could not create Movement Reversal Line for @Line@ " + rLine.getLine() + ", @M_Product_ID@=" + rLine.getProduct().getValue(); return null; } diff --git a/org.adempiere.base/src/org/compiere/util/Language.java b/org.adempiere.base/src/org/compiere/util/Language.java index 980fb7134e..5590bb9c12 100644 --- a/org.adempiere.base/src/org/compiere/util/Language.java +++ b/org.adempiere.base/src/org/compiere/util/Language.java @@ -42,7 +42,7 @@ public class Language implements Serializable /** * */ - private static final long serialVersionUID = 8855937839841807335L; + private static final long serialVersionUID = 7039775951366180267L; /** * @@ -368,6 +368,7 @@ public class Language implements Serializable private Boolean m_decimalPoint; private Boolean m_leftToRight; private SimpleDateFormat m_dateFormat; + private String m_dbDateFormat; private MediaSize m_mediaSize = MediaSize.ISO.A4; private boolean m_fromDB = false; @@ -566,12 +567,18 @@ public class Language implements Serializable /** * Get Database Date Pattern. - * Derive from date pattern (make upper case) + * Derive from date pattern (make upper case and replace month as word with MM) * @return date pattern */ public String getDBdatePattern() { - return getDateFormat().toPattern().toUpperCase(m_locale); + if (m_dbDateFormat == null) + { + m_dbDateFormat = getDateFormat().toPattern().toUpperCase(m_locale); + // IDEMPIERE-3888 - temporary hack - a better solution would be to implement AD_Language.DBDatePattern + m_dbDateFormat = m_dbDateFormat.replaceFirst("MMM*", "MM"); + } + return m_dbDateFormat; } // getDBdatePattern /** diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java index 825fd2c89b..b4221e07e4 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java @@ -119,7 +119,6 @@ import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Column; import org.zkoss.zul.Columns; import org.zkoss.zul.Div; -import org.zkoss.zul.Grid; import org.zkoss.zul.Menuitem; import org.zkoss.zul.Menupopup; import org.zkoss.zul.Window.Mode; @@ -1811,22 +1810,22 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements public void onRefresh() { GridTab gridTab = adTabbox.getSelectedGridTab(); - if (gridTab != null && gridTab.getTableModel() != null) + /*if (gridTab != null && gridTab.getTableModel() != null) { gridTab.getTableModel().resetCacheSortState(); } - Column sortColumn = findCurrentSortColumn(); + Column sortColumn = findCurrentSortColumn();*/ onRefresh(true, false); - if (sortColumn != null) + /*if (sortColumn != null) { sortColumn.setSortDirection("natural"); - } + }*/ if (gridTab.isSortTab()) { // refresh is not refreshing sort tabs IADTabpanel tabPanel = adTabbox.getSelectedTabpanel(); tabPanel.query(false, 0, 0); } } - +/* private Column findCurrentSortColumn() { IADTabpanel iadtabpanel = getADTab().getSelectedTabpanel(); if (iadtabpanel instanceof ADTabpanel) { @@ -1849,7 +1848,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements } return null; } - +*/ /** * @see ToolbarListener#onHelp() */ diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java index 7f6accd3c3..0b4a5e0b27 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java @@ -39,6 +39,7 @@ import org.adempiere.webui.util.ZKUpdateUtil; import org.adempiere.webui.window.WFieldRecordInfo; import org.adempiere.webui.window.WLocationDialog; import org.compiere.model.GridField; +import org.compiere.model.GridTable; import org.compiere.model.Lookup; import org.compiere.model.MBPartnerLocation; import org.compiere.model.MLocation; @@ -413,7 +414,16 @@ ContextMenuListener, IZoomableEditor { if (lookup != null) { - NamePair pair = lookup.getDirect(oldValue, false, false); + String trxName = null; + if ( gridField != null + && gridField.getGridTab() != null + && gridField.getGridTab().getTableModel() != null) { + GridTable gt = gridField.getGridTab().getTableModel(); + if (gt.isImporting()) { + trxName = gt.get_TrxName(); + } + } + NamePair pair = lookup.getDirect(oldValue, false, false, trxName); if (pair != null) { if (pair instanceof KeyNamePair) { int key = ((KeyNamePair)pair).getKey(); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkJRViewer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkJRViewer.java index ac0f4e675f..4f5fbc55b8 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkJRViewer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkJRViewer.java @@ -334,10 +334,9 @@ public class ZkJRViewer extends Window implements EventListener, ITabOnCl prefix = makePrefix(jasperPrintList.get(0).getName())+"_List"; else prefix = makePrefix(jasperPrint.getName()); - if (log.isLoggable(Level.FINE)) - { - log.log(Level.FINE, "Path="+path + " Prefix="+prefix); - } + if (prefix.length() < 3) + prefix += "_".repeat(3-prefix.length()); + if (log.isLoggable(Level.FINE)) log.log(Level.FINE, "Path="+path + " Prefix="+prefix); File file = File.createTempFile(prefix, ".html", new File(path)); HtmlExporter exporter = new HtmlExporter(); @@ -360,10 +359,9 @@ public class ZkJRViewer extends Window implements EventListener, ITabOnCl prefix = makePrefix(jasperPrintList.get(0).getName())+"_List"; else prefix = makePrefix(jasperPrint.getName()); - if (log.isLoggable(Level.FINE)) - { - log.log(Level.FINE, "Path="+path + " Prefix="+prefix); - } + if (prefix.length() < 3) + prefix += "_".repeat(3-prefix.length()); + if (log.isLoggable(Level.FINE)) log.log(Level.FINE, "Path="+path + " Prefix="+prefix); File file = File.createTempFile(prefix, ".xls", new File(path)); FileOutputStream fos = new FileOutputStream(file); @@ -389,10 +387,9 @@ public class ZkJRViewer extends Window implements EventListener, ITabOnCl prefix = makePrefix(jasperPrintList.get(0).getName())+"_List"; else prefix = makePrefix(jasperPrint.getName()); - if (log.isLoggable(Level.FINE)) - { - log.log(Level.FINE, "Path="+path + " Prefix="+prefix); - } + if (prefix.length() < 3) + prefix += "_".repeat(3-prefix.length()); + if (log.isLoggable(Level.FINE)) log.log(Level.FINE, "Path="+path + " Prefix="+prefix); File file = File.createTempFile(prefix, ".csv", new File(path)); FileOutputStream fos = new FileOutputStream(file); JRCsvExporter exporter= new JRCsvExporter(); @@ -413,10 +410,9 @@ public class ZkJRViewer extends Window implements EventListener, ITabOnCl prefix = makePrefix(jasperPrintList.get(0).getName())+"_List"; else prefix = makePrefix(jasperPrint.getName()); - if (log.isLoggable(Level.FINE)) - { - log.log(Level.FINE, "Path="+path + " Prefix="+prefix); - } + if (prefix.length() < 3) + prefix += "_".repeat(3-prefix.length()); + if (log.isLoggable(Level.FINE)) log.log(Level.FINE, "Path="+path + " Prefix="+prefix); File file = File.createTempFile(prefix, ".ssv", new File(path)); FileOutputStream fos = new FileOutputStream(file); JRCsvExporter exporter= new JRCsvExporter(); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java index 73507e3367..4bfd60e9d6 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java @@ -1556,10 +1556,9 @@ public class ZkReportViewer extends Window implements EventListener, ITab log.warning("Cannot archive Document"); String path = System.getProperty("java.io.tmpdir"); String prefix = viewer.makePrefix(viewer.m_reportEngine.getName()); - if (log.isLoggable(Level.FINE)) - { - log.log(Level.FINE, "Path="+path + " Prefix="+prefix); - } + if (prefix.length() < 3) + prefix += "_".repeat(3-prefix.length()); + if (log.isLoggable(Level.FINE)) log.log(Level.FINE, "Path="+path + " Prefix="+prefix); File file = File.createTempFile(prefix, ".pdf", new File(path)); viewer.m_reportEngine.createPDF(file); viewer.media = new AMedia(file.getName(), "pdf", "application/pdf", file, true); @@ -1603,10 +1602,9 @@ public class ZkReportViewer extends Window implements EventListener, ITab log.warning("Cannot archive Document"); String path = System.getProperty("java.io.tmpdir"); String prefix = viewer.makePrefix(viewer.m_reportEngine.getName()); - if (log.isLoggable(Level.FINE)) - { - log.log(Level.FINE, "Path="+path + " Prefix="+prefix); - } + if (prefix.length() < 3) + prefix += "_".repeat(3-prefix.length()); + if (log.isLoggable(Level.FINE)) log.log(Level.FINE, "Path="+path + " Prefix="+prefix); File file = File.createTempFile(prefix, ".html", new File(path)); viewer.m_reportEngine.createHTML(file, false, viewer.m_reportEngine.getPrintFormat().getLanguage(), new HTMLExtension(contextPath, "rp", viewer.getUuid())); viewer.media = new AMedia(file.getName(), "html", "text/html", file, false); @@ -1649,10 +1647,9 @@ public class ZkReportViewer extends Window implements EventListener, ITab log.warning("Cannot archive Document"); String path = System.getProperty("java.io.tmpdir"); String prefix = viewer.makePrefix(viewer.m_reportEngine.getName()); - if (log.isLoggable(Level.FINE)) - { - log.log(Level.FINE, "Path="+path + " Prefix="+prefix); - } + if (prefix.length() < 3) + prefix += "_".repeat(3-prefix.length()); + if (log.isLoggable(Level.FINE)) log.log(Level.FINE, "Path="+path + " Prefix="+prefix); File file = File.createTempFile(prefix, ".xls", new File(path)); viewer.m_reportEngine.createXLS(file, viewer.m_reportEngine.getPrintFormat().getLanguage()); viewer.media = new AMedia(file.getName(), "xls", "application/vnd.ms-excel", file, true); diff --git a/org.idempiere.fitnesse.fixture/src/org/idempiere/fitnesse/fixture/Login.java b/org.idempiere.fitnesse.fixture/src/org/idempiere/fitnesse/fixture/Login.java index 86a7bcfb0a..079aa680cd 100644 --- a/org.idempiere.fitnesse.fixture/src/org/idempiere/fitnesse/fixture/Login.java +++ b/org.idempiere.fitnesse.fixture/src/org/idempiere/fitnesse/fixture/Login.java @@ -167,12 +167,16 @@ public class Login extends TableFixture { KeyNamePair[] clients = login.getClients(m_user, m_password); boolean okclient = false; KeyNamePair selectedClient = null; - for (KeyNamePair client : clients) { - if (client.getKey() == m_client_id) { - okclient = true; - selectedClient = client; - break; + if (clients != null) { + for (KeyNamePair client : clients) { + if (client.getKey() == m_client_id) { + okclient = true; + selectedClient = client; + break; + } } + } else { + return "Error logging in - user/password combination not valid"; } if (!okclient) return "Error logging in - client not allowed for this user";