IDEMPIERE-5315 Mismatch in queries WWFActivity.getWhereActivities and DPActivitiesModel.getWorkflowCount (#1363)

* IDEMPIERE-5315 Mismatch in queries WWFActivity.getWhereActivities and DPActivitiesModel.getWorkflowCount

- Found that DPActivities is deprecated, so deprecated too the DPActivitiesModel
- Also found that DefaultDesktop had a dependency to show the total of DPActivities, refactored to do the same with the new DPDocumentStatus
- Moved the query to MWFActivity to use where required
- Refactored JDBC to Query

* Better name for method

* serialVersionUID
This commit is contained in:
Carlos Ruiz 2022-06-14 13:19:19 +02:00 committed by GitHub
parent 34458fa8a1
commit 39a5fe5663
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 87 additions and 203 deletions

View File

@ -85,7 +85,7 @@ public class MWFActivity extends X_AD_WF_Activity implements Runnable
/** /**
* *
*/ */
private static final long serialVersionUID = -3282235931100223816L; private static final long serialVersionUID = 8180781075902940080L;
private static final String CURRENT_WORKFLOW_PROCESS_INFO_ATTR = "Workflow.ProcessInfo"; private static final String CURRENT_WORKFLOW_PROCESS_INFO_ATTR = "Workflow.ProcessInfo";
@ -2126,4 +2126,31 @@ public class MWFActivity extends X_AD_WF_Activity implements Runnable
trx.removeTrxEventListener(this); trx.removeTrxEventListener(this);
} }
} }
/**
* Where to get the pending activities related to a User (unprocessed and suspended)
* The where returned requires the AD_User_ID parameter 5 times, and then AD_Client_ID
* @return Where Clause
*/
public static String getWhereUserPendingActivities() {
final String where =
"AD_WF_Activity.Processed='N' AND AD_WF_Activity.WFState='OS' AND ("
// Owner of Activity
+ " AD_WF_Activity.AD_User_ID=?" // #1
// Invoker (if no invoker = all)
+ " OR EXISTS (SELECT * FROM AD_WF_Responsible r WHERE AD_WF_Activity.AD_WF_Responsible_ID=r.AD_WF_Responsible_ID"
+ " AND r.ResponsibleType='H' AND COALESCE(r.AD_User_ID,0)=0 AND COALESCE(r.AD_Role_ID,0)=0 AND (AD_WF_Activity.AD_User_ID=? OR AD_WF_Activity.AD_User_ID IS NULL))" // #2
// Responsible User
+ " OR EXISTS (SELECT * FROM AD_WF_Responsible r WHERE AD_WF_Activity.AD_WF_Responsible_ID=r.AD_WF_Responsible_ID"
+ " AND r.ResponsibleType='H' AND r.AD_User_ID=?)" // #3
// Responsible Role
+ " OR EXISTS (SELECT * FROM AD_WF_Responsible r INNER JOIN AD_User_Roles ur ON (r.AD_Role_ID=ur.AD_Role_ID)"
+ " WHERE AD_WF_Activity.AD_WF_Responsible_ID=r.AD_WF_Responsible_ID AND r.ResponsibleType='R' AND ur.AD_User_ID=? AND ur.isActive = 'Y')" // #4
///* Manual Responsible */
+ " OR EXISTS (SELECT * FROM AD_WF_ActivityApprover r "
+ " WHERE AD_WF_Activity.AD_WF_Activity_ID=r.AD_WF_Activity_ID AND r.AD_User_ID=? AND r.isActive = 'Y')"
+ ") AND AD_WF_Activity.AD_Client_ID=?"; // #5
return where;
}
} // MWFActivity } // MWFActivity

View File

@ -50,10 +50,7 @@ import org.zkoss.zul.Div;
* Document Status Indicator * Document Status Indicator
*/ */
public class WDocumentStatusIndicator extends Panel implements EventListener<Event> { public class WDocumentStatusIndicator extends Panel implements EventListener<Event> {
/** private static final long serialVersionUID = -9076405331101242792L;
*
*/
private static final long serialVersionUID = 794746556509546913L;
/** /**
* Constructor * Constructor
@ -173,4 +170,12 @@ public class WDocumentStatusIndicator extends Panel implements EventListener<Eve
statusLabel.setText(Integer.toString(statusCount)); statusLabel.setText(Integer.toString(statusCount));
} }
/**
* Return the count for this indicator
* @return
*/
public int getStatusCount() {
return statusCount;
}
} }

