From e7e2d079a8ed53a5dac45e3e0ad1634bf090443e Mon Sep 17 00:00:00 2001
From: hieplq <hieplq@hasuvimex.vn>
Date: Wed, 6 Mar 2019 16:30:58 +0700
Subject: [PATCH 1/9] IDEMPIERE-3897:export csv: reference column export like
 normal column

I_AD_Language special treatment, it use AD_Language a string column to reference not AD_Language_id
---
 .../src/org/adempiere/impexp/GridTabCSVImporter.java        | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java b/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java
index f28128cf0f..091f614040 100644
--- a/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java
+++ b/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java
@@ -48,6 +48,7 @@ import org.compiere.model.GridField;
 import org.compiere.model.GridTab;
 import org.compiere.model.GridWindow;
 import org.compiere.model.GridWindowVO;
+import org.compiere.model.I_AD_Language;
 import org.compiere.model.MColumn;
 import org.compiere.model.MLocation;
 import org.compiere.model.MProcess;
@@ -1074,8 +1075,9 @@ public class GridTabCSVImporter implements IGridTabImporter
 			
 			if(isForeing) 
 			   foreignColumn = header.get(i).substring(header.get(i).indexOf("[")+1,header.get(i).indexOf("]"));
-			
-			if(!"C_Location".equals(gridTab.getTableName()) && header.get(i).contains(MTable.getTableName(Env.getCtx(),MLocation.Table_ID))){
+			if(!isForeing && !isKeyColumn && I_AD_Language.Table_Name.equals(columnName))
+				setValue = value;
+			else if(!"C_Location".equals(gridTab.getTableName()) && header.get(i).contains(MTable.getTableName(Env.getCtx(),MLocation.Table_ID))){
 		    
 				if(address == null){
 				    if(isInsertMode()){

From f42859d5e4e69fa6e9311843a5a82dbc83b61cbd Mon Sep 17 00:00:00 2001
From: Carlos Ruiz <carg67@gmail.com>
Date: Sat, 9 Mar 2019 20:32:55 +0100
Subject: [PATCH 2/9] IDEMPIERE-3897 apply same solution as AD_Language to
 Entitytype

---
 .../src/org/adempiere/impexp/GridTabCSVImporter.java           | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java b/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java
index 091f614040..7fcec58d31 100644
--- a/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java
+++ b/org.adempiere.base/src/org/adempiere/impexp/GridTabCSVImporter.java
@@ -48,7 +48,6 @@ import org.compiere.model.GridField;
 import org.compiere.model.GridTab;
 import org.compiere.model.GridWindow;
 import org.compiere.model.GridWindowVO;
-import org.compiere.model.I_AD_Language;
 import org.compiere.model.MColumn;
 import org.compiere.model.MLocation;
 import org.compiere.model.MProcess;
@@ -1075,7 +1074,7 @@ public class GridTabCSVImporter implements IGridTabImporter
 			
 			if(isForeing) 
 			   foreignColumn = header.get(i).substring(header.get(i).indexOf("[")+1,header.get(i).indexOf("]"));
-			if(!isForeing && !isKeyColumn && I_AD_Language.Table_Name.equals(columnName))
+			if(!isForeing && !isKeyColumn && ("AD_Language".equals(columnName) || "EntityType".equals(columnName)))
 				setValue = value;
 			else if(!"C_Location".equals(gridTab.getTableName()) && header.get(i).contains(MTable.getTableName(Env.getCtx(),MLocation.Table_ID))){
 		    

From e3f84efcb0d6197cf89d304bd7d69c76d3e43214 Mon Sep 17 00:00:00 2001
From: Carlos Ruiz <carg67@gmail.com>
Date: Sat, 9 Mar 2019 20:58:41 +0100
Subject: [PATCH 3/9] IDEMPIERE-3912 Report customization sort criteria moving
 down up make sort no. as 0 and doesnt sort properly / Fix suggested by
 Pritesh Shah

---
 .../src/org/adempiere/webui/panel/WRC3SortCriteriaPanel.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WRC3SortCriteriaPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WRC3SortCriteriaPanel.java
index 6301324757..c2f7abebbd 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WRC3SortCriteriaPanel.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WRC3SortCriteriaPanel.java
@@ -417,7 +417,7 @@ public class WRC3SortCriteriaPanel extends WRCTabPanel implements  EventListener
 				  targetPI = m_pfi.indexOf(getPrintFormatItem(newObject.m_key));
 				updateSortNo (selectedPI,targetPI);
 				
-				yesItems.get(index).setSortNo(yesItems.get(index).getSortNo()-10);
+				yesItems.get(index).setSortNo(yesItems.get(index).getSortNo());
 				orig = yesItems.get(index);
 				yesItems.get(index - 1).setSeqNo(yesItems.get(index - 1).getSeqNo()+10);
 				yesItems.set(index, yesItems.get(index-1));

From 51abcd9c80a8a6d4a8738123201e01b1098e8517 Mon Sep 17 00:00:00 2001
From: Carlos Ruiz <carg67@gmail.com>
Date: Thu, 14 Mar 2019 00:35:13 +0100
Subject: [PATCH 4/9] IDEMPIERE-3916 Process to move client between databases /
 FHEG-599

---
 .../oracle/201903131326_IDEMPIERE-3916.sql    | 285 ++++++
 .../201903131326_IDEMPIERE-3916.sql           | 282 ++++++
 .../src/org/idempiere/process/MoveClient.java | 839 ++++++++++++++++++
 3 files changed, 1406 insertions(+)
 create mode 100644 migration/i6.2/oracle/201903131326_IDEMPIERE-3916.sql
 create mode 100644 migration/i6.2/postgresql/201903131326_IDEMPIERE-3916.sql
 create mode 100644 org.adempiere.base/src/org/idempiere/process/MoveClient.java

diff --git a/migration/i6.2/oracle/201903131326_IDEMPIERE-3916.sql b/migration/i6.2/oracle/201903131326_IDEMPIERE-3916.sql
new file mode 100644
index 0000000000..8bb6814724
--- /dev/null
+++ b/migration/i6.2/oracle/201903131326_IDEMPIERE-3916.sql
@@ -0,0 +1,285 @@
+SET SQLBLANKLINES ON
+SET DEFINE OFF
+
+-- IDEMPIERE-3916 Process to move client between databases
+-- Mar 13, 2019 1:17:24 PM CET
+INSERT INTO AD_Process (AD_Process_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,IsReport,Value,IsDirectPrint,Classname,AccessLevel,EntityType,Statistic_Count,Statistic_Seconds,IsBetaFunctionality,IsServerProcess,ShowHelp,CopyFromProcess,AD_Process_UU) VALUES (200110,0,0,'Y',TO_DATE('2019-03-13 13:17:24','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:17:24','YYYY-MM-DD HH24:MI:SS'),100,'Move Client','Process to move a client from an external database to current','N','MoveClient','N','org.idempiere.process.MoveClient','4','D',0,0,'N','N','Y','N','365a132a-7b8e-4f0f-b1d3-70db173df7f9')
+;
+
+-- Mar 13, 2019 1:17:54 PM CET
+INSERT INTO AD_Menu (AD_Menu_ID,Name,Description,Action,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsSummary,AD_Process_ID,IsSOTrx,IsReadOnly,EntityType,IsCentrallyMaintained,AD_Menu_UU) VALUES (200168,'Move Client','Process to move a client from an external database to current','P',0,0,'Y',TO_DATE('2019-03-13 13:17:53','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:17:53','YYYY-MM-DD HH24:MI:SS'),100,'N',200110,'Y','N','D','Y','63aa38c7-b332-42d3-813e-912389e4f767')
+;
+
+-- Mar 13, 2019 1:17:54 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, 200168, 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=200168)
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=0, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=218
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=1, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=153
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=2, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=263
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=3, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=166
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=4, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=203
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=5, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53242
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=6, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=1000016
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=7, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=236
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=8, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=183
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=9, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=160
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=10, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=278
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=11, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=345
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=12, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53296
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=13, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53014
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=14, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53108
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=15, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=1000036
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=16, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=1000095
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=0, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=161
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=1, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=367
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=2, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=456
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=3, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=501
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=4, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=326
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=5, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=566
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=6, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=392
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=7, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=113
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=8, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=220
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=9, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=351
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=10, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=289
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=11, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=302
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=12, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=200168
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=13, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=303
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=14, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=200047
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=15, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=200048
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=16, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=321
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=17, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=461
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=18, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53193
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=19, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53322
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=20, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=383
+;
+
+-- Mar 13, 2019 1:19:21 PM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203294,0,0,'Y',TO_DATE('2019-03-13 13:19:21','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:19:21','YYYY-MM-DD HH24:MI:SS'),100,'ClientsToExclude','Clients to Exclude','Comma separated list of client IDs to exclude','Clients to Exclude','D','6e7efabf-8c3c-424a-a22f-ccfcb7ff426d')
+;
+
+-- Mar 13, 2019 1:20:08 PM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203295,0,0,'Y',TO_DATE('2019-03-13 13:20:08','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:20:08','YYYY-MM-DD HH24:MI:SS'),100,'ClientsToInclude','Clients to Include','Comma separated list of client IDs to include','Clients to Include','D','d43df270-66c5-4f08-a3a0-7a9125f2b19a')
+;
+
+-- Mar 13, 2019 1:20:21 PM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203296,0,0,'Y',TO_DATE('2019-03-13 13:20:21','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:20:21','YYYY-MM-DD HH24:MI:SS'),100,'TablesToExclude','Tables to Exclude','Comma separated list of tables to exclude','Tables to Exclude','D','9e56bd23-c125-46a4-a1e7-c126c8398888')
+;
+
+-- Mar 13, 2019 1:20:34 PM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,PrintName,EntityType,AD_Element_UU) VALUES (203297,0,0,'Y',TO_DATE('2019-03-13 13:20:34','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:20:34','YYYY-MM-DD HH24:MI:SS'),100,'JDBC_URL','JDBC URL','JDBC URL','D','dcae66f5-4e3c-4ede-9cc1-f590e4e01ff1')
+;
+
+-- Mar 13, 2019 1:21:19 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200256,0,0,'Y',TO_DATE('2019-03-13 13:21:19','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:21:19','YYYY-MM-DD HH24:MI:SS'),100,'JDBC URL',200110,10,10,'N',1000,'Y','JDBC_URL','Y','D',203297,'d85a4590-ebdb-412a-8356-8acd1afc2d58','N')
+;
+
+-- Mar 13, 2019 1:21:42 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200257,0,0,'Y',TO_DATE('2019-03-13 13:21:41','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:21:41','YYYY-MM-DD HH24:MI:SS'),100,'User Name',200110,20,10,'N',100,'N','UserName','Y','D',1903,'47c346a2-5bdf-46e2-baef-43c5b5e4c800','N')
+;
+
+-- Mar 13, 2019 1:22:13 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,Help,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200258,0,0,'Y',TO_DATE('2019-03-13 13:22:12','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:22:12','YYYY-MM-DD HH24:MI:SS'),100,'Password','Password of any length (case sensitive)','The Password for this User.  Passwords are required to identify authorized users.  For iDempiere Users, you can change the password via the Process "Reset Password".',200110,30,10,'N',100,'N','Password','Y','D',498,'7e5b47a3-5bd1-4e92-adb7-d58d4a725932','Y')
+;
+
+-- Mar 13, 2019 1:22:34 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200259,0,0,'Y',TO_DATE('2019-03-13 13:22:34','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:22:34','YYYY-MM-DD HH24:MI:SS'),100,'Tables to Exclude','Comma separated list of tables to exclude',200110,40,10,'N',32000,'N','TablesToExclude','Y','D',203296,'25677162-7d62-4319-9c0e-1ff8dfbccf09','N')
+;
+
+-- Mar 13, 2019 1:23:04 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200260,0,0,'Y',TO_DATE('2019-03-13 13:23:04','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:23:04','YYYY-MM-DD HH24:MI:SS'),100,'Clients to Include','Comma separated list of client IDs to include',200110,50,10,'N',32000,'N','ClientsToInclude','Y','D',203295,'3284012a-252f-4410-9a55-ae8f1c121f5a','N')
+;
+
+-- Mar 13, 2019 1:23:30 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200261,0,0,'Y',TO_DATE('2019-03-13 13:23:30','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:23:30','YYYY-MM-DD HH24:MI:SS'),100,'Clients to Exclude','Comma separated list of client IDs to exclude',200110,60,10,'N',32000,'N','ClientsToExclude','Y','D',203294,'cac0280e-0e34-4c66-b055-51276d75821c','N')
+;
+
+-- Mar 13, 2019 1:23:54 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,DefaultValue,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200262,0,0,'Y',TO_DATE('2019-03-13 13:23:54','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:23:54','YYYY-MM-DD HH24:MI:SS'),100,'Only Validate Data','Validate the date and do not process',200110,70,20,'N',0,'Y','Y','IsValidateOnly','Y','D',2168,'cb303081-dc25-48b1-b6d4-dcf8d17708c2','N')
+;
+
+-- Mar 13, 2019 1:24:35 PM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,PrintName,EntityType,AD_Element_UU) VALUES (203298,0,0,'Y',TO_DATE('2019-03-13 13:24:34','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:24:34','YYYY-MM-DD HH24:MI:SS'),100,'IsPreserveIDs','Preserve IDs','Preserve IDs','D','717c4728-0178-499b-a846-e70a790e7f96')
+;
+
+-- Mar 13, 2019 1:24:55 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,DefaultValue,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200263,0,0,'Y',TO_DATE('2019-03-13 13:24:55','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-13 13:24:55','YYYY-MM-DD HH24:MI:SS'),100,'Preserve IDs',200110,80,20,'N',1,'Y','N','IsPreserveIDs','Y','D',203298,'e81f21da-5126-4009-876b-c477315ba0ea','N')
+;
+
+-- Mar 13, 2019 1:25:01 PM CET
+UPDATE AD_Process_Para SET FieldLength=1,Updated=TO_DATE('2019-03-13 13:25:01','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200262
+;
+
+-- Mar 13, 2019 6:39:33 PM CET
+UPDATE AD_Process_Para SET Description='Comma separated list of tables that require to preserve the IDs', AD_Reference_ID=10, FieldLength=32000, IsMandatory='N', DefaultValue=NULL,Updated=TO_DATE('2019-03-13 18:39:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200263
+;
+
+CREATE TABLE T_MoveClient (AD_PInstance_ID NUMBER(10), TableName VARCHAR2(40), Source_ID NUMBER(10), Target_ID NUMBER(10))
+;
+
+CREATE UNIQUE INDEX UX_T_MoveClient ON T_MoveClient (AD_PInstance_ID,TableName,Source_ID)
+;
+
+-- Mar 13, 2019 7:28:16 PM CET
+UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:28:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200259
+;
+
+-- Mar 13, 2019 7:28:19 PM CET
+UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:28:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200260
+;
+
+-- Mar 13, 2019 7:28:22 PM CET
+UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:28:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200261
+;
+
+-- Mar 13, 2019 7:28:27 PM CET
+UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:28:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200263
+;
+
+-- Mar 13, 2019 7:29:49 PM CET
+UPDATE AD_Column SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:29:49','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5664
+;
+
+-- Mar 13, 2019 7:29:51 PM CET
+ALTER TABLE AD_PInstance_Para MODIFY Info VARCHAR2(2000) DEFAULT NULL 
+;
+
+-- Mar 13, 2019 7:29:59 PM CET
+UPDATE AD_Column SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:29:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5665
+;
+
+-- Mar 13, 2019 7:30:00 PM CET
+ALTER TABLE AD_PInstance_Para MODIFY Info_To VARCHAR2(2000) DEFAULT NULL 
+;
+
+-- Mar 13, 2019 7:30:20 PM CET
+UPDATE AD_Column SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:30:20','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2791
+;
+
+-- Mar 13, 2019 7:30:21 PM CET
+ALTER TABLE AD_PInstance_Para MODIFY P_String VARCHAR2(2000) DEFAULT NULL 
+;
+
+-- Mar 13, 2019 7:30:28 PM CET
+UPDATE AD_Column SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:30:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2792
+;
+
+-- Mar 13, 2019 7:30:30 PM CET
+ALTER TABLE AD_PInstance_Para MODIFY P_String_To VARCHAR2(2000) DEFAULT NULL 
+;
+
+SELECT register_migration_script('201903131326_IDEMPIERE-3916.sql') FROM dual
+;
+
diff --git a/migration/i6.2/postgresql/201903131326_IDEMPIERE-3916.sql b/migration/i6.2/postgresql/201903131326_IDEMPIERE-3916.sql
new file mode 100644
index 0000000000..30b90b8e97
--- /dev/null
+++ b/migration/i6.2/postgresql/201903131326_IDEMPIERE-3916.sql
@@ -0,0 +1,282 @@
+-- IDEMPIERE-3916 Process to move client between databases
+-- Mar 13, 2019 1:17:24 PM CET
+INSERT INTO AD_Process (AD_Process_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,IsReport,Value,IsDirectPrint,Classname,AccessLevel,EntityType,Statistic_Count,Statistic_Seconds,IsBetaFunctionality,IsServerProcess,ShowHelp,CopyFromProcess,AD_Process_UU) VALUES (200110,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:17:24','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:17:24','YYYY-MM-DD HH24:MI:SS'),100,'Move Client','Process to move a client from an external database to current','N','MoveClient','N','org.idempiere.process.MoveClient','4','D',0,0,'N','N','Y','N','365a132a-7b8e-4f0f-b1d3-70db173df7f9')
+;
+
+-- Mar 13, 2019 1:17:54 PM CET
+INSERT INTO AD_Menu (AD_Menu_ID,Name,Description,"action",AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsSummary,AD_Process_ID,IsSOTrx,IsReadOnly,EntityType,IsCentrallyMaintained,AD_Menu_UU) VALUES (200168,'Move Client','Process to move a client from an external database to current','P',0,0,'Y',TO_TIMESTAMP('2019-03-13 13:17:53','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:17:53','YYYY-MM-DD HH24:MI:SS'),100,'N',200110,'Y','N','D','Y','63aa38c7-b332-42d3-813e-912389e4f767')
+;
+
+-- Mar 13, 2019 1:17:54 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, 200168, 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=200168)
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=0, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=218
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=1, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=153
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=2, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=263
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=3, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=166
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=4, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=203
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=5, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53242
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=6, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=1000016
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=7, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=236
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=8, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=183
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=9, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=160
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=10, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=278
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=11, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=345
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=12, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53296
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=13, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53014
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=14, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53108
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=15, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=1000036
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=16, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=1000095
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=0, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=161
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=1, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=367
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=2, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=456
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=3, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=501
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=4, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=326
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=5, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=566
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=6, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=392
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=7, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=113
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=8, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=220
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=9, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=351
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=10, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=289
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=11, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=302
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=12, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=200168
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=13, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=303
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=14, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=200047
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=15, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=200048
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=16, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=321
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=17, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=461
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=18, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53193
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=19, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53322
+;
+
+-- Mar 13, 2019 1:18:30 PM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=20, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=383
+;
+
+-- Mar 13, 2019 1:19:21 PM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203294,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:19:21','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:19:21','YYYY-MM-DD HH24:MI:SS'),100,'ClientsToExclude','Clients to Exclude','Comma separated list of client IDs to exclude','Clients to Exclude','D','6e7efabf-8c3c-424a-a22f-ccfcb7ff426d')
+;
+
+-- Mar 13, 2019 1:20:08 PM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203295,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:20:08','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:20:08','YYYY-MM-DD HH24:MI:SS'),100,'ClientsToInclude','Clients to Include','Comma separated list of client IDs to include','Clients to Include','D','d43df270-66c5-4f08-a3a0-7a9125f2b19a')
+;
+
+-- Mar 13, 2019 1:20:21 PM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203296,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:20:21','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:20:21','YYYY-MM-DD HH24:MI:SS'),100,'TablesToExclude','Tables to Exclude','Comma separated list of tables to exclude','Tables to Exclude','D','9e56bd23-c125-46a4-a1e7-c126c8398888')
+;
+
+-- Mar 13, 2019 1:20:34 PM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,PrintName,EntityType,AD_Element_UU) VALUES (203297,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:20:34','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:20:34','YYYY-MM-DD HH24:MI:SS'),100,'JDBC_URL','JDBC URL','JDBC URL','D','dcae66f5-4e3c-4ede-9cc1-f590e4e01ff1')
+;
+
+-- Mar 13, 2019 1:21:19 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200256,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:21:19','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:21:19','YYYY-MM-DD HH24:MI:SS'),100,'JDBC URL',200110,10,10,'N',1000,'Y','JDBC_URL','Y','D',203297,'d85a4590-ebdb-412a-8356-8acd1afc2d58','N')
+;
+
+-- Mar 13, 2019 1:21:42 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200257,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:21:41','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:21:41','YYYY-MM-DD HH24:MI:SS'),100,'User Name',200110,20,10,'N',100,'N','UserName','Y','D',1903,'47c346a2-5bdf-46e2-baef-43c5b5e4c800','N')
+;
+
+-- Mar 13, 2019 1:22:13 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,Help,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200258,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:22:12','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:22:12','YYYY-MM-DD HH24:MI:SS'),100,'Password','Password of any length (case sensitive)','The Password for this User.  Passwords are required to identify authorized users.  For iDempiere Users, you can change the password via the Process "Reset Password".',200110,30,10,'N',100,'N','Password','Y','D',498,'7e5b47a3-5bd1-4e92-adb7-d58d4a725932','Y')
+;
+
+-- Mar 13, 2019 1:22:34 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200259,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:22:34','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:22:34','YYYY-MM-DD HH24:MI:SS'),100,'Tables to Exclude','Comma separated list of tables to exclude',200110,40,10,'N',32000,'N','TablesToExclude','Y','D',203296,'25677162-7d62-4319-9c0e-1ff8dfbccf09','N')
+;
+
+-- Mar 13, 2019 1:23:04 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200260,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:23:04','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:23:04','YYYY-MM-DD HH24:MI:SS'),100,'Clients to Include','Comma separated list of client IDs to include',200110,50,10,'N',32000,'N','ClientsToInclude','Y','D',203295,'3284012a-252f-4410-9a55-ae8f1c121f5a','N')
+;
+
+-- Mar 13, 2019 1:23:30 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200261,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:23:30','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:23:30','YYYY-MM-DD HH24:MI:SS'),100,'Clients to Exclude','Comma separated list of client IDs to exclude',200110,60,10,'N',32000,'N','ClientsToExclude','Y','D',203294,'cac0280e-0e34-4c66-b055-51276d75821c','N')
+;
+
+-- Mar 13, 2019 1:23:54 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,DefaultValue,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200262,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:23:54','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:23:54','YYYY-MM-DD HH24:MI:SS'),100,'Only Validate Data','Validate the date and do not process',200110,70,20,'N',0,'Y','Y','IsValidateOnly','Y','D',2168,'cb303081-dc25-48b1-b6d4-dcf8d17708c2','N')
+;
+
+-- Mar 13, 2019 1:24:35 PM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,PrintName,EntityType,AD_Element_UU) VALUES (203298,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:24:34','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:24:34','YYYY-MM-DD HH24:MI:SS'),100,'IsPreserveIDs','Preserve IDs','Preserve IDs','D','717c4728-0178-499b-a846-e70a790e7f96')
+;
+
+-- Mar 13, 2019 1:24:55 PM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,DefaultValue,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200263,0,0,'Y',TO_TIMESTAMP('2019-03-13 13:24:55','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-13 13:24:55','YYYY-MM-DD HH24:MI:SS'),100,'Preserve IDs',200110,80,20,'N',1,'Y','N','IsPreserveIDs','Y','D',203298,'e81f21da-5126-4009-876b-c477315ba0ea','N')
+;
+
+-- Mar 13, 2019 1:25:01 PM CET
+UPDATE AD_Process_Para SET FieldLength=1,Updated=TO_TIMESTAMP('2019-03-13 13:25:01','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200262
+;
+
+-- Mar 13, 2019 6:39:33 PM CET
+UPDATE AD_Process_Para SET Description='Comma separated list of tables that require to preserve the IDs', AD_Reference_ID=10, FieldLength=32000, IsMandatory='N', DefaultValue=NULL,Updated=TO_TIMESTAMP('2019-03-13 18:39:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200263
+;
+
+CREATE TABLE T_MoveClient (AD_PInstance_ID NUMERIC(10), TableName VARCHAR(40), Source_ID NUMERIC(10), Target_ID NUMERIC(10))
+;
+
+CREATE UNIQUE INDEX UX_T_MoveClient ON T_MoveClient (AD_PInstance_ID,TableName,Source_ID)
+;
+
+-- Mar 13, 2019 7:28:16 PM CET
+UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:28:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200259
+;
+
+-- Mar 13, 2019 7:28:19 PM CET
+UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:28:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200260
+;
+
+-- Mar 13, 2019 7:28:22 PM CET
+UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:28:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200261
+;
+
+-- Mar 13, 2019 7:28:27 PM CET
+UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:28:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200263
+;
+
+-- Mar 13, 2019 7:29:49 PM CET
+UPDATE AD_Column SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:29:49','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5664
+;
+
+-- Mar 13, 2019 7:29:51 PM CET
+INSERT INTO t_alter_column values('ad_pinstance_para','Info','VARCHAR(2000)',null,'NULL')
+;
+
+-- Mar 13, 2019 7:29:59 PM CET
+UPDATE AD_Column SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:29:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5665
+;
+
+-- Mar 13, 2019 7:30:00 PM CET
+INSERT INTO t_alter_column values('ad_pinstance_para','Info_To','VARCHAR(2000)',null,'NULL')
+;
+
+-- Mar 13, 2019 7:30:20 PM CET
+UPDATE AD_Column SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:30:20','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2791
+;
+
+-- Mar 13, 2019 7:30:21 PM CET
+INSERT INTO t_alter_column values('ad_pinstance_para','P_String','VARCHAR(2000)',null,'NULL')
+;
+
+-- Mar 13, 2019 7:30:28 PM CET
+UPDATE AD_Column SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:30:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2792
+;
+
+-- Mar 13, 2019 7:30:30 PM CET
+INSERT INTO t_alter_column values('ad_pinstance_para','P_String_To','VARCHAR(2000)',null,'NULL')
+;
+
+SELECT register_migration_script('201903131326_IDEMPIERE-3916.sql') FROM dual
+;
+
diff --git a/org.adempiere.base/src/org/idempiere/process/MoveClient.java b/org.adempiere.base/src/org/idempiere/process/MoveClient.java
new file mode 100644
index 0000000000..41bf54f363
--- /dev/null
+++ b/org.adempiere.base/src/org/idempiere/process/MoveClient.java
@@ -0,0 +1,839 @@
+/***********************************************************************
+ * 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 - globalqss                                           *
+ * Sponsored by FH                                                     *
+ **********************************************************************/
+
+package org.idempiere.process;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+
+import org.adempiere.exceptions.AdempiereException;
+import org.compiere.db.CConnection;
+import org.compiere.model.MColumn;
+import org.compiere.model.MSequence;
+import org.compiere.model.MTable;
+import org.compiere.model.Query;
+import org.compiere.process.ProcessInfoParameter;
+import org.compiere.process.SvrProcess;
+import org.compiere.util.AdempiereUserError;
+import org.compiere.util.DB;
+import org.compiere.util.DisplayType;
+import org.compiere.util.Util;
+
+public class MoveClient extends SvrProcess {
+
+	// Process to move a client from a external database to current
+
+	private String p_JDBC_URL;         // JDBC URL of the external database
+	private String p_UserName;         // optional to connect to the JDBC URL, if empty use the same as target 
+	private String p_Password;         // optional to connect to the JDBC URL, if empty use the same as target
+	private String p_TablesToExclude;  // optional, comma separated list of tables to exclude
+	private String p_ClientsToInclude; // optional, comma separated list, if empty then all clients >= 1000000 will be moved
+	private String p_ClientsToExclude; // optional, comma separated list of clients to exclude
+	private boolean p_IsValidateOnly;  // to do just validation and not execute the process
+	private String p_IsPreserveIDs;    // optional, comma separated list of tables that require to preserve IDs
+
+	final static String insertConversionId = "INSERT INTO T_MoveClient (AD_PInstance_ID, TableName, Source_ID, Target_ID) VALUES (?, ?, ?, ?)";
+
+	private Connection externalConn;
+	private StringBuffer p_excludeTablesWhere = new StringBuffer();
+	private StringBuffer p_whereClient = new StringBuffer();
+	private List<String> p_errorList = new ArrayList<String>();
+	private List<String> p_tablesVerifiedList = new ArrayList<String>();
+	private List<String> p_tablesToPreserveIDsList = new ArrayList<String>();
+	private List<String> p_tablesToExcludeList = new ArrayList<String>();
+	private List<String> p_columnsVerifiedList = new ArrayList<String>();
+	private List<String> p_idSystemConversionList = new ArrayList<String>(); // can consume lot of memory but it helps for performance
+
+	@Override
+	protected void prepare() {
+		// defaults
+		p_IsValidateOnly = true;
+		//
+		for (ProcessInfoParameter para : getParameter()) {
+			String name = para.getParameterName();
+			if ("JDBC_URL".equals(name)) {
+				p_JDBC_URL  = para.getParameterAsString();
+			} else if ("UserName".equals(name)) {
+				p_UserName = para.getParameterAsString();
+			} else if ("Password".equals(name)) {
+				p_Password = para.getParameterAsString();
+			} else if ("TablesToExclude".equals(name)) {
+				p_TablesToExclude = para.getParameterAsString();
+			} else if ("ClientsToInclude".equals(name)) {
+				p_ClientsToInclude = para.getParameterAsString();
+			} else if ("ClientsToExclude".equals(name)) {
+				p_ClientsToExclude = para.getParameterAsString();
+			} else if ("IsValidateOnly".equals(name)) {
+				p_IsValidateOnly = para.getParameterAsBoolean();
+			} else if ("IsPreserveIDs".equals(name)) {
+				p_IsPreserveIDs = para.getParameterAsString();
+			} else {
+				log.log(Level.SEVERE, "Unknown Parameter: " + name);
+			}
+		}
+	}
+
+	@Override
+	protected String doIt() throws Exception {
+		// validate parameters
+		if (Util.isEmpty(p_JDBC_URL, true))
+			throw new AdempiereException("Fill mandatory JDBC_URL");
+		if (! Util.isEmpty(p_ClientsToInclude, true) && ! Util.isEmpty(p_ClientsToExclude, true))
+			throw new AdempiereException("Clients to exclude and include cannot be used at the same time");
+		if (Util.isEmpty(p_UserName, true))
+			p_UserName = CConnection.get().getDbUid();
+		if (Util.isEmpty(p_Password, true))
+			p_Password = CConnection.get().getDbPwd();
+
+		// Construct the where clauses
+		p_excludeTablesWhere.append("(UPPER(AD_Table.TableName) NOT LIKE 'T|_%' ESCAPE '|'"); // exclude temporary tables
+		if (Util.isEmpty(p_TablesToExclude, true)) {
+			p_excludeTablesWhere.append(")");
+		} else {
+			p_excludeTablesWhere.append(" AND UPPER(TableName) NOT IN (");
+			boolean addComma = false;
+			for (String tableName : p_TablesToExclude.split(",")) {
+				p_tablesToExcludeList.add(tableName.toUpperCase());
+				if (addComma) {
+					p_excludeTablesWhere.append(",");
+				} else {
+					addComma = true;
+				}
+				p_excludeTablesWhere.append(DB.TO_STRING(tableName.toUpperCase()));
+			}
+			p_excludeTablesWhere.append("))");
+		}
+
+		p_whereClient.append("AD_Client.AD_Client_ID NOT IN (0"); // by default exclude System
+		if (! Util.isEmpty(p_ClientsToExclude, true)) {
+			for (String clientStr : p_ClientsToExclude.split(",")) {
+				p_whereClient.append(",");
+				int clientInt;
+				try {
+					clientInt = Integer.parseInt(clientStr);
+				} catch (NumberFormatException e) {
+					throw new AdempiereException("Error in parameter Clients to Exclude, must be a list of integer separated by commas, wrong format: " + clientStr);
+				}
+				p_whereClient.append(clientInt);
+			}
+		}
+		p_whereClient.append(")");
+		if (! Util.isEmpty(p_ClientsToInclude, true)) {
+			p_whereClient.append(" AND AD_Client.AD_Client_ID IN (");
+			boolean addComma = false;
+			for (String clientStr : p_ClientsToInclude.split(",")) {
+				if (addComma) {
+					p_whereClient.append(",");
+				} else {
+					addComma = true;
+				}
+				int clientInt;
+				try {
+					clientInt = Integer.parseInt(clientStr);
+				} catch (NumberFormatException e) {
+					throw new AdempiereException("Error in parameter Clients to Include, must be a list of integer separated by commas, wrong format: " + clientStr);
+				}
+				p_whereClient.append(clientInt);
+			}
+			p_whereClient.append(")");
+		}
+
+		if (! Util.isEmpty(p_IsPreserveIDs, true)) {
+			for (String tableName : p_IsPreserveIDs.split(",")) {
+				p_tablesToPreserveIDsList.add(tableName.toUpperCase());
+			}
+		}
+
+		// Make the connection to external database
+		externalConn = null;
+		try {
+			try {
+				externalConn = DB.getDatabase(p_JDBC_URL).getDriverConnection(p_JDBC_URL, p_UserName, p_Password);
+			} catch (Exception e) {
+				throw new AdempiereException("Could not get a connection to " + p_JDBC_URL + ",\nCause: " + e.getLocalizedMessage());
+			}
+
+			validate();
+			if (p_errorList.size() > 0) {
+				for (String err : p_errorList) {
+					addLog(err);
+				}
+				return "@Error@";
+			}
+
+			if (! p_IsValidateOnly) {
+				moveClient();
+			}
+		} finally {
+			if (externalConn != null)
+				externalConn.close();
+		}
+		
+		checkSequences();
+
+		return "@OK@";
+	}
+
+	private void validate() {
+		// validate there are clients to move, and doesn't exist in target
+		StringBuilder sqlValidClientsSB = new StringBuilder()
+				.append("SELECT AD_Client_ID, Value, Name, AD_Client_UU FROM AD_Client WHERE ")
+				.append(p_whereClient)
+				.append(" ORDER BY Value");
+		StringBuilder sqlValidateLocalClient = new StringBuilder()
+				.append("SELECT COUNT(*) FROM AD_Client WHERE Value=? OR Name=? OR AD_Client_UU=?");
+		if (p_tablesToPreserveIDsList.contains("AD_CLIENT")) {
+			sqlValidateLocalClient.append(" OR AD_Client_ID=?");
+		}
+		String sqlValidClients = DB.getDatabase().convertStatement(sqlValidClientsSB.toString());
+		PreparedStatement stmtVC = null;
+		ResultSet rsVC = null;
+		int noClients = 0;
+		try {
+			stmtVC = externalConn.prepareStatement(sqlValidClients, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+			rsVC = stmtVC.executeQuery();
+			while (rsVC.next()) {
+				noClients++;
+				int clientID = rsVC.getInt(1);
+				String clientValue = rsVC.getString(2);
+				String clientName = rsVC.getString(3);
+				String clientUUID = rsVC.getString(4);
+				int cnt = 0;
+				if (p_tablesToPreserveIDsList.contains("AD_CLIENT")) {
+					cnt = DB.getSQLValueEx(get_TrxName(), sqlValidateLocalClient.toString(), clientValue, clientName, clientUUID, clientID);
+				} else {
+					cnt = DB.getSQLValueEx(get_TrxName(), sqlValidateLocalClient.toString(), clientValue, clientName, clientUUID);
+				}
+				if (cnt > 0) {
+					String msg = "Client " + clientValue + "/" + clientName + " already exists.  UUID=" + clientUUID;
+					if (p_tablesToPreserveIDsList.contains("AD_CLIENT")) {
+						msg += ", ID=" + clientID;
+					}
+					p_errorList.add(msg);
+				}
+			}
+		} catch (SQLException e) {
+			throw new AdempiereException("Could not execute external query: " + sqlValidClients + "\nCause = " + e.getLocalizedMessage());
+		} finally {
+			DB.close(rsVC, stmtVC);
+		}
+		if (noClients <= 0) {
+			throw new AdempiereUserError("No clients to move");
+		}
+		if (p_errorList.size() > 0) {
+			return;
+		}
+
+		// validate if there are attachments using external storage provider - inform not implemented yet (blocking)
+		if (! p_excludeTablesWhere.toString().contains("'AD_ATTACHMENT'")) {
+			statusUpdate("Checking storage for attachments");
+			StringBuilder sqlExternalAttachment = new StringBuilder()
+					.append("SELECT COUNT(*) FROM AD_Attachment")
+					.append(" JOIN AD_Client ON (AD_Attachment.AD_Client_ID=AD_Client.AD_Client_ID)")
+					.append(" JOIN AD_ClientInfo ON (AD_Attachment.AD_Client_ID=AD_ClientInfo.AD_Client_ID)")
+					.append(" JOIN AD_Table ON (AD_Attachment.AD_Table_ID=AD_Table.AD_Table_ID)")
+					.append(" LEFT JOIN AD_StorageProvider ON (AD_StorageProvider.AD_StorageProvider_ID=AD_ClientInfo.AD_StorageProvider_ID)")
+					.append(" WHERE AD_StorageProvider.Method IS NOT NULL AND AD_StorageProvider.Method!='DB'")
+					.append(" AND ").append(p_whereClient)
+					.append(" AND ").append(p_excludeTablesWhere);
+			int cntES = countInExternal(sqlExternalAttachment.toString());
+			if (cntES > 0) {
+				throw new AdempiereUserError("There are attachments using external storage provider - that's not implemented yet");
+			}
+		}
+
+		// validate if there are archives using external storage provider - inform not implemented yet (blocking)
+		if (! p_excludeTablesWhere.toString().contains("'AD_ARCHIVE'")) {
+			statusUpdate("Checking storage for archives");
+			StringBuilder sqlExternalArchive = new StringBuilder()
+					.append("SELECT COUNT(*) FROM AD_Archive")
+					.append(" JOIN AD_Client ON (AD_Archive.AD_Client_ID=AD_Client.AD_Client_ID)")
+					.append(" JOIN AD_ClientInfo ON (AD_Archive.AD_Client_ID=AD_ClientInfo.AD_Client_ID)")
+					.append(" JOIN AD_Table ON (AD_Archive.AD_Table_ID=AD_Table.AD_Table_ID)")
+					.append(" LEFT JOIN AD_StorageProvider ON (AD_StorageProvider.AD_StorageProvider_ID=AD_ClientInfo.StorageArchive_ID)")
+					.append(" WHERE AD_StorageProvider.Method IS NOT NULL AND AD_StorageProvider.Method!='DB'")
+					.append(" AND ").append(p_whereClient)
+					.append(" AND ").append(p_excludeTablesWhere);
+			int cntEA = countInExternal(sqlExternalArchive.toString());
+			if (cntEA > 0) {
+				throw new AdempiereUserError("There are archives using external storage provider - that's not implemented yet");
+			}
+		}
+
+		// create list of tables to ignore
+		// validate tables
+		// for each source table not excluded
+		StringBuilder sqlTablesSB = new StringBuilder()
+				.append("SELECT TableName FROM AD_Table WHERE IsActive='Y' AND IsView='N' AND ")
+				.append(p_excludeTablesWhere)
+				.append(" ORDER BY TableName");
+
+		String sqlRemoteTables = DB.getDatabase().convertStatement(sqlTablesSB.toString());
+		PreparedStatement stmtRT = null;
+		ResultSet rsRT = null;
+		try {
+			stmtRT = externalConn.prepareStatement(sqlRemoteTables, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+			rsRT = stmtRT.executeQuery();
+			while (rsRT.next()) {
+				String tableName = rsRT.getString(1);
+				validateExternalTable(tableName);
+			}
+		} catch (SQLException e) {
+			throw new AdempiereException("Could not execute external query: " + sqlRemoteTables + "\nCause = " + e.getLocalizedMessage());
+		} finally {
+			DB.close(rsRT, stmtRT);
+		}
+
+	}
+
+	private void validateExternalTable(String tableName) {
+		statusUpdate("Validating table " + tableName);
+		// if table doesn't have client data (taking into account include/exclude) in the source DB
+		// add to the list of tables to ignore
+		// ignore and continue with next table
+		if (! "AD_Client".equalsIgnoreCase(tableName)) {
+			StringBuilder sqlCountData = new StringBuilder()
+					.append("SELECT COUNT(*) FROM ").append(tableName);
+			if ("AD_Attribute_Value".equalsIgnoreCase(tableName)) {
+				sqlCountData.append(" JOIN AD_Attribute ON (AD_Attribute_Value.AD_Attribute_ID=AD_Attribute.AD_Attribute_ID)");
+				sqlCountData.append(" JOIN AD_Client ON (AD_Attribute.AD_Client_ID=AD_Client.AD_Client_ID)");
+			} else if ("AD_PInstance_Log".equalsIgnoreCase(tableName)) {
+				sqlCountData.append(" JOIN AD_PInstance ON (AD_PInstance_Log.AD_PInstance_ID=AD_PInstance.AD_PInstance_ID)");
+				sqlCountData.append(" JOIN AD_Client ON (AD_PInstance.AD_Client_ID=AD_Client.AD_Client_ID)");
+			} else {
+				sqlCountData.append(" JOIN AD_Client ON (").append(tableName).append(".AD_Client_ID=AD_Client.AD_Client_ID)");
+			}
+			sqlCountData.append(" WHERE ").append(p_whereClient);
+			int cntCD = countInExternal(sqlCountData.toString());
+			if (cntCD == 0) {
+				if (log.isLoggable(Level.INFO)) log.info("Ignoring " + tableName + ", doesn't have client data");
+				return;
+			}
+			if (cntCD > 0 && "AD_Attribute_Value".equalsIgnoreCase(tableName)) {
+				throw new AdempiereUserError("Table " + tableName + " has data, migration not supported");
+			}
+		}
+
+		// if table is not present in target
+		// inform blocking as it has client data
+		MTable localTable = MTable.get(getCtx(), tableName);
+		if (localTable == null || localTable.getAD_Table_ID() <= 0) {
+			p_errorList.add("Table " + tableName + " doesn't exist");
+			return;
+		}
+
+		// for each source column
+		final String sqlRemoteColumnsST = ""
+				+ " SELECT AD_Column.ColumnName, AD_Column.AD_Reference_ID, AD_Column.FieldLength"
+				+ " FROM AD_Column"
+				+ " JOIN AD_Table ON (AD_Table.AD_Table_ID=AD_Column.AD_Table_ID)"
+				+ " WHERE UPPER(AD_Table.TableName)=? AND AD_Column.IsActive='Y' AND AD_Column.ColumnSQL IS NULL"
+				+ " ORDER BY AD_Column.ColumnName";
+		String sqlRemoteColumns = DB.getDatabase().convertStatement(sqlRemoteColumnsST);
+		PreparedStatement stmtRC = null;
+		ResultSet rsRC = null;
+		try {
+			stmtRC = externalConn.prepareStatement(sqlRemoteColumns, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+			stmtRC.setString(1, tableName.toUpperCase());
+			rsRC = stmtRC.executeQuery();
+			while (rsRC.next()) {
+				String columnName = rsRC.getString(1);
+				int refID = rsRC.getInt(2);
+				int length = rsRC.getInt(3);
+				if (columnName.equalsIgnoreCase("AD_Client_ID")) {
+					p_columnsVerifiedList.add(tableName.toUpperCase() + "." + columnName.toUpperCase());
+				} else {
+					validateExternalColumn(tableName, columnName, refID, length);
+				}
+			}
+		} catch (SQLException e) {
+			throw new AdempiereException("Could not execute external query: " + sqlRemoteColumns + "\nCause = " + e.getLocalizedMessage());
+		} finally {
+			DB.close(rsRC, stmtRC);
+		}
+		p_tablesVerifiedList.add(tableName.toUpperCase());
+	}
+
+	private void validateExternalColumn(String tableName, String columnName, int refID, int length) {
+		// inform if column is not present in target (blocking as it has client data)
+		// statusUpdate("Validating column " + tableName + "." + columnName);
+		MColumn localColumn = MColumn.get(getCtx(), tableName, columnName);
+		if (localColumn == null || localColumn.getAD_Column_ID() <= 0) {
+			p_errorList.add("Column " + tableName + "." + columnName +  " doesn't exist");
+			return;
+		}
+
+		// inform if db type is different (blocking as it has client data)
+		if (refID <= MTable.MAX_OFFICIAL_ID
+				&& localColumn.getAD_Reference_ID() <= MTable.MAX_OFFICIAL_ID 
+				&& refID != localColumn.getAD_Reference_ID()) {
+			p_errorList.add("Column " + tableName + "." + columnName +  " has different type in dictionary, external: " + refID + ", local: " + localColumn.getAD_Reference_ID());
+		}
+
+		// inform blocking if lengths are different
+		if (length != localColumn.getFieldLength()) {
+			p_errorList.add("Column " + tableName + "." + columnName +  " has different length in dictionary, external: " + length + ", local: " + localColumn.getFieldLength());
+		}
+
+		StringBuilder sqlDataNotNullInColumn = new StringBuilder()
+				.append("SELECT COUNT(*) FROM ").append(tableName)
+				.append(" JOIN AD_Client ON (").append(tableName).append(".AD_Client_ID=AD_Client.AD_Client_ID)")
+				.append(" WHERE ").append(tableName).append(".").append(columnName).append(" IS NOT NULL")
+				.append(" AND ").append(p_whereClient);
+		// validate if unsupported types have data
+		if (refID == DisplayType.SingleSelectionGrid || refID == DisplayType.MultipleSelectionGrid) {
+			int cntMI = countInExternal(sqlDataNotNullInColumn.toString());
+			if (cntMI > 0) {
+				// TODO: Implement ID conversion for multi-ID column types
+				throw new AdempiereUserError("There is data in unsupported Multi-ID column " + tableName + "." + columnName);
+			}
+		}
+		if (refID > MTable.MAX_OFFICIAL_ID) {
+			int cntET = countInExternal(sqlDataNotNullInColumn.toString());
+			if (cntET > 0) {
+				// TODO: Implement support for non-official data types (must implement how to obtain the foreign table with MColumn.getReferenceTableName)
+				throw new AdempiereUserError("There is data in unsupported non-official data type for column " + tableName + "." + columnName);
+			}
+		}
+
+		// when the column is a foreign key
+		String foreignTable = localColumn.getReferenceTableName();
+		if (foreignTable != null 
+				&& (foreignTable.equalsIgnoreCase(tableName) || "AD_PInstance_Log".equalsIgnoreCase(tableName))) {
+			foreignTable = "";
+		} else if ("C_BPartner".equalsIgnoreCase(tableName) && "AD_OrgBP_ID".equalsIgnoreCase(columnName)) {
+			// Special case for C_BPartner.AD_OrgBP_ID defined as Button in dictionary
+			foreignTable = "AD_Org";
+		}
+		if (! Util.isEmpty(foreignTable)) {
+			// verify all foreign keys pointing to a different client
+			// if pointing to a different client non-system
+			//   inform cross-client data corruption error
+			// if pointing to system
+			//   add to list of columns with system foreign keys
+			//   inform if the system record is not in target database using uuid - blocking
+			String uuidCol = MTable.getUUIDColumnName(foreignTable);
+			StringBuilder sqlForeignClientSB = new StringBuilder();
+			if ("AD_Ref_List".equalsIgnoreCase(foreignTable)) {
+				sqlForeignClientSB
+				.append("SELECT DISTINCT AD_Ref_List.AD_Client_ID, AD_Ref_List.AD_Ref_List_ID, AD_Ref_List.").append(uuidCol)
+				.append(" FROM ").append(tableName);
+				if (! "AD_Client".equalsIgnoreCase(tableName)) {
+					sqlForeignClientSB.append(" JOIN AD_Client ON (").append(tableName).append(".AD_Client_ID=AD_Client.AD_Client_ID)");
+				}
+				sqlForeignClientSB.append(" JOIN AD_Ref_List ON (").append(tableName).append(".").append(columnName).append("=AD_Ref_List.");
+				if ("AD_Ref_List_ID".equalsIgnoreCase(columnName)) {
+					sqlForeignClientSB.append("AD_Ref_List_ID");
+				} else {
+					sqlForeignClientSB.append("Value");
+				}
+				sqlForeignClientSB.append(" AND AD_Ref_List.AD_Reference_ID=")
+				.append(" (SELECT AD_Column.AD_Reference_Value_ID FROM AD_Column")
+				.append(" JOIN AD_Table ON (AD_Column.AD_Table_ID=AD_Table.AD_Table_ID)")
+				.append(" WHERE UPPER(AD_Table.TableName)='").append(tableName.toUpperCase())
+				.append("' AND UPPER(AD_Column.ColumnName)='").append(columnName.toUpperCase()).append("'))")
+				.append(" WHERE ").append(p_whereClient)
+				.append(" AND ").append(foreignTable).append(".AD_Client_ID!=").append(tableName).append(".AD_Client_ID")
+				.append(" ORDER BY 2");
+			} else {
+				sqlForeignClientSB
+				.append("SELECT DISTINCT ").append(foreignTable).append(".AD_Client_ID, ")
+				.append(foreignTable).append(".").append(foreignTable).append("_ID, ")
+				.append(foreignTable).append(".").append(uuidCol)
+				.append(" FROM ").append(tableName);
+				if (! "AD_Client".equalsIgnoreCase(tableName)) {
+					sqlForeignClientSB.append(" JOIN AD_Client ON (").append(tableName).append(".AD_Client_ID=AD_Client.AD_Client_ID)");
+				}
+				sqlForeignClientSB.append(" JOIN ").append(foreignTable)
+				.append(" ON (").append(tableName).append(".").append(columnName).append("=").append(foreignTable).append(".");
+				if ("AD_Language".equalsIgnoreCase(foreignTable) && !columnName.equalsIgnoreCase("AD_Language_ID")) {
+					sqlForeignClientSB.append("AD_Language");
+				} else if ("AD_EntityType".equalsIgnoreCase(foreignTable) && !columnName.equalsIgnoreCase("AD_EntityType_ID")) {
+					sqlForeignClientSB.append("EntityType");
+				} else {
+					sqlForeignClientSB.append(foreignTable).append("_ID");
+				}
+				sqlForeignClientSB.append(")")
+				.append(" WHERE ").append(p_whereClient)
+				.append(" AND ").append(foreignTable).append(".AD_Client_ID!=").append(tableName).append(".AD_Client_ID")
+				.append(" ORDER BY 2");
+			}
+			String sqlForeignClient = DB.getDatabase().convertStatement(sqlForeignClientSB.toString());
+			PreparedStatement stmtFC = null;
+			ResultSet rsFC = null;
+			try {
+				stmtFC = externalConn.prepareStatement(sqlForeignClient, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+				rsFC = stmtFC.executeQuery();
+				while (rsFC.next()) {
+					int clientID = rsFC.getInt(1);
+					int foreignID = rsFC.getInt(2);
+					String foreignUU = rsFC.getString(3);
+					if (clientID > 0) {
+						p_errorList.add("Column " + tableName + "." + columnName +  " has invalid cross-client reference to client " + clientID + " on ID=" + foreignID);
+						continue;
+					}
+					if (foreignID > MTable.MAX_OFFICIAL_ID) {
+						if (! p_idSystemConversionList.contains(foreignTable.toUpperCase() + "." + foreignID)) {
+							int localID = getFromUUID(foreignTable, uuidCol, tableName, columnName, foreignUU, foreignID);
+							if (localID < 0) {
+								continue;
+							}
+						}
+					}
+				}
+			} catch (SQLException e) {
+				throw new AdempiereException("Could not execute external query: " + sqlForeignClient + "\nCause = " + e.getLocalizedMessage());
+			} finally {
+				DB.close(rsFC, stmtFC);
+			}
+		}
+		// add to the list of verified columns
+		p_columnsVerifiedList.add(tableName.toUpperCase() + "." + columnName.toUpperCase());
+	}
+
+	private int countInExternal(String sql) {
+		int cnt = 0;
+		sql = DB.getDatabase().convertStatement(sql);
+		PreparedStatement stmt = null;
+		ResultSet rs = null;
+		try {
+			stmt = externalConn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+			rs = stmt.executeQuery();
+			if (rs.next())
+				cnt = rs.getInt(1);
+		} catch (SQLException e) {
+			throw new AdempiereException("Could not execute external query: " + sql + "\nCause = " + e.getLocalizedMessage());
+		} finally {
+			DB.close(rs, stmt);
+		}
+		return cnt;
+	}
+
+	private void moveClient() {
+		// first do the validation, process cannot be executed if there are blocking situations
+		// validation construct the list of tables and columns to process
+		// NOTE that the whole process will be done in a single transaction, foreign keys will be validated on commit
+
+		List<MTable> tables = new Query(getCtx(), MTable.Table_Name,
+				"IsView='N' AND " + p_excludeTablesWhere,
+				get_TrxName())
+				.setOnlyActiveRecords(true)
+				.setOrderBy("TableName")
+				.list();
+
+		// create/verify the ID conversions
+		for (MTable table : tables) {
+			String tableName = table.getTableName();
+			if (! p_tablesVerifiedList.contains(tableName.toUpperCase())) {
+				continue;
+			}
+			if (! p_columnsVerifiedList.contains(tableName.toUpperCase() + "." + tableName.toUpperCase() + "_ID")) {
+				continue;
+			}
+			statusUpdate("Converting IDs for table " + tableName);
+			StringBuilder selectVerifyIdSB = new StringBuilder()
+					.append("SELECT ").append(tableName).append("_ID FROM ").append(tableName)
+					.append(" WHERE ").append(tableName).append("_ID=?");
+			StringBuilder selectGetIdsSB = new StringBuilder()
+					.append("SELECT ").append(tableName).append(".").append(tableName).append("_ID FROM ").append(tableName);
+			if (! "AD_Client".equalsIgnoreCase(tableName)) {
+				selectGetIdsSB.append(" JOIN AD_Client ON (").append(tableName).append(".AD_Client_ID=AD_Client.AD_Client_ID)");
+			}
+			selectGetIdsSB.append(" WHERE ").append(p_whereClient)
+			.append(" ORDER BY ").append(tableName).append("_ID");
+			String selectGetIds = DB.getDatabase().convertStatement(selectGetIdsSB.toString());
+			PreparedStatement stmtGI = null;
+			ResultSet rsGI = null;
+			try {
+				stmtGI = externalConn.prepareStatement(selectGetIds, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+				rsGI = stmtGI.executeQuery();
+				while (rsGI.next()) {
+					int sourceID = rsGI.getInt(1);
+					int targetID = -1;
+					if (p_tablesToPreserveIDsList.contains(tableName.toUpperCase())) {
+						int localID = DB.getSQLValueEx(get_TrxName(), selectVerifyIdSB.toString(), sourceID);
+						if (localID < 0) {
+							targetID = sourceID;
+						} else {
+							throw new AdempiereException("In " + tableName + "." + tableName + "_ID already exist the ID=" + sourceID);
+						}
+					} else {
+						targetID = DB.getNextID(getAD_Client_ID(), tableName, get_TrxName());
+					}
+					if (targetID >= 0) {
+						DB.executeUpdateEx(insertConversionId,
+								new Object[] {getAD_PInstance_ID(), tableName.toUpperCase(), sourceID, targetID},
+								get_TrxName());
+					}
+				}
+			} catch (SQLException e) {
+				throw new AdempiereException("Could not execute external query: " + selectGetIds + "\nCause = " + e.getLocalizedMessage());
+			} finally {
+				DB.close(rsGI, stmtGI);
+			}
+
+		}
+		
+		try {
+			commitEx(); // commit the T_MoveClient table to analyze potential problems
+		} catch (SQLException e1) {
+			throw new AdempiereException(e1);
+		} 
+
+		// get the source data and insert into target converting the IDs
+		for (MTable table : tables) {
+			String tableName = table.getTableName();
+			if (! p_tablesVerifiedList.contains(tableName.toUpperCase())) {
+				continue;
+			}
+			statusUpdate("Inserting data for table " + tableName);
+			StringBuilder valuesSB = new StringBuilder();
+			StringBuilder columnsSB = new StringBuilder();
+			StringBuilder qColumnsSB = new StringBuilder();
+			int ncols = 0;
+			List<MColumn> columns = new ArrayList<MColumn>();
+			for (MColumn column : table.getColumns(false)) {
+				if (!column.isActive() || column.getColumnSQL() != null) {
+					continue;
+				}
+				String columnName = column.getColumnName();
+				if (! p_columnsVerifiedList.contains(tableName.toUpperCase() + "." + columnName.toUpperCase())) {
+					continue;
+				}
+				if (columnsSB.length() > 0) {
+					qColumnsSB.append(",");
+					columnsSB.append(",");
+					valuesSB.append(",");
+				}
+				qColumnsSB.append(tableName).append(".").append(columnName);
+				columnsSB.append(columnName);
+				valuesSB.append("?");
+				columns.add(column);
+				ncols++;
+			}
+			StringBuilder insertSB = new StringBuilder()
+					.append("INSERT INTO ").append(tableName).append("(").append(columnsSB).append(") VALUES (").append(valuesSB).append(")");
+			StringBuilder selectGetDataSB = new StringBuilder()
+					.append("SELECT ").append(qColumnsSB)
+					.append(" FROM ").append(tableName);
+			if ("AD_PInstance_Log".equalsIgnoreCase(tableName)) {
+				selectGetDataSB.append(" JOIN AD_PInstance ON (AD_PInstance_Log.AD_PInstance_ID=AD_PInstance.AD_PInstance_ID)");
+				selectGetDataSB.append(" JOIN AD_Client ON (AD_PInstance.AD_Client_ID=AD_Client.AD_Client_ID)");
+			} else if (! "AD_Client".equalsIgnoreCase(tableName)) {
+				selectGetDataSB.append(" JOIN AD_Client ON (").append(tableName).append(".AD_Client_ID=AD_Client.AD_Client_ID)");
+			}
+			selectGetDataSB.append(" WHERE ").append(p_whereClient);
+			String selectGetData = DB.getDatabase().convertStatement(selectGetDataSB.toString());
+			PreparedStatement stmtGD = null;
+			ResultSet rsGD = null;
+			Object[] parameters = new Object[ncols];
+			try {
+				stmtGD = externalConn.prepareStatement(selectGetData, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+				rsGD = stmtGD.executeQuery();
+				while (rsGD.next()) {
+					boolean insertRecord = true;
+					for (int i = 0; i < ncols; i++) {
+						MColumn column = columns.get(i);
+						String columnName = column.getColumnName();
+						String convertTable = column.getReferenceTableName();
+						if ((tableName + "_ID").equalsIgnoreCase(columnName)) {
+							convertTable = tableName;
+						} else if ("C_BPartner".equalsIgnoreCase(tableName) && "AD_OrgBP_ID".equalsIgnoreCase(columnName)) {
+							// Special case for C_BPartner.AD_OrgBP_ID defined as Button in dictionary
+							convertTable = "AD_Org";
+						} else if (convertTable != null
+								&& ("AD_Ref_List".equalsIgnoreCase(convertTable)
+										|| "AD_Language".equalsIgnoreCase(columnName)
+										|| "EntityType".equalsIgnoreCase(columnName))) {
+							convertTable = "";
+						} else if ("Record_ID".equalsIgnoreCase(columnName) && table.getColumnIndex("AD_Table_ID") > 0) {
+							// Special case for Record_ID
+							int tableId = rsGD.getInt("AD_Table_ID");
+							if (tableId > 0) {
+								convertTable = getExternalTableName(tableId);
+							} else {
+								convertTable = "";
+							}
+						} else if ("AD_Preference".equalsIgnoreCase(tableName) && "Value".equalsIgnoreCase(columnName)) {
+							// Special case for AD_Preference.Value
+							String att = rsGD.getString("Attribute");
+							if (att.toUpperCase().endsWith("_ID")) {
+								convertTable = att.substring(0, att.length()-3);
+								if ("C_DocTypeTarget".equals(convertTable)) {
+									convertTable = "C_DocType";
+								}
+							} else {
+								convertTable = "";
+							}
+						}
+						if (! Util.isEmpty(convertTable)) {
+							// Foreign - potential ID conversion
+							int id = rsGD.getInt(i + 1);
+							if (rsGD.wasNull()) {
+								parameters[i] = null;
+							} else {
+								if (id >= MTable.MAX_OFFICIAL_ID) {
+									int convertedId = -1;
+									final String query = "SELECT Target_ID FROM T_MoveClient WHERE AD_PInstance_ID=? AND TableName=? AND Source_ID=?";
+									try {
+										convertedId = DB.getSQLValueEx(get_TrxName(),
+												query,
+												getAD_PInstance_ID(), convertTable.toUpperCase(), id);
+									} catch (Exception e) {
+										throw new AdempiereException("Could not execute query: " + query + "\nCause = " + e.getLocalizedMessage());
+									}
+									if (convertedId < 0) {
+										// not found in the table - try to get it again - could be missed in first pass
+										convertedId = getLocalIDFor(convertTable, id);
+										if (convertedId < 0) {
+											if ("Record_ID".equalsIgnoreCase(columnName) && table.getColumnIndex("AD_Table_ID") > 0) {
+												if (p_tablesToExcludeList.contains(convertTable.toUpperCase())) {
+													// record is pointing to a table that is not included, ignore it
+													insertRecord = false;
+													break;
+												}
+											}
+											throw new AdempiereException("Found orphan record in " + tableName + "." + columnName + ": " + id + " related to table " + convertTable);
+										}
+									}
+									id = convertedId;
+								}
+								if ("AD_Preference".equalsIgnoreCase(tableName) && "Value".equalsIgnoreCase(columnName)) {
+									parameters[i] = String.valueOf(id);
+								} else {
+									parameters[i] = id;
+								}
+							}
+						} else {
+							parameters[i] = rsGD.getObject(i + 1);
+							if (rsGD.wasNull()) {
+								parameters[i] = null;
+							}
+						}
+					}
+					if (insertRecord) {
+						try {
+							DB.executeUpdateEx(insertSB.toString(), parameters, get_TrxName());
+						} catch (Exception e) {
+							throw new AdempiereException("Could not execute: " + insertSB + "\nCause = " + e.getLocalizedMessage());
+						}
+					}
+				}
+			} catch (SQLException e) {
+				throw new AdempiereException("Could not execute external query: " + selectGetData + "\nCause = " + e.getLocalizedMessage());
+			} finally {
+				DB.close(rsGD, stmtGD);
+			}
+
+		}
+
+		// commit - here it can throw errors because of foreign keys, verify and inform
+		statusUpdate("Committing.  Validating foreign keys");
+		try {
+			commitEx();
+		} catch (SQLException e) {
+			throw new AdempiereException("Could not commit,\nCause: " + e.getLocalizedMessage());
+		}
+	}
+
+	private String getExternalTableName(int tableId) {
+		String tableName = null;
+		String sql = DB.getDatabase().convertStatement("SELECT TableName FROM AD_Table WHERE AD_Table_ID=?");
+		PreparedStatement stmt = null;
+		ResultSet rs = null;
+		try {
+			stmt = externalConn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+			stmt.setInt(1, tableId);
+			rs = stmt.executeQuery();
+			if (rs.next())
+				tableName = rs.getString(1);
+		} catch (SQLException e) {
+			throw new AdempiereException("Could not execute external query: " + sql + "\nCause = " + e.getLocalizedMessage());
+		} finally {
+			DB.close(rs, stmt);
+		}
+		return tableName;
+	}
+
+	private void checkSequences() {
+		for (String tableName : p_tablesToPreserveIDsList) {
+			MSequence seq = MSequence.get(getCtx(), tableName, get_TrxName());
+			if (seq != null) {
+				seq.validateTableIDValue(); // ignore output messages
+			}
+		}
+	}
+
+	private int getLocalIDFor(String tableName, int foreignId) {
+		String uuidCol = MTable.getUUIDColumnName(tableName);
+		StringBuilder sqlRemoteUUSB = new StringBuilder()
+				.append("SELECT ").append(uuidCol).append(" FROM ").append(tableName)
+				.append(" WHERE ").append(tableName).append("_ID=?");
+		String sqlRemoteUU = DB.getDatabase().convertStatement(sqlRemoteUUSB.toString());
+		PreparedStatement stmtUU = null;
+		ResultSet rs = null;
+		String remoteUUID = null;
+		try {
+			stmtUU = externalConn.prepareStatement(sqlRemoteUU, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+			stmtUU.setInt(1, foreignId);
+			rs = stmtUU.executeQuery();
+			if (rs.next())
+				remoteUUID = rs.getString(1);
+		} catch (SQLException e) {
+			throw new AdempiereException("Could not execute external query: " + sqlRemoteUU + "\nCause = " + e.getLocalizedMessage());
+		} finally {
+			DB.close(rs, stmtUU);
+		}
+		int localID = -1;
+		if (remoteUUID != null) {
+			localID = getFromUUID(tableName, uuidCol, null, null, remoteUUID, foreignId);
+		}
+		return localID;
+	}
+
+	private int getFromUUID(String foreignTable, String uuidCol, String tableName, String columnName, String foreignUU, int foreignID) {
+		StringBuilder sqlCheckLocalUU = new StringBuilder()
+				.append("SELECT ").append(foreignTable).append("_ID FROM ").append(foreignTable)
+				.append(" WHERE ").append(uuidCol).append("=?");
+		int localID = DB.getSQLValueEx(get_TrxName(), sqlCheckLocalUU.toString(), foreignUU);
+		if (localID < 0) {
+			p_errorList.add("Column " + tableName + "." + columnName +  " has system reference not convertible, "
+					+ foreignTable + "." + uuidCol + "=" + foreignUU);
+			return -1;
+		}
+		DB.executeUpdateEx(insertConversionId,
+				new Object[] {getAD_PInstance_ID(), foreignTable.toUpperCase(), foreignID, localID},
+				get_TrxName());
+		p_idSystemConversionList.add(foreignTable.toUpperCase() + "." + foreignID);
+		return localID;
+	}
+
+}

From 2246afb9ff34fa02a76821c8f5ac8a9e06d87f44 Mon Sep 17 00:00:00 2001
From: Carlos Ruiz <carg67@gmail.com>
Date: Thu, 14 Mar 2019 01:34:07 +0100
Subject: [PATCH 5/9] IDEMPIERE-3916 Process to move client between databases /
 FHEG-599 / Additional process to migrate ID/UUID

---
 .../oracle/201903140056_IDEMPIERE-3916.sql    | 227 ++++++++++++++
 .../201903140056_IDEMPIERE-3916.sql           | 224 ++++++++++++++
 .../src/org/idempiere/process/MigraID.java    | 278 ++++++++++++++++++
 3 files changed, 729 insertions(+)
 create mode 100644 migration/i6.2/oracle/201903140056_IDEMPIERE-3916.sql
 create mode 100644 migration/i6.2/postgresql/201903140056_IDEMPIERE-3916.sql
 create mode 100644 org.adempiere.base/src/org/idempiere/process/MigraID.java

diff --git a/migration/i6.2/oracle/201903140056_IDEMPIERE-3916.sql b/migration/i6.2/oracle/201903140056_IDEMPIERE-3916.sql
new file mode 100644
index 0000000000..81af840dca
--- /dev/null
+++ b/migration/i6.2/oracle/201903140056_IDEMPIERE-3916.sql
@@ -0,0 +1,227 @@
+SET SQLBLANKLINES ON
+SET DEFINE OFF
+
+-- IDEMPIERE-3916 Process to migrate IDs
+-- Mar 14, 2019 12:43:30 AM CET
+INSERT INTO AD_Process (AD_Process_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,IsReport,Value,IsDirectPrint,Classname,AccessLevel,EntityType,Statistic_Count,Statistic_Seconds,IsBetaFunctionality,IsServerProcess,ShowHelp,CopyFromProcess,AD_Process_UU) VALUES (200111,0,0,'Y',TO_DATE('2019-03-14 00:43:29','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-14 00:43:29','YYYY-MM-DD HH24:MI:SS'),100,'Migrate ID','Process to migrate an ID or a UUID','N','MigrateID','N','org.idempiere.process.MigraID','4','D',0,0,'N','N','Y','N','81e52777-5d7b-4a5b-b5e2-c7a4a15c38d8')
+;
+
+-- Mar 14, 2019 12:43:43 AM CET
+INSERT INTO AD_Menu (AD_Menu_ID,Name,Description,Action,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsSummary,AD_Process_ID,IsSOTrx,IsReadOnly,EntityType,IsCentrallyMaintained,AD_Menu_UU) VALUES (200169,'Migrate ID','Process to migrate an ID or a UUID','P',0,0,'Y',TO_DATE('2019-03-14 00:43:43','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-14 00:43:43','YYYY-MM-DD HH24:MI:SS'),100,'N',200111,'Y','N','D','Y','f5af6aa0-8dfc-4274-a304-7a5c969b2ec8')
+;
+
+-- Mar 14, 2019 12:43:43 AM 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, 200169, 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=200169)
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=0, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=218
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=1, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=153
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=2, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=263
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=3, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=166
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=4, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=203
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=5, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53242
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=6, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=1000016
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=7, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=236
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=8, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=183
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=9, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=160
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=10, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=278
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=11, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=345
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=12, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53296
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=13, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53014
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=14, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53108
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=15, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=1000036
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=16, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=1000095
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=17, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=1000091
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=0, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=161
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=1, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=367
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=2, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=456
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=3, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=501
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=4, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=326
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=5, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=566
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=6, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=392
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=7, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=113
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=8, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=220
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=9, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=351
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=10, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=289
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=11, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=302
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=12, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=200168
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=13, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=200169
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=14, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=303
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=15, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=200047
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=16, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=200048
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=17, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=321
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=18, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=461
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=19, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53193
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=20, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=53322
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=21, Updated=SysDate WHERE AD_Tree_ID=10 AND Node_ID=383
+;
+
+-- Mar 14, 2019 12:47:49 AM CET
+INSERT INTO AD_Reference (AD_Reference_ID,Name,ValidationType,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,IsOrderByValue,AD_Reference_UU) VALUES (200165,'AD_Table with ID Column','T',0,0,'Y',TO_DATE('2019-03-14 00:47:48','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-14 00:47:48','YYYY-MM-DD HH24:MI:SS'),100,'D','N','5fc414bf-781e-4171-a543-6aa057de1a58')
+;
+
+-- Mar 14, 2019 12:49:52 AM CET
+INSERT INTO AD_Ref_Table (AD_Reference_ID,AD_Table_ID,AD_Key,AD_Display,WhereClause,OrderByClause,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsValueDisplayed,EntityType,AD_Ref_Table_UU) VALUES (200165,100,100,102,'AD_Table.IsView=''N'' AND AD_Table.IsActive=''Y'' AND EXISTS (SELECT 1 FROM AD_Column c WHERE c.AD_Table_ID=AD_Table.AD_Table_ID AND c.ColumnName=AD_Table.TableName||''_ID'' AND c.IsActive=''Y'')','AD_Table.TableName',0,0,'Y',TO_DATE('2019-03-14 00:49:52','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-14 00:49:52','YYYY-MM-DD HH24:MI:SS'),100,'N','D','62fe46c3-2b6f-4c6b-8f0d-fa05cae312c9')
+;
+
+-- Mar 14, 2019 12:50:02 AM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,Help,AD_Process_ID,SeqNo,AD_Reference_ID,AD_Reference_Value_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200264,0,0,'Y',TO_DATE('2019-03-14 00:50:02','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-14 00:50:02','YYYY-MM-DD HH24:MI:SS'),100,'Table','Database Table information','The Database Table provides the information of the table definition',200111,10,30,200165,'N',22,'Y','AD_Table_ID','Y','D',126,'6411cc15-450e-43b5-886e-1d510552b951','N')
+;
+
+-- Mar 14, 2019 12:51:17 AM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,Help,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200265,0,0,'Y',TO_DATE('2019-03-14 00:51:16','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-14 00:51:16','YYYY-MM-DD HH24:MI:SS'),100,'Record ID','Direct internal record ID','The Record ID is the internal unique identifier of a record. Please note that zooming to the record may not be successful for Orders, Invoices and Shipment/Receipts as sometimes the Sales Order type is not known.',200111,20,11,'N',22,'Y','Record_ID','Y','D',538,'e1d21139-e7d0-4501-a693-c448f4f10ae1','N')
+;
+
+-- Mar 14, 2019 12:51:47 AM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,Help,PrintName,EntityType,AD_Element_UU) VALUES (203299,0,0,'Y',TO_DATE('2019-03-14 00:51:25','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-14 00:51:25','YYYY-MM-DD HH24:MI:SS'),100,'To_Record_ID','To Record ID',NULL,NULL,'To Record ID','D','355c16ed-7b65-4d77-9802-a308e6ac24f2')
+;
+
+-- Mar 14, 2019 12:51:58 AM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200266,0,0,'Y',TO_DATE('2019-03-14 00:51:57','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-14 00:51:57','YYYY-MM-DD HH24:MI:SS'),100,'To Record ID',200111,30,11,'N',22,'N','To_Record_ID','Y','D',203299,'5b115049-5cf3-4059-938e-9e9f26f05e37','N')
+;
+
+-- Mar 14, 2019 12:54:00 AM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,DefaultValue,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted,MandatoryLogic) VALUES (200267,0,0,'Y',TO_DATE('2019-03-14 00:54:00','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-14 00:54:00','YYYY-MM-DD HH24:MI:SS'),100,'Source UUID','UUID from the source client',200111,40,10,'N',36,'N','@Record_ID:0@=0','Source_UUID','Y','D',202602,'cff91029-d160-4577-8192-6c2eef52be11','N','@Record_ID:0@=0')
+;
+
+-- Mar 14, 2019 12:54:18 AM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,DefaultValue,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted,MandatoryLogic) VALUES (200268,0,0,'Y',TO_DATE('2019-03-14 00:54:17','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-03-14 00:54:17','YYYY-MM-DD HH24:MI:SS'),100,'Target UUID','New UUID created by the pack in client',200111,50,10,'N',36,'N','@Record_ID:0@=0','Target_UUID','Y','D',202603,'442badef-4200-45e3-9850-c62b4fdc6631','N',NULL)
+;
+
+-- Mar 14, 2019 12:54:55 AM CET
+UPDATE AD_Process_Para SET IsMandatory='N', DisplayLogic='@Source_UUID@=''''', MandatoryLogic='@Source_UUID@=''''',Updated=TO_DATE('2019-03-14 00:54:55','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200265
+;
+
+-- Mar 14, 2019 12:55:03 AM CET
+UPDATE AD_Process_Para SET DisplayLogic='@Source_UUID@=''''',Updated=TO_DATE('2019-03-14 00:55:03','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200266
+;
+
+-- Mar 14, 2019 12:55:11 AM CET
+UPDATE AD_Process_Para SET DefaultValue=NULL, DisplayLogic='@Record_ID:0@=0',Updated=TO_DATE('2019-03-14 00:55:11','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200267
+;
+
+-- Mar 14, 2019 12:55:18 AM CET
+UPDATE AD_Process_Para SET DefaultValue=NULL, DisplayLogic='@Record_ID:0@=0',Updated=TO_DATE('2019-03-14 00:55:18','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200268
+;
+
+SELECT register_migration_script('201903140056_IDEMPIERE-3916.sql') FROM dual
+;
+
diff --git a/migration/i6.2/postgresql/201903140056_IDEMPIERE-3916.sql b/migration/i6.2/postgresql/201903140056_IDEMPIERE-3916.sql
new file mode 100644
index 0000000000..1c06819a24
--- /dev/null
+++ b/migration/i6.2/postgresql/201903140056_IDEMPIERE-3916.sql
@@ -0,0 +1,224 @@
+-- IDEMPIERE-3916 Process to migrate IDs
+-- Mar 14, 2019 12:43:30 AM CET
+INSERT INTO AD_Process (AD_Process_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,IsReport,Value,IsDirectPrint,Classname,AccessLevel,EntityType,Statistic_Count,Statistic_Seconds,IsBetaFunctionality,IsServerProcess,ShowHelp,CopyFromProcess,AD_Process_UU) VALUES (200111,0,0,'Y',TO_TIMESTAMP('2019-03-14 00:43:29','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-14 00:43:29','YYYY-MM-DD HH24:MI:SS'),100,'Migrate ID','Process to migrate an ID or a UUID','N','MigrateID','N','org.idempiere.process.MigraID','4','D',0,0,'N','N','Y','N','81e52777-5d7b-4a5b-b5e2-c7a4a15c38d8')
+;
+
+-- Mar 14, 2019 12:43:43 AM CET
+INSERT INTO AD_Menu (AD_Menu_ID,Name,Description,"action",AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsSummary,AD_Process_ID,IsSOTrx,IsReadOnly,EntityType,IsCentrallyMaintained,AD_Menu_UU) VALUES (200169,'Migrate ID','Process to migrate an ID or a UUID','P',0,0,'Y',TO_TIMESTAMP('2019-03-14 00:43:43','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-14 00:43:43','YYYY-MM-DD HH24:MI:SS'),100,'N',200111,'Y','N','D','Y','f5af6aa0-8dfc-4274-a304-7a5c969b2ec8')
+;
+
+-- Mar 14, 2019 12:43:43 AM 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, 200169, 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=200169)
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=0, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=218
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=1, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=153
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=2, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=263
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=3, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=166
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=4, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=203
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=5, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53242
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=6, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=1000016
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=7, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=236
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=8, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=183
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=9, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=160
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=10, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=278
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=11, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=345
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=12, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53296
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=13, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53014
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=14, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53108
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=15, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=1000036
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=16, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=1000095
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=0, SeqNo=17, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=1000091
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=0, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=161
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=1, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=367
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=2, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=456
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=3, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=501
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=4, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=326
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=5, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=566
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=6, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=392
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=7, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=113
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=8, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=220
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=9, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=351
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=10, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=289
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=11, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=302
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=12, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=200168
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=13, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=200169
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=14, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=303
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=15, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=200047
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=16, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=200048
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=17, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=321
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=18, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=461
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=19, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53193
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=20, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=53322
+;
+
+-- Mar 14, 2019 12:44:04 AM CET
+UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=21, Updated=statement_timestamp() WHERE AD_Tree_ID=10 AND Node_ID=383
+;
+
+-- Mar 14, 2019 12:47:49 AM CET
+INSERT INTO AD_Reference (AD_Reference_ID,Name,ValidationType,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,IsOrderByValue,AD_Reference_UU) VALUES (200165,'AD_Table with ID Column','T',0,0,'Y',TO_TIMESTAMP('2019-03-14 00:47:48','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-14 00:47:48','YYYY-MM-DD HH24:MI:SS'),100,'D','N','5fc414bf-781e-4171-a543-6aa057de1a58')
+;
+
+-- Mar 14, 2019 12:49:52 AM CET
+INSERT INTO AD_Ref_Table (AD_Reference_ID,AD_Table_ID,AD_Key,AD_Display,WhereClause,OrderByClause,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsValueDisplayed,EntityType,AD_Ref_Table_UU) VALUES (200165,100,100,102,'AD_Table.IsView=''N'' AND AD_Table.IsActive=''Y'' AND EXISTS (SELECT 1 FROM AD_Column c WHERE c.AD_Table_ID=AD_Table.AD_Table_ID AND c.ColumnName=AD_Table.TableName||''_ID'' AND c.IsActive=''Y'')','AD_Table.TableName',0,0,'Y',TO_TIMESTAMP('2019-03-14 00:49:52','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-14 00:49:52','YYYY-MM-DD HH24:MI:SS'),100,'N','D','62fe46c3-2b6f-4c6b-8f0d-fa05cae312c9')
+;
+
+-- Mar 14, 2019 12:50:02 AM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,Help,AD_Process_ID,SeqNo,AD_Reference_ID,AD_Reference_Value_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200264,0,0,'Y',TO_TIMESTAMP('2019-03-14 00:50:02','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-14 00:50:02','YYYY-MM-DD HH24:MI:SS'),100,'Table','Database Table information','The Database Table provides the information of the table definition',200111,10,30,200165,'N',22,'Y','AD_Table_ID','Y','D',126,'6411cc15-450e-43b5-886e-1d510552b951','N')
+;
+
+-- Mar 14, 2019 12:51:17 AM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,Help,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200265,0,0,'Y',TO_TIMESTAMP('2019-03-14 00:51:16','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-14 00:51:16','YYYY-MM-DD HH24:MI:SS'),100,'Record ID','Direct internal record ID','The Record ID is the internal unique identifier of a record. Please note that zooming to the record may not be successful for Orders, Invoices and Shipment/Receipts as sometimes the Sales Order type is not known.',200111,20,11,'N',22,'Y','Record_ID','Y','D',538,'e1d21139-e7d0-4501-a693-c448f4f10ae1','N')
+;
+
+-- Mar 14, 2019 12:51:47 AM CET
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,Help,PrintName,EntityType,AD_Element_UU) VALUES (203299,0,0,'Y',TO_TIMESTAMP('2019-03-14 00:51:25','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-14 00:51:25','YYYY-MM-DD HH24:MI:SS'),100,'To_Record_ID','To Record ID',NULL,NULL,'To Record ID','D','355c16ed-7b65-4d77-9802-a308e6ac24f2')
+;
+
+-- Mar 14, 2019 12:51:58 AM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted) VALUES (200266,0,0,'Y',TO_TIMESTAMP('2019-03-14 00:51:57','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-14 00:51:57','YYYY-MM-DD HH24:MI:SS'),100,'To Record ID',200111,30,11,'N',22,'N','To_Record_ID','Y','D',203299,'5b115049-5cf3-4059-938e-9e9f26f05e37','N')
+;
+
+-- Mar 14, 2019 12:54:00 AM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,DefaultValue,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted,MandatoryLogic) VALUES (200267,0,0,'Y',TO_TIMESTAMP('2019-03-14 00:54:00','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-14 00:54:00','YYYY-MM-DD HH24:MI:SS'),100,'Source UUID','UUID from the source client',200111,40,10,'N',36,'N','@Record_ID:0@=0','Source_UUID','Y','D',202602,'cff91029-d160-4577-8192-6c2eef52be11','N','@Record_ID:0@=0')
+;
+
+-- Mar 14, 2019 12:54:18 AM CET
+INSERT INTO AD_Process_Para (AD_Process_Para_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,AD_Process_ID,SeqNo,AD_Reference_ID,IsRange,FieldLength,IsMandatory,DefaultValue,ColumnName,IsCentrallyMaintained,EntityType,AD_Element_ID,AD_Process_Para_UU,IsEncrypted,MandatoryLogic) VALUES (200268,0,0,'Y',TO_TIMESTAMP('2019-03-14 00:54:17','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-03-14 00:54:17','YYYY-MM-DD HH24:MI:SS'),100,'Target UUID','New UUID created by the pack in client',200111,50,10,'N',36,'N','@Record_ID:0@=0','Target_UUID','Y','D',202603,'442badef-4200-45e3-9850-c62b4fdc6631','N',NULL)
+;
+
+-- Mar 14, 2019 12:54:55 AM CET
+UPDATE AD_Process_Para SET IsMandatory='N', DisplayLogic='@Source_UUID@=''''', MandatoryLogic='@Source_UUID@=''''',Updated=TO_TIMESTAMP('2019-03-14 00:54:55','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200265
+;
+
+-- Mar 14, 2019 12:55:03 AM CET
+UPDATE AD_Process_Para SET DisplayLogic='@Source_UUID@=''''',Updated=TO_TIMESTAMP('2019-03-14 00:55:03','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200266
+;
+
+-- Mar 14, 2019 12:55:11 AM CET
+UPDATE AD_Process_Para SET DefaultValue=NULL, DisplayLogic='@Record_ID:0@=0',Updated=TO_TIMESTAMP('2019-03-14 00:55:11','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200267
+;
+
+-- Mar 14, 2019 12:55:18 AM CET
+UPDATE AD_Process_Para SET DefaultValue=NULL, DisplayLogic='@Record_ID:0@=0',Updated=TO_TIMESTAMP('2019-03-14 00:55:18','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200268
+;
+
+SELECT register_migration_script('201903140056_IDEMPIERE-3916.sql') FROM dual
+;
+
diff --git a/org.adempiere.base/src/org/idempiere/process/MigraID.java b/org.adempiere.base/src/org/idempiere/process/MigraID.java
new file mode 100644
index 0000000000..be5c86ef37
--- /dev/null
+++ b/org.adempiere.base/src/org/idempiere/process/MigraID.java
@@ -0,0 +1,278 @@
+/***********************************************************************
+ * 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 - globalqss                                           *
+ * Sponsored by FH                                                     *
+ **********************************************************************/
+
+package org.idempiere.process;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.logging.Level;
+
+import org.compiere.model.MSequence;
+import org.compiere.model.MTable;
+import org.compiere.model.Query;
+import org.compiere.process.ProcessInfoParameter;
+import org.compiere.process.SvrProcess;
+import org.compiere.util.AdempiereUserError;
+import org.compiere.util.DB;
+import org.compiere.util.DisplayType;
+import org.compiere.util.Util;
+
+public class MigraID extends SvrProcess {
+
+	// Process to change the ID of a record in the whole database
+
+	private int p_AD_Table_ID = -1;
+	private int p_ID_From = -1;
+	private int p_ID_To = -1;
+	private String p_UUID_From = null;
+	private String p_UUID_To = null;
+
+	@Override
+	protected void prepare() {
+		//
+		for (ProcessInfoParameter para : getParameter()) {
+			String name = para.getParameterName();
+			if ("AD_Table_ID".equals(name)) {
+				p_AD_Table_ID  = para.getParameterAsInt();
+			} else if ("Record_ID".equals(name)) {
+				p_ID_From = para.getParameterAsInt();
+			} else if ("To_Record_ID".equals(name)) {
+				p_ID_To = para.getParameterAsInt();
+			} else if ("Source_UUID".equals(name)) {
+				p_UUID_From = para.getParameterAsString();
+			} else if ("Target_UUID".equals(name)) {
+				p_UUID_To = para.getParameterAsString();
+			} else {
+				log.log(Level.SEVERE, "Unknown Parameter: " + name);
+			}
+		}
+	}
+
+	@Override
+	protected String doIt() throws Exception {
+		if (p_ID_From <= 0 && Util.isEmpty(p_UUID_From)) {
+			throw new AdempiereUserError("Fill Record ID or UUID to convert");
+		}
+		if (p_ID_From > 0 && ! Util.isEmpty(p_UUID_From)) {
+			throw new AdempiereUserError("Record ID and UUID are excluyent, just one can be converted at the same time");
+		}
+		if (p_ID_From > 0 && p_ID_From == p_ID_To) {
+			throw new AdempiereUserError("Same ID");
+		}
+		if (! Util.isEmpty(p_UUID_From) && p_UUID_From.equals(p_UUID_To)) {
+			throw new AdempiereUserError("Same UUID");
+		}
+		MTable table = MTable.get(getCtx(), p_AD_Table_ID, get_TrxName());
+		String tableName = table.getTableName();
+		String msg = "";
+
+		if (! Util.isEmpty(p_UUID_From)) {
+			String uuidCol = MTable.getUUIDColumnName(tableName);
+			if (Util.isEmpty(p_UUID_To)) {
+				p_UUID_To = UUID.randomUUID().toString();
+			}
+			// convert UUID
+			StringBuilder updUUIDSB = new StringBuilder()
+					.append("UPDATE ").append(tableName)
+					.append(" SET ").append(uuidCol).append("=?")
+					.append(" WHERE ").append(uuidCol).append("=?");
+			int cnt = DB.executeUpdateEx(updUUIDSB.toString(), new Object[] {p_UUID_To, p_UUID_From}, get_TrxName());
+			if (cnt <= 0) {
+				msg = "@Error@: UUID " + p_UUID_From + " not found on table " + tableName;
+			} else {
+				msg = "UUID changed on table " + tableName + " from " + p_UUID_From + " to " + p_UUID_To;
+				StringBuilder sqlSB = new StringBuilder()
+						.append("SELECT  ").append(tableName).append("_ID")
+						.append(" FROM ").append(tableName)
+						.append(" WHERE ").append(uuidCol).append("=?");
+				int id = DB.getSQLValueEx(get_TrxName(), sqlSB.toString(), p_UUID_To);
+				addBufferLog(id, null, null, msg, p_AD_Table_ID, id);
+				msg = "@OK@";
+			}
+		} else {
+			String idCol = tableName + "_ID";
+			if (p_ID_To <= 0) {
+				p_ID_To = DB.getNextID(getAD_Client_ID(), tableName, get_TrxName());
+			}
+			// convert ID
+			int cnt = updID(tableName, idCol);
+			if (cnt <= 0) {
+				msg = "@Error@: ID " + p_ID_From + " not found on table " + tableName;
+			} else {
+				msg = "ID changed on table " + tableName + " from " + p_ID_From + " to " + p_ID_To;
+				addBufferLog(p_ID_From, null, null, msg, p_AD_Table_ID, p_ID_To);
+				msg = "@OK@";
+			}
+			migrateReference(tableName);
+			migrateChildren(tableName);
+			migrateRecordID();
+			migrateAD_Preference(idCol);
+			if ("C_DocType_ID".equals(idCol)) {
+				// special preference C_DocTypeTarget_ID
+				migrateAD_Preference("C_DocTypeTarget_ID");
+			}
+			// TODO: implement migration for SingleSelectionGrid and MultipleSelectionGrid
+			if (p_ID_To > p_ID_From) {
+				MSequence seq = MSequence.get(getCtx(), tableName, get_TrxName());
+				if (seq != null) {
+					seq.validateTableIDValue(); // ignore output messages
+				}
+			}
+		}
+
+		return msg;
+	}
+
+	private int updID(String tableName, String idCol) {
+		StringBuilder updIDSB = new StringBuilder()
+				.append("UPDATE ").append(tableName)
+				.append(" SET ").append(idCol).append("=?")
+				.append(" WHERE ").append(idCol).append("=?");
+		int cnt = DB.executeUpdateEx(updIDSB.toString(), new Object[] {p_ID_To, p_ID_From}, get_TrxName());
+		return cnt;
+	}
+
+	private void migrateReference(String tableName) {
+		// Special cases with direct reference
+		int refID = -1;
+		switch (tableName) {
+		case "C_Location"             : refID = DisplayType.Location;   break;
+		case "C_ValidCombination"     : refID = DisplayType.Account;    break;
+		case "M_Locator"              : refID = DisplayType.Locator;    break;
+		case "M_AttributeSetInstance" : refID = DisplayType.PAttribute; break;
+		case "S_ResourceAssignment"   : refID = DisplayType.Assignment; break;
+		case "AD_Image"               : refID = DisplayType.Image;      break;
+		case "AD_Color"               : refID = DisplayType.Color;      break;
+		case "AD_Chart"               : refID = DisplayType.Chart;      break;
+		}
+		if (refID > 0) {
+			final String selRef = ""
+					+ "SELECT t.TableName, c.ColumnName "
+					+ "FROM AD_Table t "
+					+ "JOIN AD_Column c ON (t.AD_Table_ID=c.AD_Table_ID) "
+					+ "WHERE t.IsView='N' AND t.IsActive='Y' AND c.IsActive='Y' AND c.ColumnSQL IS NULL AND c.AD_Reference_ID=? "
+					+ "ORDER BY t.TableName, c.ColumnName";
+			List<List<Object>> rows = DB.getSQLArrayObjectsEx(get_TrxName(), selRef, refID);
+			if (rows != null && rows.size() > 0) {
+				for (List<Object> row : rows) {
+					String tableRef = (String) row.get(0);
+					String columnRef = (String) row.get(1);
+					int cnt = updID(tableRef, columnRef);
+					if (cnt > 0) {
+						String msg = cnt + " reference records updated in " + tableRef + "." + columnRef;
+						addBufferLog(p_ID_From, null, null, msg, 0, 0);
+					}
+				}
+			}
+		}
+
+	}
+
+	private void migrateChildren(String tableName) {
+		final String sqlFK = ""
+				+ "SELECT t.TableName, c.ColumnName "
+				+ "FROM   AD_Table t, AD_Column c, AD_Reference r " 
+				+ "WHERE  t.AD_Table_ID = c.AD_Table_ID "
+				+ "       AND t.IsActive = 'Y' AND t.IsView = 'N' " 
+				+ "       AND c.IsActive = 'Y' AND c.ColumnSql IS NULL "
+				+ "       AND c.AD_Reference_ID = r.AD_Reference_ID "
+				+ "       AND ( c.AD_Reference_ID IN ( 19/*Table Direct*/ ) "
+				+ "              OR ( c.AD_Reference_ID IN ( 30/*Search*/ ) "
+				+ "                   AND c.AD_Reference_Value_ID IS NULL ) ) "
+				+ "       AND UPPER(c.ColumnName) = UPPER(? || '_ID') "
+				+ "UNION "
+				+ "SELECT t.TableName, c.ColumnName "
+				+ "FROM   AD_Table t, AD_Column c, AD_Reference r, AD_Ref_Table rt, AD_Table tr "
+				+ "WHERE  t.AD_Table_ID = c.AD_Table_ID "
+				+ "       AND t.IsActive = 'Y' AND t.IsView = 'N' " 
+				+ "       AND c.IsActive = 'Y' AND c.ColumnSql IS NULL "
+				+ "       AND c.AD_Reference_ID = r.AD_Reference_ID "
+				+ "       AND ( c.AD_Reference_ID IN ( 18/*Table*/ ) "
+				+ "              OR ( c.AD_Reference_ID IN ( 30/*Search*/ ) "
+				+ "                   AND c.AD_Reference_Value_ID IS NOT NULL ) ) "
+				+ "       AND c.AD_Reference_Value_ID = rt.AD_Reference_ID "
+				+ "       AND rt.AD_Table_ID = tr.AD_Table_ID "
+				+ "       AND UPPER(tr.TableName) = UPPER(?) "
+				+ "ORDER  BY 1, 2";
+		List<List<Object>> rows = DB.getSQLArrayObjectsEx(get_TrxName(), sqlFK, tableName, tableName);
+		if (rows != null && rows.size() > 0) {
+			for (List<Object> row : rows) {
+				String tableRef = (String) row.get(0);
+				String columnRef = (String) row.get(1);
+				// Special cases EntityType and AD_Language
+				if ("EntityType".equals(columnRef) || "AD_Language".equals(columnRef)) {
+					continue;
+				}
+				int cnt = updID(tableRef, columnRef);
+				if (cnt > 0) {
+					String msg = cnt + " children records updated in " + tableRef + "." + columnRef;
+					addBufferLog(p_ID_From, null, null, msg, 0, 0);
+				}
+			}
+		}
+		// Special case for C_BPartner.AD_OrgBP_ID defined as Button in dictionary
+		if ("AD_Org".equalsIgnoreCase(tableName)) {
+			String tableRef = "C_BPartner";
+			String columnRef = "AD_OrgBP_ID";
+			int cnt = updID(tableRef, columnRef);
+			if (cnt > 0) {
+				String msg = cnt + " children records updated in " + tableRef + "." + columnRef;
+				addBufferLog(p_ID_From, null, null, msg, 0, 0);
+			}
+		}
+	}
+
+	private void migrateRecordID() {
+		final String whereClause = "IsView='N' AND IsActive='Y'" + 
+				" AND EXISTS (SELECT 1 FROM AD_Column ct WHERE ct.AD_Table_ID=AD_Table.AD_Table_ID AND ct.ColumnName='AD_Table_ID' AND ct.ColumnSQL IS NULL AND ct.IsActive='Y')" + 
+				" AND EXISTS (SELECT 1 FROM AD_Column cr WHERE cr.AD_Table_ID=AD_Table.AD_Table_ID AND cr.ColumnName='Record_ID'   AND cr.ColumnSQL IS NULL AND cr.IsActive='Y')";
+		List<MTable> tablesWithRecordID = new Query(getCtx(), "AD_Table", whereClause, get_TrxName())
+				.setOrderBy("TableName")
+				.list();
+		for (MTable table : tablesWithRecordID) {
+			String tableName = table.getTableName();
+			StringBuilder updRISB = new StringBuilder()
+					.append("UPDATE ").append(tableName)
+					.append(" SET Record_ID=?")
+					.append(" WHERE Record_ID=? AND AD_Table_ID=?");
+			int cnt = DB.executeUpdateEx(updRISB.toString(), new Object[] {p_ID_To, p_ID_From, p_AD_Table_ID}, get_TrxName());
+			if (cnt > 0) {
+				String msg = cnt + " weak reference records updated in " + tableName;
+				addBufferLog(p_ID_From, null, null, msg, 0, 0);
+			}
+		}
+	}
+
+	private void migrateAD_Preference(String columnName) {
+		final String updPref = "UPDATE AD_Preference SET Value=? WHERE Value=? AND Attribute=?";
+		int cnt = DB.executeUpdateEx(updPref, new Object[] {String.valueOf(p_ID_To), String.valueOf(p_ID_From), columnName}, get_TrxName());
+		if (cnt > 0) {
+			String msg = cnt + " preference records updated in AD_Preference for " + columnName;
+			addBufferLog(p_ID_From, null, null, msg, 0, 0);
+		}
+	}
+
+}

From d7f6cc7b84946efd147c53810aba057df5785c39 Mon Sep 17 00:00:00 2001
From: Carlos Ruiz <carg67@gmail.com>
Date: Thu, 14 Mar 2019 11:44:03 +0100
Subject: [PATCH 6/9] IDEMPIERE-3916 Process to move client between databases /
 FHEG-599 / fix oracle script - increase size to 4.000

---
 .../oracle/201903131326_IDEMPIERE-3916.sql    | 44 ++++++++++++-------
 .../201903131326_IDEMPIERE-3916.sql           | 24 +++++-----
 2 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/migration/i6.2/oracle/201903131326_IDEMPIERE-3916.sql b/migration/i6.2/oracle/201903131326_IDEMPIERE-3916.sql
index 8bb6814724..9a42806cc3 100644
--- a/migration/i6.2/oracle/201903131326_IDEMPIERE-3916.sql
+++ b/migration/i6.2/oracle/201903131326_IDEMPIERE-3916.sql
@@ -233,52 +233,64 @@ CREATE UNIQUE INDEX UX_T_MoveClient ON T_MoveClient (AD_PInstance_ID,TableName,S
 ;
 
 -- Mar 13, 2019 7:28:16 PM CET
-UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:28:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200259
+UPDATE AD_Process_Para SET FieldLength=4000,Updated=TO_DATE('2019-03-13 19:28:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200259
 ;
 
 -- Mar 13, 2019 7:28:19 PM CET
-UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:28:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200260
+UPDATE AD_Process_Para SET FieldLength=4000,Updated=TO_DATE('2019-03-13 19:28:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200260
 ;
 
 -- Mar 13, 2019 7:28:22 PM CET
-UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:28:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200261
+UPDATE AD_Process_Para SET FieldLength=4000,Updated=TO_DATE('2019-03-13 19:28:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200261
 ;
 
 -- Mar 13, 2019 7:28:27 PM CET
-UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:28:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200263
+UPDATE AD_Process_Para SET FieldLength=4000,Updated=TO_DATE('2019-03-13 19:28:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200263
 ;
 
 -- Mar 13, 2019 7:29:49 PM CET
-UPDATE AD_Column SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:29:49','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5664
+UPDATE AD_Column SET FieldLength=4000,Updated=TO_DATE('2019-03-13 19:29:49','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5664
 ;
 
 -- Mar 13, 2019 7:29:51 PM CET
-ALTER TABLE AD_PInstance_Para MODIFY Info VARCHAR2(2000) DEFAULT NULL 
-;
+-- ALTER TABLE AD_PInstance_Para MODIFY Info VARCHAR2(4000) DEFAULT NULL 
+ALTER TABLE AD_PInstance_Para ADD Tmp_Info VARCHAR2(4000) DEFAULT NULL;
+UPDATE AD_PInstance_Para SET Tmp_Info = Info;
+ALTER TABLE AD_PInstance_Para DROP COLUMN Info;
+ALTER TABLE AD_PInstance_Para RENAME COLUMN Tmp_Info TO Info;
 
 -- Mar 13, 2019 7:29:59 PM CET
-UPDATE AD_Column SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:29:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5665
+UPDATE AD_Column SET FieldLength=4000,Updated=TO_DATE('2019-03-13 19:29:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5665
 ;
 
 -- Mar 13, 2019 7:30:00 PM CET
-ALTER TABLE AD_PInstance_Para MODIFY Info_To VARCHAR2(2000) DEFAULT NULL 
-;
+-- ALTER TABLE AD_PInstance_Para MODIFY Info_To VARCHAR2(4000) DEFAULT NULL 
+ALTER TABLE AD_PInstance_Para ADD Tmp_Info_To VARCHAR2(4000) DEFAULT NULL;
+UPDATE AD_PInstance_Para SET Tmp_Info_To = Info_To;
+ALTER TABLE AD_PInstance_Para DROP COLUMN Info_To;
+ALTER TABLE AD_PInstance_Para RENAME COLUMN Tmp_Info_To TO Info_To;
 
 -- Mar 13, 2019 7:30:20 PM CET
-UPDATE AD_Column SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:30:20','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2791
+UPDATE AD_Column SET FieldLength=4000,Updated=TO_DATE('2019-03-13 19:30:20','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2791
 ;
 
 -- Mar 13, 2019 7:30:21 PM CET
-ALTER TABLE AD_PInstance_Para MODIFY P_String VARCHAR2(2000) DEFAULT NULL 
-;
+-- ALTER TABLE AD_PInstance_Para MODIFY P_String VARCHAR2(4000) DEFAULT NULL 
+ALTER TABLE AD_PInstance_Para ADD Tmp_P_String VARCHAR2(4000) DEFAULT NULL;
+UPDATE AD_PInstance_Para SET Tmp_P_String = P_String;
+ALTER TABLE AD_PInstance_Para DROP COLUMN P_String;
+ALTER TABLE AD_PInstance_Para RENAME COLUMN Tmp_P_String TO P_String;
 
 -- Mar 13, 2019 7:30:28 PM CET
-UPDATE AD_Column SET FieldLength=2000,Updated=TO_DATE('2019-03-13 19:30:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2792
+UPDATE AD_Column SET FieldLength=4000,Updated=TO_DATE('2019-03-13 19:30:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2792
 ;
 
 -- Mar 13, 2019 7:30:30 PM CET
-ALTER TABLE AD_PInstance_Para MODIFY P_String_To VARCHAR2(2000) DEFAULT NULL 
-;
+-- ALTER TABLE AD_PInstance_Para MODIFY P_String_To VARCHAR2(4000) DEFAULT NULL 
+ALTER TABLE AD_PInstance_Para ADD Tmp_P_String_To VARCHAR2(4000) DEFAULT NULL;
+UPDATE AD_PInstance_Para SET Tmp_P_String_To = P_String_To;
+ALTER TABLE AD_PInstance_Para DROP COLUMN P_String_To;
+ALTER TABLE AD_PInstance_Para RENAME COLUMN Tmp_P_String_To TO P_String_To;
 
 SELECT register_migration_script('201903131326_IDEMPIERE-3916.sql') FROM dual
 ;
diff --git a/migration/i6.2/postgresql/201903131326_IDEMPIERE-3916.sql b/migration/i6.2/postgresql/201903131326_IDEMPIERE-3916.sql
index 30b90b8e97..830f388392 100644
--- a/migration/i6.2/postgresql/201903131326_IDEMPIERE-3916.sql
+++ b/migration/i6.2/postgresql/201903131326_IDEMPIERE-3916.sql
@@ -230,51 +230,51 @@ CREATE UNIQUE INDEX UX_T_MoveClient ON T_MoveClient (AD_PInstance_ID,TableName,S
 ;
 
 -- Mar 13, 2019 7:28:16 PM CET
-UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:28:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200259
+UPDATE AD_Process_Para SET FieldLength=4000,Updated=TO_TIMESTAMP('2019-03-13 19:28:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200259
 ;
 
 -- Mar 13, 2019 7:28:19 PM CET
-UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:28:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200260
+UPDATE AD_Process_Para SET FieldLength=4000,Updated=TO_TIMESTAMP('2019-03-13 19:28:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200260
 ;
 
 -- Mar 13, 2019 7:28:22 PM CET
-UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:28:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200261
+UPDATE AD_Process_Para SET FieldLength=4000,Updated=TO_TIMESTAMP('2019-03-13 19:28:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200261
 ;
 
 -- Mar 13, 2019 7:28:27 PM CET
-UPDATE AD_Process_Para SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:28:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200263
+UPDATE AD_Process_Para SET FieldLength=4000,Updated=TO_TIMESTAMP('2019-03-13 19:28:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=200263
 ;
 
 -- Mar 13, 2019 7:29:49 PM CET
-UPDATE AD_Column SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:29:49','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5664
+UPDATE AD_Column SET FieldLength=4000,Updated=TO_TIMESTAMP('2019-03-13 19:29:49','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5664
 ;
 
 -- Mar 13, 2019 7:29:51 PM CET
-INSERT INTO t_alter_column values('ad_pinstance_para','Info','VARCHAR(2000)',null,'NULL')
+INSERT INTO t_alter_column values('ad_pinstance_para','Info','VARCHAR(4000)',null,'NULL')
 ;
 
 -- Mar 13, 2019 7:29:59 PM CET
-UPDATE AD_Column SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:29:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5665
+UPDATE AD_Column SET FieldLength=4000,Updated=TO_TIMESTAMP('2019-03-13 19:29:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=5665
 ;
 
 -- Mar 13, 2019 7:30:00 PM CET
-INSERT INTO t_alter_column values('ad_pinstance_para','Info_To','VARCHAR(2000)',null,'NULL')
+INSERT INTO t_alter_column values('ad_pinstance_para','Info_To','VARCHAR(4000)',null,'NULL')
 ;
 
 -- Mar 13, 2019 7:30:20 PM CET
-UPDATE AD_Column SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:30:20','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2791
+UPDATE AD_Column SET FieldLength=4000,Updated=TO_TIMESTAMP('2019-03-13 19:30:20','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2791
 ;
 
 -- Mar 13, 2019 7:30:21 PM CET
-INSERT INTO t_alter_column values('ad_pinstance_para','P_String','VARCHAR(2000)',null,'NULL')
+INSERT INTO t_alter_column values('ad_pinstance_para','P_String','VARCHAR(4000)',null,'NULL')
 ;
 
 -- Mar 13, 2019 7:30:28 PM CET
-UPDATE AD_Column SET FieldLength=2000,Updated=TO_TIMESTAMP('2019-03-13 19:30:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2792
+UPDATE AD_Column SET FieldLength=4000,Updated=TO_TIMESTAMP('2019-03-13 19:30:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2792
 ;
 
 -- Mar 13, 2019 7:30:30 PM CET
-INSERT INTO t_alter_column values('ad_pinstance_para','P_String_To','VARCHAR(2000)',null,'NULL')
+INSERT INTO t_alter_column values('ad_pinstance_para','P_String_To','VARCHAR(4000)',null,'NULL')
 ;
 
 SELECT register_migration_script('201903131326_IDEMPIERE-3916.sql') FROM dual

From 4f321005d7d0e7122a4510e3cc2d79edbcc13125 Mon Sep 17 00:00:00 2001
From: Carlos Ruiz <carg67@gmail.com>
Date: Fri, 15 Mar 2019 18:09:39 +0100
Subject: [PATCH 7/9] IDEMPIERE-3916 / FHEG-599 / Implement migrate ID for
 nodes in tree tables

---
 .../src/org/compiere/model/MSequence.java     | 16 +++-
 .../src/org/idempiere/process/MigraID.java    | 94 ++++++++++++++++++-
 2 files changed, 103 insertions(+), 7 deletions(-)

diff --git a/org.adempiere.base/src/org/compiere/model/MSequence.java b/org.adempiere.base/src/org/compiere/model/MSequence.java
index 9b61346dd7..a47d66b2f8 100644
--- a/org.adempiere.base/src/org/compiere/model/MSequence.java
+++ b/org.adempiere.base/src/org/compiere/model/MSequence.java
@@ -54,7 +54,7 @@ public class MSequence extends X_AD_Sequence
 	/**
 	 * 
 	 */
-	private static final long serialVersionUID = 7331047665037991960L;
+	private static final long serialVersionUID = -2215317912000946608L;
 
 	/** Log Level for Next ID Call					*/
 	private static final Level LOGLEVEL = Level.ALL;
@@ -919,16 +919,22 @@ public class MSequence extends X_AD_Sequence
 		return retValue;
 	}	//	getNextNo
 
+	public String validateTableIDValue()
+	{
+		return validateTableIDValue(null);
+	}
+
 	/**
 	 * 	Validate Table Sequence Values
+	 *  trxName the Transaction
 	 *	@return true if updated
 	 */
-	public String validateTableIDValue()
+	public String validateTableIDValue(String trxName)
 	{
 		if (!isTableID())
 			return null;
 		String tableName = getName();
-		int AD_Column_ID = DB.getSQLValue(null, "SELECT MAX(c.AD_Column_ID) "
+		int AD_Column_ID = DB.getSQLValue(trxName, "SELECT MAX(c.AD_Column_ID) "
 			+ "FROM AD_Table t"
 			+ " INNER JOIN AD_Column c ON (t.AD_Table_ID=c.AD_Table_ID) "
 			+ "WHERE t.TableName='" + tableName + "'"
@@ -949,7 +955,7 @@ public class MSequence extends X_AD_Sequence
 		String sql = "SELECT MAX(" + tableName + "_ID) FROM " + tableName;
 		if (IDRangeEnd > 0)
 			sql += " WHERE " + tableName + "_ID < " + IDRangeEnd;
-		int maxTableID = DB.getSQLValue(null, sql);
+		int maxTableID = DB.getSQLValue(trxName, sql);
 		if (maxTableID < INIT_NO)
 			maxTableID = INIT_NO - 1;
 		maxTableID++;		//	Next
@@ -965,7 +971,7 @@ public class MSequence extends X_AD_Sequence
 		//	Get Max System_ID used in Table
 		sql = "SELECT MAX(" + tableName + "_ID) FROM " + tableName
 			+ " WHERE " + tableName + "_ID < " + INIT_NO;
-		int maxTableSysID = DB.getSQLValue(null, sql);
+		int maxTableSysID = DB.getSQLValue(trxName, sql);
 		if (maxTableSysID <= 0)
 			maxTableSysID = INIT_SYS_NO;
 		int currentNextSysValue = getCurrentNextSys();
diff --git a/org.adempiere.base/src/org/idempiere/process/MigraID.java b/org.adempiere.base/src/org/idempiere/process/MigraID.java
index be5c86ef37..c78c83844e 100644
--- a/org.adempiere.base/src/org/idempiere/process/MigraID.java
+++ b/org.adempiere.base/src/org/idempiere/process/MigraID.java
@@ -26,12 +26,14 @@
 
 package org.idempiere.process;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 import java.util.logging.Level;
 
 import org.compiere.model.MSequence;
 import org.compiere.model.MTable;
+import org.compiere.model.MTree;
 import org.compiere.model.Query;
 import org.compiere.process.ProcessInfoParameter;
 import org.compiere.process.SvrProcess;
@@ -113,9 +115,18 @@ public class MigraID extends SvrProcess {
 				msg = "@OK@";
 			}
 		} else {
+			boolean seqCheck = false;
 			String idCol = tableName + "_ID";
 			if (p_ID_To <= 0) {
 				p_ID_To = DB.getNextID(getAD_Client_ID(), tableName, get_TrxName());
+			} else {
+				StringBuilder sqlMaxSB = new StringBuilder()
+						.append("SELECT  MAX(").append(tableName).append("_ID)")
+						.append(" FROM ").append(tableName);
+				int maxID = DB.getSQLValueEx(get_TrxName(), sqlMaxSB.toString());
+				if (p_ID_To > maxID) {
+					seqCheck = true;
+				}
 			}
 			// convert ID
 			int cnt = updID(tableName, idCol);
@@ -130,15 +141,17 @@ public class MigraID extends SvrProcess {
 			migrateChildren(tableName);
 			migrateRecordID();
 			migrateAD_Preference(idCol);
+			migrateTrees(tableName);
 			if ("C_DocType_ID".equals(idCol)) {
 				// special preference C_DocTypeTarget_ID
 				migrateAD_Preference("C_DocTypeTarget_ID");
 			}
 			// TODO: implement migration for SingleSelectionGrid and MultipleSelectionGrid
-			if (p_ID_To > p_ID_From) {
+
+			if (seqCheck) {
 				MSequence seq = MSequence.get(getCtx(), tableName, get_TrxName());
 				if (seq != null) {
-					seq.validateTableIDValue(); // ignore output messages
+					seq.validateTableIDValue(get_TrxName()); // ignore output messages
 				}
 			}
 		}
@@ -275,4 +288,81 @@ public class MigraID extends SvrProcess {
 		}
 	}
 
+	private void migrateTrees(String tableName) {
+		switch (tableName) {
+		case "AD_Menu":
+			migraTree("AD_TreeBar", MTree.TREETYPE_Menu);
+			migraTree("AD_TreeNodeMM", MTree.TREETYPE_Menu);
+			break;
+		case "C_BPartner":
+			migraTree("AD_TreeNodeBP", MTree.TREETYPE_BPartner);
+			break;
+		case "CM_Container":
+			migraTree("AD_TreeNodeCMC", MTree.TREETYPE_CMContainer);
+			break;
+		case "CM_Media":
+			migraTree("AD_TreeNodeCMM", MTree.TREETYPE_CMMedia);
+			break;
+		case "CM_CStage":
+			migraTree("AD_TreeNodeCMS", MTree.TREETYPE_CMContainerStage);
+			break;
+		case "CM_Template":
+			migraTree("AD_TreeNodeCMT", MTree.TREETYPE_CMTemplate);
+			break;
+		case "M_Product":
+			migraTree("AD_TreeNodePR", MTree.TREETYPE_Product);
+			break;
+		case "C_ElementValue":
+			migraTree("AD_TreeNodeU1", MTree.TREETYPE_User1);
+			migraTree("AD_TreeNodeU2", MTree.TREETYPE_User2);
+			migraTree("AD_TreeNodeU3", MTree.TREETYPE_User3);
+			migraTree("AD_TreeNodeU4", MTree.TREETYPE_User4);
+			break;
+		case "AD_Org":
+			migraTree("AD_TreeNode", MTree.TREETYPE_Organization);
+			break;
+		case "M_Product_Category":
+			migraTree("AD_TreeNode", MTree.TREETYPE_ProductCategory);
+			break;
+		case "M_BOM":
+			migraTree("AD_TreeNode", MTree.TREETYPE_BoM);
+			break;
+		case "C_Campaign":
+			migraTree("AD_TreeNode", MTree.TREETYPE_Campaign);
+			break;
+		case "C_Project":
+			migraTree("AD_TreeNode", MTree.TREETYPE_Project);
+			break;
+		case "C_Activity":
+			migraTree("AD_TreeNode", MTree.TREETYPE_Activity);
+			break;
+		case "C_SalesRegion":
+			migraTree("AD_TreeNode", MTree.TREETYPE_SalesRegion);
+			break;
+		}
+		migraTree("AD_TreeNode", MTree.TREETYPE_CustomTable);
+	}
+
+	private void migraTree(String menuTable, String treeType) {
+		List<String> columns = new ArrayList<String>();
+		columns.add("Node_ID");
+		if (! "AD_TreeBar".equalsIgnoreCase(menuTable)) {
+			columns.add("Parent_ID");
+		}
+		for (String col : columns) {
+			StringBuilder sqlUpdTreeSB = new StringBuilder()
+					.append("UPDATE ").append(menuTable)
+					.append(" SET ").append(col).append("=? WHERE ").append(col).append("=? AND AD_Tree_ID IN (SELECT AD_Tree_ID FROM AD_Tree WHERE TreeType=?");
+			if (MTree.TREETYPE_CustomTable.equals(treeType)) {
+				sqlUpdTreeSB.append(" AND AD_Table_ID=").append(p_AD_Table_ID);
+			}
+			sqlUpdTreeSB.append(")");
+			int cnt = DB.executeUpdateEx(sqlUpdTreeSB.toString(), new Object[] {p_ID_To, p_ID_From, treeType}, get_TrxName());
+			if (cnt > 0) {
+				String msg = cnt + " tree records updated in " + menuTable + "." + col;
+				addBufferLog(p_ID_From, null, null, msg, 0, 0);
+			}
+		}
+	}
+
 }

From cfe1b77c1100c6dd3fe658981cbd2d4220cbb743 Mon Sep 17 00:00:00 2001
From: Carlos Ruiz <carg67@gmail.com>
Date: Fri, 15 Mar 2019 18:10:01 +0100
Subject: [PATCH 8/9] IDEMPIERE-3916 / FHEG-599 / pre-validate orphans in Move
 Client

---
 .../src/org/idempiere/process/MoveClient.java | 63 ++++++++++++++++++-
 1 file changed, 61 insertions(+), 2 deletions(-)

diff --git a/org.adempiere.base/src/org/idempiere/process/MoveClient.java b/org.adempiere.base/src/org/idempiere/process/MoveClient.java
index 41bf54f363..b86f118c46 100644
--- a/org.adempiere.base/src/org/idempiere/process/MoveClient.java
+++ b/org.adempiere.base/src/org/idempiere/process/MoveClient.java
@@ -196,7 +196,7 @@ public class MoveClient extends SvrProcess {
 			if (externalConn != null)
 				externalConn.close();
 		}
-		
+
 		checkSequences();
 
 		return "@OK@";
@@ -312,6 +312,10 @@ public class MoveClient extends SvrProcess {
 			DB.close(rsRT, stmtRT);
 		}
 
+		for (String tableName : p_tablesVerifiedList) {
+			validateOrphan(tableName);
+		}
+
 	}
 
 	private void validateExternalTable(String tableName) {
@@ -519,6 +523,61 @@ public class MoveClient extends SvrProcess {
 		p_columnsVerifiedList.add(tableName.toUpperCase() + "." + columnName.toUpperCase());
 	}
 
+	private void validateOrphan(String tableName) {
+		// most of tables don't have a foreign key for AD_Org, so better validate here for potential orphan records not enforced in DB
+		MTable table = MTable.get(getCtx(), tableName);
+		for (MColumn column : table.getColumns(false)) {
+			if (!column.isActive() || column.getColumnSQL() != null) {
+				continue;
+			}
+			String columnName = column.getColumnName();
+			if ("AD_Client_ID".equalsIgnoreCase(columnName)) {
+				continue;
+			}
+			String foreignTable = column.getReferenceTableName();
+			if ("C_BPartner".equalsIgnoreCase(tableName) && "AD_OrgBP_ID".equalsIgnoreCase(columnName)) {
+				// Special case for C_BPartner.AD_OrgBP_ID defined as Button in dictionary
+				foreignTable = "AD_Org";
+			}
+			if (! Util.isEmpty(foreignTable) && ! "AD_Ref_List".equalsIgnoreCase(foreignTable)) {
+				MTable tableFK = MTable.get(getCtx(), foreignTable);
+				if (tableFK == null || MTable.ACCESSLEVEL_SystemOnly.equals(tableFK.getAccessLevel())) {
+					continue;
+				}
+				StringBuilder sqlVerifFKSB = new StringBuilder()
+				.append("SELECT COUNT(*) ")
+				.append("FROM   AD_Table t ")
+				.append("       JOIN AD_Column c ")
+				.append("         ON ( c.AD_Table_ID = t.AD_Table_ID ) ")
+				.append("WHERE  UPPER(t.TableName)=").append(DB.TO_STRING(tableName.toUpperCase()))
+				.append("       AND UPPER(c.ColumnName)=").append(DB.TO_STRING(columnName.toUpperCase()))
+				.append("       AND ( c.FKConstraintType IS NULL OR c.FKConstraintType=").append(DB.TO_STRING(MColumn.FKCONSTRAINTTYPE_DoNotCreate)).append(")");
+				int cntFk = countInExternal(sqlVerifFKSB.toString());
+				if (cntFk > 0) {
+					statusUpdate("Validating orphans for " + table.getTableName() + "." + columnName);
+					// target database has not defined a foreign key, validate orphans
+					StringBuilder sqlExternalOrgOrphanSB = new StringBuilder()
+							.append("SELECT COUNT(*) FROM ").append(tableName);
+					if (! "AD_Client".equalsIgnoreCase(tableName)) {
+						sqlExternalOrgOrphanSB.append(" JOIN AD_Client ON (").append(tableName).append(".AD_Client_ID=AD_Client.AD_Client_ID)");
+					}
+					sqlExternalOrgOrphanSB.append(" WHERE ").append(tableName).append(".").append(columnName).append(">0 AND ")
+					.append(" ").append(tableName).append(".").append(columnName).append(" NOT IN (")
+					.append(" SELECT ").append(foreignTable).append(".").append(foreignTable).append("_ID")
+					.append(" FROM ").append(foreignTable)
+					.append(" WHERE ").append(foreignTable).append(".AD_Client_ID IN (0,").append(tableName).append(".AD_Client_ID)")
+					.append(")")
+					.append(" AND ").append(p_whereClient);
+					int cntOr = countInExternal(sqlExternalOrgOrphanSB.toString());
+					if (cntOr > 0) {
+						p_errorList.add("Column " + tableName + "." + columnName +  " has orphan records in table " + foreignTable);
+					}
+				}
+			}
+		}
+
+	}
+
 	private int countInExternal(String sql) {
 		int cnt = 0;
 		sql = DB.getDatabase().convertStatement(sql);
@@ -601,7 +660,7 @@ public class MoveClient extends SvrProcess {
 			}
 
 		}
-		
+
 		try {
 			commitEx(); // commit the T_MoveClient table to analyze potential problems
 		} catch (SQLException e1) {

From f2c7f02e31be0d38e9f359e988eeb29ad6253a7f Mon Sep 17 00:00:00 2001
From: Carlos Ruiz <carg67@gmail.com>
Date: Fri, 15 Mar 2019 18:26:15 +0100
Subject: [PATCH 9/9] IDEMPIERE-3916 / FHEG-599 / Implement move Client for
 nodes in tree tables

---
 .../src/org/idempiere/process/MoveClient.java | 101 ++++++++++++++++--
 1 file changed, 94 insertions(+), 7 deletions(-)

diff --git a/org.adempiere.base/src/org/idempiere/process/MoveClient.java b/org.adempiere.base/src/org/idempiere/process/MoveClient.java
index b86f118c46..42b0ccef6f 100644
--- a/org.adempiere.base/src/org/idempiere/process/MoveClient.java
+++ b/org.adempiere.base/src/org/idempiere/process/MoveClient.java
@@ -545,13 +545,13 @@ public class MoveClient extends SvrProcess {
 					continue;
 				}
 				StringBuilder sqlVerifFKSB = new StringBuilder()
-				.append("SELECT COUNT(*) ")
-				.append("FROM   AD_Table t ")
-				.append("       JOIN AD_Column c ")
-				.append("         ON ( c.AD_Table_ID = t.AD_Table_ID ) ")
-				.append("WHERE  UPPER(t.TableName)=").append(DB.TO_STRING(tableName.toUpperCase()))
-				.append("       AND UPPER(c.ColumnName)=").append(DB.TO_STRING(columnName.toUpperCase()))
-				.append("       AND ( c.FKConstraintType IS NULL OR c.FKConstraintType=").append(DB.TO_STRING(MColumn.FKCONSTRAINTTYPE_DoNotCreate)).append(")");
+						.append("SELECT COUNT(*) ")
+						.append("FROM   AD_Table t ")
+						.append("       JOIN AD_Column c ")
+						.append("         ON ( c.AD_Table_ID = t.AD_Table_ID ) ")
+						.append("WHERE  UPPER(t.TableName)=").append(DB.TO_STRING(tableName.toUpperCase()))
+						.append("       AND UPPER(c.ColumnName)=").append(DB.TO_STRING(columnName.toUpperCase()))
+						.append("       AND ( c.FKConstraintType IS NULL OR c.FKConstraintType=").append(DB.TO_STRING(MColumn.FKCONSTRAINTTYPE_DoNotCreate)).append(")");
 				int cntFk = countInExternal(sqlVerifFKSB.toString());
 				if (cntFk > 0) {
 					statusUpdate("Validating orphans for " + table.getTableName() + "." + columnName);
@@ -741,6 +741,48 @@ public class MoveClient extends SvrProcess {
 							} else {
 								convertTable = "";
 							}
+						} else if ("Node_ID".equalsIgnoreCase(columnName) && "AD_TreeBar".equalsIgnoreCase(tableName)) {
+							// Special case for AD_TreeBar.Node_ID
+							convertTable = "AD_Menu";
+						} else if (("Node_ID".equalsIgnoreCase(columnName) || "Parent_ID".equalsIgnoreCase(columnName))
+								&& "AD_TreeNodeMM".equalsIgnoreCase(tableName)) {
+							// Special case for AD_TreeNodeMM.Node/Parent_ID
+							convertTable = "AD_Menu";
+						} else if (("Node_ID".equalsIgnoreCase(columnName) || "Parent_ID".equalsIgnoreCase(columnName))
+								&& "AD_TreeNodeBP".equalsIgnoreCase(tableName)) {
+							// Special case for AD_TreeNodeBP.Node/Parent_ID
+							convertTable = "C_BPartner";
+						} else if (("Node_ID".equalsIgnoreCase(columnName) || "Parent_ID".equalsIgnoreCase(columnName))
+								&& "AD_TreeNodeCMC".equalsIgnoreCase(tableName)) {
+							// Special case for AD_TreeNodeCMC.Node/Parent_ID
+							convertTable = "CM_Container";
+						} else if (("Node_ID".equalsIgnoreCase(columnName) || "Parent_ID".equalsIgnoreCase(columnName))
+								&& "AD_TreeNodeCMM".equalsIgnoreCase(tableName)) {
+							// Special case for AD_TreeNodeCMM.Node/Parent_ID
+							convertTable = "CM_Media";
+						} else if (("Node_ID".equalsIgnoreCase(columnName) || "Parent_ID".equalsIgnoreCase(columnName))
+								&& "AD_TreeNodeCMS".equalsIgnoreCase(tableName)) {
+							// Special case for AD_TreeNodeCMS.Node/Parent_ID
+							convertTable = "CM_CStage";
+						} else if (("Node_ID".equalsIgnoreCase(columnName) || "Parent_ID".equalsIgnoreCase(columnName))
+								&& "AD_TreeNodeCMT".equalsIgnoreCase(tableName)) {
+							// Special case for AD_TreeNodeCMT.Node/Parent_ID
+							convertTable = "CM_Template";
+						} else if (("Node_ID".equalsIgnoreCase(columnName) || "Parent_ID".equalsIgnoreCase(columnName))
+								&& "AD_TreeNodePR".equalsIgnoreCase(tableName)) {
+							// Special case for AD_TreeNodePR.Node/Parent_ID
+							convertTable = "M_Product";
+						} else if (("Node_ID".equalsIgnoreCase(columnName) || "Parent_ID".equalsIgnoreCase(columnName)) 
+								&& (       "AD_TreeNodeU1".equalsIgnoreCase(tableName)
+										|| "AD_TreeNodeU2".equalsIgnoreCase(tableName) 
+										|| "AD_TreeNodeU3".equalsIgnoreCase(tableName)
+										|| "AD_TreeNodeU4".equalsIgnoreCase(tableName))) {
+							// Special case for AD_TreeNodeU*.Node/Parent_ID
+							convertTable = "C_ElementValue";
+						} else if (("Node_ID".equalsIgnoreCase(columnName) || "Parent_ID".equalsIgnoreCase(columnName)) && "AD_TreeNode".equalsIgnoreCase(tableName)) {
+							// Special case for AD_TreeNode.Node/Parent_ID - depends on AD_Tree -> TreeType and AD_Table_ID
+							int treeId = rsGD.getInt("AD_Tree_ID");
+							convertTable = getExternalTableFromTree(treeId);
 						} else if ("AD_Preference".equalsIgnoreCase(tableName) && "Value".equalsIgnoreCase(columnName)) {
 							// Special case for AD_Preference.Value
 							String att = rsGD.getString("Attribute");
@@ -823,6 +865,51 @@ public class MoveClient extends SvrProcess {
 		}
 	}
 
+	private String getExternalTableFromTree(int treeId) {
+		String tableName = null;
+		final String sqlTableTree = ""
+				+ "SELECT CASE "
+				+ "         WHEN TreeType = 'AY' THEN 'C_Activity' "
+				+ "         WHEN TreeType = 'BB' THEN 'M_BOM' "
+				+ "         WHEN TreeType = 'BP' THEN 'C_BPartner' "
+				+ "         WHEN TreeType = 'CC' THEN 'CM_Container' "
+				+ "         WHEN TreeType = 'CM' THEN 'CM_Media' "
+				+ "         WHEN TreeType = 'CS' THEN 'CM_CStage' "
+				+ "         WHEN TreeType = 'CT' THEN 'CM_Template' "
+				+ "         WHEN TreeType = 'EV' THEN 'C_ElementValue' "
+				+ "         WHEN TreeType = 'MC' THEN 'C_Campaign' "
+				+ "         WHEN TreeType = 'MM' THEN 'AD_Menu' "
+				+ "         WHEN TreeType = 'OO' THEN 'AD_Org' "
+				+ "         WHEN TreeType = 'PC' THEN 'M_Product_Category' "
+				+ "         WHEN TreeType = 'PJ' THEN 'C_Project' "
+				+ "         WHEN TreeType = 'PR' THEN 'M_Product' "
+				+ "         WHEN TreeType = 'SR' THEN 'C_SalesRegion' "
+				+ "         WHEN TreeType = 'U1' THEN 'C_ElementValue' "
+				+ "         WHEN TreeType = 'U2' THEN 'C_ElementValue' "
+				+ "         WHEN TreeType = 'U3' THEN 'C_ElementValue' "
+				+ "         WHEN TreeType = 'U4' THEN 'C_ElementValue' "
+				+ "         WHEN TreeType = 'TL' THEN AD_Table.TableName "
+				+ "         ELSE NULL "
+				+ "       END "
+				+ "FROM   AD_Tree "
+				+ "       LEFT JOIN AD_Table ON ( AD_Table.AD_Table_ID = AD_Tree.AD_Table_ID ) "
+				+ "WHERE  AD_Tree_ID = ?";
+		PreparedStatement stmt = null;
+		ResultSet rs = null;
+		try {
+			stmt = externalConn.prepareStatement(sqlTableTree, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+			stmt.setInt(1, treeId);
+			rs = stmt.executeQuery();
+			if (rs.next())
+				tableName = rs.getString(1);
+		} catch (SQLException e) {
+			throw new AdempiereException("Could not execute external query: " + sqlTableTree + "\nCause = " + e.getLocalizedMessage());
+		} finally {
+			DB.close(rs, stmt);
+		}
+		return tableName;
+	}
+
 	private String getExternalTableName(int tableId) {
 		String tableName = null;
 		String sql = DB.getDatabase().convertStatement("SELECT TableName FROM AD_Table WHERE AD_Table_ID=?");