diff --git a/migration/iD10/oracle/202210311420_IDEMPIERE-5468.sql b/migration/iD10/oracle/202210311420_IDEMPIERE-5468.sql new file mode 100644 index 0000000000..4e636ce2b8 --- /dev/null +++ b/migration/iD10/oracle/202210311420_IDEMPIERE-5468.sql @@ -0,0 +1,26 @@ +-- IDEMPIERE-5468 +SELECT register_migration_script('202210311420_IDEMPIERE-5468.sql') FROM dual; + +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Oct 31, 2022, 2:20:52 PM BRT +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 (203724,0,0,'Y',TO_TIMESTAMP('2022-10-31 14:20:51','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-10-31 14:20:51','YYYY-MM-DD HH24:MI:SS'),100,'IsNotClause','Not Clause','Indicates if a chosen multiple component value must be negate','Not Clause','D','d50d4b2c-6ba8-4165-859e-9e307d6b1421') +; + +-- Oct 31, 2022, 2:22:00 PM BRT +INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,AD_Table_ID,ColumnName,DefaultValue,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215631,0,'Not Clause','Indicates if a chosen multiple component value must be negate',283,'IsNotClause','N',1,'N','N','Y','N','N',0,'N',20,0,0,'Y',TO_TIMESTAMP('2022-10-31 14:22:00','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-10-31 14:22:00','YYYY-MM-DD HH24:MI:SS'),100,203724,'Y','N','D','N','N','N','Y','cf018b7d-a0bd-4500-b9fc-ec57ef490418','Y',0,'N','N','N','N') +; + +-- Oct 31, 2022, 2:22:06 PM BRT +ALTER TABLE AD_PInstance_Para ADD IsNotClause CHAR(1) DEFAULT 'N' CHECK (IsNotClause IN ('Y','N')) NOT NULL +; + +-- Oct 31, 2022, 2:23:59 PM BRT +ALTER TABLE AD_PInstance_Para MODIFY IsNotClause CHAR(1) DEFAULT 'N' +; + +-- Oct 31, 2022, 2:28:32 PM BRT +INSERT INTO AD_Field (AD_Field_ID,Name,Description,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan) VALUES (207410,'Not Clause','Indicates if a chosen multiple component value must be negate',664,215631,'Y',1,140,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2022-10-31 14:28:32','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-10-31 14:28:32','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','8fa2857f-38a3-4f31-bff6-d6baa56ea352','Y',140,2,2) +; + diff --git a/migration/iD10/oracle/202211301704_IDEMPIERE-5468.sql b/migration/iD10/oracle/202211301704_IDEMPIERE-5468.sql new file mode 100644 index 0000000000..f6fc2b9e28 --- /dev/null +++ b/migration/iD10/oracle/202211301704_IDEMPIERE-5468.sql @@ -0,0 +1,22 @@ +-- IDEMPIERE-5468 +SELECT register_migration_script('202211301704_IDEMPIERE-5468.sql') FROM dual; + +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Nov 30, 2022, 5:04:32 PM BRT +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Include selected values',0,0,'Y',TO_TIMESTAMP('2022-11-30 17:04:32','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-11-30 17:04:32','YYYY-MM-DD HH24:MI:SS'),100,1000000,'IncludeSelectedValues','U','9794b1f5-cd91-4d8d-95ba-a2f53eca1af5') +; + +-- Nov 30, 2022, 5:04:49 PM BRT +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Exclude selected values',0,0,'Y',TO_TIMESTAMP('2022-11-30 17:04:49','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-11-30 17:04:49','YYYY-MM-DD HH24:MI:SS'),100,1000001,'ExcludeSelectedValues','U','439b142f-26ab-4224-8e38-d42fc3757750') +; + +-- Nov 30, 2022, 5:04:54 PM BRT +UPDATE AD_Message SET EntityType='D',Updated=TO_TIMESTAMP('2022-11-30 17:04:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=1000001 +; + +-- Nov 30, 2022, 5:05:08 PM BRT +UPDATE AD_Message SET EntityType='D',Updated=TO_TIMESTAMP('2022-11-30 17:05:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=1000000 +; + diff --git a/migration/iD10/postgresql/202210311420_IDEMPIERE-5468.sql b/migration/iD10/postgresql/202210311420_IDEMPIERE-5468.sql new file mode 100644 index 0000000000..f2d68e1fec --- /dev/null +++ b/migration/iD10/postgresql/202210311420_IDEMPIERE-5468.sql @@ -0,0 +1,23 @@ +-- IDEMPIERE-5468 +SELECT register_migration_script('202210311420_IDEMPIERE-5468.sql') FROM dual; + +-- Oct 31, 2022, 2:20:52 PM BRT +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 (203724,0,0,'Y',TO_TIMESTAMP('2022-10-31 14:20:51','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-10-31 14:20:51','YYYY-MM-DD HH24:MI:SS'),100,'IsNotClause','Not Clause','Indicates if a chosen multiple component value must be negate','Not Clause','D','d50d4b2c-6ba8-4165-859e-9e307d6b1421') +; + +-- Oct 31, 2022, 2:22:00 PM BRT +INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,AD_Table_ID,ColumnName,DefaultValue,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215631,0,'Not Clause','Indicates if a chosen multiple component value must be negate',283,'IsNotClause','N',1,'N','N','Y','N','N',0,'N',20,0,0,'Y',TO_TIMESTAMP('2022-10-31 14:22:00','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-10-31 14:22:00','YYYY-MM-DD HH24:MI:SS'),100,203724,'Y','N','D','N','N','N','Y','cf018b7d-a0bd-4500-b9fc-ec57ef490418','Y',0,'N','N','N','N') +; + +-- Oct 31, 2022, 2:22:06 PM BRT +ALTER TABLE AD_PInstance_Para ADD COLUMN IsNotClause CHAR(1) DEFAULT 'N' CHECK (IsNotClause IN ('Y','N')) NOT NULL +; + +-- Oct 31, 2022, 2:23:59 PM BRT +INSERT INTO t_alter_column values('ad_pinstance_para','IsNotClause','CHAR(1)',null,'N') +; + +-- Oct 31, 2022, 2:28:32 PM BRT +INSERT INTO AD_Field (AD_Field_ID,Name,Description,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan) VALUES (207410,'Not Clause','Indicates if a chosen multiple component value must be negate',664,215631,'Y',1,140,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2022-10-31 14:28:32','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-10-31 14:28:32','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','8fa2857f-38a3-4f31-bff6-d6baa56ea352','Y',140,2,2) +; + diff --git a/migration/iD10/postgresql/202211301704_IDEMPIERE-5468.sql b/migration/iD10/postgresql/202211301704_IDEMPIERE-5468.sql new file mode 100644 index 0000000000..e69184da91 --- /dev/null +++ b/migration/iD10/postgresql/202211301704_IDEMPIERE-5468.sql @@ -0,0 +1,19 @@ +-- IDEMPIERE-5468 +SELECT register_migration_script('202211301704_IDEMPIERE-5468.sql') FROM dual; + +-- Nov 30, 2022, 5:04:32 PM BRT +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Include selected values',0,0,'Y',TO_TIMESTAMP('2022-11-30 17:04:32','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-11-30 17:04:32','YYYY-MM-DD HH24:MI:SS'),100,1000000,'IncludeSelectedValues','U','9794b1f5-cd91-4d8d-95ba-a2f53eca1af5') +; + +-- Nov 30, 2022, 5:04:49 PM BRT +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Exclude selected values',0,0,'Y',TO_TIMESTAMP('2022-11-30 17:04:49','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-11-30 17:04:49','YYYY-MM-DD HH24:MI:SS'),100,1000001,'ExcludeSelectedValues','U','439b142f-26ab-4224-8e38-d42fc3757750') +; + +-- Nov 30, 2022, 5:04:54 PM BRT +UPDATE AD_Message SET EntityType='D',Updated=TO_TIMESTAMP('2022-11-30 17:04:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=1000001 +; + +-- Nov 30, 2022, 5:05:08 PM BRT +UPDATE AD_Message SET EntityType='D',Updated=TO_TIMESTAMP('2022-11-30 17:05:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=1000000 +; + diff --git a/org.adempiere.base/src/org/compiere/db/AdempiereDatabase.java b/org.adempiere.base/src/org/compiere/db/AdempiereDatabase.java index 64b3309c19..b6661bb2ff 100644 --- a/org.adempiere.base/src/org/compiere/db/AdempiereDatabase.java +++ b/org.adempiere.base/src/org/compiere/db/AdempiereDatabase.java @@ -348,6 +348,14 @@ public interface AdempiereDatabase */ public String intersectClauseForCSV(String columnName, String csv); + /** + * @param columnName + * @param csv comma separated value + * @param isNotClause + * @return subset sql clause + */ + public String intersectClauseForCSV(String columnName, String csv, boolean isNotClause); + /** * Quote column name if necessary (usually to avoid conflict with reserved keywords) * @param columnName diff --git a/org.adempiere.base/src/org/compiere/model/I_AD_PInstance_Para.java b/org.adempiere.base/src/org/compiere/model/I_AD_PInstance_Para.java index 33e93f43fc..c23c6543ee 100644 --- a/org.adempiere.base/src/org/compiere/model/I_AD_PInstance_Para.java +++ b/org.adempiere.base/src/org/compiere/model/I_AD_PInstance_Para.java @@ -22,7 +22,7 @@ import org.compiere.util.KeyNamePair; /** Generated Interface for AD_PInstance_Para * @author iDempiere (generated) - * @version Release 9 + * @version Release 10 */ public interface I_AD_PInstance_Para { @@ -44,8 +44,8 @@ public interface I_AD_PInstance_Para /** Column name AD_Client_ID */ public static final String COLUMNNAME_AD_Client_ID = "AD_Client_ID"; - /** Get Client. - * Client/Tenant for this installation. + /** Get Tenant. + * Tenant for this installation. */ public int getAD_Client_ID(); @@ -53,12 +53,12 @@ public interface I_AD_PInstance_Para public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID"; /** Set Organization. - * Organizational entity within client + * Organizational entity within tenant */ public void setAD_Org_ID (int AD_Org_ID); /** Get Organization. - * Organizational entity within client + * Organizational entity within tenant */ public int getAD_Org_ID(); @@ -137,14 +137,18 @@ public interface I_AD_PInstance_Para */ public boolean isActive(); - /** Column name ParameterName */ - public static final String COLUMNNAME_ParameterName = "ParameterName"; + /** Column name IsNotClause */ + public static final String COLUMNNAME_IsNotClause = "IsNotClause"; - /** Set Parameter Name */ - public void setParameterName (String ParameterName); + /** Set Is not clause. + * Indicates if a chosen multiple component value must be negate + */ + public void setIsNotClause (boolean IsNotClause); - /** Get Parameter Name */ - public String getParameterName(); + /** Get Is not clause. + * Indicates if a chosen multiple component value must be negate + */ + public boolean isNotClause(); /** Column name P_Date */ public static final String COLUMNNAME_P_Date = "P_Date"; @@ -224,6 +228,15 @@ public interface I_AD_PInstance_Para */ public String getP_String_To(); + /** Column name ParameterName */ + public static final String COLUMNNAME_ParameterName = "ParameterName"; + + /** Set Parameter Name */ + public void setParameterName (String ParameterName); + + /** Get Parameter Name */ + public String getParameterName(); + /** Column name SeqNo */ public static final String COLUMNNAME_SeqNo = "SeqNo"; diff --git a/org.adempiere.base/src/org/compiere/model/MQuery.java b/org.adempiere.base/src/org/compiere/model/MQuery.java index 8d868411c2..cc0070382e 100644 --- a/org.adempiere.base/src/org/compiere/model/MQuery.java +++ b/org.adempiere.base/src/org/compiere/model/MQuery.java @@ -93,7 +93,8 @@ public class MQuery implements Serializable, Cloneable + "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, pp.Query, " // 10..13 - + "pp.AD_Process_ID, pp.AD_Process_Para_ID " // 14..15 + + "pp.AD_Process_ID, pp.AD_Process_Para_ID, " // 14..15 + + "ip.IsNotClause " + "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" @@ -105,7 +106,8 @@ public class MQuery implements Serializable, Cloneable 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, pp.Query, " - + "pp.AD_Process_ID, pp.AD_Process_Para_ID " + + "pp.AD_Process_ID, pp.AD_Process_Para_ID, " + + "ip.IsNotClause " + "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" @@ -163,10 +165,12 @@ public class MQuery implements Serializable, Cloneable Reference_ID = udpp.getAD_Reference_ID(); String P_Query = rs.getString(13); + boolean isNotClause = "Y".equals(rs.getString(16)); // 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); + + "; Name=" + Name + ", Info=" + Info + "-" + Info_To + ", Range=" + isRange + + ", Not Clause=" + isNotClause); // //custom query or column not exists - render as report parameters if (!Util.isEmpty(P_Query) || (table != null && table.getColumn(ParameterName) == null)) @@ -185,17 +189,17 @@ public class MQuery implements Serializable, Cloneable String columnName = TableName + "." + ParameterName; int cnt = DB.getSQLValueEx(null, "SELECT Count(*) From AD_Column WHERE IsActive='Y' AND AD_Client_ID=0 AND Upper(ColumnName)=? AND AD_Reference_ID=?", ParameterName.toUpperCase(), DisplayType.ChosenMultipleSelectionList); if (cnt > 0) - query.addRestriction(DB.intersectClauseForCSV(columnName, P_String), MQuery.EQUAL, Name, Info); + query.addRestriction(DB.intersectClauseForCSV(columnName, P_String, isNotClause), isNotClause ? MQuery.NOT_EQUAL : MQuery.EQUAL, Name, Info); else - query.addRestriction(DB.inClauseForCSV(columnName, P_String), MQuery.EQUAL, Name, Info); + query.addRestriction(DB.inClauseForCSV(columnName, P_String, isNotClause), isNotClause ? MQuery.NOT_EQUAL : MQuery.EQUAL, Name, Info); } else if (Reference_ID == DisplayType.ChosenMultipleSelectionTable || Reference_ID == DisplayType.ChosenMultipleSelectionSearch) { String columnName = TableName + "." + ParameterName; if (columnName.endsWith("_ID")) - query.addRestriction(DB.inClauseForCSV(columnName, P_String), MQuery.EQUAL, Name, Info); + query.addRestriction(DB.inClauseForCSV(columnName, P_String, isNotClause), isNotClause ? MQuery.NOT_EQUAL : MQuery.EQUAL, Name, Info); else - query.addRestriction(DB.intersectClauseForCSV(columnName, P_String), MQuery.EQUAL, Name, Info); + query.addRestriction(DB.intersectClauseForCSV(columnName, P_String, isNotClause), isNotClause ? MQuery.NOT_EQUAL : MQuery.EQUAL, Name, Info); } else { diff --git a/org.adempiere.base/src/org/compiere/model/X_AD_PInstance_Para.java b/org.adempiere.base/src/org/compiere/model/X_AD_PInstance_Para.java index da58e2df2d..ad3b66db46 100644 --- a/org.adempiere.base/src/org/compiere/model/X_AD_PInstance_Para.java +++ b/org.adempiere.base/src/org/compiere/model/X_AD_PInstance_Para.java @@ -26,7 +26,7 @@ import org.compiere.util.KeyNamePair; /** Generated Model for AD_PInstance_Para * @author iDempiere (generated) - * @version Release 9 - $Id$ */ + * @version Release 10 - $Id$ */ @org.adempiere.base.Model(table="AD_PInstance_Para") public class X_AD_PInstance_Para extends PO implements I_AD_PInstance_Para, I_Persistent { @@ -34,7 +34,7 @@ public class X_AD_PInstance_Para extends PO implements I_AD_PInstance_Para, I_Pe /** * */ - private static final long serialVersionUID = 20220116L; + private static final long serialVersionUID = 20221028L; /** Standard Constructor */ public X_AD_PInstance_Para (Properties ctx, int AD_PInstance_Para_ID, String trxName) @@ -43,6 +43,8 @@ public class X_AD_PInstance_Para extends PO implements I_AD_PInstance_Para, I_Pe /** if (AD_PInstance_Para_ID == 0) { setAD_PInstance_ID (0); + setIsNotClause (false); +// N setSeqNo (0); } */ } @@ -54,6 +56,8 @@ public class X_AD_PInstance_Para extends PO implements I_AD_PInstance_Para, I_Pe /** if (AD_PInstance_Para_ID == 0) { setAD_PInstance_ID (0); + setIsNotClause (false); +// N setSeqNo (0); } */ } @@ -160,29 +164,29 @@ public class X_AD_PInstance_Para extends PO implements I_AD_PInstance_Para, I_Pe return (String)get_Value(COLUMNNAME_Info_To); } - /** Set Parameter Name. - @param ParameterName Parameter Name + /** Set Is not clause. + @param IsNotClause Indicates if a chosen multiple component value must be negate */ - public void setParameterName (String ParameterName) + public void setIsNotClause (boolean IsNotClause) { - set_Value (COLUMNNAME_ParameterName, ParameterName); + set_Value (COLUMNNAME_IsNotClause, Boolean.valueOf(IsNotClause)); } - /** Get Parameter Name. - @return Parameter Name */ - public String getParameterName() + /** Get Is not clause. + @return Indicates if a chosen multiple component value must be negate + */ + public boolean isNotClause() { - return (String)get_Value(COLUMNNAME_ParameterName); + Object oo = get_Value(COLUMNNAME_IsNotClause); + if (oo != null) + { + if (oo instanceof Boolean) + return ((Boolean)oo).booleanValue(); + return "Y".equals(oo); + } + return false; } - /** Get Record ID/ColumnName - @return ID/ColumnName pair - */ - public KeyNamePair getKeyNamePair() - { - return new KeyNamePair(get_ID(), getParameterName()); - } - /** Set Process Date. @param P_Date Process Parameter */ @@ -285,6 +289,29 @@ public class X_AD_PInstance_Para extends PO implements I_AD_PInstance_Para, I_Pe return (String)get_Value(COLUMNNAME_P_String_To); } + /** Set Parameter Name. + @param ParameterName Parameter Name + */ + public void setParameterName (String ParameterName) + { + set_Value (COLUMNNAME_ParameterName, ParameterName); + } + + /** Get Parameter Name. + @return Parameter Name */ + public String getParameterName() + { + return (String)get_Value(COLUMNNAME_ParameterName); + } + + /** Get Record ID/ColumnName + @return ID/ColumnName pair + */ + public KeyNamePair getKeyNamePair() + { + return new KeyNamePair(get_ID(), getParameterName()); + } + /** Set Sequence. @param SeqNo Method of ordering records; lowest number comes first */ diff --git a/org.adempiere.base/src/org/compiere/process/ProcessInfoParameter.java b/org.adempiere.base/src/org/compiere/process/ProcessInfoParameter.java index 44c212c599..6d2674909c 100644 --- a/org.adempiere.base/src/org/compiere/process/ProcessInfoParameter.java +++ b/org.adempiere.base/src/org/compiere/process/ProcessInfoParameter.java @@ -52,12 +52,27 @@ public class ProcessInfoParameter implements Serializable * @param info_To to info */ public ProcessInfoParameter (String parameterName, Object parameter, Object parameter_To, String info, String info_To) + { + this(parameterName, parameter, parameter_To, info, info_To, false); + } // ProcessInfoParameter + + /** + * Construct Parameter + * @param parameterName parameter name + * @param parameter parameter + * @param parameter_To to parameter + * @param info info + * @param info_To to info + * @param isNotClause is not clause + */ + public ProcessInfoParameter (String parameterName, Object parameter, Object parameter_To, String info, String info_To, boolean isNotClause) { setParameterName (parameterName); setParameter (parameter); setParameter_To (parameter_To); setInfo (info); setInfo_To (info_To); + setIsNotClause(isNotClause); } // ProcessInfoParameter private String m_ParameterName; @@ -65,6 +80,7 @@ public class ProcessInfoParameter implements Serializable private Object m_Parameter_To; private String m_Info = ""; private String m_Info_To = ""; + private boolean m_IsNotClause; /** * String Representation @@ -261,6 +277,14 @@ public class ProcessInfoParameter implements Serializable { return m_ParameterName; } + + /** + * Method isNotClause + * @return boolean + */ + public boolean isNotClause() { + return m_IsNotClause; + } /** * Method setInfo @@ -312,6 +336,14 @@ public class ProcessInfoParameter implements Serializable { m_ParameterName = ParameterName; } + + /** + * Method setIsNotClause + * @param IsNotClause boolean + */ + public void setIsNotClause(boolean IsNotClause) { + this.m_IsNotClause = IsNotClause; + } /** * Return the value of the parameter as a comma separated integer string. Validate every value is an integer and throws NumberFormatException if one of the value is not a valid integer. diff --git a/org.adempiere.base/src/org/compiere/process/ProcessInfoUtil.java b/org.adempiere.base/src/org/compiere/process/ProcessInfoUtil.java index c240156410..2a3bc8bc35 100644 --- a/org.adempiere.base/src/org/compiere/process/ProcessInfoUtil.java +++ b/org.adempiere.base/src/org/compiere/process/ProcessInfoUtil.java @@ -187,7 +187,8 @@ public class ProcessInfoUtil String sql = "SELECT p.ParameterName," // 1 + " p.P_String,p.P_String_To, p.P_Number,p.P_Number_To," // 2/3 4/5 + " p.P_Date,p.P_Date_To, p.Info,p.Info_To, " // 6/7 8/9 - + " i.AD_Client_ID, i.AD_Org_ID, i.AD_User_ID " // 10..12 + + " i.AD_Client_ID, i.AD_Org_ID, i.AD_User_ID, " // 10..12 + + " p.IsNotClause " // 13 + "FROM AD_PInstance_Para p" + " INNER JOIN AD_PInstance i ON (p.AD_PInstance_ID=i.AD_PInstance_ID) " + "WHERE p.AD_PInstance_ID=? " @@ -221,7 +222,8 @@ public class ProcessInfoUtil String Info = rs.getString(8); String Info_To = rs.getString(9); // - list.add (new ProcessInfoParameter(ParameterName, Parameter, Parameter_To, Info, Info_To)); + boolean isNotClause = "Y".equals(rs.getString(13)); + list.add (new ProcessInfoParameter(ParameterName, Parameter, Parameter_To, Info, Info_To, isNotClause)); // if (pi.getAD_Client_ID() == null) pi.setAD_Client_ID (rs.getInt(10)); diff --git a/org.adempiere.base/src/org/compiere/util/DB.java b/org.adempiere.base/src/org/compiere/util/DB.java index 5adbeec3c7..c78fec4ee7 100644 --- a/org.adempiere.base/src/org/compiere/util/DB.java +++ b/org.adempiere.base/src/org/compiere/util/DB.java @@ -2602,15 +2602,32 @@ public final class DB return ProxyFactory.newCPreparedStatement(resultSetType, resultSetConcurrency, sql, trxName); } + /** * @param columnName * @param csv comma separated value * @return IN clause */ public static String inClauseForCSV(String columnName, String csv) + { + return inClauseForCSV(columnName, csv, false); + } + + /** + * @param columnName + * @param csv comma separated value + * @param isNotClause + * @return IN clause + */ + public static String inClauseForCSV(String columnName, String csv, boolean isNotClause) { StringBuilder builder = new StringBuilder(); - builder.append(columnName).append(" IN ("); + builder.append(columnName); + + if(isNotClause) + builder.append(" NOT "); + + builder.append(" IN ("); String[] values = csv.split("[,]"); for(int i = 0; i < values.length; i++) { @@ -2653,7 +2670,18 @@ public final class DB */ public static String intersectClauseForCSV(String columnName, String csv) { - return getDatabase().intersectClauseForCSV(columnName, csv); + return intersectClauseForCSV(columnName, csv, false); + } + /** + * + * @param columnName + * @param csv + * @param isNotClause + * @return intersect sql clause + */ + public static String intersectClauseForCSV(String columnName, String csv, boolean isNotClause) + { + return getDatabase().intersectClauseForCSV(columnName, csv, isNotClause); } /** diff --git a/org.adempiere.base/src/org/compiere/util/DisplayType.java b/org.adempiere.base/src/org/compiere/util/DisplayType.java index 1bddb96e4e..8a6abe5b4f 100644 --- a/org.adempiere.base/src/org/compiere/util/DisplayType.java +++ b/org.adempiere.base/src/org/compiere/util/DisplayType.java @@ -503,6 +503,20 @@ public final class DisplayType return false; } + /** + * + * @param displayType + * @return true if displayType is a ChosenMultipleSelection + */ + public static boolean isChosenMultipleSelection(int displayType) + { + if (displayType == ChosenMultipleSelectionList || displayType == ChosenMultipleSelectionSearch + || displayType == ChosenMultipleSelectionTable) + return true; + else + return false; + } + /************************************************************************** * Return Format for numeric DisplayType * @param displayType Display Type (default Number) diff --git a/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java b/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java index 0d9c3a8f3f..494f0b2f7b 100644 --- a/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java +++ b/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java @@ -1013,6 +1013,7 @@ public class ReportStarter implements ProcessCall, ClientProcess .append(",").append(X_AD_PInstance_Para.COLUMNNAME_P_Date_To) .append(",").append(X_AD_PInstance_Para.COLUMNNAME_Info) .append(",").append(X_AD_PInstance_Para.COLUMNNAME_Info_To) + .append(",").append(X_AD_PInstance_Para.COLUMNNAME_IsNotClause) .append(" FROM ").append(X_AD_PInstance_Para.Table_Name) .append(" WHERE ").append(X_AD_PInstance_Para.COLUMNNAME_AD_PInstance_ID+"=?"); PreparedStatement pstmt = null; @@ -1067,8 +1068,10 @@ public class ReportStarter implements ProcessCall, ClientProcess // Add parameter info - teo_sarca FR [ 2581145 ] String info = rs.getString(8); String infoTo = rs.getString(9); + String isNotClause = rs.getString(10); params.put(name+"_Info1", (info != null ? info : "")); params.put(name+"_Info2", (infoTo != null ? infoTo : "")); + params.put(name+"_NOT", isNotClause); } } catch (SQLException e) diff --git a/org.adempiere.ui.zk/WEB-INF/src/metainfo/zk/lang-addon.xml b/org.adempiere.ui.zk/WEB-INF/src/metainfo/zk/lang-addon.xml index 9705b859aa..eb25926ccf 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/metainfo/zk/lang-addon.xml +++ b/org.adempiere.ui.zk/WEB-INF/src/metainfo/zk/lang-addon.xml @@ -57,6 +57,6 @@ Copyright (C) 2007 Ashley G Ramdass (ADempiere WebUI). - + diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessParameterPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessParameterPanel.java index 0c00dab058..3117ea991b 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessParameterPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessParameterPanel.java @@ -28,6 +28,7 @@ import java.util.logging.Level; import org.adempiere.webui.Extensions; import org.adempiere.webui.LayoutUtils; +import org.adempiere.webui.component.Button; import org.adempiere.webui.component.Column; import org.adempiere.webui.component.Columns; import org.adempiere.webui.component.EditorBox; @@ -47,6 +48,7 @@ import org.adempiere.webui.editor.WebEditorFactory; import org.adempiere.webui.event.ContextMenuListener; import org.adempiere.webui.event.ValueChangeEvent; import org.adempiere.webui.event.ValueChangeListener; +import org.adempiere.webui.factory.ButtonFactory; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.util.ZKUpdateUtil; import org.adempiere.webui.window.DateRangeButton; @@ -425,10 +427,10 @@ public class ProcessParameterPanel extends Panel implements div.appendChild(label.getDecorator()); row.appendChild(div); // + Div box = new Div(); + box.setStyle("display: flex; align-items: center;"); + ZKUpdateUtil.setWidth(box, "100%"); if (voF.isRange) { - Div box = new Div(); - box.setStyle("display: flex; align-items: center;"); - ZKUpdateUtil.setWidth(box, "100%"); box.appendChild(editor.getComponent()); ZKUpdateUtil.setWidth((HtmlBasedComponent) editor.getComponent(), "49%"); // @@ -470,11 +472,23 @@ public class ProcessParameterPanel extends Panel implements box.appendChild(dateRangeButton); } } else { - row.appendChild(editor.getComponent()); + box.appendChild(editor.getComponent()); m_mFields2.add(null); m_wEditors2.add(null); m_separators.add(null); + if(DisplayType.isChosenMultipleSelection(mField.getDisplayType())) { + Button bNegate = ButtonFactory.createButton("", null, null); + bNegate.setTooltiptext(Msg.translate(Env.getCtx(), "IncludeSelectedValues")); + bNegate.setIconSclass("z-icon-IncludeSelected"); + bNegate.setSclass("btn-negate btn-negate-include"); + bNegate.setAttribute("isSelected", false); + bNegate.setVisible(false); + bNegate.addActionListener(this); + box.appendChild(bNegate); + editor.getComponent().setAttribute("isNotClause", bNegate); + } } + row.appendChild(box); } // createField private void setEditorPlaceHolder(WEditor editor, String msg) { @@ -590,6 +604,10 @@ public class ProcessParameterPanel extends Panel implements MPInstancePara para = params[i]; if ( mField.getColumnName().equals(para.getParameterName()) ) { + Button bNegate = null; + if(editor.getComponent() != null) + bNegate = (Button) editor.getComponent().getAttribute("isNotClause"); + if (para.getP_Date() != null || para.getP_Date_To() != null ) { editor.setValue(para.getP_Date()); @@ -624,6 +642,23 @@ public class ProcessParameterPanel extends Panel implements valueChange(changeEvent); } + if(bNegate != null) { + if(para.isNotClause()) { + bNegate.setTooltiptext(Msg.translate(Env.getCtx(), "ExcludeSelectedValues")); + bNegate.setIconSclass("z-icon-ExcludeSelected"); + bNegate.setSclass("btn-negate btn-negate-exclude"); + bNegate.setAttribute("isSelected", true); + } + else { + bNegate.setTooltiptext(Msg.translate(Env.getCtx(), "IncludeSelectedValues")); + bNegate.setIconSclass("z-icon-IncludeSelected"); + bNegate.setSclass("btn-negate btn-negate-include"); + bNegate.setAttribute("isSelected", false); + } + + if(editor.getValue() != null) + bNegate.setVisible(true); + } log.fine(para.toString()); break; } @@ -726,6 +761,14 @@ public class ProcessParameterPanel extends Panel implements GridField mField = (GridField) m_mFields.get(i); para.setParameterName(mField.getColumnName()); + Button bNegate = null; + if(editor.getComponent() != null) + bNegate = (Button)editor.getComponent().getAttribute("isNotClause"); + + if(bNegate != null) { + para.setIsNotClause((boolean)bNegate.getAttribute("isSelected")); + } + // Date if (result instanceof Timestamp || result2 instanceof Timestamp) { if (result instanceof Timestamp) @@ -918,7 +961,39 @@ public class ProcessParameterPanel extends Panel implements dynamicDisplay(); } else if (event.getName().equals("onPostEditorValueChange")) { - onPostEditorValueChange((WEditor)event.getData()); + WEditor editor = (WEditor)event.getData(); + onPostEditorValueChange(editor); + if(editor.getComponent() != null) { + Button bNegate = (Button) editor.getComponent().getAttribute("isNotClause"); + if (bNegate != null) { + if (editor.getValue() != null) { + bNegate.setVisible(true); + } else { + bNegate.setVisible(false); + bNegate.setAttribute("isSelected", false); + bNegate.setTooltiptext(Msg.translate(Env.getCtx(), "IncludeSelectedValues")); + bNegate.setIconSclass("z-icon-IncludeSelected"); + bNegate.setSclass("btn-negate btn-negate-include"); + } + } + } + } + else if (event.getName().equals(Events.ON_CLICK)) { + if(event.getTarget() instanceof Button) { + Button bNegate = (Button)event.getTarget(); + boolean isSelected = !(boolean)bNegate.getAttribute("isSelected"); + if(isSelected) { + bNegate.setTooltiptext(Msg.translate(Env.getCtx(), "ExcludeSelectedValues")); + bNegate.setIconSclass("z-icon-ExcludeSelected"); + bNegate.setSclass("btn-negate btn-negate-exclude"); + } + else { + bNegate.setTooltiptext(Msg.translate(Env.getCtx(), "IncludeSelectedValues")); + bNegate.setIconSclass("z-icon-IncludeSelected"); + bNegate.setSclass("btn-negate btn-negate-include"); + } + bNegate.setAttribute("isSelected", isSelected); + } } } @@ -1009,6 +1084,13 @@ public class ProcessParameterPanel extends Panel implements m_separators.get(i).setVisible(true); m_wEditors2.get(i).setVisible(true); } + + Button bNegate = null; + if(editor.getComponent() != null) + bNegate = (Button) editor.getComponent().getAttribute("isNotClause"); + if(bNegate != null) { + bNegate.setVisible(true); + } } boolean rw = mField.isEditablePara(true); // r/w - check if field is Editable editor.setReadWrite(rw); @@ -1026,6 +1108,13 @@ public class ProcessParameterPanel extends Panel implements m_separators.get(i).setVisible(false); m_wEditors2.get(i).setVisible(false); } + + Button bNegate = null; + if(editor.getComponent() != null) + bNegate = (Button) editor.getComponent().getAttribute("isNotClause"); + if(bNegate != null) { + bNegate.setVisible(false); + } } editor.setMandatory(mField.isMandatory(true)); editor.updateStyle(); diff --git a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/button.css.dsp b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/button.css.dsp index 5cf2102cfd..3378df75c1 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/button.css.dsp +++ b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/button.css.dsp @@ -138,4 +138,29 @@ } .btn-cancel.z-button [class^="z-icon-"]:before { color: red; -} \ No newline at end of file +} + +.btn-negate.z-button { + background: none; + border: none; + margin: 0px !important; + padding: 0px; + min-width: 16px; + width: 16px; + height: 10px; + min-height:10px; + font-size: 14px; + font-weight: lighter; + position: absolute; + top: 5px; + right: 25px; +} +.btn-negate.z-button:active, .btn-negate.z-button:focus { + border: none; + box-shadow: none; +} +.btn-negate.z-button [class^="z-icon-"] { + font-size: 14px; + padding: 0px; + line-height: 14px; +} diff --git a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/font-icons.css.dsp b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/font-icons.css.dsp index d5a8d2ce3d..6c7526590c 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/font-icons.css.dsp +++ b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/font-icons.css.dsp @@ -66,6 +66,9 @@ color: yellow; font-family: FontAwesome; } +.z-icon-ExcludeSelected:before { + content: "\f05e"; +} .z-icon-Expand:before { content: "\f0d7"; } @@ -117,6 +120,9 @@ .z-icon-Import:before { content: "\f0ee"; } +.z-icon-IncludeSelected:before { + content: "\f05d"; +} .z-icon-Info:before { content: "\f0eb"; } diff --git a/org.compiere.db.oracle.provider/src/org/compiere/db/DB_Oracle.java b/org.compiere.db.oracle.provider/src/org/compiere/db/DB_Oracle.java index 8be02c361c..6ad62abea2 100644 --- a/org.compiere.db.oracle.provider/src/org/compiere/db/DB_Oracle.java +++ b/org.compiere.db.oracle.provider/src/org/compiere/db/DB_Oracle.java @@ -962,17 +962,26 @@ public class DB_Oracle implements AdempiereDatabase return builder.toString(); } - + @Override public String intersectClauseForCSV(String columnName, String csv) { + return intersectClauseForCSV(columnName, csv, false); + } + + @Override + public String intersectClauseForCSV(String columnName, String csv, boolean isNotClause) { StringBuilder builder = new StringBuilder(); builder.append("toTableOfVarchar2(") .append(columnName) .append(")"); builder.append(" MULTISET INTERSECT ") .append("toTableOfVarchar2(") - .append(DB.TO_STRING(csv)) - .append(") IS NOT EMPTY"); + .append(DB.TO_STRING(csv)).append(") IS "); + + if(!isNotClause) + builder.append("NOT "); + + builder.append("EMPTY"); return builder.toString(); } diff --git a/org.compiere.db.postgresql.provider/src/org/compiere/db/DB_PostgreSQL.java b/org.compiere.db.postgresql.provider/src/org/compiere/db/DB_PostgreSQL.java index 1b93587680..eb0999152c 100755 --- a/org.compiere.db.postgresql.provider/src/org/compiere/db/DB_PostgreSQL.java +++ b/org.compiere.db.postgresql.provider/src/org/compiere/db/DB_PostgreSQL.java @@ -1049,14 +1049,21 @@ public class DB_PostgreSQL implements AdempiereDatabase @Override public String intersectClauseForCSV(String columnName, String csv) { + return intersectClauseForCSV(columnName, csv, false); + } + + @Override + public String intersectClauseForCSV(String columnName, String csv, boolean isNotClause) { StringBuilder builder = new StringBuilder(); - builder.append("string_to_array(") + if(isNotClause) + builder.append("NOT"); + builder.append("(string_to_array(") .append(columnName) .append(",',')"); builder.append(" && "); //intersect builder.append("string_to_array(") .append(DB.TO_STRING(csv)) - .append(",',')"); + .append(",','))"); return builder.toString(); }