View File

@ -36,9 +36,13 @@ import org.adempiere.webui.component.Grid;
import org.adempiere.webui.component.Panel; import org.adempiere.webui.component.Panel;
import org.adempiere.webui.component.Row; import org.adempiere.webui.component.Row;
import org.adempiere.webui.component.Rows; import org.adempiere.webui.component.Rows;
import org.adempiere.webui.desktop.IDesktop;
import org.compiere.model.MDocumentStatus; import org.compiere.model.MDocumentStatus;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventQueue;
import org.zkoss.zk.ui.event.EventQueues;
public class WDocumentStatusPanel extends Panel { public class WDocumentStatusPanel extends Panel {
/** /**
@ -104,9 +108,15 @@ public class WDocumentStatusPanel extends Panel {
} // init } // init
public void refresh() { public void refresh() {
int count = 0;
for (WDocumentStatusIndicator indicator : indicatorList) { for (WDocumentStatusIndicator indicator : indicatorList) {
indicator.refresh(); indicator.refresh();
if (indicator.getDocumentStatus().getAD_Client_ID() == 0)
count += indicator.getStatusCount();
} }
EventQueue<Event> queue = EventQueues.lookup(IDesktop.ACTIVITIES_EVENT_QUEUE, true);
Event event = new Event(IDesktop.ON_ACTIVITIES_CHANGED_EVENT, null, count);
queue.publish(event);
} }
public void updateUI() { public void updateUI() {

View File

@ -13,10 +13,9 @@
*****************************************************************************/ *****************************************************************************/
package org.adempiere.webui.apps.wf; package org.adempiere.webui.apps.wf;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
@ -47,10 +46,9 @@ import org.compiere.model.MLookup;
import org.compiere.model.MLookupFactory; import org.compiere.model.MLookupFactory;
import org.compiere.model.MQuery; import org.compiere.model.MQuery;
import org.compiere.model.MRefList; import org.compiere.model.MRefList;
import org.compiere.model.MRole;
import org.compiere.model.MSysConfig; import org.compiere.model.MSysConfig;
import org.compiere.model.Query;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.DisplayType; import org.compiere.util.DisplayType;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.Msg; import org.compiere.util.Msg;
@ -66,11 +64,11 @@ import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.util.Clients; import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.Borderlayout; import org.zkoss.zul.Borderlayout;
import org.zkoss.zul.Center; import org.zkoss.zul.Center;
import org.zkoss.zul.North;
import org.zkoss.zul.South;
import org.zkoss.zul.Div; import org.zkoss.zul.Div;
import org.zkoss.zul.Hbox; import org.zkoss.zul.Hbox;
import org.zkoss.zul.Html; import org.zkoss.zul.Html;
import org.zkoss.zul.North;
import org.zkoss.zul.South;
/** /**
* Direct port from WFActivity * Direct port from WFActivity
@ -319,42 +317,13 @@ public class WWFActivity extends ADForm implements EventListener<Event>
*/ */
public int getActivitiesCount() public int getActivitiesCount()
{ {
int count = 0;
String sql = "SELECT COUNT(*) FROM AD_WF_Activity a "
+ "WHERE " + getWhereActivities();
int AD_User_ID = Env.getAD_User_ID(Env.getCtx()); int AD_User_ID = Env.getAD_User_ID(Env.getCtx());
int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx()); int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx());
MRole role = MRole.get(Env.getCtx(), Env.getAD_Role_ID(Env.getCtx())); int count = new Query(Env.getCtx(), MWFActivity.Table_Name, MWFActivity.getWhereUserPendingActivities(), null)
sql = role.addAccessSQL(sql, "a", true, false); .setApplyAccessFilter(true, false)
PreparedStatement pstmt = null; .setParameters(AD_User_ID, AD_User_ID, AD_User_ID, AD_User_ID, AD_User_ID, AD_Client_ID)
ResultSet rs = null; .count();
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt (1, AD_User_ID);
pstmt.setInt (2, AD_User_ID);
pstmt.setInt (3, AD_User_ID);
pstmt.setInt (4, AD_User_ID);
pstmt.setInt (5, AD_User_ID);
pstmt.setInt (6, AD_Client_ID);
rs = pstmt.executeQuery ();
if (rs.next ()) {
count = rs.getInt(1);
}
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
}
finally
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
}
return count; return count;
} }
/** /**
@ -369,52 +338,29 @@ public class WWFActivity extends ADForm implements EventListener<Event>
model = new ListModelTable(); model = new ListModelTable();
ArrayList<MWFActivity> list = new ArrayList<MWFActivity>();
String sql = "SELECT * FROM AD_WF_Activity a "
+ "WHERE " + getWhereActivities()
+ " ORDER BY a.Priority DESC, Created";
int AD_User_ID = Env.getAD_User_ID(Env.getCtx()); int AD_User_ID = Env.getAD_User_ID(Env.getCtx());
int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx()); int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx());
MRole role = MRole.get(Env.getCtx(), Env.getAD_Role_ID(Env.getCtx())); Iterator<MWFActivity> it = new Query(Env.getCtx(), MWFActivity.Table_Name, MWFActivity.getWhereUserPendingActivities(), null)
sql = role.addAccessSQL(sql, "a", true, false); .setApplyAccessFilter(true, false)
PreparedStatement pstmt = null; .setParameters(AD_User_ID, AD_User_ID, AD_User_ID, AD_User_ID, AD_User_ID, AD_Client_ID)
ResultSet rs = null; .setOrderBy("AD_WF_Activity.Priority DESC, AD_WF_Activity.Created")
try .iterate();
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt (1, AD_User_ID);
pstmt.setInt (2, AD_User_ID);
pstmt.setInt (3, AD_User_ID);
pstmt.setInt (4, AD_User_ID);
pstmt.setInt (5, AD_User_ID);
pstmt.setInt (6, AD_Client_ID);
rs = pstmt.executeQuery(); List<MWFActivity> list = new ArrayList<MWFActivity>();
while (rs.next ()) while (it.hasNext()) {
MWFActivity activity = it.next();
list.add (activity);
List<Object> rowData = new ArrayList<Object>();
rowData.add(activity.getPriority());
rowData.add(activity.getNodeName());
rowData.add(activity.getSummary());
model.add(rowData);
if (list.size() > MAX_ACTIVITIES_IN_LIST && MAX_ACTIVITIES_IN_LIST > 0)
{ {
MWFActivity activity = new MWFActivity(Env.getCtx(), rs, null); log.warning("More than " + MAX_ACTIVITIES_IN_LIST + " Activities - ignored");
list.add (activity); break;
List<Object> rowData = new ArrayList<Object>();
rowData.add(activity.getPriority());
rowData.add(activity.getNodeName());
rowData.add(activity.getSummary());
model.add(rowData);
if (list.size() > MAX_ACTIVITIES_IN_LIST && MAX_ACTIVITIES_IN_LIST > 0)
{
log.warning("More then 200 Activities - ignored");
break;
}
} }
} }
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
}
finally
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
}
m_activities = new MWFActivity[list.size ()]; m_activities = new MWFActivity[list.size ()];
list.toArray (m_activities); list.toArray (m_activities);
// //
@ -446,27 +392,6 @@ public class WWFActivity extends ADForm implements EventListener<Event>
return m_activities.length; return m_activities.length;
} // loadActivities } // loadActivities
private String getWhereActivities() {
final String where =
"a.Processed='N' AND a.WFState='OS' AND ("
// Owner of Activity
+ " a.AD_User_ID=?" // #1
// Invoker (if no invoker = all)
+ " OR EXISTS (SELECT * FROM AD_WF_Responsible r WHERE a.AD_WF_Responsible_ID=r.AD_WF_Responsible_ID"
+ " AND r.ResponsibleType='H' AND COALESCE(r.AD_User_ID,0)=0 AND COALESCE(r.AD_Role_ID,0)=0 AND (a.AD_User_ID=? OR a.AD_User_ID IS NULL))" // #2
// Responsible User
+ " OR EXISTS (SELECT * FROM AD_WF_Responsible r WHERE a.AD_WF_Responsible_ID=r.AD_WF_Responsible_ID"
+ " AND r.ResponsibleType='H' AND r.AD_User_ID=?)" // #3
// Responsible Role
+ " OR EXISTS (SELECT * FROM AD_WF_Responsible r INNER JOIN AD_User_Roles ur ON (r.AD_Role_ID=ur.AD_Role_ID)"
+ " WHERE a.AD_WF_Responsible_ID=r.AD_WF_Responsible_ID AND r.ResponsibleType='R' AND ur.AD_User_ID=? AND ur.isActive = 'Y')" // #4
///* Manual Responsible */
+ " OR EXISTS (SELECT * FROM AD_WF_ActivityApprover r "
+ " WHERE a.AD_WF_Activity_ID=r.AD_WF_Activity_ID AND r.AD_User_ID=? AND r.isActive = 'Y')"
+ ") AND a.AD_Client_ID=?"; // #5
return where;
}
/** /**
* Reset Display * Reset Display
* @param selIndex select index * @param selIndex select index

View File

@ -13,9 +13,6 @@
*****************************************************************************/ *****************************************************************************/
package org.adempiere.webui.dashboard; package org.adempiere.webui.dashboard;
import java.util.HashMap;
import java.util.Map;
import org.adempiere.webui.component.Button; import org.adempiere.webui.component.Button;
import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.desktop.IDesktop;
import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.session.SessionManager;
@ -148,12 +145,7 @@ public class DPActivities extends DashboardPanel implements EventListener<Event>
btnUnprocessed.setLabel(labelU + " : " + noOfUnprocessed); btnUnprocessed.setLabel(labelU + " : " + noOfUnprocessed);
EventQueue<Event> queue = EventQueues.lookup(IDesktop.ACTIVITIES_EVENT_QUEUE, true); EventQueue<Event> queue = EventQueues.lookup(IDesktop.ACTIVITIES_EVENT_QUEUE, true);
Map<String, Object> map = new HashMap<String, Object>(); Event event = new Event(IDesktop.ON_ACTIVITIES_CHANGED_EVENT, null, noOfNotice + noOfRequest+ noOfWorkflow + noOfUnprocessed);
map.put("notice", noOfNotice);
map.put("request", noOfRequest);
map.put("workflow", noOfWorkflow);
map.put("unprocessed", noOfUnprocessed);
Event event = new Event(IDesktop.ON_ACTIVITIES_CHANGED_EVENT, null, map);
queue.publish(event); queue.publish(event);
} }

View File

@ -13,14 +13,11 @@
*****************************************************************************/ *****************************************************************************/
package org.adempiere.webui.dashboard; package org.adempiere.webui.dashboard;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.logging.Level;
import org.compiere.model.MRole; import org.compiere.model.MRole;
import org.compiere.util.CLogger; import org.compiere.model.Query;
import org.compiere.util.DB; import org.compiere.util.DB;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.wf.MWFActivity;
/** /**
* Dashboard item: Workflow activities, notices and requests * Dashboard item: Workflow activities, notices and requests
@ -34,10 +31,9 @@ import org.compiere.util.Env;
* Contributors: * Contributors:
* Deepak Pansheriya - showing only notes message * Deepak Pansheriya - showing only notes message
*/ */
@Deprecated // replaced with DPDocumentStatus
public class DPActivitiesModel { public class DPActivitiesModel {
private static final CLogger logger = CLogger.getCLogger(DPActivitiesModel.class);
public static boolean isShowUnprocessed() { public static boolean isShowUnprocessed() {
return (Env.getAD_Client_ID(Env.getCtx()) > 0); return (Env.getAD_Client_ID(Env.getCtx()) > 0);
} }
@ -77,52 +73,12 @@ public class DPActivitiesModel {
*/ */
public static int getWorkflowCount() public static int getWorkflowCount()
{ {
int count = 0;
String sql = "SELECT count(*) FROM AD_WF_Activity a "
+ "WHERE "
+ "a.Processed='N' AND a.WFState='OS' AND ("
// Owner of Activity
+ " a.AD_User_ID=?" // #1
// Invoker (if no invoker = all)
+ " OR EXISTS (SELECT * FROM AD_WF_Responsible r WHERE a.AD_WF_Responsible_ID=r.AD_WF_Responsible_ID"
+ " AND r.ResponsibleType='H' AND COALESCE(r.AD_User_ID,0)=0 AND COALESCE(r.AD_Role_ID,0)=0 AND (a.AD_User_ID=? OR a.AD_User_ID IS NULL))" // #2
// Responsible User
+ " OR EXISTS (SELECT * FROM AD_WF_Responsible r WHERE a.AD_WF_Responsible_ID=r.AD_WF_Responsible_ID"
+ " AND r.ResponsibleType='H' AND r.AD_User_ID=?)" // #3
// Responsible Role
+ " OR EXISTS (SELECT * FROM AD_WF_Responsible r INNER JOIN AD_User_Roles ur ON (r.AD_Role_ID=ur.AD_Role_ID)"
+ " WHERE a.AD_WF_Responsible_ID=r.AD_WF_Responsible_ID AND r.ResponsibleType='R' AND ur.AD_User_ID=?)" // #4
//
+ ") AND a.AD_Client_ID=?"; // #5
int AD_User_ID = Env.getAD_User_ID(Env.getCtx()); int AD_User_ID = Env.getAD_User_ID(Env.getCtx());
int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx()); int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx());
sql = MRole.getDefault().addAccessSQL(sql, "a", true, false); int count = new Query(Env.getCtx(), MWFActivity.Table_Name, MWFActivity.getWhereUserPendingActivities(), null)
PreparedStatement pstmt = null; .setApplyAccessFilter(true, false)
ResultSet rs = null; .setParameters(AD_User_ID, AD_User_ID, AD_User_ID, AD_User_ID, AD_User_ID, AD_Client_ID)
try .count();
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt (1, AD_User_ID);
pstmt.setInt (2, AD_User_ID);
pstmt.setInt (3, AD_User_ID);
pstmt.setInt (4, AD_User_ID);
pstmt.setInt (5, AD_Client_ID);
rs = pstmt.executeQuery ();
if (rs.next ()) {
count = rs.getInt(1);
}
}
catch (Exception e)
{
logger.log(Level.SEVERE, sql, e);
}
finally
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
}
return count; return count;
} }

