IDEMPIERE-4904 Add custom query clause support to report parameter (#821)

This commit is contained in:
hengsin 2021-08-12 21:02:01 +08:00 committed by GitHub
parent 5ede13acee
commit 184e8191e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 228 additions and 6 deletions

View File

@ -0,0 +1,18 @@
SET SQLBLANKLINES ON
SET DEFINE OFF
-- Aug 9, 2021 12:54:11 PM GMT+08:00
-- IDEMPIERE-4904 Add custom query clause support to report parameter
INSERT INTO AD_Column (AD_Column_ID,SeqNoSelection,IsSyncDatabase,Version,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,IsAutocomplete,IsAllowLogging,MandatoryLogic,AD_Column_UU,Updated,IsUpdateable,ColumnName,Description,Name,IsAllowCopy,IsActive,CreatedBy,UpdatedBy,IsAlwaysUpdateable,AD_Client_ID,AD_Org_ID,Created,EntityType,IsEncrypted,IsSecure,AD_Element_ID,AD_Reference_ID,AD_Table_ID,IsToolbarButton) VALUES (213185,0,'N',0,'N','N','N',0,'N',2000,'N','N','N','Y',NULL,'04f9c29a-7806-444f-a313-45204f9efa84',TO_DATE('2021-08-09 12:54:09','YYYY-MM-DD HH24:MI:SS'),'Y','Query','SQL','Query','N','Y',100,100,'N',0,0,TO_DATE('2021-08-09 12:54:09','YYYY-MM-DD HH24:MI:SS'),'D','N','N',53775,14,285,'N')
;
-- Aug 9, 2021 12:54:23 PM GMT+08:00
ALTER TABLE AD_Process_Para ADD Query VARCHAR2(2000 CHAR) DEFAULT NULL
;
-- Aug 9, 2021 12:57:18 PM GMT+08:00
INSERT INTO AD_Field (SortNo,AD_Field_ID,IsEncrypted,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,IsReadOnly,DisplayLogic,AD_Org_ID,Updated,Description,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,CreatedBy,UpdatedBy,IsActive,IsDisplayedGrid,SeqNoGrid,XPosition,IsQuickEntry,AD_Client_ID,Created,ColumnSpan,NumLines,IsAdvancedField,IsDefaultFocus,AD_Column_ID,EntityType,AD_Tab_ID) VALUES (0,205193,'N',0,'N','N',270,'Y','N','@IsReport@=Y',0,TO_DATE('2021-08-09 12:57:17','YYYY-MM-DD HH24:MI:SS'),'SQL','Query','ed208c1d-a58a-43d5-912f-af8294e5d276','Y','N',100,100,'Y','Y',270,1,'N',0,TO_DATE('2021-08-09 12:57:17','YYYY-MM-DD HH24:MI:SS'),5,3,'N','N',213185,'D',246)
;
SELECT register_migration_script('202108091122_IDEMPIERE-4904.sql') FROM dual
;

View File

@ -0,0 +1,15 @@
-- Aug 9, 2021 12:54:11 PM GMT+08:00
-- IDEMPIERE-4904 Add custom query clause support to report parameter
INSERT INTO AD_Column (AD_Column_ID,SeqNoSelection,IsSyncDatabase,Version,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,IsAutocomplete,IsAllowLogging,MandatoryLogic,AD_Column_UU,Updated,IsUpdateable,ColumnName,Description,Name,IsAllowCopy,IsActive,CreatedBy,UpdatedBy,IsAlwaysUpdateable,AD_Client_ID,AD_Org_ID,Created,EntityType,IsEncrypted,IsSecure,AD_Element_ID,AD_Reference_ID,AD_Table_ID,IsToolbarButton) VALUES (213185,0,'N',0,'N','N','N',0,'N',2000,'N','N','N','Y',NULL,'04f9c29a-7806-444f-a313-45204f9efa84',TO_TIMESTAMP('2021-08-09 12:54:09','YYYY-MM-DD HH24:MI:SS'),'Y','Query','SQL','Query','N','Y',100,100,'N',0,0,TO_TIMESTAMP('2021-08-09 12:54:09','YYYY-MM-DD HH24:MI:SS'),'D','N','N',53775,14,285,'N')
;
-- Aug 9, 2021 12:54:23 PM GMT+08:00
ALTER TABLE AD_Process_Para ADD COLUMN Query VARCHAR(2000) DEFAULT NULL
;
-- Aug 9, 2021 12:57:18 PM GMT+08:00
INSERT INTO AD_Field (SortNo,AD_Field_ID,IsEncrypted,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,IsReadOnly,DisplayLogic,AD_Org_ID,Updated,Description,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,CreatedBy,UpdatedBy,IsActive,IsDisplayedGrid,SeqNoGrid,XPosition,IsQuickEntry,AD_Client_ID,Created,ColumnSpan,NumLines,IsAdvancedField,IsDefaultFocus,AD_Column_ID,EntityType,AD_Tab_ID) VALUES (0,205193,'N',0,'N','N',270,'Y','N','@IsReport@=Y',0,TO_TIMESTAMP('2021-08-09 12:57:17','YYYY-MM-DD HH24:MI:SS'),'SQL','Query','ed208c1d-a58a-43d5-912f-af8294e5d276','Y','N',100,100,'Y','Y',270,1,'N',0,TO_TIMESTAMP('2021-08-09 12:57:17','YYYY-MM-DD HH24:MI:SS'),5,3,'N','N',213185,'D',246)
;
SELECT register_migration_script('202108091122_IDEMPIERE-4904.sql') FROM dual
;

View File

@ -414,6 +414,19 @@ public interface I_AD_Process_Para
/** Get Placeholder2 */
public String getPlaceholder2();
/** Column name Query */
public static final String COLUMNNAME_Query = "Query";
/** Set Query.
* SQL
*/
public void setQuery (String Query);
/** Get Query.
* SQL
*/
public String getQuery();
/** Column name ReadOnlyLogic */
public static final String COLUMNNAME_ReadOnlyLogic = "ReadOnlyLogic";

View File

@ -21,7 +21,11 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
@ -29,8 +33,10 @@ import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.Evaluatee;
import org.compiere.util.KeyNamePair;
import org.compiere.util.Msg;
import org.compiere.util.Util;
import org.compiere.util.ValueNamePair;
/**
@ -79,12 +85,14 @@ public class MQuery implements Serializable, Cloneable
if (rows < 1)
return reportQuery;
Map<String, String> parameterMap = new HashMap<>();
List<String> queryList = new ArrayList<>();
boolean trl = !Env.isBaseLanguage(ctx, "AD_Process_Para");
if (!trl)
SQL = "SELECT ip.ParameterName,ip.P_String,ip.P_String_To," // 1..3
+ "ip.P_Number,ip.P_Number_To," // 4..5
+ "ip.P_Date,ip.P_Date_To, ip.Info,ip.Info_To, " // 6..9
+ "pp.Name, pp.IsRange, pp.AD_Reference_ID " // 10..12
+ "pp.Name, pp.IsRange, pp.AD_Reference_ID, pp.Query " // 10..13
+ "FROM AD_PInstance_Para ip, AD_PInstance i, AD_Process_Para pp "
+ "WHERE i.AD_PInstance_ID=ip.AD_PInstance_ID"
+ " AND pp.AD_Process_ID=i.AD_Process_ID"
@ -95,7 +103,7 @@ public class MQuery implements Serializable, Cloneable
else
SQL = "SELECT ip.ParameterName,ip.P_String,ip.P_String_To, ip.P_Number,ip.P_Number_To,"
+ "ip.P_Date,ip.P_Date_To, ip.Info,ip.Info_To, "
+ "ppt.Name, pp.IsRange, pp.AD_Reference_ID "
+ "ppt.Name, pp.IsRange, pp.AD_Reference_ID, pp.Query "
+ "FROM AD_PInstance_Para ip, AD_PInstance i, AD_Process_Para pp, AD_Process_Para_Trl ppt "
+ "WHERE i.AD_PInstance_ID=ip.AD_PInstance_ID"
+ " AND pp.AD_Process_ID=i.AD_Process_ID"
@ -147,13 +155,14 @@ public class MQuery implements Serializable, Cloneable
boolean isRange = "Y".equals(rs.getString(11));
//
int Reference_ID = rs.getInt(12);
String P_Query = rs.getString(13);
//
if (s_log.isLoggable(Level.FINE)) s_log.fine(ParameterName + " S=" + P_String + "-" + P_String_To
+ ", N=" + P_Number + "-" + P_Number_To + ", D=" + P_Date + "-" + P_Date_To
+ "; Name=" + Name + ", Info=" + Info + "-" + Info_To + ", Range=" + isRange);
//
//custom query or column not exists - render as report parameters
if (table != null && table.getColumn(ParameterName) == null)
if (!Util.isEmpty(P_Query) || (table != null && table.getColumn(ParameterName) == null))
{
query = reportQuery.getReportProcessQuery();
}
@ -161,6 +170,7 @@ public class MQuery implements Serializable, Cloneable
//-------------------------------------------------------------
if (P_String != null)
{
parameterMap.put(ParameterName, P_String);
if (P_String_To == null)
{
if (Reference_ID == DisplayType.ChosenMultipleSelectionList)
@ -191,14 +201,18 @@ public class MQuery implements Serializable, Cloneable
}
}
else
{
query.addRangeRestriction(ParameterName,
P_String, P_String_To, Name, Info, Info_To);
parameterMap.put("To_"+ParameterName, P_String_To);
}
}
// Number
else if (P_Number != null || P_Number_To != null)
{
if (P_Number_To == null)
{
parameterMap.put(ParameterName, P_Number.toString());
if (isRange)
query.addRestriction(ParameterName, MQuery.GREATER_EQUAL,
P_Number, Name, Info);
@ -208,12 +222,16 @@ public class MQuery implements Serializable, Cloneable
}
else // P_Number_To != null
{
if (P_Number == null)
parameterMap.put("To_"+ParameterName, P_Number_To.toString());
if (P_Number == null)
query.addRestriction(ParameterName, MQuery.LESS_EQUAL,
P_Number_To, Name, Info);
else
{
query.addRangeRestriction(ParameterName,
P_Number, P_Number_To, Name, Info, Info_To);
parameterMap.put(ParameterName, P_Number.toString());
}
}
}
// Date
@ -224,6 +242,7 @@ public class MQuery implements Serializable, Cloneable
if (P_Date_To == null)
{
parameterMap.put(ParameterName, DisplayType.getDateFormat().format(P_Date));
if (isRange)
query.addRestriction(paramName, MQuery.GREATER_EQUAL, P_Date, Name, Info);
else
@ -231,12 +250,21 @@ public class MQuery implements Serializable, Cloneable
}
else // P_Date_To != null
{
parameterMap.put("To_"+ParameterName, DisplayType.getDateFormat().format(P_Date_To));
if (P_Date == null)
query.addRestriction(paramName, MQuery.LESS_EQUAL, P_Date_To, Name, Info);
else
{
query.addRangeRestriction(paramName, P_Date, P_Date_To, Name, Info, Info_To);
parameterMap.put(ParameterName, DisplayType.getDateFormat().format(P_Date));
}
}
}
//keep custom query for later context parsing
if (!Util.isEmpty(P_Query) && (parameterMap.containsKey(ParameterName) || parameterMap.containsKey("To_"+ParameterName)))
queryList.add(P_Query);
//add to reportprocessquery if new restriction added to reportquery
if (query == reportQuery && reportQuery.getReportProcessQuery() != null
&& reportQuery.getRestrictionCount() > restrictionCount)
@ -254,10 +282,76 @@ public class MQuery implements Serializable, Cloneable
DB.close(rs, pstmt);
rs = null; pstmt = null;
}
//add custom query
if (queryList.size() > 0)
{
QueryEvaluatee evaluatee= new QueryEvaluatee(parameterMap);
for(String query : queryList)
{
if (query.indexOf("@") >= 0)
{
query = parseVariable(evaluatee, query, false);
reportQuery.addRestriction(query);
}
}
}
if (s_log.isLoggable(Level.INFO)) s_log.info(reportQuery.toString());
return reportQuery;
} // get
private static String parseVariable(Evaluatee evaluatee, String expression, boolean ignoreUnparseable) {
if (expression == null || expression.length() == 0)
return "";
String token;
String inStr = new String(expression);
StringBuilder outStr = new StringBuilder();
int i = inStr.indexOf('@');
while (i != -1)
{
outStr.append(inStr.substring(0, i)); // up to @
inStr = inStr.substring(i+1, inStr.length()); // from first @
int j = inStr.indexOf('@'); // next @
if (j < 0)
{
s_log.log(Level.SEVERE, "No second tag: " + inStr);
return ""; // no second tag
}
token = inStr.substring(0, j);
//format string
String format = "";
int f = token.indexOf('<');
if (f > 0 && token.endsWith(">")) {
format = token.substring(f+1, token.length()-1);
token = token.substring(0, f);
}
String v = evaluatee.get_ValueAsString(token);
if (!Util.isEmpty(v)) {
if (format != null && format.length() > 0) {
MessageFormat mf = new MessageFormat(format);
outStr.append(mf.format(v));
} else {
outStr.append(v.toString());
}
} else if (!ignoreUnparseable) {
return "";
}
inStr = inStr.substring(j+1, inStr.length()); // from second @
i = inStr.indexOf('@');
}
outStr.append(inStr); // add the rest of the string
return outStr.toString();
}
/**
* Get Zoom Column Name.
* Converts Synonyms like SalesRep_ID to AD_User_ID
@ -1350,3 +1444,68 @@ class Restriction implements Serializable
} // getInfoDisplay
} // Restriction
class QueryEvaluatee implements Evaluatee {
private Map<String, String> parameterMap;
public QueryEvaluatee(Map<String, String> parameterMap) {
this.parameterMap = parameterMap;
}
/**
* Get Variable Value (Evaluatee)
* @param variableName name
* @return value
*/
public String get_ValueAsString (Properties ctx, String variableName)
{
//ref column
String foreignColumn = "";
int f = variableName.indexOf('.');
if (f > 0) {
foreignColumn = variableName.substring(f+1, variableName.length());
variableName = variableName.substring(0, f);
}
String value = null;
if (variableName.startsWith("#") || variableName.startsWith("$")) {
value = Env.getContext(ctx, variableName);
} else {
value = parameterMap.get(variableName);
}
if (!Util.isEmpty(value) && !Util.isEmpty(foreignColumn) && variableName.endsWith("_ID")) {
String refValue = "";
int id = 0;
try {
id = Integer.parseInt(value);
} catch (Exception e){}
if (id > 0) {
if (variableName.startsWith("#") || variableName.startsWith("$")) {
variableName = variableName.substring(1);
} else if (variableName.indexOf("|") > 0) {
variableName = variableName.substring(variableName.lastIndexOf("|")+1);
}
String foreignTable = null;
if (foreignColumn.indexOf(".") > 0) {
foreignTable = foreignColumn.substring(0, foreignColumn.indexOf("."));
} else {
foreignTable = variableName.substring(0, variableName.length()-3);
}
MTable t = MTable.get(Env.getCtx(), foreignTable);
if (t != null) {
refValue = DB.getSQLValueString(null,
"SELECT " + foreignColumn + " FROM " + foreignTable + " WHERE "
+ foreignTable + "_ID = ?", id);
}
}
return refValue;
}
return value;
} // get_ValueAsString
@Override
public String get_ValueAsString(String variableName) {
return get_ValueAsString(Env.getCtx(), variableName);
}
}

View File

@ -30,7 +30,7 @@ public class X_AD_Process_Para extends PO implements I_AD_Process_Para, I_Persis
/**
*
*/
private static final long serialVersionUID = 20210723L;
private static final long serialVersionUID = 20210809L;
/** Standard Constructor */
public X_AD_Process_Para (Properties ctx, int AD_Process_Para_ID, String trxName)
@ -43,7 +43,7 @@ public class X_AD_Process_Para extends PO implements I_AD_Process_Para, I_Persis
setAD_Reference_ID (0);
setColumnName (null);
setEntityType (null);
// @SQL=select get_sysconfig('DEFAULT_ENTITYTYPE','U',0,0) from dual
// @SQL=SELECT CASE WHEN '@P|AdempiereSys:N@'='Y' THEN 'D' ELSE get_sysconfig('DEFAULT_ENTITYTYPE','U',0,0) END FROM Dual
setFieldLength (0);
setIsAutocomplete (false);
// N
@ -618,6 +618,23 @@ public class X_AD_Process_Para extends PO implements I_AD_Process_Para, I_Persis
return (String)get_Value(COLUMNNAME_Placeholder2);
}
/** Set Query.
@param Query
SQL
*/
public void setQuery (String Query)
{
set_Value (COLUMNNAME_Query, Query);
}
/** Get Query.
@return SQL
*/
public String getQuery ()
{
return (String)get_Value(COLUMNNAME_Query);
}
/** Set Read Only Logic.
@param ReadOnlyLogic
Logic to determine if field is read only (applies only when field is read-write)