9.2 重新指派过程任务
从上一节的分析可以看出,未完成的任务有两种情况,一种是已经被用户选择并等待处理的任务,一种是刚创建、尚没有用户选择执行的任务。对第一种情况可以通过重新指派用户完成该任务(即修改任务实例的TaskUserID字段,并记录由谁重新指派了任务以及重新指派的原因),以推动业务过程继续进行;对第二种情况,可以督促相关角色用户完成任务,或为相应角色添加用户以完成任务。
9.2.1 ReassignTaskUser.aspx文件代码
页面设计如图9.2所示:
图9.2 重新指派过程任务
......
<form id="Form1" method="post" runat="server">
<table cellSpacing="2" cellPadding="2" width="100%" border="0">
<tr><td align="right" width="10%"></td>
<td align="right" width="15%">当前业务名称:</td>
<td align="left" width="65%">
<asp:label id="Label1" runat="server" ForeColor="Black"></asp:label></td>
<td width="10%"><FONT face="宋体"></FONT></td>
</tr>
<TR>
<TD align="right" width="10%"></TD>
<TD align="right" width="15%"><FONT face="宋体">业务内容:</FONT></TD>
<TD align="left" width="65%"><asp:label id="Label2" runat="server"></asp:label></TD>
<TD width="10%"></TD>
</TR>
<tr>
<td align="right" width="10%"><FONT face="宋体"></FONT></td>
<td align="right" width="15%">未完成的任务说明:</td>
<td align="left" width="65%"><asp:label id="Label3" runat="server"></asp:label></td>
<td width="10%"></td>
</tr>
<%
//如果需要重新指派
if(ViewState["needreassigntask"].ToString () == "Y")
{
%>
<TR>
<TD align="right"><FONT face="宋体"></FONT></TD>
<TD align="right">重新指派任务的原因:</TD>
<TD align="left"><asp:textbox id="TextBox1" runat="server" Rows="3"
TextMode="MultiLine" Columns="106"></asp:textbox></TD>
<TD></TD></TR>
<TR>
<TD align="right"> </TD>
<TD align="right"><FONT face="宋体">将任务重新指派给:</FONT></TD>
<TD align="left"><asp:dropdownlist id="DropDownList1" runat="server">
</asp:dropdownlist></TD><TD> </TD></TR>
<TR>
<TD> </TD><TD> </TD>
<TD align="center">
<asp:button id="Button1" runat="server" Text="确认"></asp:button>
<asp:button id="Button2" runat="server" Text="取消"></asp:button></TD>
<TD></TD>
</TR>
<%
}
%>
</table>
</form>
9.2.2 ReassignTaskUser.aspx.cs文件代码
......
using DataAccess;
using WFEngine;
using UserResourceManagement;
namespace workflow.Controls
{
public class ReassignTaskUser : System.Web.UI.Page
{
......
private void Page_Load(object sender, System.EventArgs e)
{
if(! IsPostBack)
{
//获取来源页地址
ViewState["BackUrl"] = Request.UrlReferrer.ToString();
//是否需要重新指派任务用户
ViewState["needreassigntask"]="N";
//验证用户是否登录
if(Session["userid"] == null)
Response.Redirect("../Message.aspx");
//获取过程实例编号和任务实例编号参数
string processinstanceid=Request.QueryString["pid"].ToString();
ViewState["processinstanceid"]=processinstanceid;
string taskinstanceid=Request.QueryString["tid"].ToString();
ViewState["taskinstanceid"]=taskinstanceid;
//获取业务名称与业务实例内容描述
string strSql="select (select ProcessName from ProcessDefinition where
ProcessID=ProcessDefinitionID) as process_name,Description from
ProcessInstance where ProcessInstanceID="+processinstanceid;
Base basecode=new Base();
DataSet ds=basecode.SQLExeDataSet(strSql);
Label1.Text=ds.Tables[0].Rows[0]["process_name"].ToString();
Label2.Text=ds.Tables[0].Rows[0]["Description"].ToString();
strSql="select TaskDefinitionID,TaskUserID from TaskInstance where
TaskInstanceID="+taskinstanceid;
ds=basecode.SQLExeDataSet(strSql);
if(ds == null || ds.Tables[0].Rows.Count < 1)
{
Label3.Text="出现程序错误,请与管理员联系!";
return;
}
strSql="select TaskName,AssignedRole,(select RoleName from RolesManagement
where RoleID=AssignedRole) as rolename from TaskDefinition where
TaskID="+ds.Tables[0].Rows[0]["TaskDefinitionID"].ToString();
DataSet taskds=basecode.SQLExeDataSet(strSql);
string taskname=taskds.Tables[0].Rows[0]["TaskName"].ToString();
ViewState["taskname"]=taskname;
string rolename=taskds.Tables[0].Rows[0]["rolename"].ToString();
string roleid=taskds.Tables[0].Rows[0]["AssignedRole"].ToString();
//获取所有对应角色用户名(包括活动用户和被冻结用户)
strSql="select EmployeeName from Employees where EmployeeID in (select
EmployeeID from Users where UserID in (select UserID from RolesAssigned
where RoleID="+roleid+" and UserID in (select UserID from Users where
Active='A')));"
+"select EmployeeName from Employees where EmployeeID in (select
EmployeeID from Users where UserID in (select UserID from
RolesAssigned where RoleID="+roleid+" and UserID in (select UserID
from Users where Active != 'A')))";
taskds=basecode.SQLExeDataSet(strSql);
string activeEmployees="";
string noactiveEmployees="";
if(taskds != null)
{
if(taskds.Tables[0] != null & taskds.Tables[0].Rows.Count >=1)
{
activeEmployees=taskds.Tables[0].Rows[0]["EmployeeName"].ToString();
for(int i=1;i<taskds.Tables[0].Rows.Count;i++)
activeEmployees=activeEmployees+","
+taskds.Tables[0].Rows[i]["EmployeeName"].ToString();
}
if(taskds.Tables[1] != null & taskds.Tables[1].Rows.Count >=1)
{
noactiveEmployees=taskds.Tables[1].Rows[0]["EmployeeName"].ToString();
for(int i=1;i<taskds.Tables[1].Rows.Count;i++)
noactiveEmployees=noactiveEmployees+","
+taskds.Tables[1].Rows[i]["EmployeeName"].ToString();
}
}
//对于新任务实例(尚没有用户选择处理该任务)
if(ds.Tables[0].Rows[0]["TaskUserID"] == DBNull.Value)
{
Label3.Text="未完成的任务为"+taskname+",对应角色为"+rolename;
if(activeEmployees != "")
Label3.Text=Label3.Text+".对应活动用户为"+activeEmployees;
if(noactiveEmployees != "")
Label3.Text=Label3.Text+";对应不活动用户为"+noactiveEmployees;
Label3.Text=Label3.Text+".请通知活动用户完成任务,或者联系管理员将无法完成任
务的活动用户设置为不活动,并添加新用户来完成任务!";
}
else
{
ViewState["needreassigntask"]="Y";
Label3.Text="未完成的任务为"+taskname+",对应角色为"+rolename;
if(activeEmployees != "")
Label3.Text=Label3.Text+".对应活动用户为"+activeEmployees;
if(noactiveEmployees != "")
Label3.Text=Label3.Text+";对应不活动用户为"+noactiveEmployees;
string taskusername=new UserManagement().GetEmployeeName(ds.Tables[0]
.Rows[0]["TaskUserID"].ToString ());
//保存当前任务用户
ViewState["taskusername"]=taskusername;
Label3.Text=Label3.Text+".当前任务用户为"+taskusername+".";
//设置用户选择下拉列表
strSql="select EmployeeName,UserID from Employees,Users where
Employees.EmployeeID=Users.EmployeeID AND Users.Active='A' and
Users.EmployeeID in (select EmployeeID from Users where UserID in
(select UserID from RolesAssigned where RoleID="+roleid+"))";
ds=basecode.SQLExeDataSet(strSql);
DropDownList1.DataSource=ds;
DropDownList1.DataTextField="EmployeeName";
DropDownList1.DataValueField="UserID";
DropDownList1.DataBind();
}
}
}
//取消按钮
private void Button2_Click(object sender, System.EventArgs e)
{
Response.Redirect(ViewState["BackUrl"].ToString());
}
//确定按钮
private void Button1_Click(object sender, System.EventArgs e)
{
//保存重新指派任务的原因到流程实例的留言字段
string strSql="update ProcessInstance set Message=@Message where
ProcessInstanceID="+ViewState["processinstanceid"].ToString();
SqlCommand mycommand=new SqlCommand();
mycommand.CommandText=strSql;
Base basecode=new Base();
//记录谁重新指派了任务
string whoassigntask=new UserManagement().GetEmployeeName(Session["userid"]
.ToString ());
string employeename=DropDownList1.SelectedItem.Text;//记录指派给谁
string reason=TextBox1.Text.Trim();
try
{
//在原留言信息基础上追加信息
strSql="select Message from ProcessInstance where ProcessInstanceID="
+ViewState["processinstanceid"].ToString();
DataSet myds=basecode.SQLExeDataSet(strSql);
//在参数设置中不指定字段长度,默认与数据库结构中的字段长度相同
mycommand.Parameters.Add(new SqlParameter("@Message",SqlDbType.VarChar));
if(myds.Tables[0].Rows[0]["Message"] != DBNull.Value)
mycommand.Parameters["@Message"].Value=myds.Tables[0]
.Rows[0]["Message"].ToString()+whoassigntask+"(将"
+ViewState["taskname"].ToString()+"任务从"
+ViewState["taskusername"].ToString()
+"重新指派给"+employeename+"):"+reason+"<br>";
else
mycommand.Parameters["@Message"].Value=whoassigntask
+"(将"+ViewState["taskname"].ToString()+"任务从"
+ViewState["taskusername"].ToString()
+"重新指派给"+employeename+"):"+reason+"<br>";
if(! basecode.SQLExeNonQuery_proc(mycommand))
{
//测试用,为了数据安全不要显示详细异常信息,改为显示自己编写的错误提示
Label1.Text=basecode.BaseSqlErrDes;
return;
}
}
catch(System.FormatException exp)
{
Label1.Text=exp.Message;
return;
}
string userid=DropDownList1.SelectedValue;
strSql="update TaskInstance set TaskUserID="+userid+" where
TaskInstanceID="+ViewState["taskinstanceid"].ToString();
if(! basecode.SQLExeNonQuery(strSql))
{
Label1.Text=basecode.BaseSqlErrDes;
return;
}
Response.Redirect(ViewState["BackUrl"].ToString());
}
}
}
9.3 业务流程监控的其它内容
除了超期限业务流程监控之外,在流程监控板块中还有其它的监控内容,如查询已完成的业务过程、查看正在处理(未超出承诺期限)的业务过程等,其实现与超期限流程监控类似,无非就是获取流程列表的SQL查询条件稍有变化,这里不再详细介绍。
需要提到的是流程监控中的冻结或取消业务过程的操作。冻结业务流程操作实际上就是把流程实例的字段IsSuspended设置为“Y”,并记录执行冻结操作的时间(DateTime.Now.ToString()),这样被冻结的业务过程任务将不再出现在用户的任务列表中;对被冻结的业务过程还可以执行解冻操作,即将IsSuspended字段置空,使过程得以重新执行。
如果被冻结的流程已经不具备重新执行的条件,可以考虑取消该流程。被冻结的流程,只有超过一定期限才可以执行取消操作。
为了保留历史记录,取消流程操作并不是删除流程实例,而是将流程实例的字段IsCanceled设置为“Y”,并把取消原因记录到字段CanceledReason中,同时删除与过程关联的业务数据记录以及过程中上传的附件资料,这样用户在查询共享的业务数据是就不会再看到已被取消的业务数据。