IDEMPIERE-5586 Implement ID independent migration script (#1685)
* IDEMPIERE-5586 Implement ID independent migration script * IDEMPIERE-5586 Implement ID independent migration script - add Oracle script (99% converted by ChatGPT from PostgreSQL :)). * IDEMPIERE-5586 Implement ID independent migration script - handle official id value for foreign key reference . - add back centralized id support. * IDEMPIERE-5586 Implement ID independent migration script - minor refactoring - add support for AD_Table_ID+Record_ID usage * IDEMPIERE-5586 Implement ID independent migration script - add support for Delete - add unit test * IDEMPIERE-5586 Implement ID independent migration script - add insert_accounting and insert_tree support. * IDEMPIERE-5586 Implement ID independent migration script - add ADSortTab support. * IDEMPIERE-5586 Implement ID independent migration script - move migration script from iD11 to iD10.
This commit is contained in:
parent
a69162fff8
commit
6a66903ec6
|
@ -0,0 +1,41 @@
|
|||
CREATE OR REPLACE FUNCTION torecordid (
|
||||
p_tablename IN VARCHAR2,
|
||||
p_uu_value IN VARCHAR2
|
||||
)
|
||||
RETURN NUMBER AS
|
||||
id_column VARCHAR2(200);
|
||||
uu_column VARCHAR2(200);
|
||||
o_id NUMBER;
|
||||
BEGIN
|
||||
SELECT a.ColumnName
|
||||
INTO id_column
|
||||
FROM AD_Column a
|
||||
JOIN AD_Table b ON (a.AD_Table_ID=b.AD_Table_ID)
|
||||
WHERE a.IsActive='Y' AND a.IsKey='Y' AND lower(b.TableName) = lower(p_tablename);
|
||||
|
||||
IF (id_column IS NULL) THEN
|
||||
raise_application_error(-20001, 'ID column not found for table ' || p_tablename);
|
||||
END IF;
|
||||
|
||||
IF (length(p_tablename) <= 27) THEN
|
||||
uu_column := p_tablename || '_UU';
|
||||
ELSE
|
||||
SELECT a.ColumnName
|
||||
INTO uu_column
|
||||
FROM AD_Column a
|
||||
JOIN AD_Table b ON (a.AD_Table_ID=b.AD_Table_ID)
|
||||
WHERE a.IsActive='Y' AND a.FieldLength=36 AND lower(a.ColumnName) LIKE (lower(SUBSTR(p_tablename, 1, 27)) || '%UU')
|
||||
AND lower(b.TableName) = lower(p_tablename);
|
||||
END IF;
|
||||
|
||||
IF (uu_column IS NULL) THEN
|
||||
raise_application_error(-20002, 'UUID column not found for table ' || p_tablename);
|
||||
END IF;
|
||||
|
||||
EXECUTE IMMEDIATE 'SELECT ' || id_column || ' FROM ' || p_tablename || ' WHERE ' || uu_column || '=:1'
|
||||
INTO o_id
|
||||
USING p_uu_value;
|
||||
|
||||
RETURN o_id;
|
||||
END;
|
||||
/
|
|
@ -0,0 +1,42 @@
|
|||
CREATE OR REPLACE FUNCTION torecordid(
|
||||
p_tablename IN VARCHAR,
|
||||
p_uu_value IN VARCHAR
|
||||
)
|
||||
RETURNS INTEGER AS $body$
|
||||
DECLARE
|
||||
id_column VARCHAR;
|
||||
uu_column VARCHAR;
|
||||
o_id INTEGER;
|
||||
BEGIN
|
||||
SELECT a.ColumnName
|
||||
INTO id_column
|
||||
FROM AD_Column a
|
||||
JOIN AD_Table b ON (a.AD_Table_ID=b.AD_Table_ID)
|
||||
WHERE a.IsActive='Y' AND a.IsKey='Y' AND lower(b.TableName) = lower(p_tablename);
|
||||
|
||||
IF (id_column IS NULL) THEN
|
||||
RAISE EXCEPTION 'ID column not found for table %', p_tablename;
|
||||
END IF;
|
||||
|
||||
IF (length(p_tablename) <= 27) THEN
|
||||
uu_column = p_tablename || '_UU';
|
||||
ELSE
|
||||
SELECT a.ColumnName
|
||||
INTO uu_column
|
||||
FROM AD_Column a
|
||||
JOIN AD_Table b ON (a.AD_Table_ID=b.AD_Table_ID)
|
||||
WHERE a.IsActive='Y' AND a.FieldLength=36 AND lower(ColumnName) like (lower(substring(p_tablename from 0 for 27)) || '%UU')
|
||||
AND lower(b.TableName) = lower(p_tablename);
|
||||
END IF;
|
||||
|
||||
IF (uu_column IS NULL) THEN
|
||||
RAISE EXCEPTION 'UUID column not found for table %', p_tablename;
|
||||
END IF;
|
||||
|
||||
EXECUTE 'SELECT ' || quote_ident(lower(id_column)) || ' FROM ' || quote_ident(lower(p_tablename)) || ' WHERE ' || uu_column || '=$1'
|
||||
INTO STRICT o_id
|
||||
USING p_uu_value;
|
||||
|
||||
RETURN o_id;
|
||||
END;
|
||||
$body$ LANGUAGE plpgsql;
|
|
@ -0,0 +1,47 @@
|
|||
-- IDEMPIERE-5586
|
||||
SELECT register_migration_script('202302220654_IDEMPIERE-5586.sql') FROM dual;
|
||||
|
||||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
CREATE OR REPLACE FUNCTION torecordid (
|
||||
p_tablename IN VARCHAR2,
|
||||
p_uu_value IN VARCHAR2
|
||||
)
|
||||
RETURN NUMBER AS
|
||||
id_column VARCHAR2(200);
|
||||
uu_column VARCHAR2(200);
|
||||
o_id NUMBER;
|
||||
BEGIN
|
||||
SELECT a.ColumnName
|
||||
INTO id_column
|
||||
FROM AD_Column a
|
||||
JOIN AD_Table b ON (a.AD_Table_ID=b.AD_Table_ID)
|
||||
WHERE a.IsActive='Y' AND a.IsKey='Y' AND lower(b.TableName) = lower(p_tablename);
|
||||
|
||||
IF (id_column IS NULL) THEN
|
||||
raise_application_error(-20001, 'ID column not found for table ' || p_tablename);
|
||||
END IF;
|
||||
|
||||
IF (length(p_tablename) <= 27) THEN
|
||||
uu_column := p_tablename || '_UU';
|
||||
ELSE
|
||||
SELECT a.ColumnName
|
||||
INTO uu_column
|
||||
FROM AD_Column a
|
||||
JOIN AD_Table b ON (a.AD_Table_ID=b.AD_Table_ID)
|
||||
WHERE a.IsActive='Y' AND a.FieldLength=36 AND lower(a.ColumnName) LIKE (lower(SUBSTR(p_tablename, 1, 27)) || '%UU')
|
||||
AND lower(b.TableName) = lower(p_tablename);
|
||||
END IF;
|
||||
|
||||
IF (uu_column IS NULL) THEN
|
||||
raise_application_error(-20002, 'UUID column not found for table ' || p_tablename);
|
||||
END IF;
|
||||
|
||||
EXECUTE IMMEDIATE 'SELECT ' || id_column || ' FROM ' || p_tablename || ' WHERE ' || uu_column || '=:1'
|
||||
INTO o_id
|
||||
USING p_uu_value;
|
||||
|
||||
RETURN o_id;
|
||||
END;
|
||||
/
|
|
@ -0,0 +1,48 @@
|
|||
-- IDEMPIERE-5586
|
||||
SELECT register_migration_script('202302220654_IDEMPIERE-5586.sql') FROM dual;
|
||||
|
||||
CREATE OR REPLACE FUNCTION torecordid(
|
||||
p_tablename IN VARCHAR,
|
||||
p_uu_value IN VARCHAR
|
||||
)
|
||||
RETURNS INTEGER AS $body$
|
||||
DECLARE
|
||||
id_column VARCHAR;
|
||||
uu_column VARCHAR;
|
||||
o_id INTEGER;
|
||||
BEGIN
|
||||
SELECT a.ColumnName
|
||||
INTO id_column
|
||||
FROM AD_Column a
|
||||
JOIN AD_Table b ON (a.AD_Table_ID=b.AD_Table_ID)
|
||||
WHERE a.IsActive='Y' AND a.IsKey='Y' AND lower(b.TableName) = lower(p_tablename);
|
||||
|
||||
IF (id_column IS NULL) THEN
|
||||
RAISE EXCEPTION 'ID column not found for table %', p_tablename;
|
||||
END IF;
|
||||
|
||||
IF (length(p_tablename) <= 27) THEN
|
||||
uu_column = p_tablename || '_UU';
|
||||
ELSE
|
||||
SELECT a.ColumnName
|
||||
INTO uu_column
|
||||
FROM AD_Column a
|
||||
JOIN AD_Table b ON (a.AD_Table_ID=b.AD_Table_ID)
|
||||
WHERE a.IsActive='Y' AND a.FieldLength=36 AND lower(ColumnName) like (lower(substring(p_tablename from 0 for 27)) || '%UU')
|
||||
AND lower(b.TableName) = lower(p_tablename);
|
||||
END IF;
|
||||
|
||||
IF (uu_column IS NULL) THEN
|
||||
RAISE EXCEPTION 'UUID column not found for table %', p_tablename;
|
||||
END IF;
|
||||
|
||||
EXECUTE 'SELECT ' || quote_ident(lower(id_column)) || ' FROM ' || quote_ident(lower(p_tablename)) || ' WHERE ' || uu_column || '=$1'
|
||||
INTO STRICT o_id
|
||||
USING p_uu_value;
|
||||
|
||||
RETURN o_id;
|
||||
END;
|
||||
$body$ LANGUAGE plpgsql
|
||||
;
|
||||
|
||||
|
|
@ -42,10 +42,12 @@ import java.util.regex.Pattern;
|
|||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.compiere.Adempiere;
|
||||
import org.compiere.db.Database;
|
||||
import org.compiere.model.I_AD_UserPreference;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DisplayType;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Ini;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
* Convert SQL to Target DB
|
||||
|
@ -441,6 +443,11 @@ public abstract class Convert
|
|||
*/
|
||||
public abstract boolean isOracle();
|
||||
|
||||
/**
|
||||
* Log oraStatement and pgStatement to SQL migration script file.
|
||||
* @param oraStatement
|
||||
* @param pgStatement
|
||||
*/
|
||||
public synchronized static void logMigrationScript(String oraStatement, String pgStatement) {
|
||||
// Check AdempiereSys
|
||||
// check property Log migration script
|
||||
|
@ -456,26 +463,10 @@ public abstract class Convert
|
|||
String prm_COMMENT = null;
|
||||
try {
|
||||
if (fosScriptOr == null || fosScriptPg == null) {
|
||||
String now = new SimpleDateFormat("yyyyMMddHHmm").format(new Date());
|
||||
prm_COMMENT = Env.getContext(Env.getCtx(), "MigrationScriptComment");
|
||||
String pattern = "(IDEMPIERE-[0-9]*)";
|
||||
Pattern p = Pattern.compile(pattern);
|
||||
Matcher m = p.matcher(prm_COMMENT);
|
||||
String ticket = null;
|
||||
if (m.find())
|
||||
ticket = m.group(1);
|
||||
if (ticket == null)
|
||||
ticket = "PlaceholderForTicket";
|
||||
fileName = now + "_" + ticket + ".sql";
|
||||
String version = Adempiere.MAIN_VERSION.substring(8);
|
||||
boolean isIDE = Files.isDirectory(Paths.get(Adempiere.getAdempiereHome() + File.separator + "org.adempiere.base"));
|
||||
String homeScript;
|
||||
if (isIDE)
|
||||
homeScript = Adempiere.getAdempiereHome() + File.separator;
|
||||
else
|
||||
homeScript = System.getProperty("java.io.tmpdir") + File.separator;
|
||||
folderOr = homeScript + "migration" + File.separator + "iD" + version + File.separator + "oracle" + File.separator;
|
||||
folderPg = homeScript + "migration" + File.separator + "iD" + version + File.separator + "postgresql" + File.separator;
|
||||
prm_COMMENT = Env.getContext(Env.getCtx(), I_AD_UserPreference.COLUMNNAME_MigrationScriptComment);
|
||||
fileName = getMigrationScriptFileName(prm_COMMENT);
|
||||
folderOr = getMigrationScriptFolder("oracle");
|
||||
folderPg = getMigrationScriptFolder("postgresql");
|
||||
Files.createDirectories(Paths.get(folderOr));
|
||||
Files.createDirectories(Paths.get(folderPg));
|
||||
}
|
||||
|
@ -511,6 +502,42 @@ public abstract class Convert
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ticketComment
|
||||
* @return migration script file name
|
||||
*/
|
||||
public static String getMigrationScriptFileName(String ticketComment) {
|
||||
// [timestamp]_[ticket].sql
|
||||
String fileName;
|
||||
String now = new SimpleDateFormat("yyyyMMddHHmm").format(new Date());
|
||||
String pattern = "(IDEMPIERE-[0-9]*)";
|
||||
Pattern p = Pattern.compile(pattern);
|
||||
Matcher m = p.matcher(ticketComment);
|
||||
String ticket = null;
|
||||
if (m.find())
|
||||
ticket = m.group(1);
|
||||
if (ticket == null)
|
||||
ticket = "PlaceholderForTicket";
|
||||
fileName = now + "_" + ticket + ".sql";
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dbtype oracle or postgresql
|
||||
* @return absolute migration script folder path for dbtype
|
||||
*/
|
||||
public static String getMigrationScriptFolder(String dbtype) {
|
||||
// migration/iD[version]/[oracle|postgresql] directory
|
||||
String version = Adempiere.MAIN_VERSION.substring(8);
|
||||
boolean isIDE = Files.isDirectory(Paths.get(Adempiere.getAdempiereHome() + File.separator + "org.adempiere.base"));
|
||||
String homeScript;
|
||||
if (isIDE)
|
||||
homeScript = Adempiere.getAdempiereHome() + File.separator;
|
||||
else
|
||||
homeScript = System.getProperty("java.io.tmpdir") + File.separator;
|
||||
return homeScript + "migration" + File.separator + "iD" + version + File.separator + dbtype + File.separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if it is in log migration script mode
|
||||
*/
|
||||
|
@ -519,13 +546,12 @@ public abstract class Convert
|
|||
if (Ini.isClient()) {
|
||||
logMigrationScript = Ini.isPropertyBool(Ini.P_LOGMIGRATIONSCRIPT);
|
||||
} else {
|
||||
String sysProperty = Env.getCtx().getProperty("LogMigrationScript", "N");
|
||||
String sysProperty = Env.getCtx().getProperty(Ini.P_LOGMIGRATIONSCRIPT, "N");
|
||||
logMigrationScript = "y".equalsIgnoreCase(sysProperty) || "true".equalsIgnoreCase(sysProperty);
|
||||
}
|
||||
return logMigrationScript;
|
||||
}
|
||||
|
||||
|
||||
private static String [] dontLogTables = new String[] {
|
||||
"AD_ACCESSLOG",
|
||||
"AD_ALERTPROCESSORLOG",
|
||||
|
@ -573,6 +599,25 @@ public abstract class Convert
|
|||
"T_TRIALBALANCE"
|
||||
};
|
||||
|
||||
/**
|
||||
* @param tableName
|
||||
* @return true if log migration script should ignore tableName
|
||||
*/
|
||||
public static boolean isDontLogTable(String tableName) {
|
||||
if (Util.isEmpty(tableName))
|
||||
return false;
|
||||
|
||||
// Don't log trl - those will be created/maintained using synchronize terminology
|
||||
if (tableName.endsWith("_TRL"))
|
||||
return true;
|
||||
|
||||
for (String t : dontLogTables) {
|
||||
if (t.equalsIgnoreCase(tableName))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean dontLog(String statement) {
|
||||
// Do not log *Access records - teo_Sarca BF [ 2782095 ]
|
||||
// IDEMPIERE-323 Migration script log AD_Document_Action_Access (nmicoud / CarlosRuiz_globalqss)
|
||||
|
@ -599,6 +644,8 @@ public abstract class Convert
|
|||
return true;
|
||||
if (uppStmt.matches("INSERT INTO .*_TRL .*"))
|
||||
return true;
|
||||
if (uppStmt.matches("DELETE FROM .*_TRL .*"))
|
||||
return true;
|
||||
// Don't log tree custom table statements (not present in core)
|
||||
if (uppStmt.startsWith("INSERT INTO AD_TREENODE ") && uppStmt.contains(" AND T.TREETYPE='TL' AND T.AD_TABLE_ID="))
|
||||
return true;
|
||||
|
@ -619,6 +666,12 @@ public abstract class Convert
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use writer to append SQL statement to an output media (usually file).
|
||||
* @param w {@link Writer}
|
||||
* @param statement SQL statement
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void writeLogMigrationScript(Writer w, String statement) throws IOException
|
||||
{
|
||||
// log time and date
|
||||
|
|
|
@ -989,7 +989,10 @@ public class MBPartner extends X_C_BPartner implements ImmutablePOSupport
|
|||
// Trees
|
||||
insert_Tree(MTree_Base.TREETYPE_BPartner);
|
||||
// Accounting
|
||||
StringBuilder msgacc = new StringBuilder("p.C_BP_Group_ID=").append(getC_BP_Group_ID());
|
||||
StringBuilder msgacc = new StringBuilder("p.C_BP_Group_ID=")
|
||||
.append(getC_BP_Group_ID() > MTable.MAX_OFFICIAL_ID && Env.isLogMigrationScript(get_TableName())
|
||||
? "toRecordId('C_BP_Group',"+DB.TO_STRING(MBPGroup.get(getC_BP_Group_ID()).getC_BP_Group_UU())+")"
|
||||
: getC_BP_Group_ID());
|
||||
insert_Accounting("C_BP_Customer_Acct", "C_BP_Group_Acct", msgacc.toString());
|
||||
insert_Accounting("C_BP_Vendor_Acct", "C_BP_Group_Acct",msgacc.toString());
|
||||
}
|
||||
|
|
|
@ -854,7 +854,10 @@ public class MProduct extends X_M_Product implements ImmutablePOSupport
|
|||
if (newRecord)
|
||||
{
|
||||
insert_Accounting("M_Product_Acct", "M_Product_Category_Acct",
|
||||
"p.M_Product_Category_ID=" + getM_Product_Category_ID());
|
||||
"p.M_Product_Category_ID=" +
|
||||
(getM_Product_Category_ID() > MTable.MAX_OFFICIAL_ID && Env.isLogMigrationScript(get_TableName())
|
||||
? "toRecordId('M_Product_Category',"+DB.TO_STRING(MProductCategory.get(getM_Product_Category_ID()).getM_Product_Category_UU())+")"
|
||||
: getM_Product_Category_ID()));
|
||||
insert_Tree(X_AD_Tree.TREETYPE_Product);
|
||||
}
|
||||
if (newRecord || is_ValueChanged(COLUMNNAME_Value))
|
||||
|
|
|
@ -86,7 +86,7 @@ public class MSequence extends X_AD_Sequence
|
|||
}
|
||||
else
|
||||
{
|
||||
String sysProperty = Env.getCtx().getProperty("AdempiereSys", "N");
|
||||
String sysProperty = Env.getCtx().getProperty(Ini.P_ADEMPIERESYS, "N");
|
||||
adempiereSys = "y".equalsIgnoreCase(sysProperty) || "true".equalsIgnoreCase(sysProperty);
|
||||
}
|
||||
if (adempiereSys && AD_Client_ID > 11)
|
||||
|
@ -315,7 +315,7 @@ public class MSequence extends X_AD_Sequence
|
|||
}
|
||||
else
|
||||
{
|
||||
String sysProperty = Env.getCtx().getProperty("AdempiereSys", "N");
|
||||
String sysProperty = Env.getCtx().getProperty(Ini.P_ADEMPIERESYS, "N");
|
||||
adempiereSys = "y".equalsIgnoreCase(sysProperty) || "true".equalsIgnoreCase(sysProperty);
|
||||
}
|
||||
if (adempiereSys && Env.getAD_Client_ID(Env.getCtx()) > 11)
|
||||
|
@ -1103,7 +1103,7 @@ public class MSequence extends X_AD_Sequence
|
|||
String prm_PASSWORD = MSysConfig.getValue(MSysConfig.DICTIONARY_ID_PASSWORD); // "password_inseguro";
|
||||
String prm_TABLE = TableName;
|
||||
String prm_ALTKEY = ""; // TODO: generate alt-key based on key of table
|
||||
String prm_COMMENT = Env.getContext(Env.getCtx(), "MigrationScriptComment");
|
||||
String prm_COMMENT = Env.getContext(Env.getCtx(), I_AD_UserPreference.COLUMNNAME_MigrationScriptComment);
|
||||
String prm_PROJECT = new String("Adempiere");
|
||||
|
||||
return getNextID_HTTP(TableName, website, prm_USER,
|
||||
|
@ -1122,7 +1122,7 @@ public class MSequence extends X_AD_Sequence
|
|||
String prm_PASSWORD = MSysConfig.getValue(MSysConfig.PROJECT_ID_PASSWORD); // "password_inseguro";
|
||||
String prm_TABLE = TableName;
|
||||
String prm_ALTKEY = ""; // TODO: generate alt-key based on key of table
|
||||
String prm_COMMENT = Env.getContext(Env.getCtx(), "MigrationScriptComment");
|
||||
String prm_COMMENT = Env.getContext(Env.getCtx(), I_AD_UserPreference.COLUMNNAME_MigrationScriptComment);
|
||||
String prm_PROJECT = MSysConfig.getValue(MSysConfig.PROJECT_ID_PROJECT);
|
||||
|
||||
return getNextID_HTTP(TableName, website, prm_USER,
|
||||
|
@ -1219,7 +1219,11 @@ public class MSequence extends X_AD_Sequence
|
|||
"T_TRIALBALANCE"
|
||||
};
|
||||
|
||||
private static boolean isExceptionCentralized(String tableName) {
|
||||
/**
|
||||
* @param tableName
|
||||
* @return true if centralized id shouldn't be used for tableName
|
||||
*/
|
||||
public static boolean isExceptionCentralized(String tableName) {
|
||||
|
||||
for (String exceptionTable : dontUseCentralized) {
|
||||
if (tableName.equalsIgnoreCase(exceptionTable))
|
||||
|
@ -1232,8 +1236,12 @@ public class MSequence extends X_AD_Sequence
|
|||
|
||||
private static CCache<String,String> tablesWithEntityType = new CCache<String,String>(Table_Name, "TablesWithEntityType", 60, 0, false, 0);
|
||||
|
||||
private synchronized static boolean isTableWithEntityType(String tableName) {
|
||||
if (tablesWithEntityType == null || tablesWithEntityType.size() == 0) {
|
||||
/**
|
||||
* @param tableName
|
||||
* @return true if tableName has entity type column name
|
||||
*/
|
||||
public static synchronized boolean isTableWithEntityType(String tableName) {
|
||||
if (tablesWithEntityType.size() == 0) {
|
||||
final String sql = "SELECT TableName FROM AD_Table WHERE AD_Table_ID IN (SELECT AD_Table_ID FROM AD_Column WHERE ColumnName='EntityType') ORDER BY TableName";
|
||||
List<List<Object>> list = DB.getSQLArrayObjectsEx(null, sql);
|
||||
for (List<Object> row : list) {
|
||||
|
|
|
@ -66,7 +66,6 @@ import org.compiere.util.DB;
|
|||
import org.compiere.util.DisplayType;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Evaluatee;
|
||||
import org.compiere.util.Ini;
|
||||
import org.compiere.util.Language;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.SecureEngine;
|
||||
|
@ -468,6 +467,17 @@ public abstract class PO
|
|||
return m_idOld;
|
||||
} // getID
|
||||
|
||||
/**
|
||||
* @return UUID value
|
||||
*/
|
||||
public String get_UUID() {
|
||||
String uidColumn = getUUIDColumnName();
|
||||
if (p_info.getColumnIndex(uidColumn) >=0)
|
||||
return get_ValueAsString(uidColumn);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Context
|
||||
* @return context
|
||||
|
@ -2630,22 +2640,18 @@ public abstract class PO
|
|||
return saveFinish (false, ok);
|
||||
} // saveUpdate
|
||||
|
||||
/**
|
||||
* @return true if sql migration script should be logged for changes to this PO instance
|
||||
*/
|
||||
private boolean isLogSQLScript() {
|
||||
boolean logMigrationScript = false;
|
||||
if (Ini.isClient()) {
|
||||
logMigrationScript = Ini.isPropertyBool(Ini.P_LOGMIGRATIONSCRIPT);
|
||||
} else {
|
||||
String sysProperty = Env.getCtx().getProperty("LogMigrationScript", "N");
|
||||
logMigrationScript = "y".equalsIgnoreCase(sysProperty) || "true".equalsIgnoreCase(sysProperty);
|
||||
}
|
||||
return logMigrationScript;
|
||||
return Env.isLogMigrationScript(p_info.getTableName());
|
||||
}
|
||||
|
||||
private boolean doUpdate(boolean withValues) {
|
||||
//params for insert statement
|
||||
List<Object> params = new ArrayList<Object>();
|
||||
|
||||
String where = get_WhereClause(true);
|
||||
|
||||
String where = withValues ? get_WhereClause(true, get_ValueAsString(getUUIDColumnName())) : get_WhereClause(true);
|
||||
|
||||
List<Object> optimisticLockingParams = new ArrayList<Object>();
|
||||
if (is_UseOptimisticLocking() && m_optimisticLockingColumns != null && m_optimisticLockingColumns.length > 0)
|
||||
|
@ -2737,6 +2743,55 @@ public abstract class PO
|
|||
// values
|
||||
if (value == Null.NULL)
|
||||
sql.append("NULL");
|
||||
else if (value instanceof Integer && "Record_ID".equalsIgnoreCase(columnName))
|
||||
{
|
||||
Integer idValue = (Integer) value;
|
||||
if (idValue <= MTable.MAX_OFFICIAL_ID)
|
||||
{
|
||||
sql.append(value);
|
||||
}
|
||||
else if (p_info.getColumnIndex("AD_Table_ID") >= 0)
|
||||
{
|
||||
int tableId = get_ValueAsInt("AD_Table_ID");
|
||||
if (tableId > 0)
|
||||
{
|
||||
MTable refTable = MTable.get(Env.getCtx(), tableId);
|
||||
String refTableName = refTable.getTableName();
|
||||
String refKeyColumnName = refTable.getKeyColumns()[0];
|
||||
String refUUColumnName = MTable.getUUIDColumnName(refTableName);
|
||||
String refUUValue = DB.getSQLValueString(get_TrxName(), "SELECT " + refUUColumnName + " FROM "
|
||||
+ refTableName + " WHERE " + refKeyColumnName + "=?", (Integer)value);
|
||||
sql.append("toRecordId('"+ refTableName + "','" + refUUValue + "')");
|
||||
}
|
||||
else
|
||||
{
|
||||
sql.append(value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sql.append(value);
|
||||
}
|
||||
}
|
||||
else if (value instanceof Integer && p_info.isColumnLookup(i))
|
||||
{
|
||||
Integer idValue = (Integer) value;
|
||||
if (idValue <= MTable.MAX_OFFICIAL_ID)
|
||||
{
|
||||
sql.append(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
MColumn col = MColumn.get(p_info.getAD_Column_ID(columnName));
|
||||
String refTableName = col.getReferenceTableName();
|
||||
MTable refTable = MTable.get(Env.getCtx(), refTableName);
|
||||
String refKeyColumnName = refTable.getKeyColumns()[0];
|
||||
String refUUColumnName = MTable.getUUIDColumnName(refTableName);
|
||||
String refUUValue = DB.getSQLValueString(get_TrxName(), "SELECT " + refUUColumnName + " FROM "
|
||||
+ refTableName + " WHERE " + refKeyColumnName + "=?", (Integer)value);
|
||||
sql.append("toRecordId('"+ refTableName + "','" + refUUValue + "')");
|
||||
}
|
||||
}
|
||||
else if (value instanceof Integer || value instanceof BigDecimal)
|
||||
sql.append(value);
|
||||
else if (c == Boolean.class)
|
||||
|
@ -3038,7 +3093,7 @@ public abstract class PO
|
|||
{
|
||||
// Set ID for single key - Multi-Key values need explicitly be set previously
|
||||
if (m_IDs.length == 1 && p_info.hasKeyColumn()
|
||||
&& m_KeyColumns[0].endsWith("_ID")) // AD_Language, EntityType
|
||||
&& m_KeyColumns[0].endsWith("_ID") && (Env.isUseCentralizedId(p_info.getTableName()) || !isLogSQLScript())) // AD_Language, EntityType
|
||||
{
|
||||
int no = saveNew_getID();
|
||||
if (no <= 0)
|
||||
|
@ -3172,10 +3227,65 @@ public abstract class PO
|
|||
{
|
||||
try
|
||||
{
|
||||
if (c == Object.class) // may have need to deal with null values differently
|
||||
if (m_IDs.length == 1 && p_info.hasKeyColumn()
|
||||
&& m_KeyColumns[0].endsWith("_ID") && m_KeyColumns[0].equals(p_info.getColumnName(i)) && !Env.isUseCentralizedId(p_info.getTableName()))
|
||||
{
|
||||
MSequence sequence = MSequence.get(Env.getCtx(), p_info.getTableName(), get_TrxName(), true);
|
||||
sqlValues.append("nextidfunc("+sequence.getAD_Sequence_ID()+",'N')");
|
||||
}
|
||||
else if (c == Object.class) // may have need to deal with null values differently
|
||||
sqlValues.append (saveNewSpecial (value, i));
|
||||
else if (value == null || value.equals (Null.NULL))
|
||||
sqlValues.append ("NULL");
|
||||
else if (value instanceof Integer && "Record_ID".equalsIgnoreCase(p_info.getColumnName(i)))
|
||||
{
|
||||
Integer idValue = (Integer) value;
|
||||
if (idValue <= MTable.MAX_OFFICIAL_ID)
|
||||
{
|
||||
sqlValues.append(value);
|
||||
}
|
||||
else if (p_info.getColumnIndex("AD_Table_ID") >= 0)
|
||||
{
|
||||
int tableId = get_ValueAsInt("AD_Table_ID");
|
||||
if (tableId > 0)
|
||||
{
|
||||
MTable refTable = MTable.get(Env.getCtx(), tableId);
|
||||
String refTableName = refTable.getTableName();
|
||||
String refKeyColumnName = refTable.getKeyColumns()[0];
|
||||
String refUUColumnName = MTable.getUUIDColumnName(refTableName);
|
||||
String refUUValue = DB.getSQLValueString(get_TrxName(), "SELECT " + refUUColumnName + " FROM "
|
||||
+ refTableName + " WHERE " + refKeyColumnName + "=?", (Integer)value);
|
||||
sqlValues.append("toRecordId('"+ refTableName + "','" + refUUValue + "')");
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlValues.append(value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlValues.append(value);
|
||||
}
|
||||
}
|
||||
else if (value instanceof Integer && p_info.isColumnLookup(i))
|
||||
{
|
||||
Integer idValue = (Integer) value;
|
||||
if (idValue <= MTable.MAX_OFFICIAL_ID)
|
||||
{
|
||||
sqlValues.append(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
MColumn col = MColumn.get(p_info.getAD_Column_ID(p_info.getColumnName(i)));
|
||||
String refTableName = col.getReferenceTableName();
|
||||
MTable refTable = MTable.get(Env.getCtx(), refTableName);
|
||||
String refKeyColumnName = refTable.getKeyColumns()[0];
|
||||
String refUUColumnName = MTable.getUUIDColumnName(refTable.getTableName());
|
||||
String refUUValue = DB.getSQLValueString(get_TrxName(), "SELECT " + refUUColumnName + " FROM "
|
||||
+ refTableName + " WHERE " + refKeyColumnName + "=?", (Integer)value);
|
||||
sqlValues.append("toRecordId('"+ refTableName + "','" + refUUValue + "')");
|
||||
}
|
||||
}
|
||||
else if (value instanceof Integer || value instanceof BigDecimal)
|
||||
sqlValues.append (value);
|
||||
else if (c == Boolean.class)
|
||||
|
@ -3268,17 +3378,19 @@ public abstract class PO
|
|||
}
|
||||
}
|
||||
|
||||
// Change Log - Only
|
||||
String insertLog = MSysConfig.getValue(MSysConfig.SYSTEM_INSERT_CHANGELOG, "Y", getAD_Client_ID());
|
||||
if ( session != null
|
||||
&& m_IDs.length == 1
|
||||
&& p_info.isAllowLogging(i) // logging allowed
|
||||
&& !p_info.isEncrypted(i) // not encrypted
|
||||
&& !p_info.isVirtualColumn(i) // no virtual column
|
||||
&& !"Password".equals(p_info.getColumnName(i))
|
||||
&& (insertLog.equalsIgnoreCase("Y")
|
||||
|| (insertLog.equalsIgnoreCase("K") && p_info.getColumn(i).IsKey))
|
||||
)
|
||||
if (!withValues || Env.isUseCentralizedId(p_info.getTableName()))
|
||||
{
|
||||
// Change Log - Only
|
||||
String insertLog = MSysConfig.getValue(MSysConfig.SYSTEM_INSERT_CHANGELOG, "Y", getAD_Client_ID());
|
||||
if ( session != null
|
||||
&& m_IDs.length == 1
|
||||
&& p_info.isAllowLogging(i) // logging allowed
|
||||
&& !p_info.isEncrypted(i) // not encrypted
|
||||
&& !p_info.isVirtualColumn(i) // no virtual column
|
||||
&& !"Password".equals(p_info.getColumnName(i))
|
||||
&& (insertLog.equalsIgnoreCase("Y")
|
||||
|| (insertLog.equalsIgnoreCase("K") && p_info.getColumn(i).IsKey))
|
||||
)
|
||||
{
|
||||
// change log on new
|
||||
MChangeLog cLog = session.changeLog (
|
||||
|
@ -3288,7 +3400,7 @@ public abstract class PO
|
|||
if (cLog != null)
|
||||
AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// Custom Columns
|
||||
if (m_custom != null)
|
||||
|
@ -3336,6 +3448,36 @@ public abstract class PO
|
|||
boolean ok = no == 1;
|
||||
if (ok)
|
||||
{
|
||||
if (withValues && m_IDs.length == 1 && p_info.hasKeyColumn()
|
||||
&& m_KeyColumns[0].endsWith("_ID") && !Env.isUseCentralizedId(p_info.getTableName()))
|
||||
{
|
||||
int id = DB.getSQLValueEx(get_TrxName(), "SELECT " + m_KeyColumns[0] + " FROM "
|
||||
+ p_info.getTableName() + " WHERE " + getUUIDColumnName() + "=?", get_ValueAsString(getUUIDColumnName()));
|
||||
m_IDs[0] = Integer.valueOf(id);
|
||||
set_ValueNoCheck(m_KeyColumns[0], m_IDs[0]);
|
||||
|
||||
int ki = p_info.getColumnIndex(m_KeyColumns[0]);
|
||||
// Change Log - Only
|
||||
String insertLog = MSysConfig.getValue(MSysConfig.SYSTEM_INSERT_CHANGELOG, "Y", getAD_Client_ID());
|
||||
if ( session != null
|
||||
&& m_IDs.length == 1
|
||||
&& p_info.isAllowLogging(ki) // logging allowed
|
||||
&& !p_info.isEncrypted(ki) // not encrypted
|
||||
&& !p_info.isVirtualColumn(ki) // no virtual column
|
||||
&& !"Password".equals(p_info.getColumnName(ki))
|
||||
&& (insertLog.equalsIgnoreCase("Y")
|
||||
|| (insertLog.equalsIgnoreCase("K") && p_info.getColumn(ki).IsKey))
|
||||
)
|
||||
{
|
||||
// change log on new
|
||||
MChangeLog cLog = session.changeLog (
|
||||
m_trxName, AD_ChangeLog_ID,
|
||||
p_info.getAD_Table_ID(), p_info.getColumn(ki).AD_Column_ID,
|
||||
get_ID(), getAD_Client_ID(), getAD_Org_ID(), null, id, MChangeLog.EVENTCHANGELOG_Insert);
|
||||
if (cLog != null)
|
||||
AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID();
|
||||
}
|
||||
}
|
||||
ok = lobSave();
|
||||
if (!load(m_trxName)) // re-read Info
|
||||
{
|
||||
|
@ -3666,7 +3808,7 @@ public abstract class PO
|
|||
}
|
||||
|
||||
// The Delete Statement
|
||||
String where = get_WhereClause(true);
|
||||
String where = isLogSQLScript() ? get_WhereClause(true, get_ValueAsString(getUUIDColumnName())) : get_WhereClause(true);
|
||||
List<Object> optimisticLockingParams = new ArrayList<Object>();
|
||||
if (is_UseOptimisticLocking() && m_optimisticLockingColumns != null && m_optimisticLockingColumns.length > 0)
|
||||
{
|
||||
|
@ -4153,7 +4295,7 @@ public abstract class PO
|
|||
//
|
||||
String tableName = p_info.getTableName();
|
||||
String keyColumn = m_KeyColumns[0];
|
||||
StringBuilder sql = new StringBuilder ("DELETE FROM ")
|
||||
StringBuilder sql = new StringBuilder ("DELETE FROM ")
|
||||
.append(tableName).append("_Trl WHERE ")
|
||||
.append(keyColumn).append("=").append(get_ID());
|
||||
int no = DB.executeUpdate(sql.toString(), trxName);
|
||||
|
@ -4222,7 +4364,9 @@ public abstract class PO
|
|||
if (uuidColumn != null && uuidFunction)
|
||||
sb.append(",").append(PO.getUUIDColumnName(acctTableName));
|
||||
// .. SELECT
|
||||
sb.append(") SELECT ").append(get_ID())
|
||||
sb.append(") SELECT ").append(get_ID() > MTable.MAX_OFFICIAL_ID && Env.isLogMigrationScript(get_TableName())
|
||||
? "toRecordId("+DB.TO_STRING(get_TableName())+","+DB.TO_STRING(get_UUID())+")"
|
||||
: get_ID())
|
||||
.append(", p.C_AcctSchema_ID, p.AD_Client_ID,0,'Y', getDate(),")
|
||||
.append(getUpdatedBy()).append(",getDate(),").append(getUpdatedBy());
|
||||
for (int i = 0; i < s_acctColumns.size(); i++)
|
||||
|
@ -4231,12 +4375,19 @@ public abstract class PO
|
|||
sb.append(",generate_uuid()");
|
||||
// .. FROM
|
||||
sb.append(" FROM ").append(acctBaseTable)
|
||||
.append(" p WHERE p.AD_Client_ID=").append(getAD_Client_ID());
|
||||
.append(" p WHERE p.AD_Client_ID=")
|
||||
.append(getAD_Client_ID() > MTable.MAX_OFFICIAL_ID && Env.isLogMigrationScript(get_TableName())
|
||||
? "toRecordId('AD_Client',"+DB.TO_STRING(MClient.get(getAD_Client_ID()).getAD_Client_UU())+")"
|
||||
: getAD_Client_ID());
|
||||
if (whereClause != null && whereClause.length() > 0)
|
||||
sb.append (" AND ").append(whereClause);
|
||||
sb.append(" AND NOT EXISTS (SELECT * FROM ").append(acctTableName)
|
||||
.append(" e WHERE e.C_AcctSchema_ID=p.C_AcctSchema_ID AND e.")
|
||||
.append(get_TableName()).append("_ID=").append(get_ID()).append(")");
|
||||
.append(get_TableName()).append("_ID=");
|
||||
if (get_ID() > MTable.MAX_OFFICIAL_ID && Env.isLogMigrationScript(get_TableName()))
|
||||
sb.append("toRecordId(").append(DB.TO_STRING(get_TableName())).append(",").append(DB.TO_STRING(get_UUID())).append("))");
|
||||
else
|
||||
sb.append(get_ID()).append(")");
|
||||
//
|
||||
int no = DB.executeUpdate(sb.toString(), get_TrxName());
|
||||
if (no > 0) {
|
||||
|
@ -4304,24 +4455,41 @@ public abstract class PO
|
|||
else
|
||||
sb.append(") ");
|
||||
sb.append("SELECT t.AD_Client_ID, 0, 'Y', getDate(), "+getUpdatedBy()+", getDate(), "+getUpdatedBy()+","
|
||||
+ "t.AD_Tree_ID, ").append(get_ID()).append(", 0, 999");
|
||||
+ "t.AD_Tree_ID, ")
|
||||
.append(get_ID() > MTable.MAX_OFFICIAL_ID && Env.isLogMigrationScript(get_TableName())
|
||||
? "toRecordId("+DB.TO_STRING(get_TableName())+","+DB.TO_STRING(get_UUID())+")"
|
||||
: get_ID())
|
||||
.append(", 0, 999");
|
||||
if (uuidColumn != null && uuidFunction)
|
||||
sb.append(", Generate_UUID() ");
|
||||
else
|
||||
sb.append(" ");
|
||||
sb.append("FROM AD_Tree t "
|
||||
+ "WHERE t.AD_Client_ID=").append(getAD_Client_ID()).append(" AND t.IsActive='Y'");
|
||||
+ "WHERE t.AD_Client_ID=")
|
||||
.append(getAD_Client_ID() > MTable.MAX_OFFICIAL_ID && Env.isLogMigrationScript(get_TableName())
|
||||
? "toRecordId('AD_Client',"+DB.TO_STRING(MClient.get(getAD_Client_ID()).getAD_Client_UU())+")"
|
||||
: getAD_Client_ID())
|
||||
.append(" AND t.IsActive='Y'");
|
||||
// Account Element Value handling
|
||||
if (C_Element_ID != 0)
|
||||
sb.append(" AND EXISTS (SELECT * FROM C_Element ae WHERE ae.C_Element_ID=")
|
||||
.append(C_Element_ID).append(" AND t.AD_Tree_ID=ae.AD_Tree_ID)");
|
||||
.append(C_Element_ID > MTable.MAX_OFFICIAL_ID && Env.isLogMigrationScript(get_TableName())
|
||||
? "toRecordId('C_Element',"+DB.TO_STRING(new MElement(getCtx(), C_Element_ID, get_TrxName()).getC_Element_UU())+")"
|
||||
: C_Element_ID)
|
||||
.append(" AND t.AD_Tree_ID=ae.AD_Tree_ID)");
|
||||
else // std trees
|
||||
sb.append(" AND t.IsAllNodes='Y' AND t.TreeType='").append(treeType).append("'");
|
||||
if (MTree_Base.TREETYPE_CustomTable.equals(treeType))
|
||||
sb.append(" AND t.AD_Table_ID=").append(get_Table_ID());
|
||||
sb.append(" AND t.AD_Table_ID=")
|
||||
.append(get_Table_ID() > MTable.MAX_OFFICIAL_ID && Env.isLogMigrationScript(get_TableName())
|
||||
? "toRecordId('AD_Table',"+DB.TO_STRING(MTable.get(get_Table_ID()).getAD_Table_UU())+")"
|
||||
: get_Table_ID());
|
||||
// Duplicate Check
|
||||
sb.append(" AND NOT EXISTS (SELECT * FROM " + MTree_Base.getNodeTableName(treeType) + " e "
|
||||
+ "WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=").append(get_ID()).append(")");
|
||||
+ "WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=")
|
||||
.append(get_ID() > MTable.MAX_OFFICIAL_ID && Env.isLogMigrationScript(get_TableName())
|
||||
? "toRecordId("+DB.TO_STRING(get_TableName())+","+DB.TO_STRING(get_UUID())+")"
|
||||
: get_ID()).append(")");
|
||||
int no = DB.executeUpdate(sb.toString(), get_TrxName());
|
||||
if (no > 0) {
|
||||
if (log.isLoggable(Level.FINE)) log.fine("#" + no + " - TreeType=" + treeType);
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.adempiere.util.ServerContext;
|
|||
import org.adempiere.util.ServerContextProvider;
|
||||
import org.compiere.Adempiere;
|
||||
import org.compiere.db.CConnection;
|
||||
import org.compiere.dbPort.Convert;
|
||||
import org.compiere.model.GridTab;
|
||||
import org.compiere.model.GridWindowVO;
|
||||
import org.compiere.model.MClient;
|
||||
|
@ -55,6 +56,7 @@ import org.compiere.model.MLookupCache;
|
|||
import org.compiere.model.MQuery;
|
||||
import org.compiere.model.MRefList;
|
||||
import org.compiere.model.MRole;
|
||||
import org.compiere.model.MSequence;
|
||||
import org.compiere.model.MSession;
|
||||
import org.compiere.model.MSysConfig;
|
||||
import org.compiere.model.MTable;
|
||||
|
@ -142,7 +144,6 @@ public final class Env
|
|||
private static final String PREFIX_SYSTEM_VARIABLE = "$env.";
|
||||
|
||||
private final static ContextProvider clientContextProvider = new DefaultContextProvider();
|
||||
|
||||
|
||||
private static List<IEnvEventListener> eventListeners = new ArrayList<IEnvEventListener>();
|
||||
|
||||
|
@ -2201,4 +2202,51 @@ public final class Env
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tableName
|
||||
* @return true if log migration script is turn on and should be used for tableName
|
||||
*/
|
||||
public static boolean isLogMigrationScript(String tableName) {
|
||||
boolean logMigrationScript = false;
|
||||
if (Ini.isClient()) {
|
||||
logMigrationScript = Ini.isPropertyBool(Ini.P_LOGMIGRATIONSCRIPT);
|
||||
} else {
|
||||
String sysProperty = Env.getCtx().getProperty(Ini.P_LOGMIGRATIONSCRIPT, "N");
|
||||
logMigrationScript = "y".equalsIgnoreCase(sysProperty) || "true".equalsIgnoreCase(sysProperty);
|
||||
}
|
||||
|
||||
return logMigrationScript ? !Convert.isDontLogTable(tableName) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if centralized id is turn on and should be used for tableName
|
||||
*/
|
||||
public static boolean isUseCentralizedId(String tableName)
|
||||
{
|
||||
String sysProperty = Env.getCtx().getProperty(Ini.P_ADEMPIERESYS, "N");
|
||||
boolean adempiereSys = "y".equalsIgnoreCase(sysProperty) || "true".equalsIgnoreCase(sysProperty);
|
||||
if (adempiereSys && Env.getAD_Client_ID(Env.getCtx()) > 11)
|
||||
adempiereSys = false;
|
||||
|
||||
if (adempiereSys)
|
||||
{
|
||||
boolean b = MSysConfig.getBooleanValue(MSysConfig.DICTIONARY_ID_USE_CENTRALIZED_ID, true);
|
||||
if (b)
|
||||
return !MSequence.isExceptionCentralized(tableName);
|
||||
else
|
||||
return b;
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean queryProjectServer = false;
|
||||
if (MSequence.isTableWithEntityType(tableName))
|
||||
queryProjectServer = true;
|
||||
if (!queryProjectServer && MSequence.Table_Name.equalsIgnoreCase(tableName))
|
||||
queryProjectServer = true;
|
||||
if (queryProjectServer && !MSequence.isExceptionCentralized(tableName)) {
|
||||
return MSysConfig.getBooleanValue(MSysConfig.PROJECT_ID_USE_CENTRALIZED_ID, false);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // Env
|
|
@ -21,7 +21,9 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
@ -42,12 +44,15 @@ import org.adempiere.webui.window.Dialog;
|
|||
import org.compiere.model.GridTab;
|
||||
import org.compiere.model.MRole;
|
||||
import org.compiere.model.MSysConfig;
|
||||
import org.compiere.model.MTable;
|
||||
import org.compiere.model.PO;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.KeyNamePair;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.NamePair;
|
||||
import org.compiere.util.Trx;
|
||||
import org.compiere.util.Util;
|
||||
import org.zkoss.zk.au.out.AuFocus;
|
||||
import org.zkoss.zk.ui.event.DropEvent;
|
||||
|
@ -701,66 +706,102 @@ public class ADSortTab extends Panel implements IADTabpanel
|
|||
if (!adWindowPanel.getToolbar().isSaveEnable())
|
||||
return;
|
||||
boolean ok = true;
|
||||
//TODO: should use model instead to enable change log and event handling
|
||||
StringBuilder info = new StringBuilder();
|
||||
StringBuffer sql = null;
|
||||
// noList - Set SortColumn to null and optional YesNo Column to 'N'
|
||||
for (int i = 0; i < noModel.getSize(); i++)
|
||||
{
|
||||
ListElement pp = (ListElement)noModel.getElementAt(i);
|
||||
if (!pp.isUpdateable())
|
||||
continue;
|
||||
if(pp.getSortNo() == 0 && (m_ColumnYesNoName == null || !pp.isYes()))
|
||||
continue; // no changes
|
||||
//
|
||||
sql = new StringBuffer();
|
||||
sql.append("UPDATE ").append(m_TableName)
|
||||
.append(" SET ").append(m_ColumnSortName).append("=0");
|
||||
if (m_ColumnYesNoName != null)
|
||||
sql.append(",").append(m_ColumnYesNoName).append("='N'");
|
||||
sql.append(", Updated=getDate(), UpdatedBy=").append(Env.getAD_User_ID(Env.getCtx()));
|
||||
sql.append(" WHERE ").append(m_KeyColumnName).append("=").append(pp.getKey());
|
||||
if (DB.executeUpdate(sql.toString(), null) == 1) {
|
||||
pp.setSortNo(0);
|
||||
pp.setIsYes(false);
|
||||
MTable table = MTable.get(Env.getCtx(), m_TableName);
|
||||
Map<Integer, ListElement> noModelBackup = new HashMap<>();
|
||||
Map<Integer, ListElement> yesModelBackup = new HashMap<>();
|
||||
|
||||
Trx trx = Trx.get(Trx.createTrxName("ADSortTab_save"), true);
|
||||
try {
|
||||
trx.start();
|
||||
// noList - Set SortColumn to null and optional YesNo Column to 'N'
|
||||
for (int i = 0; i < noModel.getSize(); i++)
|
||||
{
|
||||
ListElement pp = (ListElement)noModel.getElementAt(i);
|
||||
if (!pp.isUpdateable())
|
||||
continue;
|
||||
if(pp.getSortNo() == 0 && (m_ColumnYesNoName == null || !pp.isYes()))
|
||||
continue; // no changes
|
||||
//
|
||||
PO po = table.getPO(pp.getKey(), trx.getTrxName());
|
||||
po.set_ValueOfColumn(m_ColumnSortName, 0);
|
||||
if (m_ColumnYesNoName != null)
|
||||
po.set_ValueOfColumn(m_ColumnYesNoName, "N");
|
||||
try {
|
||||
po.saveEx();
|
||||
ListElement backup = new ListElement(pp.getKey(), pp.getName(), pp.getSortNo(), pp.isYes(), pp.getAD_Client_ID(), pp.getAD_Org_ID());
|
||||
noModelBackup.put(i, backup);
|
||||
pp.setSortNo(0);
|
||||
pp.setIsYes(false);
|
||||
} catch (Exception e) {
|
||||
ok = false;
|
||||
trx.rollback();
|
||||
if (info.length() > 0)
|
||||
info.append(", ");
|
||||
info.append(pp.getName());
|
||||
log.log(Level.SEVERE, "NoModel - Not updated: " + m_KeyColumnName + "=" + pp.getKey(), e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ok = false;
|
||||
if (info.length() > 0)
|
||||
info.append(", ");
|
||||
info.append(pp.getName());
|
||||
log.log(Level.SEVERE, "NoModel - Not updated: " + m_KeyColumnName + "=" + pp.getKey());
|
||||
|
||||
if (ok) {
|
||||
// yesList - Set SortColumn to value and optional YesNo Column to 'Y'
|
||||
int index = 0;
|
||||
for (int i = 0; i < yesModel.getSize(); i++)
|
||||
{
|
||||
ListElement pp = (ListElement)yesModel.getElementAt(i);
|
||||
if (!pp.isUpdateable())
|
||||
continue;
|
||||
index += 10;
|
||||
if(pp.getSortNo() == index && (m_ColumnYesNoName == null || pp.isYes()))
|
||||
continue; // no changes
|
||||
//
|
||||
PO po = table.getPO(pp.getKey(), trx.getTrxName());
|
||||
po.set_ValueOfColumn(m_ColumnSortName, index);
|
||||
if (m_ColumnYesNoName != null)
|
||||
po.set_ValueOfColumn(m_ColumnYesNoName, "Y");
|
||||
try {
|
||||
po.saveEx();
|
||||
ListElement backup = new ListElement(pp.getKey(), pp.getName(), pp.getSortNo(), pp.isYes(), pp.getAD_Client_ID(), pp.getAD_Org_ID());
|
||||
yesModelBackup.put(i, backup);
|
||||
pp.setSortNo(index);
|
||||
pp.setIsYes(true);
|
||||
} catch (Exception e) {
|
||||
ok = false;
|
||||
trx.rollback();
|
||||
if (info.length() > 0)
|
||||
info.append(", ");
|
||||
info.append(pp.getName());
|
||||
log.log(Level.SEVERE, "YesModel - Not updated: " + m_KeyColumnName + "=" + pp.getKey(), e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// yesList - Set SortColumn to value and optional YesNo Column to 'Y'
|
||||
int index = 0;
|
||||
for (int i = 0; i < yesModel.getSize(); i++)
|
||||
{
|
||||
ListElement pp = (ListElement)yesModel.getElementAt(i);
|
||||
if (!pp.isUpdateable())
|
||||
continue;
|
||||
index += 10;
|
||||
if(pp.getSortNo() == index && (m_ColumnYesNoName == null || pp.isYes()))
|
||||
continue; // no changes
|
||||
//
|
||||
sql = new StringBuffer();
|
||||
sql.append("UPDATE ").append(m_TableName)
|
||||
.append(" SET ").append(m_ColumnSortName).append("=").append(index);
|
||||
if (m_ColumnYesNoName != null)
|
||||
sql.append(",").append(m_ColumnYesNoName).append("='Y'");
|
||||
sql.append(", Updated=getDate(), UpdatedBy=").append(Env.getAD_User_ID(Env.getCtx()));
|
||||
sql.append(" WHERE ").append(m_KeyColumnName).append("=").append(pp.getKey());
|
||||
if (DB.executeUpdate(sql.toString(), null) == 1) {
|
||||
pp.setSortNo(index);
|
||||
pp.setIsYes(true);
|
||||
|
||||
if (ok) {
|
||||
try {
|
||||
trx.commit(true);
|
||||
} catch (Exception e) {
|
||||
ok = false;
|
||||
trx.rollback();
|
||||
info.append("Failed to commit database transaction");
|
||||
log.log(Level.SEVERE, "Failed to commit database transaction", e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ok = false;
|
||||
if (info.length() > 0)
|
||||
info.append(", ");
|
||||
info.append(pp.getName());
|
||||
log.log(Level.SEVERE, "YesModel - Not updated: " + m_KeyColumnName + "=" + pp.getKey());
|
||||
|
||||
if (!ok) {
|
||||
//rollback changes to yes and no model
|
||||
for(Integer index : noModelBackup.keySet()) {
|
||||
ListElement e = noModelBackup.get(index);
|
||||
noModel.setElementAt(e, index);
|
||||
}
|
||||
for(Integer index : yesModelBackup.keySet()) {
|
||||
ListElement e = yesModelBackup.get(index);
|
||||
yesModel.setElementAt(e, index);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
trx.close();
|
||||
}
|
||||
//
|
||||
if (ok) {
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.compiere.model.MUserPreference;
|
|||
import org.compiere.model.SystemIDs;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Ini;
|
||||
import org.compiere.util.Msg;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
|
@ -136,24 +137,24 @@ public class WPreference extends WQuickEntry implements EventListener<Event>, Va
|
|||
|
||||
if (Env.getAD_Client_ID(Env.getCtx()) <= 20 && Env.getAD_User_ID(Env.getCtx()) <= 102) {
|
||||
this.appendChild(new Space());
|
||||
adempiereSys = new WYesNoEditor("AdempiereSys", Msg.getMsg(Env.getCtx(), "AdempiereSys", true),
|
||||
adempiereSys = new WYesNoEditor(Ini.P_ADEMPIERESYS, Msg.getMsg(Env.getCtx(), Ini.P_ADEMPIERESYS, true),
|
||||
null, false, false, true);
|
||||
adempiereSys.getComponent().setTooltiptext(Msg.getMsg(Env.getCtx(), "AdempiereSys", false));
|
||||
adempiereSys.getComponent().setTooltiptext(Msg.getMsg(Env.getCtx(), Ini.P_ADEMPIERESYS, false));
|
||||
div = new Div();
|
||||
div.setStyle(LINE_DIV_STYLE);
|
||||
div.appendChild(adempiereSys.getComponent());
|
||||
this.appendChild(div);
|
||||
adempiereSys.setValue(Env.getCtx().getProperty("AdempiereSys"));
|
||||
adempiereSys.setValue(Env.getCtx().getProperty(Ini.P_ADEMPIERESYS));
|
||||
adempiereSys.addValueChangeListener(this);
|
||||
|
||||
logMigrationScript = new WYesNoEditor("LogMigrationScript", Msg.getMsg(Env.getCtx(), "LogMigrationScript", true),
|
||||
logMigrationScript = new WYesNoEditor(Ini.P_LOGMIGRATIONSCRIPT, Msg.getMsg(Env.getCtx(), Ini.P_LOGMIGRATIONSCRIPT, true),
|
||||
null, false, false, true);
|
||||
logMigrationScript.getComponent().setTooltiptext(Msg.getMsg(Env.getCtx(), "LogMigrationScript", false));
|
||||
logMigrationScript.getComponent().setTooltiptext(Msg.getMsg(Env.getCtx(), Ini.P_LOGMIGRATIONSCRIPT, false));
|
||||
div = new Div();
|
||||
div.setStyle(LINE_DIV_STYLE);
|
||||
div.appendChild(logMigrationScript.getComponent());
|
||||
this.appendChild(div);
|
||||
logMigrationScript.setValue(Env.getCtx().getProperty("LogMigrationScript"));
|
||||
logMigrationScript.setValue(Env.getCtx().getProperty(Ini.P_LOGMIGRATIONSCRIPT));
|
||||
logMigrationScript.addValueChangeListener(this);
|
||||
}
|
||||
|
||||
|
@ -250,12 +251,12 @@ public class WPreference extends WQuickEntry implements EventListener<Event>, Va
|
|||
|
||||
// Log Migration Script and AdempiereSys are just in-memory preferences, must not be saved
|
||||
if (logMigrationScript != null) {
|
||||
Env.getCtx().setProperty("LogMigrationScript", (Boolean)logMigrationScript.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty("P|LogMigrationScript", (Boolean)logMigrationScript.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty(Ini.P_LOGMIGRATIONSCRIPT, (Boolean)logMigrationScript.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty("P|"+Ini.P_LOGMIGRATIONSCRIPT, (Boolean)logMigrationScript.getValue() ? "Y" : "N");
|
||||
}
|
||||
if (adempiereSys != null) {
|
||||
Env.getCtx().setProperty("AdempiereSys", (Boolean)adempiereSys.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty("P|AdempiereSys", (Boolean)adempiereSys.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty(Ini.P_ADEMPIERESYS, (Boolean)adempiereSys.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty("P|"+Ini.P_ADEMPIERESYS, (Boolean)adempiereSys.getValue() ? "Y" : "N");
|
||||
}
|
||||
|
||||
this.detach();
|
||||
|
@ -265,12 +266,12 @@ public class WPreference extends WQuickEntry implements EventListener<Event>, Va
|
|||
if (evt.getSource() instanceof WYesNoEditor) {
|
||||
// Log Migration Script and AdempiereSys are just in-memory preferences, set them without need to save
|
||||
if (evt.getSource() == logMigrationScript) {
|
||||
Env.getCtx().setProperty("LogMigrationScript", (Boolean)logMigrationScript.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty("P|LogMigrationScript", (Boolean)logMigrationScript.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty(Ini.P_LOGMIGRATIONSCRIPT, (Boolean)logMigrationScript.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty("P|"+Ini.P_LOGMIGRATIONSCRIPT, (Boolean)logMigrationScript.getValue() ? "Y" : "N");
|
||||
dynamicDisplay();
|
||||
} else if (evt.getSource() == adempiereSys) {
|
||||
Env.getCtx().setProperty("AdempiereSys", (Boolean)adempiereSys.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty("P|AdempiereSys", (Boolean)adempiereSys.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty(Ini.P_ADEMPIERESYS, (Boolean)adempiereSys.getValue() ? "Y" : "N");
|
||||
Env.getCtx().setProperty("P|"+Ini.P_ADEMPIERESYS, (Boolean)adempiereSys.getValue() ? "Y" : "N");
|
||||
}
|
||||
}
|
||||
super.valueChange(evt);
|
||||
|
|
|
@ -32,20 +32,29 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.adempiere.exceptions.DBException;
|
||||
import org.compiere.dbPort.Convert;
|
||||
import org.compiere.model.I_AD_UserPreference;
|
||||
import org.compiere.model.MAcctSchema;
|
||||
import org.compiere.model.MBPartner;
|
||||
import org.compiere.model.MClient;
|
||||
import org.compiere.model.MMessage;
|
||||
import org.compiere.model.MProduct;
|
||||
import org.compiere.model.MProductCategory;
|
||||
import org.compiere.model.MProductCategoryAcct;
|
||||
import org.compiere.model.MTest;
|
||||
import org.compiere.model.POInfo;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Ini;
|
||||
import org.compiere.util.Trx;
|
||||
import org.idempiere.test.AbstractTestCase;
|
||||
import org.idempiere.test.DictionaryIDs;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
|
@ -480,4 +489,56 @@ public class POTest extends AbstractTestCase
|
|||
assertEquals(expected, testPo.getTestVirtualQty().setScale(2, RoundingMode.HALF_UP), "Wrong value returned");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogMigrationScript() {
|
||||
MClient client = MClient.get(Env.getCtx());
|
||||
MAcctSchema as = client.getAcctSchema();
|
||||
|
||||
assertFalse(Env.isLogMigrationScript(MProduct.Table_Name), "Unexpected Log Migration Script default for MProduct");
|
||||
Env.getCtx().setProperty(Ini.P_LOGMIGRATIONSCRIPT, "Y");
|
||||
Env.setContext(Env.getCtx(), I_AD_UserPreference.COLUMNNAME_MigrationScriptComment, "testLogMigrationScript");
|
||||
assertTrue(Env.isLogMigrationScript(MProduct.Table_Name), "Unexpected Log Migration Script Y/N value for MProduct");
|
||||
String fileName = Convert.getMigrationScriptFileName("testLogMigrationScript");
|
||||
String folderPg = Convert.getMigrationScriptFolder("postgresql");
|
||||
String folderOr = Convert.getMigrationScriptFolder("oracle");
|
||||
|
||||
MProductCategory lotLevel = new MProductCategory(Env.getCtx(), 0, null);
|
||||
lotLevel.setName("testLogMigrationScript");
|
||||
lotLevel.saveEx();
|
||||
MProduct product = null;
|
||||
try {
|
||||
MProductCategoryAcct lotLevelAcct = MProductCategoryAcct.get(lotLevel.get_ID(), as.get_ID());
|
||||
lotLevelAcct = new MProductCategoryAcct(Env.getCtx(), lotLevelAcct);
|
||||
lotLevelAcct.setCostingLevel(MAcctSchema.COSTINGLEVEL_BatchLot);
|
||||
lotLevelAcct.saveEx();
|
||||
|
||||
product = new MProduct(Env.getCtx(), 0, null);
|
||||
product.setM_Product_Category_ID(lotLevel.get_ID());
|
||||
product.setName("testLogMigrationScript");
|
||||
product.setProductType(MProduct.PRODUCTTYPE_Item);
|
||||
product.setIsStocked(true);
|
||||
product.setIsSold(true);
|
||||
product.setIsPurchased(true);
|
||||
product.setC_UOM_ID(DictionaryIDs.C_UOM.EACH.id);
|
||||
product.setC_TaxCategory_ID(DictionaryIDs.C_TaxCategory.STANDARD.id);
|
||||
product.setM_AttributeSet_ID(DictionaryIDs.M_AttributeSet.FERTILIZER_LOT.id);
|
||||
product.saveEx();
|
||||
} finally {
|
||||
rollback();
|
||||
|
||||
if (product != null) {
|
||||
product.set_TrxName(null);
|
||||
product.deleteEx(true);
|
||||
}
|
||||
|
||||
lotLevel.deleteEx(true);
|
||||
}
|
||||
|
||||
File file = new File(folderPg + fileName);
|
||||
assertTrue(file.exists(), "Not found: " + folderPg + fileName);
|
||||
file.delete();
|
||||
file = new File(folderOr + fileName);
|
||||
assertTrue(file.exists(), "Not found: " + folderOr + fileName);
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue