📄 workflowprocessor.java
字号:
/******************************************************************************
* The contents of this file are subject to the Compiere License Version 1.1
* ("License"); You may not use this file except in compliance with the License
* You may obtain a copy of the License at http://www.compiere.org/license.html
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
* The Original Code is Compiere ERP & CRM Smart Business Solution. The Initial
* Developer of the Original Code is Jorg Janke. Portions created by Jorg Janke
* are Copyright (C) 1999-2005 Jorg Janke.
* All parts are Copyright (C) 1999-2005 ComPiere, Inc. All Rights Reserved.
* Contributor(s): ______________________________________.
*****************************************************************************/
package org.compiere.server;
import java.sql.*;
import java.util.*;
import java.io.*;
import java.util.logging.*;
import org.compiere.util.*;
import org.compiere.wf.*;
import org.compiere.model.*;
import org.compiere.process.*;
/**
* Workflow Processor
*
* @author Jorg Janke
* @version $Id: WorkflowProcessor.java,v 1.10 2005/11/12 23:00:29 jjanke Exp $
*/
public class WorkflowProcessor extends CompiereServer
{
/**
* WorkflowProcessor
* @param model model
*/
public WorkflowProcessor (MWorkflowProcessor model)
{
super (model, 120); // 2 minute dalay
m_model = model;
m_client = MClient.get(model.getCtx(), model.getAD_Client_ID());
} // WorkflowProcessor
/** The Concrete Model */
private MWorkflowProcessor m_model = null;
/** Last Summary */
private StringBuffer m_summary = new StringBuffer();
/** Client onfo */
private MClient m_client = null;
/**
* Work
*/
protected void doWork ()
{
m_summary = new StringBuffer();
//
wakeup();
dynamicPriority();
sendAlerts();
//
int no = m_model.deleteLog();
m_summary.append("Logs deleted=").append(no);
//
MWorkflowProcessorLog pLog = new MWorkflowProcessorLog(m_model, m_summary.toString());
pLog.setReference("#" + String.valueOf(p_runCount)
+ " - " + TimeUtil.formatElapsed(new Timestamp(p_startWork)));
pLog.save();
} // doWork
/**
* Continue Workflow After Sleep
*/
private void wakeup()
{
String sql = "SELECT * "
+ "FROM AD_WF_Activity a "
+ "WHERE Processed='N' AND WFState='OS'" // suspended
+ " AND EndWaitTime > SysDate"
+ " AND AD_Client_ID=?"
+ " AND EXISTS (SELECT * FROM AD_Workflow wf "
+ " INNER JOIN AD_WF_Node wfn ON (wf.AD_Workflow_ID=wfn.AD_Workflow_ID) "
+ "WHERE a.AD_WF_Node_ID=wfn.AD_WF_Node_ID"
+ " AND wfn.Action='Z'" // sleeping
+ " AND wf.AD_WorkflowProcessor_ID IS NULL OR wf.AD_WorkflowProcessor_ID=?)";
PreparedStatement pstmt = null;
int count = 0;
int countEMails = 0;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt (1, m_model.getAD_Client_ID());
pstmt.setInt (2, m_model.getAD_WorkflowProcessor_ID());
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
MWFActivity activity = new MWFActivity (getCtx(), rs, null);
activity.setWFState (StateEngine.STATE_Completed);
// saves and calls MWFProcess.checkActivities();
count++;
}
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, "wakeup", e);
}
m_summary.append("Wakeup #").append(count).append (" - ");
} // wakeup
/**
* Set/Increase Priority dynamically
*/
private void dynamicPriority()
{
// suspened activities with dynamic priority node
String sql = "SELECT * "
+ "FROM AD_WF_Activity a "
+ "WHERE Processed='N' AND WFState='OS'" // suspended
+ " AND EXISTS (SELECT * FROM AD_Workflow wf"
+ " INNER JOIN AD_WF_Node wfn ON (wf.AD_Workflow_ID=wfn.AD_Workflow_ID) "
+ "WHERE a.AD_WF_Node_ID=wfn.AD_WF_Node_ID AND wf.AD_WorkflowProcessor_ID=?"
+ " AND wfn.DynPriorityUnit IS NOT NULL AND wfn.DynPriorityChange IS NOT NULL)";
PreparedStatement pstmt = null;
int count = 0;
int countEMails = 0;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt(1, m_model.getAD_WorkflowProcessor_ID());
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
MWFActivity activity = new MWFActivity (getCtx(), rs, null);
if (activity.getDynPriorityStart() == 0)
activity.setDynPriorityStart(activity.getPriority());
long ms = System.currentTimeMillis() - activity.getCreated().getTime();
MWFNode node = activity.getNode();
int prioDiff = node.calculateDynamicPriority ((int)(ms / 1000));
activity.setPriority(activity.getDynPriorityStart() + prioDiff);
activity.save();
count++;
}
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
}
m_summary.append("DynPriority #").append(count).append (" - ");
// Cleanup
try
{
if (pstmt != null)
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
pstmt = null;
}
} // setPriority
/**
* Send Alerts
*/
private void sendAlerts()
{
// Alert over Priority
if (m_model.getAlertOverPriority() > 0)
{
String sql = "SELECT * "
+ "FROM AD_WF_Activity a "
+ "WHERE Processed='N' AND WFState='OS'" // suspended
+ " AND Priority >= ?" // ##1
+ " AND (DateLastAlert IS NULL";
if (m_model.getRemindDays() > 0)
sql += " OR (DateLastAlert+" + m_model.getRemindDays()
+ ") < SysDate";
sql += ") AND EXISTS (SELECT * FROM AD_Workflow wf "
+ " INNER JOIN AD_WF_Node wfn ON (wf.AD_Workflow_ID=wfn.AD_Workflow_ID) "
+ "WHERE a.AD_WF_Node_ID=wfn.AD_WF_Node_ID"
+ " AND wf.AD_WorkflowProcessor_ID IS NULL OR wf.AD_WorkflowProcessor_ID=?)";
int count = 0;
int countEMails = 0;
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, null);
pstmt.setInt (1, m_model.getAlertOverPriority());
pstmt.setInt (2, m_model.getAD_WorkflowProcessor_ID());
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
MWFActivity activity = new MWFActivity (getCtx(), rs, null);
boolean escalate = activity.getDateLastAlert() != null;
countEMails += sendEmail (activity, "ActivityOverPriority",
escalate, true);
activity.setDateLastAlert(new Timestamp(System.currentTimeMillis()));
activity.save();
count++;
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, "(Priority) - " + sql, e);
}
m_summary.append("OverPriority #").append(count);
if (countEMails > 0)
m_summary.append(" (").append(countEMails).append(" EMail)");
m_summary.append (" - ");
} // Alert over Priority
/**
* Over End Wait
*/
String sql = "SELECT * "
+ "FROM AD_WF_Activity a "
+ "WHERE Processed='N' AND WFState='OS'" // suspended
+ " AND EndWaitTime > SysDate"
+ " AND (DateLastAlert IS NULL";
if (m_model.getRemindDays() > 0)
sql += " OR (DateLastAlert+" + m_model.getRemindDays()
+ ") < SysDate";
sql += ") AND EXISTS (SELECT * FROM AD_Workflow wf "
+ " INNER JOIN AD_WF_Node wfn ON (wf.AD_Workflow_ID=wfn.AD_Workflow_ID) "
+ "WHERE a.AD_WF_Node_ID=wfn.AD_WF_Node_ID"
+ " AND wfn.Action<>'Z'" // not sleeping
+ " AND wf.AD_WorkflowProcessor_ID IS NULL OR wf.AD_WorkflowProcessor_ID=?)";
PreparedStatement pstmt = null;
int count = 0;
int countEMails = 0;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt(1, m_model.getAD_WorkflowProcessor_ID());
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
MWFActivity activity = new MWFActivity (getCtx(), rs, null);
boolean escalate = activity.getDateLastAlert() != null;
countEMails += sendEmail (activity, "ActivityEndWaitTime",
escalate, false);
activity.setDateLastAlert(new Timestamp(System.currentTimeMillis()));
activity.save();
count++;
}
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, "(EndWaitTime) - " + sql, e);
}
m_summary.append("EndWaitTime #").append(count);
if (countEMails > 0)
m_summary.append(" (").append(countEMails).append(" EMail)");
m_summary.append (" - ");
/**
* Send inactivity alerts
*/
if (m_model.getInactivityAlertDays() > 0)
{
sql = "SELECT * "
+ "FROM AD_WF_Activity a "
+ "WHERE Processed='N' AND WFState='OS'" // suspended
+ " AND (Updated+" + m_model.getInactivityAlertDays() + ") < SysDate"
+ " AND (DateLastAlert IS NULL";
if (m_model.getRemindDays() > 0)
sql += " OR (DateLastAlert+" + m_model.getRemindDays()
+ ") < SysDate";
sql += ") AND EXISTS (SELECT * FROM AD_Workflow wf "
+ " INNER JOIN AD_WF_Node wfn ON (wf.AD_Workflow_ID=wfn.AD_Workflow_ID) "
+ "WHERE a.AD_WF_Node_ID=wfn.AD_WF_Node_ID"
+ " AND wf.AD_WorkflowProcessor_ID IS NULL OR wf.AD_WorkflowProcessor_ID=?)";
count = 0;
countEMails = 0;
try
{
pstmt = DB.prepareStatement(sql, null);
pstmt.setInt (1, m_model.getAD_WorkflowProcessor_ID());
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
MWFActivity activity = new MWFActivity (getCtx(), rs, null);
boolean escalate = activity.getDateLastAlert() != null;
countEMails += sendEmail (activity, "ActivityInactivity",
escalate, false);
activity.setDateLastAlert(new Timestamp(System.currentTimeMillis()));
activity.save();
count++;
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, "(Inactivity): " + sql, e);
}
m_summary.append("Inactivity #").append(count);
if (countEMails > 0)
m_summary.append(" (").append(countEMails).append(" EMail)");
m_summary.append (" - ");
} // Inactivity
// Cleanup
try
{
if (pstmt != null)
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
pstmt = null;
}
} // sendAlerts
/**
* Send Alert EMail
* @param activity activity
* @param AD_Message message
* @return number of mails sent
*/
private int sendEmail (MWFActivity activity, String AD_Message,
boolean toProcess, boolean toSupervisor)
{
if (m_client == null || m_client.getAD_Client_ID() != activity.getAD_Client_ID())
m_client = MClient.get(getCtx(), activity.getAD_Client_ID());
MWFProcess process = new MWFProcess (getCtx(), activity.getAD_WF_Process_ID(), null);
String subjectVar = activity.getNode().getName();
String message = activity.getTextMsg();
if (message == null || message.length() == 0)
message = process.getTextMsg();
File pdf = null;
PO po = activity.getPO();
if (po instanceof DocAction)
{
message = ((DocAction)po).getDocumentInfo() + "\n" + message;
pdf = ((DocAction)po).createPDF();
}
// Inactivity Alert: Workflow Activity {0}
String subject = Msg.getMsg(m_client.getAD_Language(), AD_Message,
new Object[] {subjectVar});
// Prevent duplicates
ArrayList<Integer> list = new ArrayList<Integer>();
int counter = 0;
// To Activity Owner
if (m_client.sendEMail(activity.getAD_User_ID(), subject, message, pdf))
counter++;
list.add (new Integer(activity.getAD_User_ID()));
// To Process Owner
if (toProcess
&& process.getAD_User_ID() != activity.getAD_User_ID())
{
if (m_client.sendEMail(process.getAD_User_ID(), subject, message, pdf))
counter++;
list.add (new Integer(process.getAD_User_ID()));
}
// To Activity Responsible
MWFResponsible responsible = MWFResponsible.get(getCtx(), activity.getAD_WF_Responsible_ID());
counter += sendAlertToResponsible (responsible, list, process,
subject, message, pdf);
// To Process Responsible
if (toProcess
&& process.getAD_WF_Responsible_ID() != activity.getAD_WF_Responsible_ID())
{
responsible = MWFResponsible.get(getCtx(), process.getAD_WF_Responsible_ID());
counter += sendAlertToResponsible (responsible, list, process,
subject, message, pdf);
}
// Processor SuperVisor
if (toSupervisor
&& m_model.getSupervisor_ID() != 0
&& !list.contains(new Integer(m_model.getSupervisor_ID())))
{
if (m_client.sendEMail(m_model.getSupervisor_ID(), subject, message, pdf))
counter++;
list.add (new Integer(m_model.getSupervisor_ID()));
}
return counter;
} // sendAlert
/**
* Send Alert To Responsible
* @param responsible responsible
* @param list list of already sent users
* @param process process
* @param subject subject
* @param message message
* @param pdf optional pdf
* @return number of mail sent
*/
private int sendAlertToResponsible (MWFResponsible responsible,
ArrayList<Integer> list, MWFProcess process,
String subject, String message, File pdf)
{
int counter = 0;
if (responsible.isInvoker())
;
// Human
else if (MWFResponsible.RESPONSIBLETYPE_Human.equals(responsible.getResponsibleType())
&& responsible.getAD_User_ID() != 0
&& !list.contains(new Integer(responsible.getAD_User_ID())))
{
if (m_client.sendEMail(responsible.getAD_User_ID(), subject, message, pdf))
counter++;
list.add (new Integer(responsible.getAD_User_ID()));
}
// Org of the Document
else if (MWFResponsible.RESPONSIBLETYPE_Organization.equals(responsible.getResponsibleType()))
{
PO document = process.getPO();
if (document != null)
{
MOrgInfo org = MOrgInfo.get (getCtx(), document.getAD_Org_ID());
if (org.getSupervisor_ID() != 0
&& !list.contains(new Integer(org.getSupervisor_ID())))
{
if (m_client.sendEMail(org.getSupervisor_ID(), subject, message, pdf))
counter++;
list.add (new Integer(org.getSupervisor_ID()));
}
}
}
// Role
else if (MWFResponsible.RESPONSIBLETYPE_Role.equals(responsible.getResponsibleType())
&& responsible.getAD_Role_ID() != 0)
{
MUserRoles[] userRoles = MUserRoles.getOfRole(getCtx(), responsible.getAD_Role_ID());
for (int i = 0; i < userRoles.length; i++)
{
MUserRoles roles = userRoles[i];
int AD_User_ID = roles.getAD_User_ID();
if (!list.contains(new Integer(AD_User_ID)))
{
if (m_client.sendEMail(AD_User_ID, subject, message, pdf))
counter++;
list.add (new Integer(AD_User_ID));
}
}
}
return counter;
} // sendAlertToResponsible
/**
* Get Server Info
* @return info
*/
public String getServerInfo()
{
return "#" + p_runCount + " - Last=" + m_summary.toString();
} // getServerInfo
} // WorkflowProcessor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -