From c049ebfeafe2f9a55f97c1591bcc9d5c455d44b5 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Sat, 6 Oct 2018 23:42:20 +0200 Subject: [PATCH 01/10] IDEMPIERE-2395 NoteDelete leaving orphan attachments --- .../oracle/201810062307_IDEMPIERE-2395.sql | 159 ++++++++++++++++++ .../201810062307_IDEMPIERE-2395.sql | 156 +++++++++++++++++ .../idempiere/process/CleanOrphanCascade.java | 140 +++++++++++++++ 3 files changed, 455 insertions(+) create mode 100644 migration/i5.1/oracle/201810062307_IDEMPIERE-2395.sql create mode 100644 migration/i5.1/postgresql/201810062307_IDEMPIERE-2395.sql create mode 100644 org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java diff --git a/migration/i5.1/oracle/201810062307_IDEMPIERE-2395.sql b/migration/i5.1/oracle/201810062307_IDEMPIERE-2395.sql new file mode 100644 index 0000000000..46e609b1e5 --- /dev/null +++ b/migration/i5.1/oracle/201810062307_IDEMPIERE-2395.sql @@ -0,0 +1,159 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- IDEMPIERE-2395 NoteDelete leaving orphan attachments +-- Oct 6, 2018 11:05:15 PM CEST +INSERT INTO AD_Process (AD_Process_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Help,IsReport,Value,IsDirectPrint,Classname,AccessLevel,EntityType,Statistic_Count,Statistic_Seconds,IsBetaFunctionality,IsServerProcess,ShowHelp,CopyFromProcess,AD_Process_UU) VALUES (200102,0,0,'Y',TO_DATE('2018-10-06 23:05:15','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2018-10-06 23:05:15','YYYY-MM-DD HH24:MI:SS'),100,'Clean Orphan Cascade Records','Some processes accessing directly the database can leave orphan records, this process clean those orphan records deleting them','N','CleanOrphanCascade','N','org.idempiere.process.CleanOrphanCascade','4','D',0,0,'N','N','Y','N','d3826a84-1467-4d6e-931b-e395f349f60c') +; + +-- Oct 6, 2018 11:05:55 PM CEST +INSERT INTO AD_Menu (AD_Menu_ID,Name,Action,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsSummary,AD_Process_ID,IsSOTrx,IsReadOnly,EntityType,IsCentrallyMaintained,AD_Menu_UU) VALUES (200161,'Clean Orphan Cascade Records','P',0,0,'Y',TO_DATE('2018-10-06 23:05:55','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2018-10-06 23:05:55','YYYY-MM-DD HH24:MI:SS'),100,'N',200102,'Y','N','D','Y','67e5ec6c-93d0-47f9-bd45-f0d60d552b16') +; + +-- Oct 6, 2018 11:05:55 PM CEST +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, 200161, 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=200161) +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=0, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=218 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=1, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=153 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=2, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=263 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=3, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=166 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=4, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=203 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=5, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53242 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=6, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=236 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=7, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=183 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=8, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=160 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=9, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=278 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=10, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=345 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=11, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53296 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=12, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53014 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=13, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53108 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=0, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=161 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=1, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=367 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=2, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=456 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=3, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=501 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=4, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=326 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=5, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=566 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=6, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=392 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=7, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=113 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=8, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=220 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=9, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=351 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=10, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=289 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=11, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=302 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=12, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=303 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=13, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=200047 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=14, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=200048 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=15, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=321 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=16, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=461 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=17, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53193 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=18, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53322 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=19, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=383 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=20, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=200161 +; + +SELECT register_migration_script('201810062307_IDEMPIERE-2395.sql') FROM dual +; + diff --git a/migration/i5.1/postgresql/201810062307_IDEMPIERE-2395.sql b/migration/i5.1/postgresql/201810062307_IDEMPIERE-2395.sql new file mode 100644 index 0000000000..2c40843c5f --- /dev/null +++ b/migration/i5.1/postgresql/201810062307_IDEMPIERE-2395.sql @@ -0,0 +1,156 @@ +-- IDEMPIERE-2395 NoteDelete leaving orphan attachments +-- Oct 6, 2018 11:05:15 PM CEST +INSERT INTO AD_Process (AD_Process_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Help,IsReport,Value,IsDirectPrint,Classname,AccessLevel,EntityType,Statistic_Count,Statistic_Seconds,IsBetaFunctionality,IsServerProcess,ShowHelp,CopyFromProcess,AD_Process_UU) VALUES (200102,0,0,'Y',TO_TIMESTAMP('2018-10-06 23:05:15','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2018-10-06 23:05:15','YYYY-MM-DD HH24:MI:SS'),100,'Clean Orphan Cascade Records','Some processes accessing directly the database can leave orphan records, this process clean those orphan records deleting them','N','CleanOrphanCascade','N','org.idempiere.process.CleanOrphanCascade','4','D',0,0,'N','N','Y','N','d3826a84-1467-4d6e-931b-e395f349f60c') +; + +-- Oct 6, 2018 11:05:55 PM CEST +INSERT INTO AD_Menu (AD_Menu_ID,Name,"action",AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsSummary,AD_Process_ID,IsSOTrx,IsReadOnly,EntityType,IsCentrallyMaintained,AD_Menu_UU) VALUES (200161,'Clean Orphan Cascade Records','P',0,0,'Y',TO_TIMESTAMP('2018-10-06 23:05:55','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2018-10-06 23:05:55','YYYY-MM-DD HH24:MI:SS'),100,'N',200102,'Y','N','D','Y','67e5ec6c-93d0-47f9-bd45-f0d60d552b16') +; + +-- Oct 6, 2018 11:05:55 PM CEST +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, 200161, 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=200161) +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=0, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=218 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=1, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=153 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=2, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=263 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=3, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=166 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=4, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=203 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=5, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53242 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=6, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=236 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=7, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=183 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=8, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=160 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=9, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=278 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=10, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=345 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=11, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53296 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=12, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53014 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=13, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53108 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=0, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=161 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=1, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=367 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=2, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=456 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=3, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=501 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=4, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=326 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=5, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=566 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=6, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=392 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=7, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=113 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=8, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=220 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=9, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=351 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=10, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=289 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=11, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=302 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=12, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=303 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=13, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=200047 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=14, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=200048 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=15, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=321 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=16, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=461 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=17, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53193 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=18, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53322 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=19, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=383 +; + +-- Oct 6, 2018 11:07:01 PM CEST +UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=20, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=200161 +; + +SELECT register_migration_script('201810062307_IDEMPIERE-2395.sql') FROM dual +; + diff --git a/org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java b/org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java new file mode 100644 index 0000000000..4c737823c6 --- /dev/null +++ b/org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java @@ -0,0 +1,140 @@ +/********************************************************************** +* This file is part of iDempiere ERP Open Source * +* http://www.idempiere.org * +* * +* Copyright (C) Contributors * +* * +* This program is free software; you can redistribute it and/or * +* modify it under the terms of the GNU General Public License * +* as published by the Free Software Foundation; either version 2 * +* of the License, or (at your option) any later version. * +* * +* 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., 51 Franklin Street, Fifth Floor, Boston, * +* MA 02110-1301, USA. * +* * +* Contributors: * +* - Carlos Ruiz * +**********************************************************************/ +package org.idempiere.process; + +import java.math.BigDecimal; +import java.util.List; +import java.util.logging.Level; + +import org.compiere.model.MArchive; +import org.compiere.model.MAttachment; +import org.compiere.model.MTable; +import org.compiere.model.Query; +import org.compiere.process.ProcessInfoParameter; +import org.compiere.process.SvrProcess; +import org.compiere.util.DB; +import org.compiere.util.Msg; + +/** + * IDEMPIERE-2395 + * @author Carlos Ruiz - globalqss + */ +public class CleanOrphanCascade extends SvrProcess +{ + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + for (ProcessInfoParameter para : getParameter()) + { + String name = para.getParameterName(); + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws Exception + { + if (log.isLoggable(Level.INFO)) log.info(""); + + String whereTables = "" + + " IsView = 'N' " + + "AND TableName != 'AD_ChangeLog' " + + "AND EXISTS (SELECT 1 " + + " FROM AD_Column ct " + + " WHERE ct.IsActive='Y' AND ct.AD_Table_ID = AD_Table.AD_Table_ID " + + " AND ct.ColumnName = 'AD_Table_ID') " + + "AND EXISTS (SELECT 1 " + + " FROM AD_Column cr " + + " WHERE cr.IsActive='Y' AND cr.AD_Table_ID = AD_Table.AD_Table_ID " + + " AND cr.ColumnName = 'Record_ID') " + + "AND EXISTS (SELECT 1 " + + " FROM AD_Column ck " + + " WHERE ck.IsActive='Y' AND ck.AD_Table_ID = AD_Table.AD_Table_ID " + + " AND ck.ColumnName = AD_Table.TableName || '_ID')"; + + List tables = new Query(getCtx(), "AD_Table", whereTables, get_TrxName()) + .setOnlyActiveRecords(true) + .setOrderBy("TableName") + .list(); + for (MTable table : tables) { + String tableName = table.getTableName(); + + StringBuilder sqlRef = new StringBuilder(); + sqlRef.append("SELECT DISTINCT t.AD_Table_ID, "); + sqlRef.append(" t.TableName "); + sqlRef.append("FROM ").append(tableName).append(" r "); + sqlRef.append(" JOIN AD_Table t ON ( r.AD_Table_ID = t.AD_Table_ID ) "); + sqlRef.append("ORDER BY t.Tablename"); + List> rowTables = DB.getSQLArrayObjectsEx(get_TrxName(), sqlRef.toString()); + if (rowTables != null) { + for (List row : rowTables) { + int refTableID = ((BigDecimal) row.get(0)).intValue(); + String refTableName = row.get(1).toString(); + + StringBuilder whereClause = new StringBuilder(); + whereClause.append("AD_Table_ID = ").append(refTableID); + whereClause.append(" AND NOT EXISTS (SELECT ").append(refTableName).append("_ID "); + whereClause.append(" FROM ").append(refTableName).append(" "); + whereClause.append(" WHERE ").append(refTableName).append(".").append(refTableName).append("_ID = ").append(tableName).append(".Record_ID)"); + + int noDel = 0; + if (MAttachment.Table_Name.equals(tableName)) { + // special case for attachment because of store + List attachments = new Query(getCtx(), tableName, whereClause.toString(), get_TrxName()).list(); + for (MAttachment attachment : attachments) { + attachment.deleteEx(true, get_TrxName()); + noDel++; + } + } else if (MArchive.Table_Name.equals(tableName)) { + // special case for archive because of store + List archives = new Query(getCtx(), tableName, whereClause.toString(), get_TrxName()).list(); + for (MArchive archive : archives) { + archive.deleteEx(true, get_TrxName()); + noDel++; + } + } else { + StringBuilder sqlDelete = new StringBuilder(); + sqlDelete.append("DELETE FROM ").append(tableName).append(" WHERE ").append(whereClause); + noDel = DB.executeUpdateEx(sqlDelete.toString(), get_TrxName()); + } + if (noDel > 0) { + addLog(Msg.parseTranslation(getCtx(), noDel + " " + tableName + " " + "@Deleted@ -> " + refTableName)); + } + } + + } + } + + return "@OK@"; + } // doIt + +} // CleanOrphanCascade From 0640e29b1355878e82265c12115ef14fe18865cd Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Fri, 12 Oct 2018 10:45:32 +0200 Subject: [PATCH 02/10] IDEMPIERE-3802 Bug in ResetLockedAccount when using USER_LOCKING_MAX_INACTIVE_PERIOD_DAY --- .../src/org/adempiere/process/ResetLockedAccount.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/org.adempiere.base/src/org/adempiere/process/ResetLockedAccount.java b/org.adempiere.base/src/org/adempiere/process/ResetLockedAccount.java index a50fd3aa0f..2880e88e75 100644 --- a/org.adempiere.base/src/org/adempiere/process/ResetLockedAccount.java +++ b/org.adempiere.base/src/org/adempiere/process/ResetLockedAccount.java @@ -69,16 +69,16 @@ public class ResetLockedAccount extends SvrProcess { if (DB.isPostgreSQL()) { if (MAX_ACCOUNT_LOCK_MINUTES > 0) - sql.append( " AND EXTRACT(MINUTE FROM (now()-DateAccountLocked)) * 24 * 60 > ").append(MAX_ACCOUNT_LOCK_MINUTES); + sql.append(" AND EXTRACT(EPOCH FROM (now()-DateAccountLocked)) / 60 > ").append(MAX_ACCOUNT_LOCK_MINUTES); if (MAX_INACTIVE_PERIOD > 0) - sql.append(" AND EXTRACT(DAY FROM (now()-DateLastLogin)) * 24 <= ").append(MAX_INACTIVE_PERIOD); + sql.append(" AND EXTRACT(EPOCH FROM (now()-DateLastLogin)) / 86400 <= ").append(MAX_INACTIVE_PERIOD); } else { if (MAX_ACCOUNT_LOCK_MINUTES > 0) - sql.append(" AND (SysDate-DateAccountLocked) * 24 * 60 > ").append(MAX_ACCOUNT_LOCK_MINUTES); + sql.append(" AND (SysDate-DateAccountLocked) * 1440 > ").append(MAX_ACCOUNT_LOCK_MINUTES); if (MAX_INACTIVE_PERIOD > 0) - sql.append(" AND (SysDate-DateLastLogin) * 24 <= ").append(MAX_INACTIVE_PERIOD); + sql.append(" AND (SysDate-DateLastLogin) <= ").append(MAX_INACTIVE_PERIOD); } int no = DB.executeUpdate(sql.toString(), p_AD_Client_ID, get_TrxName()); From 428e00ae8634264d4a95ec7a53b6e185f77428a4 Mon Sep 17 00:00:00 2001 From: Nicolas Micoud Date: Fri, 12 Oct 2018 11:07:23 +0200 Subject: [PATCH 03/10] IDEMPIERE-3801 System user can't use saved queries --- .../WEB-INF/src/org/adempiere/webui/window/FindWindow.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java index 7940d7f659..8b5c59912c 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java @@ -134,7 +134,7 @@ public class FindWindow extends Window implements EventListener, ValueCha /** * */ - private static final long serialVersionUID = -4461202150492732658L; + private static final long serialVersionUID = -2476692172080549315L; // values and label for history combo private static final String HISTORY_DAY_ALL = "All"; @@ -1740,7 +1740,7 @@ public class FindWindow extends Window implements EventListener, ValueCha uq = new MUserQuery (Env.getCtx(), 0, null); uq.setName (name); uq.setAD_Tab_ID(m_AD_Tab_ID); //red1 UserQuery [ 1798539 ] taking in new field from Compiere - uq.setAD_User_ID(Env.getAD_User_ID(Env.getCtx())); //red1 - [ 1798539 ] missing in Compiere delayed source :-) + uq.set_ValueOfColumn("AD_User_ID", Env.getAD_User_ID(Env.getCtx())); // required set_Value for System=0 user } } else if (code.length() <= 0){ // Delete the query From f70f76d73264c5307335e3379be7da259a207339 Mon Sep 17 00:00:00 2001 From: Diego Ruiz Date: Fri, 12 Oct 2018 11:19:50 +0200 Subject: [PATCH 04/10] IDEMPIERE-3800 Improvements to CSV Export - fix and integrate improvements from Heng Sin --- .../adempiere/impexp/GridTabCSVExporter.java | 52 ++++++++++--------- .../adempiere/impexp/GridTabCSVImporter.java | 43 ++++++++++----- 2 files changed, 56 insertions(+), 39 deletions(-) diff --git a/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVExporter.java b/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVExporter.java index b074057fd1..b8f2416605 100644 --- a/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVExporter.java +++ b/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVExporter.java @@ -147,8 +147,8 @@ public class GridTabCSVExporter implements IGridTabExporter if(detail.getDisplayLogic()!=null){ //if(!currentRowOnly) - //numOfTabs--; - //TODO: it's need? DisplayLogic is evaluated when call detail.isDisplayed() + //numOfTabs--; + //TODO: it's need? DisplayLogic is evaluated when call detail.isDisplayed() if(currentRowOnly && !Evaluator.evaluateLogic(detail,detail.getDisplayLogic())) continue; } @@ -223,7 +223,7 @@ public class GridTabCSVExporter implements IGridTabExporter int index =0; int rowDetail=0; int record_Id = 0; - boolean isActiveRow = true; +// boolean isActiveRow = true; gridTab.setCurrentRow(idxrow); for(GridField field : getFields(gridTab)){ MColumn column = MColumn.get(Env.getCtx(), field.getAD_Column_ID()); @@ -241,16 +241,16 @@ public class GridTabCSVExporter implements IGridTabExporter value = resolveValue(gridTab, table, column, idxrow, headName); } //Ignore row - if("IsActive".equals(headName) && value!=null && Boolean.valueOf((Boolean)value)==false){ - isActiveRow=false; - break; - } +// if("IsActive".equals(headName) && value!=null && Boolean.valueOf((Boolean)value)==false){ +// isActiveRow=false; +// break; +// } row.put(headName,value); idxfld++; index++; } - if(!isActiveRow) - continue; +// if(!isActiveRow) +// continue; if(specialHDispayType > 0 && record_Id > 0){ switch(specialHDispayType) { @@ -336,8 +336,8 @@ public class GridTabCSVExporter implements IGridTabExporter if (tab.isReadOnly()) result = Msg.getMsg(Env.getCtx(),"FieldIsReadOnly", new Object[] {gridTab.getName()}); - if (gridTab.getTableName().endsWith("_Acct")) - result = "Accounting Tab are not exported by default: "+ gridTab.getName(); +// if (gridTab.getTableName().endsWith("_Acct")) +// result = "Accounting Tab are not exported by default: "+ gridTab.getName(); return result; } @@ -354,10 +354,10 @@ public class GridTabCSVExporter implements IGridTabExporter for(Map.Entry childTabDetail : tabMapDetails.entrySet()) { GridTab childTab = childTabDetail.getKey(); - //String whereCla = getWhereClause (childTab, parentGrid, currentParentIndex); + //String whereCla = getWhereClause (childTab ,record_Id ,keyColumnParent); //childTab.getTableModel().dataRequery(whereCla, false, 0); Map row = new HashMap(); - boolean isActiveRow = true; +// boolean isActiveRow = true; if (childTab.getRowCount() > 0) { int specialRecordId = 0; for(GridField field : childTabDetail.getValue()){ @@ -374,19 +374,19 @@ public class GridTabCSVExporter implements IGridTabExporter String headName = headArray.get(headArray.indexOf(childTab.getTableName()+">"+resolveColumnName(tableDetail,column))); value = resolveValue(childTab, MTable.get(Env.getCtx(),childTab.getTableName()), column, currentDetRow, headName.substring(headName.indexOf(">")+ 1,headName.length())); - if(DisplayType.Payment == field.getDisplayType()) + if(DisplayType.Payment == field.getDisplayType() && value != null) value = MRefList.getListName(Env.getCtx(),REFERENCE_PAYMENTRULE, value.toString()); row.put(headName,value); if(value!=null) hasDetails = true; //Ignore row - if(headName.contains("IsActive")&& value!=null && Boolean.valueOf((Boolean)value)==false){ - isActiveRow=false; - break; - } +// if(headName.contains("IsActive")&& value!=null && Boolean.valueOf((Boolean)value)==false){ +// isActiveRow=false; +// break; +// } } - if(isActiveRow && specialDetDispayType > 0 && specialRecordId > 0){ + if(/* isActiveRow && */ specialDetDispayType > 0 && specialRecordId > 0){ MLocation address = new MLocation (Env.getCtx(),specialRecordId,null); for(String specialHeader:resolveSpecialColumnName(specialDetDispayType)){ String columnName = specialHeader.substring(specialHeader.indexOf(">")+1,specialHeader.length()); @@ -411,7 +411,7 @@ public class GridTabCSVExporter implements IGridTabExporter } } } - if(isActiveRow) +// if(isActiveRow) activeRow.putAll(row); } if (hasDetails) @@ -495,6 +495,8 @@ public class GridTabCSVExporter implements IGridTabExporter name.append("[DocumentNo]"); } } + } else if (DisplayType.Account == column.getAD_Reference_ID()) { + name.append("[Combination]"); } return name.toString(); } @@ -588,11 +590,11 @@ public class GridTabCSVExporter implements IGridTabExporter if (DisplayType.Button == MColumn.get(Env.getCtx(),field.getAD_Column_ID()).getAD_Reference_ID()) continue; if ( field.isVirtualColumn() - || field.isEncrypted() - || field.isEncryptedColumn() - || !(field.isDisplayed() || field.isDisplayedGrid())) - continue; - if (field.isParentValue() || (!field.isReadOnly() && field.isDisplayedGrid())) + || field.isEncrypted() + || field.isEncryptedColumn() + || !(field.isDisplayed() || field.isDisplayedGrid())) + continue; + if (field.isParentValue() || (!field.isReadOnly() && field.isDisplayedGrid()) || field.isParentColumn()) gridFieldList.add(field); } diff --git a/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java b/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java index 81193e7a82..e5be3fea25 100644 --- a/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java +++ b/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; +import java.math.BigDecimal; import java.nio.charset.Charset; import java.sql.SQLException; import java.sql.Timestamp; @@ -905,16 +906,20 @@ public class GridTabCSVImporter implements IGridTabImporter String columnName = header.get(i); Object value = tmpRow.get(i); //Validate Address - if(header.get(i).contains(MTable.getTableName(Env.getCtx(),MLocation.Table_ID)) && !isAddressValidated){ - StringBuilder specialColumns = new StringBuilder(); - specialColumns = validateSpecialFields(gridTab,header,tmpRow,i,"C_Location_ID"); - isAddressValidated = true; - if(specialColumns==null) - continue; - else - return specialColumns; - }else if (header.get(i).contains(MTable.getTableName(Env.getCtx(),MLocation.Table_ID)) && isAddressValidated){ - continue; + if (!"C_Location".equals(gridTab.getTableName())) + { + //Validate Address + if(header.get(i).contains(MTable.getTableName(Env.getCtx(),MLocation.Table_ID)) && !isAddressValidated){ + StringBuilder specialColumns = new StringBuilder(); + specialColumns = validateSpecialFields(gridTab,header,tmpRow,i,"C_Location_ID"); + isAddressValidated = true; + if(specialColumns==null) + continue; + else + return specialColumns; + }else if (header.get(i).contains(MTable.getTableName(Env.getCtx(),MLocation.Table_ID)) && isAddressValidated){ + continue; + } } if(value!=null) @@ -1067,7 +1072,7 @@ public class GridTabCSVImporter implements IGridTabImporter if(isForeing) foreignColumn = header.get(i).substring(header.get(i).indexOf("[")+1,header.get(i).indexOf("]")); - if(header.get(i).contains(MTable.getTableName(Env.getCtx(),MLocation.Table_ID))){ + if(!"C_Location".equals(gridTab.getTableName()) && header.get(i).contains(MTable.getTableName(Env.getCtx(),MLocation.Table_ID))){ if(address == null){ if(isInsertMode()){ @@ -1173,7 +1178,7 @@ public class GridTabCSVImporter implements IGridTabImporter } else { int id = resolveForeign(foreignTable, foreignColumn, value,field,trx); - if (id < 0) + if(id < 0) return Msg.getMsg(Env.getCtx(),id==-2?"ForeignMultipleResolved":"ForeignNotResolved",new Object[]{header.get(i),value}); setValue = id; @@ -1219,7 +1224,17 @@ public class GridTabCSVImporter implements IGridTabImporter }else{ return Msg.getMsg(Env.getCtx(),"Invalid") + " Column ["+column.getColumnName()+"]"; } - } + } else if (DisplayType.isNumeric(field.getDisplayType()) || DisplayType.isID(field.getDisplayType())) { + if (columnName.endsWith("_ID")) { + if (!(value instanceof Integer)) { + Integer idValue = Integer.valueOf(value.toString()); + value = idValue; + } + } else if (!(value instanceof BigDecimal)) { + BigDecimal decValue = new BigDecimal(value.toString()); + value = decValue; + } + } setValue = value; isThereRow =true; } @@ -1349,7 +1364,7 @@ public class GridTabCSVImporter implements IGridTabImporter //Process columnKeys + Foreign to add restrictions. for (int i = startindx ; i < endindx + 1 ; i++){ boolean isKeyColumn = header.get(i).indexOf("/") > 0 && ( header.get(i).endsWith("K") || header.get(i).endsWith("KT")); - if(isKeyColumn && !header.get(i).contains(MTable.getTableName(Env.getCtx(),MLocation.Table_ID))){ + if(isKeyColumn && ("C_Location".equals(gridTab.getTableName()) || !header.get(i).contains(MTable.getTableName(Env.getCtx(),MLocation.Table_ID)))){ boolean isForeing = header.get(i).indexOf("[") > 0 && header.get(i).indexOf("]")>0; boolean isDetail = header.get(i).indexOf(">") > 0; columnwithKey = getColumnName(isKeyColumn,isForeing,isDetail,header.get(i)); From 069bc5e5ba6e4d1c78af9ccad1f43b641bfc34d8 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Sat, 13 Oct 2018 10:33:53 +0200 Subject: [PATCH 05/10] IDEMPIERE-2771 Improve 2pack tracing for errors / AP2-694 Packin sometimes notifies Success when is a Failure --- .../src/org/adempiere/pipo/srv/PipoDictionaryService.java | 3 ++- org.adempiere.pipo/src/org/adempiere/pipo2/PackInProcess.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/org.adempiere.pipo/src/org/adempiere/pipo/srv/PipoDictionaryService.java b/org.adempiere.pipo/src/org/adempiere/pipo/srv/PipoDictionaryService.java index 18f79c12d3..c1f4885a50 100644 --- a/org.adempiere.pipo/src/org/adempiere/pipo/srv/PipoDictionaryService.java +++ b/org.adempiere.pipo/src/org/adempiere/pipo/srv/PipoDictionaryService.java @@ -111,7 +111,8 @@ public class PipoDictionaryService implements IDictionaryService { if (logger.isLoggable(Level.INFO)) logger.info("commit " + trxName); } catch (Exception e) { adPackageImp.setP_Msg(e.getLocalizedMessage()); - packIn.getNotifier().addStatusLine(e.getLocalizedMessage()); + packIn.getNotifier().addFailureLine(e.getLocalizedMessage()); + packIn.setSuccess(false); logger.log(Level.SEVERE, "importXML:", e); throw e; } finally { diff --git a/org.adempiere.pipo/src/org/adempiere/pipo2/PackInProcess.java b/org.adempiere.pipo/src/org/adempiere/pipo2/PackInProcess.java index 8bcfd56027..250aae0b39 100644 --- a/org.adempiere.pipo/src/org/adempiere/pipo2/PackInProcess.java +++ b/org.adempiere.pipo/src/org/adempiere/pipo2/PackInProcess.java @@ -147,7 +147,8 @@ public class PackInProcess extends SvrProcess { commitEx(); // we need to commit to capture HERE when the deferred validation of foreign keys can fail } catch (Exception e) { adPackageImp.setP_Msg(e.getLocalizedMessage()); - packIn.getNotifier().addStatusLine(e.getLocalizedMessage()); + packIn.getNotifier().addFailureLine(e.getLocalizedMessage()); + packIn.setSuccess(false); log.log(Level.SEVERE, "importXML:", e); throw e; } finally { From 38ac6686fecf2b092e70a87a80f1441eaedc2b83 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Sat, 13 Oct 2018 15:44:31 +0200 Subject: [PATCH 06/10] IDEMPIERE-2395 NoteDelete leaving orphan attachments --- .../src/org/idempiere/process/CleanOrphanCascade.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java b/org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java index 4c737823c6..bec999a7c3 100644 --- a/org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java +++ b/org.adempiere.base.process/src/org/idempiere/process/CleanOrphanCascade.java @@ -100,11 +100,18 @@ public class CleanOrphanCascade extends SvrProcess int refTableID = ((BigDecimal) row.get(0)).intValue(); String refTableName = row.get(1).toString(); + MTable refTable = MTable.get(getCtx(), refTableID); + if (refTable.getKeyColumns().length != 1) { + log.warning("Wrong reference for table " + tableName + " -> " + refTableName); + continue; + } + String colRef = refTable.getKeyColumns()[0]; + StringBuilder whereClause = new StringBuilder(); whereClause.append("AD_Table_ID = ").append(refTableID); - whereClause.append(" AND NOT EXISTS (SELECT ").append(refTableName).append("_ID "); + whereClause.append(" AND NOT EXISTS (SELECT ").append(colRef); whereClause.append(" FROM ").append(refTableName).append(" "); - whereClause.append(" WHERE ").append(refTableName).append(".").append(refTableName).append("_ID = ").append(tableName).append(".Record_ID)"); + whereClause.append(" WHERE ").append(refTableName).append(".").append(colRef).append(" = ").append(tableName).append(".Record_ID)"); int noDel = 0; if (MAttachment.Table_Name.equals(tableName)) { From 7b8157861fe233e7adac69495766da080a29b7c5 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Mon, 15 Oct 2018 11:19:03 +0200 Subject: [PATCH 07/10] IDEMPIERE-3599 allow DocActions to be selected in a more flexible way / Allow adding Reactivate on Closed --- org.adempiere.base/src/org/compiere/process/DocAction.java | 2 +- .../src/org/compiere/process/DocumentEngine.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/org.adempiere.base/src/org/compiere/process/DocAction.java b/org.adempiere.base/src/org/compiere/process/DocAction.java index 5b0a238be3..9f1ccd6c2f 100644 --- a/org.adempiere.base/src/org/compiere/process/DocAction.java +++ b/org.adempiere.base/src/org/compiere/process/DocAction.java @@ -61,7 +61,7 @@ public interface DocAction /** Invalidate = IN */ public static final String ACTION_Invalidate = "IN"; /** ReOpen = OP */ - public static final String ACTION_ReOpen = "OP"; + // public static final String ACTION_ReOpen = "OP"; /** Drafted = DR */ public static final String STATUS_Drafted = "DR"; diff --git a/org.adempiere.base/src/org/compiere/process/DocumentEngine.java b/org.adempiere.base/src/org/compiere/process/DocumentEngine.java index e86b21c651..4773229560 100644 --- a/org.adempiere.base/src/org/compiere/process/DocumentEngine.java +++ b/org.adempiere.base/src/org/compiere/process/DocumentEngine.java @@ -692,7 +692,7 @@ public class DocumentEngine implements DocAction ACTION_Post, ACTION_Void}; if (isClosed()) - return new String[] {ACTION_Post, ACTION_ReOpen}; + return new String[] {ACTION_Post, ACTION_ReActivate}; if (isReversed() || isVoided()) return new String[] {ACTION_Post}; @@ -965,11 +965,13 @@ public class DocumentEngine implements DocAction options[index++] = DocumentEngine.ACTION_Void; options[index++] = DocumentEngine.ACTION_Prepare; } + /* IDEMPIERE-3599 - commented to allow adding options to these terminal status // Closed, Voided, REversed .. CL/VO/RE else if (docStatus.equals(DocumentEngine.STATUS_Closed) || docStatus.equals(DocumentEngine.STATUS_Voided) || docStatus.equals(DocumentEngine.STATUS_Reversed)) return 0; + */ /******************** * Order From 6434e17bcad133d7ec76e48caa07c336b7daeaea Mon Sep 17 00:00:00 2001 From: Diego Ruiz Date: Wed, 17 Oct 2018 17:48:00 +0200 Subject: [PATCH 08/10] IDEMPIERE-3804 - Reports exported to Excel don't use Print Format Item -> Format Pattern --- .../impexp/AbstractExcelExporter.java | 27 ++++++++++++------- .../print/export/PrintDataExcelExporter.java | 22 +++++++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/org.adempiere.base/src/org/adempiere/impexp/AbstractExcelExporter.java b/org.adempiere.base/src/org/adempiere/impexp/AbstractExcelExporter.java index db5d908eb9..886ab170e1 100644 --- a/org.adempiere.base/src/org/adempiere/impexp/AbstractExcelExporter.java +++ b/org.adempiere.base/src/org/adempiere/impexp/AbstractExcelExporter.java @@ -228,7 +228,6 @@ public abstract class AbstractExcelExporter String key = "cell-"+col+"-"+displayType; HSSFCellStyle cs = m_styles.get(key); if (cs == null) { - boolean isHighlightNegativeNumbers = true; cs = m_workbook.createCellStyle(); HSSFFont font = getFont(false); cs.setFont(font); @@ -238,18 +237,28 @@ public abstract class AbstractExcelExporter cs.setBorderRight((short)1); cs.setBorderBottom((short)1); // - if (DisplayType.isDate(displayType)) { - cs.setDataFormat(m_dataFormat.getFormat(DisplayType.getDateFormat(getLanguage()).toPattern())); - } - else if (DisplayType.isNumeric(displayType)) { - DecimalFormat df = DisplayType.getNumberFormat(displayType, getLanguage()); - String format = getFormatString(df, isHighlightNegativeNumbers); - cs.setDataFormat(m_dataFormat.getFormat(format)); - } + String cellFormat = getCellFormat(row, col); + if (cellFormat != null) + cs.setDataFormat(m_dataFormat.getFormat(cellFormat)); m_styles.put(key, cs); } return cs; } + + protected String getCellFormat(int row, int col) { + boolean isHighlightNegativeNumbers = true; + int displayType = getDisplayType(row, col); + String cellFormat = null; + + if (DisplayType.isDate(displayType)) { + cellFormat = DisplayType.getDateFormat(getLanguage()).toPattern(); + } else if (DisplayType.isNumeric(displayType)) { + DecimalFormat df = DisplayType.getNumberFormat(displayType, getLanguage()); + cellFormat = getFormatString(df, isHighlightNegativeNumbers); + } + + return cellFormat; + } private HSSFCellStyle getHeaderStyle(int col) { diff --git a/org.adempiere.base/src/org/adempiere/print/export/PrintDataExcelExporter.java b/org.adempiere.base/src/org/adempiere/print/export/PrintDataExcelExporter.java index c77de78b27..0dc8e4affe 100644 --- a/org.adempiere.base/src/org/adempiere/print/export/PrintDataExcelExporter.java +++ b/org.adempiere.base/src/org/adempiere/print/export/PrintDataExcelExporter.java @@ -26,6 +26,8 @@ import org.compiere.print.MPrintFormatItem; import org.compiere.print.MPrintPaper; import org.compiere.print.PrintData; import org.compiere.print.PrintDataElement; +import org.compiere.util.DisplayType; +import org.compiere.util.Util; /** * Export PrintData to Excel (XLS) file @@ -192,4 +194,24 @@ extends AbstractExcelExporter sheet.setMargin(HSSFSheet.BottomMargin, ((double)paper.getMarginBottom()) / 72); // } + + @Override + protected String getCellFormat(int row, int col) { + String cellFormat = null; + PrintDataElement pde = getPDE(row, col); + + if (pde != null && !Util.isEmpty(pde.getM_formatPattern())) { + String formatPattern = pde.getM_formatPattern(); + int displayType = pde.getDisplayType(); + if (DisplayType.isDate(displayType)) { + cellFormat = DisplayType.getDateFormat(displayType, getLanguage(), formatPattern).toPattern(); + } else if (DisplayType.isNumeric(displayType)) { + cellFormat = DisplayType.getNumberFormat(displayType, getLanguage(), formatPattern).toPattern(); + } + } else { + return super.getCellFormat(row, col); + } + + return cellFormat; + } } From 86c3c5638f42dabbb089b8463fdb3141b8fc23d2 Mon Sep 17 00:00:00 2001 From: Diego Ruiz Date: Tue, 23 Oct 2018 13:56:36 +0200 Subject: [PATCH 09/10] IDEMPIERE-3807 --- .../idempiere/process/ImportCSVProcess.java | 1 + .../org/compiere/model/MImportTemplate.java | 69 +++++++++++++++++++ .../webui/panel/action/CSVImportAction.java | 63 +---------------- 3 files changed, 73 insertions(+), 60 deletions(-) diff --git a/org.adempiere.base.process/src/org/idempiere/process/ImportCSVProcess.java b/org.adempiere.base.process/src/org/idempiere/process/ImportCSVProcess.java index 45fca381c8..9ceac6bf8d 100644 --- a/org.adempiere.base.process/src/org/idempiere/process/ImportCSVProcess.java +++ b/org.adempiere.base.process/src/org/idempiere/process/ImportCSVProcess.java @@ -144,6 +144,7 @@ public class ImportCSVProcess extends SvrProcess implements DataStatusListener { protected void importFile(String filePath, IGridTabImporter csvImporter, GridTab activeTab, List childTabs) throws Exception { m_file_istream = new FileInputStream(filePath); + m_file_istream = m_importTemplate.validateFile(m_file_istream); File outFile = csvImporter.fileImport(activeTab, childTabs, m_file_istream, Charset.forName(m_importTemplate.getCharacterSet()), p_ImportMode, processUI); // TODO: Potential improvement - traverse the outFile and call addLog with the results diff --git a/org.adempiere.base/src/org/compiere/model/MImportTemplate.java b/org.adempiere.base/src/org/compiere/model/MImportTemplate.java index 1f3bf507ed..783e8eb007 100644 --- a/org.adempiere.base/src/org/compiere/model/MImportTemplate.java +++ b/org.adempiere.base/src/org/compiere/model/MImportTemplate.java @@ -13,11 +13,20 @@ *****************************************************************************/ package org.compiere.model; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.nio.charset.Charset; import java.sql.ResultSet; import java.util.List; import java.util.Properties; +import org.adempiere.exceptions.AdempiereException; import org.compiere.util.CCache; import org.compiere.util.CLogger; import org.compiere.util.DB; @@ -132,5 +141,65 @@ public class MImportTemplate extends X_AD_ImportTemplate int cnt = DB.getSQLValueEx(get_TrxName(), sql.toString(), getAD_ImportTemplate_ID(), roleID, roleID); return cnt > 0; } + + /** + * Validate that InputStream header is CSVHeader or AliasCSVHeader + * If the header is AliasCSVHeader it replaces it with the CSVHeader so it can be + * processed + * @param in input file + * @return InputStream with the CSVHeader that can be processed by CsvMapReader + */ + public InputStream validateFile(InputStream in) { + // because the input stream cannot be reset we need to copy here the file to a new one (replacing the header if it's the alias) + Charset charset = Charset.forName(getCharacterSet()); + BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset)); + File tmpfile = null; + InputStream is = null; + BufferedWriter bw = null; + try { + tmpfile = File.createTempFile("CSVImportAction", "csv"); + bw = new BufferedWriter(new FileWriter(tmpfile)); + String firstLine = null; + String line = null; + while ((line = reader.readLine()) != null) { + if (firstLine == null) { + firstLine = line; + /* Validate that m_file_istream header is CSVHeader or AliasCSVHeader */ + if ( firstLine.equals(getCSVHeader()) + || firstLine.equals(getCSVAliasHeader())) { + bw.write(getCSVHeader()); + } else { + reader.close(); + throw new AdempiereException(Msg.getMsg(Env.getCtx(), "WrongCSVHeader")); + } + } else { + bw.write(line); + } + bw.write('\n'); + } + is = new FileInputStream(tmpfile); + } catch (IOException e) { + throw new AdempiereException(e); + } finally { + if (in != null) + try { + in.close(); + } catch (IOException e) { + } + + if (bw != null) + try { + bw.close(); + } catch (IOException e) { + } + + if (reader != null) + try { + reader.close(); + } catch (IOException e) { + } + } + return is; + } } // MImportTemplate diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/action/CSVImportAction.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/action/CSVImportAction.java index c2f72d2113..a7e1678a08 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/action/CSVImportAction.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/action/CSVImportAction.java @@ -24,14 +24,8 @@ **********************************************************************/ package org.adempiere.webui.panel.action; -import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; -import java.io.FileInputStream; -import java.io.FileWriter; -import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashSet; @@ -63,6 +57,8 @@ import org.adempiere.webui.util.ReaderInputStream; import org.adempiere.webui.util.ZKUpdateUtil; import org.compiere.model.GridTab; import org.compiere.model.MImportTemplate; +import org.compiere.model.MQuery; +import org.compiere.model.MRole; import org.compiere.util.DB; import org.compiere.util.Env; import org.compiere.util.Msg; @@ -330,7 +326,7 @@ public class CSVImportAction implements EventListener return; String iMode = (String)importItem.getValue(); - m_file_istream = validateFile(m_file_istream, theTemplate); + m_file_istream = theTemplate.validateFile(m_file_istream); File outFile = theCSVImporter.fileImport(panel.getActiveGridTab(), childs, m_file_istream, charset,iMode); winImportFile.onClose(); winImportFile = null; @@ -347,57 +343,4 @@ public class CSVImportAction implements EventListener } } - private InputStream validateFile(InputStream in, MImportTemplate template) { - // because the input stream cannot be reset we need to copy here the file to a new one (replacing the header if it's the alias) - Charset charset = Charset.forName(template.getCharacterSet()); - BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset)); - File tmpfile = null; - InputStream is = null; - BufferedWriter bw = null; - try { - tmpfile = File.createTempFile("CSVImportAction", "csv"); - bw = new BufferedWriter(new FileWriter(tmpfile)); - String firstLine = null; - String line = null; - while ((line = reader.readLine()) != null) { - if (firstLine == null) { - firstLine = line; - /* Validate that m_file_istream header is CSVHeader or AliasCSVHeader */ - if ( firstLine.equals(template.getCSVHeader()) - || firstLine.equals(template.getCSVAliasHeader())) { - bw.write(template.getCSVHeader()); - } else { - reader.close(); - throw new AdempiereException(Msg.getMsg(Env.getCtx(), "WrongCSVHeader")); - } - } else { - bw.write(line); - } - bw.write('\n'); - } - is = new FileInputStream(tmpfile); - } catch (IOException e) { - throw new AdempiereException(e); - } finally { - if (in != null) - try { - in.close(); - } catch (IOException e) { - } - - if (bw != null) - try { - bw.close(); - } catch (IOException e) { - } - - if (reader != null) - try { - reader.close(); - } catch (IOException e) { - } - } - return is; - } - } From 02a89750aed506453f542635c94475d9c342029c Mon Sep 17 00:00:00 2001 From: Diego Ruiz Date: Mon, 22 Oct 2018 18:37:29 +0200 Subject: [PATCH 10/10] IDEMPIERE-3805 Query gets lost when Importing a csv file from the toolbar button --- .../webui/panel/action/CSVImportAction.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/action/CSVImportAction.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/action/CSVImportAction.java index a7e1678a08..4aeb7723bd 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/action/CSVImportAction.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/action/CSVImportAction.java @@ -291,6 +291,13 @@ public class CSVImportAction implements EventListener private void importFile() { try { + MQuery query = panel.getActiveGridTab().getQuery(); + MQuery detailQuery = null; + if (panel.getADTab() != null && panel.getADTab().getSelectedDetailADTabpanel() != null + && panel.getADTab().getSelectedDetailADTabpanel().getGridTab() != null) + detailQuery = panel.getADTab().getSelectedDetailADTabpanel().getGridTab().getQuery(); + + IADTabbox adTab = panel.getADTab(); int selected = adTab.getSelectedIndex(); int tabLevel = panel.getActiveGridTab().getTabLevel(); @@ -335,6 +342,19 @@ public class CSVImportAction implements EventListener media = new AMedia(theCSVImporter.getSuggestedFileName(panel.getActiveGridTab()), null, theCSVImporter.getContentType(), outFile, true); Filedownload.save(media); + if (query != null) { + query.addRestriction("1=1"); + panel.getActiveGridTab().setQuery(query); + panel.getADTab().getSelectedTabpanel().query(false, 0, MRole.getDefault().getMaxQueryRecords()); + } + panel.getActiveGridTab().dataRefresh(false); + + if (detailQuery != null){ + detailQuery.addRestriction("1=1"); + panel.getADTab().getSelectedDetailADTabpanel().getGridTab().setQuery(detailQuery); + panel.getADTab().getSelectedDetailADTabpanel().query(false, 0, MRole.getDefault().getMaxQueryRecords()); + panel.getADTab().getSelectedDetailADTabpanel().getGridTab().dataRefresh(false); + } } catch (Exception e) { throw new AdempiereException(e); } finally {