IDEMPIERE-2675: Adding custom table support in Tree

This commit is contained in:
Carlos Ruiz 2015-08-05 12:42:53 -05:00
parent a1702112f1
commit 3b86669894
6 changed files with 177 additions and 22 deletions

View File

@ -0,0 +1,55 @@
SET SQLBLANKLINES ON
SET DEFINE OFF
-- IDEMPIERE-2675 Supporting tree on any custom table
-- Aug 5, 2015 11:07:44 AM COT
UPDATE AD_Ref_List SET IsActive='N',Updated=TO_DATE('2015-08-05 11:07:44','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=888
;
-- Aug 5, 2015 11:07:47 AM COT
UPDATE AD_Ref_List SET IsActive='N',Updated=TO_DATE('2015-08-05 11:07:47','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=891
;
-- Aug 5, 2015 11:07:52 AM COT
UPDATE AD_Ref_List SET IsActive='N',Updated=TO_DATE('2015-08-05 11:07:52','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=889
;
-- Aug 5, 2015 11:07:55 AM COT
UPDATE AD_Ref_List SET IsActive='N',Updated=TO_DATE('2015-08-05 11:07:55','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=890
;
-- Aug 5, 2015 11:15:48 AM COT
UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_DATE('2015-08-05 11:15:48','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=115
;
-- Aug 5, 2015 11:15:59 AM COT
UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_DATE('2015-08-05 11:15:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=118
;
-- Aug 5, 2015 11:16:01 AM COT
UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_DATE('2015-08-05 11:16:01','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=116
;
-- Aug 5, 2015 11:16:04 AM COT
UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_DATE('2015-08-05 11:16:04','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=117
;
-- Aug 5, 2015 11:25:19 AM COT
UPDATE AD_Column SET IsUpdateable='N',Updated=TO_DATE('2015-08-05 11:25:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212
;
-- Aug 5, 2015 11:25:59 AM COT
UPDATE AD_Column SET MandatoryLogic='@TreeType@=''TL''',Updated=TO_DATE('2015-08-05 11:25:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212
;
-- Aug 5, 2015 11:29:40 AM COT
INSERT INTO AD_Val_Rule (AD_Val_Rule_ID,Name,Type,Code,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,AD_Val_Rule_UU) VALUES (200083,'AD_Table with IsSummary','S','EXISTS (SELECT * FROM AD_Column c WHERE AD_Table.AD_Table_ID=c.AD_Table_ID AND c.ColumnName=''IsSummary'' AND c.IsActive=''Y'') AND AD_Table.IsView=''N''',0,0,'Y',TO_DATE('2015-08-05 11:29:39','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2015-08-05 11:29:39','YYYY-MM-DD HH24:MI:SS'),100,'D','8a00a911-354b-40c8-9cfa-a40ec65df11d')
;
-- Aug 5, 2015 11:29:51 AM COT
UPDATE AD_Column SET AD_Val_Rule_ID=200083,Updated=TO_DATE('2015-08-05 11:29:51','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212
;
SELECT register_migration_script('201508051109_IDEMPIERE-2675.sql') FROM dual
;

View File

@ -1,4 +1,3 @@
-- Jun 18, 2015 10:47:07 AM IST
INSERT INTO AD_Column (SeqNoSelection,AD_Column_ID,IsAlwaysUpdateable,IsSyncDatabase,AD_Client_ID,AD_Org_ID,CreatedBy,Updated,UpdatedBy,EntityType,IsSecure,IsEncrypted,IsParent,IsMandatory,IsIdentifier,SeqNo,Help,Version,FieldLength,IsKey,IsTranslated,Created,IsUpdateable,IsAutocomplete,IsAllowLogging,IsAllowCopy,Description,ColumnName,Name,IsSelectionColumn,AD_Column_UU,IsActive,IsToolbarButton,FKConstraintType,AD_Element_ID,AD_Reference_ID,AD_Table_ID) VALUES (0,212212,'N','N',0,0,100,TO_TIMESTAMP('2015-06-18 10:47:06','YYYY-MM-DD HH24:MI:SS'),100,'D','N','N','N','N','N',0,'The Database Table provides the information of the table definition',0,10,'N','N',TO_TIMESTAMP('2015-06-18 10:47:06','YYYY-MM-DD HH24:MI:SS'),'Y','N','Y','Y','Database Table information','AD_Table_ID','Table','N','cd639a6d-243f-4737-80b7-e953534cafa6','Y','N','N',126,19,288)
;

View File

@ -0,0 +1,52 @@
-- IDEMPIERE-2675 Supporting tree on any custom table
-- Aug 5, 2015 11:07:44 AM COT
UPDATE AD_Ref_List SET IsActive='N',Updated=TO_TIMESTAMP('2015-08-05 11:07:44','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=888
;
-- Aug 5, 2015 11:07:47 AM COT
UPDATE AD_Ref_List SET IsActive='N',Updated=TO_TIMESTAMP('2015-08-05 11:07:47','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=891
;
-- Aug 5, 2015 11:07:52 AM COT
UPDATE AD_Ref_List SET IsActive='N',Updated=TO_TIMESTAMP('2015-08-05 11:07:52','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=889
;
-- Aug 5, 2015 11:07:55 AM COT
UPDATE AD_Ref_List SET IsActive='N',Updated=TO_TIMESTAMP('2015-08-05 11:07:55','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=890
;
-- Aug 5, 2015 11:15:48 AM COT
UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_TIMESTAMP('2015-08-05 11:15:48','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=115
;
-- Aug 5, 2015 11:15:59 AM COT
UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_TIMESTAMP('2015-08-05 11:15:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=118
;
-- Aug 5, 2015 11:16:01 AM COT
UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_TIMESTAMP('2015-08-05 11:16:01','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=116
;
-- Aug 5, 2015 11:16:04 AM COT
UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_TIMESTAMP('2015-08-05 11:16:04','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=117
;
-- Aug 5, 2015 11:25:19 AM COT
UPDATE AD_Column SET IsUpdateable='N',Updated=TO_TIMESTAMP('2015-08-05 11:25:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212
;
-- Aug 5, 2015 11:25:59 AM COT
UPDATE AD_Column SET MandatoryLogic='@TreeType@=''TL''',Updated=TO_TIMESTAMP('2015-08-05 11:25:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212
;
-- Aug 5, 2015 11:29:40 AM COT
INSERT INTO AD_Val_Rule (AD_Val_Rule_ID,Name,Type,Code,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,AD_Val_Rule_UU) VALUES (200083,'AD_Table with IsSummary','S','EXISTS (SELECT * FROM AD_Column c WHERE AD_Table.AD_Table_ID=c.AD_Table_ID AND c.ColumnName=''IsSummary'' AND c.IsActive=''Y'') AND AD_Table.IsView=''N''',0,0,'Y',TO_TIMESTAMP('2015-08-05 11:29:39','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2015-08-05 11:29:39','YYYY-MM-DD HH24:MI:SS'),100,'D','8a00a911-354b-40c8-9cfa-a40ec65df11d')
;
-- Aug 5, 2015 11:29:51 AM COT
UPDATE AD_Column SET AD_Val_Rule_ID=200083,Updated=TO_TIMESTAMP('2015-08-05 11:29:51','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212
;
SELECT register_migration_script('201508051109_IDEMPIERE-2675.sql') FROM dual
;

View File

@ -29,6 +29,7 @@ import java.util.logging.Level;
import javax.sql.RowSet;
import org.compiere.print.MPrintColor;
import org.compiere.util.CCache;
import org.compiere.util.CLogMgt;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
@ -111,6 +112,8 @@ public class MTree extends MTree_Base
/** Logger */
private static CLogger s_log = CLogger.getCLogger(MTree.class);
/** Cache */
private static CCache<String,Integer> tree_cache = new CCache<String,Integer>("AD_Tree_ID", 5);
/**************************************************************************
* Get default (oldest) complete AD_Tree_ID for KeyColumn.
@ -121,6 +124,10 @@ public class MTree extends MTree_Base
*/
public static int getDefaultAD_Tree_ID (int AD_Client_ID, String keyColumnName)
{
String key = AD_Client_ID + "|" + keyColumnName;
if (tree_cache.containsKey(key))
return tree_cache.get(key);
s_log.config(keyColumnName);
if (keyColumnName == null || keyColumnName.length() == 0)
return 0;
@ -160,14 +167,19 @@ public class MTree extends MTree_Base
else
{
String tableName = keyColumnName.substring(0, keyColumnName.length() - 3);
String query = "SELECT tr.AD_Tree_ID FROM AD_Tree tr inner join AD_Table t on (tr.AD_Table_ID=t.AD_Table_ID) WHERE tr.AD_Client_ID=? AND tr.TreeType='"
+ TREETYPE_Table
+ " ' AND tr.IsActive='Y' AND tr.IsAllNodes='Y' AND t.TableName = ?";
int treeID = DB.getSQLValue(null, query, Env.getAD_Client_ID(Env.getCtx()),tableName);
String query = "SELECT tr.AD_Tree_ID "
+ "FROM AD_Tree tr "
+ "JOIN AD_Table t ON (tr.AD_Table_ID=t.AD_Table_ID) "
+ "WHERE tr.AD_Client_ID=? AND tr.TreeType=? AND tr.IsActive='Y' AND tr.IsAllNodes='Y' AND t.TableName = ? "
+ "ORDER BY tr.AD_Tree_ID";
int treeID = DB.getSQLValueEx(null, query, Env.getAD_Client_ID(Env.getCtx()), TREETYPE_Table, tableName);
if (treeID != -1)
if (treeID != -1) {
tree_cache.put(key, treeID);
return treeID;
}
s_log.log(Level.SEVERE, "Could not map " + keyColumnName);
tree_cache.put(key, 0);
return 0;
}
@ -197,6 +209,7 @@ public class MTree extends MTree_Base
pstmt = null;
}
tree_cache.put(key, AD_Tree_ID);
return AD_Tree_ID;
} // getDefaultAD_Tree_ID

View File

@ -190,10 +190,6 @@ public class MTree_Base extends X_AD_Tree
treeType.equals(TREETYPE_User3) ||
treeType.equals(TREETYPE_User4))
sourceTable = "C_ElementValue";
// else if (treeType.equals(TREETYPE_User1))
// sourceTable = "??";
// end afalcone
return sourceTable;
} // getSourceTableName
@ -300,6 +296,11 @@ public class MTree_Base extends X_AD_Tree
public String getSourceTableName (boolean tableNameOnly)
{
String tableName = getSourceTableName(getTreeType());
if (tableName == null)
{
if (getAD_Table_ID() > 0)
tableName = MTable.getTableName(getCtx(), getAD_Table_ID());
}
if (tableNameOnly)
return tableName;
if ("M_Product".equals(tableName))
@ -343,18 +344,22 @@ public class MTree_Base extends X_AD_Tree
if (!isActive() || !isAllNodes())
setIsDefault(false);
String tableName = getSourceTableName(true);
MTable table = MTable.get(getCtx(), tableName);
if (table.getColumnIndex("IsSummary") < 0) {
// IsSummary is mandatory column to have a tree
log.saveError("Error", "IsSummary column required for tree tables");
return false;
}
if (isTreeDrivenByValue()) {
String tableName = getSourceTableName(true);
MTable table = MTable.get(getCtx(), tableName);
// Value and IsSummary are mandatory columns to have a tree driven by Value
if ( table.getColumn("Value") == null
|| table.getColumn("IsSummary") == null) {
if (table.getColumnIndex("Value") < 0) {
// Value is mandatory column to have a tree driven by Value
setIsTreeDrivenByValue(false);
}
}
return true;
} // beforeSabe
} // beforeSave
/**
* After Save

View File

@ -2241,6 +2241,15 @@ public abstract class PO
insertTranslations();
else
updateTranslations();
// table with potential tree
if (get_ColumnIndex("IsSummary") >= 0) {
if (newRecord)
insert_Tree(MTree_Base.TREETYPE_Table);
int idxValue = get_ColumnIndex("Value");
if (newRecord || (idxValue >= 0 && is_ValueChanged(idxValue)))
update_Tree(MTree_Base.TREETYPE_Table);
}
}
//
try
@ -3250,6 +3259,9 @@ public abstract class PO
{
//
deleteTranslations(localTrxName);
if (get_ColumnIndex("IsSummary") >= 0) {
delete_Tree(MTree_Base.TREETYPE_Table);
}
// Delete Cascade AD_Table_ID/Record_ID (Attachments, ..)
PO_Record.deleteCascade(AD_Table_ID, Record_ID, localTrxName);
@ -3859,6 +3871,8 @@ public abstract class PO
.append(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_Table.equals(treeType))
sb.append(" AND t.AD_Table_ID=").append(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(")");
@ -3895,16 +3909,27 @@ public abstract class PO
return;
String tableName = MTree_Base.getNodeTableName(treeType);
String sourceTableName = MTree_Base.getSourceTableName(treeType);
String sourceTableName;
String whereTree;
Object[] parameters;
if (MTree_Base.TREETYPE_Table.equals(treeType)) {
sourceTableName = this.get_TableName();
whereTree = "TreeType=? AND AD_Table_ID=?";
parameters = new Object[]{treeType, this.get_Table_ID()};
} else {
sourceTableName = MTree_Base.getSourceTableName(treeType);
whereTree = "TreeType=?";
parameters = new Object[]{treeType};
}
String updateSeqNo = "UPDATE " + tableName + " SET SeqNo=SeqNo+1 WHERE Parent_ID=? AND SeqNo>=? AND AD_Tree_ID=?";
String update = "UPDATE " + tableName + " SET SeqNo=?, Parent_ID=? WHERE Node_ID=? AND AD_Tree_ID=?";
String selMinSeqNo = "SELECT COALESCE(MIN(tn.SeqNo),-1) FROM AD_TreeNode tn JOIN " + sourceTableName + " n ON (tn.Node_ID=n." + sourceTableName + "_ID) WHERE tn.Parent_ID=? AND tn.AD_Tree_ID=? AND n.Value>?";
String selMaxSeqNo = "SELECT COALESCE(MAX(tn.SeqNo)+1,999) FROM AD_TreeNode tn JOIN " + sourceTableName + " n ON (tn.Node_ID=n." + sourceTableName + "_ID) WHERE tn.Parent_ID=? AND tn.AD_Tree_ID=? AND n.Value<?";
List<MTree_Base> trees = new Query(getCtx(), MTree_Base.Table_Name, "TreeType=?", get_TrxName())
List<MTree_Base> trees = new Query(getCtx(), MTree_Base.Table_Name, whereTree, get_TrxName())
.setClient_ID()
.setOnlyActiveRecords(true)
.setParameters(treeType)
.setParameters(parameters)
.list();
for (MTree_Base tree : trees) {
@ -3948,8 +3973,11 @@ public abstract class PO
// IDEMPIERE-2453
StringBuilder countSql = new StringBuilder("SELECT COUNT(*) FROM ")
.append(MTree_Base.getNodeTableName(treeType))
.append(" WHERE Parent_ID=?");
int cnt = DB.getSQLValue( get_TrxName(), countSql.toString(), id);
.append(" n JOIN AD_Tree t ON n.AD_Tree_ID=t.AD_Tree_ID")
.append(" WHERE Parent_ID=? AND t.TreeType=?");
if (MTree_Base.TREETYPE_Table.equals(treeType))
countSql.append(" AND t.AD_Table_ID=").append(get_Table_ID());
int cnt = DB.getSQLValueEx( get_TrxName(), countSql.toString(), id, treeType);
if (cnt > 0)
throw new AdempiereException(Msg.getMsg(Env.getCtx(),"NoParentDelete", new Object[] {cnt}));
@ -3958,7 +3986,10 @@ public abstract class PO
.append(" n WHERE Node_ID=").append(id)
.append(" AND EXISTS (SELECT * FROM AD_Tree t "
+ "WHERE t.AD_Tree_ID=n.AD_Tree_ID AND t.TreeType='")
.append(treeType).append("')");
.append(treeType).append("'");
if (MTree_Base.TREETYPE_Table.equals(treeType))
sb.append(" AND t.AD_Table_ID=").append(get_Table_ID());
sb.append(")");
int no = DB.executeUpdate(sb.toString(), get_TrxName());
if (no > 0) {
if (log.isLoggable(Level.FINE)) log.fine("#" + no + " - TreeType=" + treeType);