View File

@ -22,7 +22,6 @@ import static org.compiere.model.SystemIDs.TREE_MENUPRIMARY;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
@ -137,13 +136,7 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
private Borderlayout layout; private Borderlayout layout;
private int noOfNotice; private int noCount;
private int noOfRequest;
private int noOfWorkflow;
private int noOfUnprocessed;
private Tabpanel homeTab; private Tabpanel homeTab;
@ -700,28 +693,11 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
} }
else if (eventName.equals(ON_ACTIVITIES_CHANGED_EVENT)) else if (eventName.equals(ON_ACTIVITIES_CHANGED_EVENT))
{ {
@SuppressWarnings("unchecked") Integer count = (Integer) event.getData();
Map<String, Object> map = (Map<String, Object>) event.getData();
Integer notice = (Integer) map.get("notice");
Integer request = (Integer) map.get("request");
Integer workflow = (Integer) map.get("workflow");
Integer unprocessed = (Integer) map.get("unprocessed");
boolean change = false; boolean change = false;
if (notice != null && notice.intValue() != noOfNotice) if (count != null && count.intValue() != noCount)
{ {
noOfNotice = notice.intValue(); change = true; noCount = count.intValue(); change = true;
}
if (request != null && request.intValue() != noOfRequest)
{
noOfRequest = request.intValue(); change = true;
}
if (workflow != null && workflow.intValue() != noOfWorkflow)
{
noOfWorkflow = workflow.intValue(); change = true;
}
if (unprocessed != null && unprocessed.intValue() != noOfUnprocessed)
{
noOfUnprocessed = unprocessed.intValue(); change = true;
} }
if (change) if (change)
updateUI(); updateUI();
@ -851,14 +827,7 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
} }
public void updateUI() { public void updateUI() {
int total = noOfNotice + noOfRequest + noOfWorkflow + noOfUnprocessed; windowContainer.setTabTitle(0, Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Home")) + " (" + noCount + ")", null);
windowContainer.setTabTitle(0, Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Home"))
+ " (" + total + ")",
Msg.translate(Env.getCtx(), "AD_Note_ID") + " : " + noOfNotice
+ ", " + Msg.translate(Env.getCtx(), "R_Request_ID") + " : " + noOfRequest
+ ", " + Util.cleanAmp(Msg.getMsg (Env.getCtx(), "WorkflowActivities")) + " : " + noOfWorkflow
+ (noOfUnprocessed>0 ? ", " + Msg.getMsg (Env.getCtx(), "UnprocessedDocs") + " : " + noOfUnprocessed : "")
);
} }
//use _docClick undocumented api. need verification after major zk release update //use _docClick undocumented api. need verification after major zk release update