private WorkNode DoReturnSubFlow(int backtoNodeID, string msg, bool isHiden) { Node nd = new Node(backtoNodeID); ps = new Paras(); ps.SQL = "DELETE FROM WF_GenerWorkerList WHERE FK_Node=" + dbStr + "FK_Node AND WorkID=" + dbStr + "WorkID AND FID=" + dbStr + "FID"; ps.Add("FK_Node", backtoNodeID); ps.Add("WorkID", this.HisWork.OID); ps.Add("FID", this.HisWork.FID); BP.DA.DBAccess.RunSQL(ps); // 找出分合流点处理的人员. ps = new Paras(); ps.SQL = "SELECT FK_Emp FROM WF_GenerWorkerList WHERE FK_Node=" + dbStr + "FK_Node AND WorkID=" + dbStr + "FID"; ps.Add("FID", this.HisWork.FID); ps.Add("FK_Node", backtoNodeID); DataTable dt = DBAccess.RunSQLReturnTable(ps); if (dt.Rows.Count != 1) { throw new Exception("@ system error , this values must be =1"); } string FK_Emp = dt.Rows[0][0].ToString(); // 获取当前工作的信息. GenerWorkerList wl = new GenerWorkerList(this.HisWork.FID, this.HisNode.NodeID, FK_Emp); Emp emp = new Emp(FK_Emp); // 改变部分属性让它适应新的数据,并显示一条新的待办工作让用户看到。 wl.IsPass = false; wl.WorkID = this.HisWork.OID; wl.FID = this.HisWork.FID; wl.RDT = DataType.CurrentDataTime; wl.FK_Emp = FK_Emp; wl.FK_EmpText = emp.Name; wl.FK_Node = backtoNodeID; wl.FK_NodeText = nd.Name; wl.WarningDays = nd.WarningDays; wl.FK_Dept1 = emp.FK_Dept; DateTime dtNew = DateTime.Now; dtNew = dtNew.AddDays(nd.WarningDays); wl.SDT = dtNew.ToString(DataType.SysDataFormat); // DataType.CurrentDataTime; wl.FK_Flow = this.HisNode.FK_Flow; wl.Insert(); GenerWorkFlow gwf = new GenerWorkFlow(this.HisWork.OID); gwf.FK_Node = backtoNodeID; gwf.NodeName = nd.Name; gwf.DirectUpdate(); ps = new Paras(); ps.Add("FK_Node", backtoNodeID); ps.Add("WorkID", this.HisWork.OID); ps.SQL = "UPDATE WF_GenerWorkerList SET IsPass=3 WHERE FK_Node=" + dbStr + "FK_Node AND WorkID=" + dbStr + "WorkID"; BP.DA.DBAccess.RunSQL(ps); /* 如果是隐性退回。*/ BP.WF.ReturnWork rw = new ReturnWork(); rw.WorkID = wl.WorkID; rw.ReturnToNode = wl.FK_Node; rw.ReturnNode = this.HisNode.NodeID; rw.ReturnNodeName = this.HisNode.Name; rw.ReturnToEmp = FK_Emp; rw.Note = msg; try { rw.MyPK = rw.ReturnToNode + "_" + rw.WorkID + "_" + DateTime.Now.ToString("yyyyMMddhhmmss"); rw.Insert(); } catch { rw.MyPK = rw.ReturnToNode + "_" + rw.WorkID + "_" + BP.DA.DBAccess.GenerOID(); rw.Insert(); } // 加入track. this.AddToTrack(ActionType.Return, FK_Emp, emp.Name, backtoNodeID, nd.Name, msg); WorkNode wn = new WorkNode(this.HisWork.FID, backtoNodeID); if (Glo.IsEnableSysMessage) { // WF.Port.WFEmp wfemp = new Port.WFEmp(wn.HisWork.Rec); string title = string.Format("工作退回:流程:{0}.工作:{1},退回人:{2},需您处理", wn.HisNode.FlowName, wn.HisNode.Name, WebUser.Name); BP.WF.Dev2Interface.Port_SendMail(wn.HisWork.Rec, title, msg, "RESub" + backtoNodeID + "_" + this.WorkID, nd.FK_Flow, nd.NodeID, this.WorkID, this.FID); } return(wn); }
/// <summary> /// 构造工作人员集合 /// </summary> /// <param name="workId">工作ID</param> /// <param name="nodeId">节点ID</param> /// <param name="isWithEmpExts">是否包含为分配的人员</param> public GenerWorkerLists(Int64 workId, int nodeId, bool isWithEmpExts) { QueryObject qo = new QueryObject(this); qo.addLeftBracket(); qo.AddWhere(GenerWorkerListAttr.WorkID, workId); qo.addOr(); qo.AddWhere(GenerWorkerListAttr.FID, workId); qo.addRightBracket(); qo.addAnd(); qo.AddWhere(GenerWorkerListAttr.FK_Node, nodeId); int i = qo.DoQuery(); if (isWithEmpExts == false) { return; } if (i == 0) { throw new Exception("@系统错误,工作人员丢失请与管理员联系。NodeID=" + nodeId + " WorkID=" + workId); } RememberMe rm = new RememberMe(); rm.FK_Emp = BP.Web.WebUser.No; rm.FK_Node = nodeId; if (rm.RetrieveFromDBSources() == 0) { return; } GenerWorkerList wl = (GenerWorkerList)this[0]; string[] emps = rm.Emps.Split('@'); foreach (string emp in emps) { if (emp == null || emp == "") { continue; } if (this.GetCountByKey(GenerWorkerListAttr.FK_Emp, emp) >= 1) { continue; } GenerWorkerList mywl = new GenerWorkerList(); mywl.Copy(wl); mywl.IsEnable = false; mywl.FK_Emp = emp; WF.Port.WFEmp myEmp = new Port.WFEmp(emp); mywl.FK_EmpText = myEmp.Name; try { mywl.Insert(); } catch { mywl.Update(); continue; } this.AddEntity(mywl); } return; }
/// <summary> /// 子线程退回给分流点 /// </summary> /// <returns></returns> private string ExeReturn5_2() { GenerWorkFlow gwf = new GenerWorkFlow(this.WorkID); gwf.FK_Node = this.ReturnToNode.NodeID; string info = "@工作已经成功的退回到(" + ReturnToNode.Name + ")退回给:"; //查询退回到的工作人员列表. GenerWorkerLists gwls = new GenerWorkerLists(); gwls.Retrieve(GenerWorkerListAttr.WorkID, this.WorkID, GenerWorkerListAttr.FK_Node, this.ReturnToNode.NodeID); string toEmp = ""; string toEmpName = ""; if (gwls.Count == 1) { /*有可能多次退回的情况,表示曾经退回过n次。*/ foreach (GenerWorkerList item in gwls) { item.IsPass = false; // 显示待办, 这个是合流节点的工作人员. item.IsRead = false; // item.Update(); info += item.FK_Emp + "," + item.FK_EmpText; toEmp = item.FK_Emp; toEmpName = item.FK_EmpText; info += "(" + item.FK_Emp + "," + item.FK_EmpText + ")"; } } else { // 找到合流点的发送人. Nodes nds = this.HisNode.FromNodes; gwls = new GenerWorkerLists(); GenerWorkerList gwl = new GenerWorkerList(); foreach (Node nd in nds) { gwls.Retrieve(GenerWorkerListAttr.WorkID, this.FID, GenerWorkerListAttr.FK_Node, nd.NodeID, GenerWorkerListAttr.IsPass, 1); if (gwls.Count == 0) { continue; } if (gwls.Count != 1) { throw new Exception("@应该只有一个记录,现在有多个,可能错误。"); } //求出分流节点的发送人. gwl = (GenerWorkerList)gwls[0]; toEmp = gwl.FK_Emp; toEmpName = gwl.FK_EmpText; info += "(" + toEmp + "," + toEmpName + ")"; } if (string.IsNullOrEmpty(toEmp) == true) { throw new Exception("@在退回时出现错误,没有找到分流节点的发送人。"); } // 插入一条数据, 行程一个工作人员记录,这个记录就是子线程的延长点. 给合流点上的接受人设置待办. gwl.WorkID = this.WorkID; gwl.FID = this.FID; gwl.IsPass = false; if (gwl.IsExits == false) { gwl.Insert(); } else { gwl.Update(); } } // 记录退回轨迹。 ReturnWork rw = new ReturnWork(); rw.WorkID = this.WorkID; rw.ReturnToNode = this.ReturnToNode.NodeID; rw.ReturnNodeName = this.ReturnToNode.Name; rw.ReturnNode = this.HisNode.NodeID; // 当前退回节点. rw.ReturnToEmp = toEmp; //退回给。 rw.MyPK = DBAccess.GenerOIDByGUID().ToString(); rw.Note = Msg; rw.IsBackTracking = this.IsBackTrack; rw.Insert(); // 加入track. this.AddToTrack(ActionType.Return, toEmp, toEmpName, this.ReturnToNode.NodeID, this.ReturnToNode.Name, Msg); gwf.WFState = WFState.ReturnSta; gwf.FK_Node = this.ReturnToNode.NodeID; gwf.NodeName = this.ReturnToNode.Name; gwf.Starter = toEmp; gwf.StarterName = toEmpName; gwf.Update(); //找到当前的工作数据. GenerWorkerList currWorker = new GenerWorkerList(); int i = currWorker.Retrieve(GenerWorkerListAttr.FK_Emp, WebUser.No, GenerWorkerListAttr.WorkID, this.WorkID, GenerWorkerListAttr.FK_Node, this.HisNode.NodeID); if (i != 1) { throw new Exception("@当前的工作人员列表数据丢失了,流程引擎错误."); } //设置当前的工作数据为退回状态,让其不能看到待办, 这个是约定的值. currWorker.IsPassInt = (int)WFState.ReturnSta; currWorker.Update(); // 返回退回信息. return(info); }
/// <summary> /// 创建WorkID /// </summary> /// <param name="flowNo">流程编号</param> /// <param name="ht">表单参数,可以为null。</param> /// <param name="workDtls">明细表参数,可以为null。</param> /// <param name="starter">流程的发起人</param> /// <param name="title">创建工作时的标题,如果为null,就按设置的规则生成。</param> /// <param name="parentWorkID">父流程的WorkID,如果没有父流程就传入为0.</param> /// <param name="parentFlowNo">父流程的流程编号,如果没有父流程就传入为null.</param> /// <returns>为开始节点创建工作后产生的WorkID.</returns> public static Int64 Node_CreateBlankWork(string flowNo, Hashtable ht, DataSet workDtls, string guestNo, string title, Int64 parentWorkID, string parentFlowNo, int parentNodeID, string parentEmp) { //if (BP.Web.WebUser.No != "Guest") // throw new Exception("@必须是Guest登陆才能发起."); string dbstr = SystemConfig.AppCenterDBVarStr; Flow fl = new Flow(flowNo); Node nd = new Node(fl.StartNodeID); //把一些其他的参数也增加里面去,传递给ccflow. Hashtable htPara = new Hashtable(); if (parentWorkID != 0) { htPara.Add(StartFlowParaNameList.PWorkID, parentWorkID); } if (parentFlowNo != null) { htPara.Add(StartFlowParaNameList.PFlowNo, parentFlowNo); } if (parentNodeID != 0) { htPara.Add(StartFlowParaNameList.PNodeID, parentNodeID); } if (parentEmp != null) { htPara.Add(StartFlowParaNameList.PEmp, parentEmp); } Emp empStarter = new Emp(BP.Web.WebUser.No); Work wk = fl.NewWork(empStarter, htPara); Int64 workID = wk.OID; #region 给各个属性-赋值 if (ht != null) { foreach (string str in ht.Keys) { wk.SetValByKey(str, ht[str]); } } wk.OID = workID; if (workDtls != null) { //保存从表 foreach (DataTable dt in workDtls.Tables) { foreach (MapDtl dtl in wk.HisMapDtls) { if (dt.TableName != dtl.No) { continue; } //获取dtls GEDtls daDtls = new GEDtls(dtl.No); daDtls.Delete(GEDtlAttr.RefPK, wk.OID); // 清除现有的数据. GEDtl daDtl = daDtls.GetNewEntity as GEDtl; daDtl.RefPK = wk.OID.ToString(); // 为从表复制数据. foreach (DataRow dr in dt.Rows) { daDtl.ResetDefaultVal(); daDtl.RefPK = wk.OID.ToString(); //明细列. foreach (DataColumn dc in dt.Columns) { //设置属性. daDtl.SetValByKey(dc.ColumnName, dr[dc.ColumnName]); } daDtl.InsertAsOID(DBAccess.GenerOID("Dtl")); //插入数据. } } } } #endregion 赋值 Paras ps = new Paras(); // 执行对报表的数据表WFState状态的更新,让它为runing的状态. if (DataType.IsNullOrEmpty(title) == false) { ps = new Paras(); ps.SQL = "UPDATE " + fl.PTable + " SET WFState=" + dbstr + "WFState,Title=" + dbstr + "Title WHERE OID=" + dbstr + "OID"; ps.Add(GERptAttr.WFState, (int)WFState.Blank); ps.Add(GERptAttr.Title, title); ps.Add(GERptAttr.OID, wk.OID); DBAccess.RunSQL(ps); } else { ps = new Paras(); ps.SQL = "UPDATE " + fl.PTable + " SET WFState=" + dbstr + "WFState,FK_Dept=" + dbstr + "FK_Dept,Title=" + dbstr + "Title WHERE OID=" + dbstr + "OID"; ps.Add(GERptAttr.WFState, (int)WFState.Blank); ps.Add(GERptAttr.FK_Dept, empStarter.FK_Dept); ps.Add(GERptAttr.Title, BP.WF.WorkFlowBuessRole.GenerTitle(fl, wk)); ps.Add(GERptAttr.OID, wk.OID); DBAccess.RunSQL(ps); } // 删除有可能产生的垃圾数据,比如上一次没有发送成功,导致数据没有清除. ps = new Paras(); ps.SQL = "DELETE FROM WF_GenerWorkFlow WHERE WorkID=" + dbstr + "WorkID1 OR FID=" + dbstr + "WorkID2"; ps.Add("WorkID1", wk.OID); ps.Add("WorkID2", wk.OID); DBAccess.RunSQL(ps); ps = new Paras(); ps.SQL = "DELETE FROM WF_GenerWorkerList WHERE WorkID=" + dbstr + "WorkID1 OR FID=" + dbstr + "WorkID2"; ps.Add("WorkID1", wk.OID); ps.Add("WorkID2", wk.OID); DBAccess.RunSQL(ps); // 设置流程信息 if (parentWorkID != 0) { BP.WF.Dev2Interface.SetParentInfo(flowNo, workID, parentWorkID); } #region 处理generworkid // 设置父流程信息. GenerWorkFlow gwf = new GenerWorkFlow(); gwf.WorkID = wk.OID; int i = gwf.RetrieveFromDBSources(); //将流程信息提前写入wf_GenerWorkFlow,避免查询不到 gwf.FlowName = fl.Name; gwf.FK_Flow = flowNo; gwf.FK_FlowSort = fl.FK_FlowSort; gwf.SysType = fl.SysType; gwf.FK_Dept = WebUser.FK_Dept; gwf.DeptName = WebUser.FK_DeptName; gwf.FK_Node = fl.StartNodeID; gwf.NodeName = nd.Name; gwf.WFState = WFState.Runing; if (DataType.IsNullOrEmpty(title)) { gwf.Title = BP.WF.WorkFlowBuessRole.GenerTitle(fl, wk); } else { gwf.Title = title; } gwf.Starter = WebUser.No; gwf.StarterName = WebUser.Name; gwf.RDT = DataType.CurrentDataTimess; gwf.PWorkID = parentWorkID; // gwf.PFID = parentFID; gwf.PFlowNo = parentFlowNo; gwf.PNodeID = parentNodeID; if (i == 0) { gwf.Insert(); } else { gwf.Update(); } //插入待办. GenerWorkerList gwl = new GenerWorkerList(); gwl.WorkID = wk.OID; gwl.FK_Node = nd.NodeID; gwl.FK_Emp = WebUser.No; i = gwl.RetrieveFromDBSources(); gwl.FK_EmpText = WebUser.Name; gwl.FK_NodeText = nd.Name; gwl.FID = 0; gwl.FK_Flow = fl.No; gwl.FK_Dept = WebUser.FK_Dept; gwl.FK_DeptT = WebUser.FK_DeptName; gwl.SDT = "无"; gwl.DTOfWarning = DataType.CurrentDataTime; gwl.IsEnable = true; gwl.IsPass = false; gwl.PRI = gwf.PRI; if (i == 0) { gwl.Insert(); } else { gwl.Update(); } #endregion return(wk.OID); }
/// <summary> /// 执行子线程的撤销. /// </summary> /// <returns></returns> private string DoThreadUnSend() { //定义当前的节点. WorkNode wn = this.GetCurrentWorkNode(); GenerWorkFlow gwf = new GenerWorkFlow(this.WorkID); Node nd = new Node(gwf.FK_Node); #region 求的撤销的节点. int cancelToNodeID = 0; if (nd.HisCancelRole == CancelRole.SpecNodes) { /*1.指定的节点可以撤销,首先判断是否设置指定的节点.*/ // NodeCancels ncs = new NodeCancels(); ncs.Retrieve(NodeCancelAttr.FK_Node, wn.HisNode.NodeID); if (ncs.Count == 0) { throw new Exception("@流程设计错误, 您设置了当前节点(" + wn.HisNode.Name + ")可以让指定的节点人员撤销,但是您没有设置指定的节点."); } //获取Track表 string truckTable = "ND" + int.Parse(wn.HisNode.FK_Flow) + "Track"; //获取到当前节点走过的节点 与 设定可撤销节点的交集 string sql = "SELECT DISTINCT(FK_Node) FROM WF_GenerWorkerlist WHERE "; sql += " FK_Node IN(SELECT CancelTO FROM WF_NodeCancel WHERE FK_Node=" + wn.HisNode.NodeID + ") AND FK_Emp='" + WebUser.No + "'"; string nds = DBAccess.RunSQLReturnString(sql); if (DataType.IsNullOrEmpty(nds)) { throw new Exception("@您不能执行撤消发送,两种原因:1,你不具备撤销该节点的功能;2.流程设计错误,你指定的可以撤销的节点不在流程运转中走过的节点."); } //获取可以删除到的节点 cancelToNodeID = int.Parse(nds.Split(',')[0]); } if (nd.HisCancelRole == CancelRole.OnlyNextStep) { /*如果仅仅允许撤销上一步骤.*/ WorkNode wnPri = wn.GetPreviousWorkNode(); GenerWorkerList wl = new GenerWorkerList(); int num = wl.Retrieve(GenerWorkerListAttr.FK_Emp, BP.Web.WebUser.No, GenerWorkerListAttr.FK_Node, wnPri.HisNode.NodeID); if (num == 0) { throw new Exception("@您不能执行撤消发送,因为当前工作不是您发送的或下一步工作已处理。"); } cancelToNodeID = wnPri.HisNode.NodeID; } if (cancelToNodeID == 0) { throw new Exception("@没有求出要撤销到的节点."); } #endregion 求的撤销的节点. /********** 开始执行撤销. **********************/ Node cancelToNode = new Node(cancelToNodeID); switch (cancelToNode.HisNodeWorkType) { case NodeWorkType.StartWorkFL: case NodeWorkType.WorkFHL: case NodeWorkType.WorkFL: // 调用撤消发送前事件。 nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneBefore, nd, wn.HisWork, null); BP.WF.Dev2Interface.Node_FHL_KillSubFlow(cancelToNode.FK_Flow, this.FID, this.WorkID); //杀掉子线程. // 调用撤消发送前事件。 nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneAfter, nd, wn.HisWork, null); return("KillSubThared@子线程撤销成功."); default: break; } // if (cancelToNode.HisNodeWorkType == NodeWorkType.StartWorkFL) WorkNode wnOfCancelTo = new WorkNode(this.WorkID, cancelToNodeID); // 调用撤消发送前事件。 string msg = nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneBefore, nd, wn.HisWork, null); #region 除当前节点数据。 // 删除产生的工作列表。 GenerWorkerLists wls = new GenerWorkerLists(); wls.Delete(GenerWorkerListAttr.WorkID, this.WorkID, GenerWorkerListAttr.FK_Node, gwf.FK_Node); // 删除工作信息,如果是按照ccflow格式存储的。 if (this.HisFlow.HisDataStoreModel == BP.WF.Template.DataStoreModel.ByCCFlow) { wn.HisWork.Delete(); } // 删除附件信息。 DBAccess.RunSQL("DELETE FROM Sys_FrmAttachmentDB WHERE FK_MapData='ND" + gwf.FK_Node + "' AND RefPKVal='" + this.WorkID + "'"); #endregion 除当前节点数据。 // 更新. gwf.FK_Node = cancelToNode.NodeID; gwf.NodeName = cancelToNode.Name; //如果不启动自动记忆,删除tonodes,用于 选择节点发送。撤消后,可重新选择节点发送 if (cancelToNode.IsRememberMe == false) { gwf.Paras_ToNodes = ""; } if (cancelToNode.IsEnableTaskPool && Glo.IsEnableTaskPool) { gwf.TaskSta = TaskSta.Takeback; } else { gwf.TaskSta = TaskSta.None; } gwf.TodoEmps = WebUser.No + "," + WebUser.Name + ";"; gwf.Update(); if (cancelToNode.IsEnableTaskPool && Glo.IsEnableTaskPool) { //设置全部的人员不可用。 BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0, IsEnable=-1 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node); //设置当前人员可用。 BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0, IsEnable=1 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node + " AND FK_Emp='" + WebUser.No + "'"); } else { BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node); } //更新当前节点,到rpt里面。 BP.DA.DBAccess.RunSQL("UPDATE " + this.HisFlow.PTable + " SET FlowEndNode=" + gwf.FK_Node + " WHERE OID=" + this.WorkID); // 记录日志.. wn.AddToTrack(ActionType.UnSend, WebUser.No, WebUser.Name, cancelToNode.NodeID, cancelToNode.Name, "无"); // 删除数据. if (wn.HisNode.IsStartNode) { DBAccess.RunSQL("DELETE FROM WF_GenerWorkFlow WHERE WorkID=" + this.WorkID); DBAccess.RunSQL("DELETE FROM WF_GenerWorkerlist WHERE WorkID=" + this.WorkID + " AND FK_Node=" + nd.NodeID); } if (wn.HisNode.IsEval) { /*如果是质量考核节点,并且撤销了。*/ DBAccess.RunSQL("DELETE FROM WF_CHEval WHERE FK_Node=" + wn.HisNode.NodeID + " AND WorkID=" + this.WorkID); } #region 恢复工作轨迹,解决工作抢办。 if (cancelToNode.IsStartNode == false && cancelToNode.IsEnableTaskPool == false) { WorkNode ppPri = wnOfCancelTo.GetPreviousWorkNode(); GenerWorkerList wl = new GenerWorkerList(); wl.Retrieve(GenerWorkerListAttr.FK_Node, wnOfCancelTo.HisNode.NodeID, GenerWorkerListAttr.WorkID, this.WorkID); // BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerList SET IsPass=0 WHERE FK_Node=" + backtoNodeID + " AND WorkID=" + this.WorkID); RememberMe rm = new RememberMe(); rm.Retrieve(RememberMeAttr.FK_Node, wnOfCancelTo.HisNode.NodeID, RememberMeAttr.FK_Emp, ppPri.HisWork.Rec); string[] empStrs = rm.Objs.Split('@'); foreach (string s in empStrs) { if (s == "" || s == null) { continue; } if (s == wl.FK_Emp) { continue; } GenerWorkerList wlN = new GenerWorkerList(); wlN.Copy(wl); wlN.FK_Emp = s; WF.Port.WFEmp myEmp = new Port.WFEmp(s); wlN.FK_EmpText = myEmp.Name; wlN.Insert(); } } #endregion 恢复工作轨迹,解决工作抢办。 #region 如果是开始节点, 检查此流程是否有子线程,如果有则删除它们。 if (nd.IsStartNode) { /*要检查一个是否有 子流程,如果有,则删除它们。*/ GenerWorkFlows gwfs = new GenerWorkFlows(); gwfs.Retrieve(GenerWorkFlowAttr.PWorkID, this.WorkID); if (gwfs.Count > 0) { foreach (GenerWorkFlow item in gwfs) { /*删除每个子线程.*/ BP.WF.Dev2Interface.Flow_DoDeleteFlowByReal(item.FK_Flow, item.WorkID, true); } } } #endregion #region 计算完成率。 bool isSetEnable = false; //是否关闭合流节点待办. string mysql = "SELECT COUNT(DISTINCT WorkID) FROM WF_GenerWorkerlist WHERE FID=" + this.FID + " AND IsPass=1 AND FK_Node IN (SELECT Node FROM WF_Direction WHERE ToNode=" + wn.HisNode.NodeID + ")"; decimal numOfPassed = DBAccess.RunSQLReturnValDecimal(mysql, 0, 1); if (nd.PassRate == 100) { isSetEnable = true; } else { mysql = "SELECT COUNT(DISTINCT WorkID) FROM WF_GenerWorkFlow WHERE FID=" + this.FID; decimal numOfAll = DBAccess.RunSQLReturnValDecimal(mysql, 0, 1); decimal rate = numOfPassed / numOfAll * 100; if (nd.PassRate > rate) { isSetEnable = true; } } GenerWorkFlow maingwf = new GenerWorkFlow(this.FID); maingwf.SetPara("ThreadCount", numOfPassed.ToString()); maingwf.Update(); //是否关闭合流节点待办. if (isSetEnable == true) { DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=3 WHERE WorkID=" + this.FID + " AND FK_Node=" + wn.HisNode.NodeID); } #endregion //调用撤消发送后事件。 msg += nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneAfter, nd, wn.HisWork, null); if (wnOfCancelTo.HisNode.IsStartNode) { return("@撤消执行成功. " + msg); } else { return("@撤消执行成功. " + msg); } return("工作已经被您撤销到:" + cancelToNode.Name); }
/// <summary> /// 执行撤消 /// </summary> private string DoUnSendIt() { GenerWorkFlow gwf = new GenerWorkFlow(this.WorkID); if (gwf.WFState == WFState.Complete) { return("err@该流程已经完成,您不能撤销。"); } // 如果停留的节点是分合流。 Node nd = new Node(gwf.FK_Node); /*该节点不允许退回.*/ if (nd.HisCancelRole == CancelRole.None) { throw new Exception("当前节点,不允许撤销。"); } if (nd.IsStartNode && nd.HisNodeWorkType != NodeWorkType.StartWorkFL) { throw new Exception("当前节点是开始节点,所以您不能撤销。"); } //如果撤销到的节点和当前流程运行到的节点相同,则是分流、或者分河流 if (this.UnSendToNode == nd.NodeID) { //如果当前节点是分流、分合流节点则可以撤销 if (nd.HisNodeWorkType == NodeWorkType.StartWorkFL || nd.HisNodeWorkType == NodeWorkType.WorkFL || nd.HisNodeWorkType == NodeWorkType.WorkFHL) { //获取当前节点的子线程 string truckTable = "ND" + int.Parse(nd.FK_Flow) + "Track"; string threadSQL = "SELECT FK_Node,WorkID FROM WF_GenerWorkFlow WHERE FID=" + this.WorkID + " AND FK_Node" + " IN(SELECT DISTINCT(NDTo) FROM " + truckTable + " WHERE ActionType=" + (int)ActionType.ForwardFL + " AND WorkID=" + this.WorkID + " AND NDFrom='" + nd.NodeID + "'" + " ) "; DataTable dt = DBAccess.RunSQLReturnTable(threadSQL); if (dt == null || dt.Rows.Count == 0) { throw new Exception("err@流程运行错误:当不存在子线程时,改过程应该处于待办状态"); } foreach (DataRow dr in dt.Rows) { Node threadnd = new Node(dr["FK_Node"].ToString()); // 调用撤消发送前事件。 nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneBefore, nd, nd.HisWork, null); BP.WF.Dev2Interface.Node_FHL_KillSubFlow(threadnd.FK_Flow, this.WorkID, long.Parse(dr["WorkID"].ToString())); //杀掉子线程. // 调用撤消发送前事件。 nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneAfter, nd, nd.HisWork, null); } return("撤销成功"); } } //如果启用了对方已读,就不能撤销. if (nd.CancelDisWhenRead == true) { //撤销到的节点是干流程节点/子线程撤销到子线程 int i = DBAccess.RunSQLReturnValInt("SELECT SUM(IsRead) AS Num FROM WF_GenerWorkerList WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node, 0); if (i >= 1) { return("err@当前待办已经有[" + i + "]个工作人员打开了该工作,您不能执行撤销."); } else { //干流节点撤销到子线程 i = DBAccess.RunSQLReturnValInt("SELECT SUM(IsRead) AS Num FROM WF_GenerWorkerList WHERE WorkID=" + this.FID + " AND FK_Node=" + gwf.FK_Node, 0); if (i >= 1) { return("err@当前待办已经有[" + i + "]个工作人员打开了该工作,您不能执行撤销."); } } } #region 如果是越轨流程状态 @fanleiwei. string sql = "SELECT COUNT(*) AS Num FROM WF_GenerWorkerlist WHERE WorkID=" + this.WorkID + " AND IsPass=80"; if (DBAccess.RunSQLReturnValInt(sql, 0) != 0) { //求出来越轨子流程workid并把它删除掉. GenerWorkFlow gwfSubFlow = new GenerWorkFlow(); int i = gwfSubFlow.Retrieve(GenerWorkFlowAttr.PWorkID, this.WorkID); if (i == 1) { BP.WF.Dev2Interface.Flow_DoDeleteFlowByReal(gwfSubFlow.FK_Flow, gwfSubFlow.WorkID, true); } //执行回复当前节点待办.. sql = "UPDATE WF_GenerWorkerlist SET IsPass=0 WHERE IsPass=80 AND FK_Node=" + gwf.FK_Node + " AND WorkID=" + this.WorkID; DBAccess.RunSQL(sql); return("撤销延续流程执行成功,撤销到[" + gwf.NodeName + "],撤销给[" + gwf.TodoEmps + "]"); } #endregion 如果是越轨流程状态 . if (BP.WF.Dev2Interface.Flow_IsCanDoCurrentWork(this.WorkID, WebUser.No) == true) { return("info@您有处理当前工作的权限,可能您已经执行了撤销,请使用退回或者发送功能."); } #region 判断是否是会签状态,是否是会签人做的撤销. 主持人是不能撤销的. if (gwf.HuiQianTaskSta != HuiQianTaskSta.None) { string IsEnableUnSendWhenHuiQian = SystemConfig.AppSettings["IsEnableUnSendWhenHuiQian"]; if (DataType.IsNullOrEmpty(IsEnableUnSendWhenHuiQian) == false && IsEnableUnSendWhenHuiQian.Equals("0")) { return("info@当前节点是会签状态,您不能执行撤销."); } GenerWorkerList gwl = new GenerWorkerList(); int numOfmyGwl = gwl.Retrieve(GenerWorkerListAttr.FK_Emp, WebUser.No, GenerWorkerListAttr.WorkID, this.WorkID, GenerWorkerListAttr.FK_Node, gwf.FK_Node); //如果没有找到当前会签人. if (numOfmyGwl == 0) { return("err@当前节点[" + gwf.NodeName + "]是会签状态,[" + gwf.TodoEmps + "]在执行会签,您不能执行撤销."); } if (gwl.IsHuiQian == true) { } //如果是会签人,就让其显示待办. gwl.IsPassInt = 0; gwl.IsEnable = true; gwl.Update(); // 在待办人员列表里加入他. 要判断当前人员是否是主持人,如果是主持人的话,主持人是否在发送的时候, // 就选择方向与接受人. if (gwf.HuiQianZhuChiRen == WebUser.No) { gwf.TodoEmps = WebUser.No + "," + BP.Web.WebUser.Name + ";" + gwf.TodoEmps; } else { gwf.TodoEmps = gwf.TodoEmps + BP.Web.WebUser.Name + ";"; } gwf.Update(); return("会签人撤销成功."); } #endregion 判断是否是会签状态,是否是会签人做的撤销. if (gwf.FID != 0) { //执行子线程的撤销. return(DoThreadUnSend()); } //定义当前的节点. WorkNode wn = this.GetCurrentWorkNode(); #region 求的撤销的节点. int cancelToNodeID = 0; if (nd.HisCancelRole == CancelRole.SpecNodes) { /*指定的节点可以撤销,首先判断当前人员是否有权限.*/ NodeCancels ncs = new NodeCancels(); ncs.Retrieve(NodeCancelAttr.FK_Node, wn.HisNode.NodeID); if (ncs.Count == 0) { throw new Exception("@流程设计错误, 您设置了当前节点(" + wn.HisNode.Name + ")可以让指定的节点人员撤销,但是您没有设置指定的节点."); } /* 查询出来. */ sql = "SELECT FK_Node FROM WF_GenerWorkerList WHERE FK_Emp='" + WebUser.No + "' AND IsPass=1 AND IsEnable=1 AND WorkID=" + wn.HisWork.OID + " ORDER BY RDT DESC "; DataTable dt = DBAccess.RunSQLReturnTable(sql); if (dt.Rows.Count == 0) { throw new Exception("err@撤销流程错误,您没有权限执行撤销发送."); } // 找到将要撤销到的NodeID. foreach (DataRow dr in dt.Rows) { foreach (NodeCancel nc in ncs) { if (nc.CancelTo == int.Parse(dr[0].ToString())) { cancelToNodeID = nc.CancelTo; break; } } if (cancelToNodeID != 0) { break; } } if (cancelToNodeID == 0) { throw new Exception("@撤销流程错误,您没有权限执行撤销发送,当前节点不可以执行撤销."); } } if (nd.HisCancelRole == CancelRole.OnlyNextStep) { /*如果仅仅允许撤销上一步骤.*/ WorkNode wnPri = wn.GetPreviousWorkNode(); GenerWorkerList wl = new GenerWorkerList(); int num = wl.Retrieve(GenerWorkerListAttr.FK_Emp, BP.Web.WebUser.No, GenerWorkerListAttr.FK_Node, wnPri.HisNode.NodeID, GenerWorkerListAttr.WorkID, this.WorkID); if (num == 0) { throw new Exception("err@您不能执行撤消发送,因为当前工作不是您发送的或下一步工作已处理。"); } cancelToNodeID = wnPri.HisNode.NodeID; } if (cancelToNodeID == 0) { throw new Exception("err@没有求出要撤销到的节点."); } #endregion 求的撤销的节点. if (this.UnSendToNode != 0 && gwf.FK_Node != this.UnSendToNode) { Node toNode = new Node(this.UnSendToNode); /* 要撤销的节点是分流节点,并且当前节点不在分流节点而是在合流节点的情况, for:华夏银行. * 1, 分流节点发送给n个人. * 2, 其中一个人发送到合流节点,另外一个人退回给分流节点。 * 3,现在分流节点的人接收到一个待办,并且需要撤销整个分流节点的发送. * 4, UnSendToNode 这个时间没有值,并且当前干流节点的停留的节点与要撤销到的节点不一致。 */ if (toNode.HisNodeWorkType == NodeWorkType.WorkFL && nd.HisNodeWorkType == NodeWorkType.WorkHL) { return(DoUnSendInFeiLiuHeiliu(gwf)); } } #region 判断当前节点的模式. switch (nd.HisNodeWorkType) { case NodeWorkType.WorkFHL: return(this.DoUnSendFeiLiu(gwf)); case NodeWorkType.WorkFL: case NodeWorkType.StartWorkFL: break; case NodeWorkType.WorkHL: if (this.IsMainFlow) { /* 首先找到与他最近的一个分流点,并且判断当前的操作员是不是分流点上的工作人员。*/ return(this.DoUnSendHeiLiu_Main(gwf)); } else { return(this.DoUnSendSubFlow(gwf)); //是子流程时. } break; case NodeWorkType.SubThreadWork: break; default: break; } #endregion 判断当前节点的模式. /********** 开始执行撤销. **********************/ Node cancelToNode = new Node(cancelToNodeID); #region 如果撤销到的节点是普通的节点,并且当前的节点是分流(分流)节点,并且分流(分流)节点已经发送下去了,就不允许撤销了. if (cancelToNode.HisRunModel == RunModel.Ordinary && nd.HisRunModel == RunModel.HL && nd.HisRunModel == RunModel.FHL && nd.HisRunModel == RunModel.FL) { /* 检查一下是否还有没有完成的子线程,如果有就抛出不允许撤销的异常。 */ sql = "SELECT COUNT(*) as NUM FROM WF_GenerWorkerList WHERE FID=" + this.WorkID + " AND IsPass=0"; if (BP.DA.DBAccess.RunSQLReturnValInt(sql) != 0) { return("err@不允许撤销,因为有未完成的子线程."); } // return this.DoUnSendHeiLiu_Main(gwf); } #endregion 如果撤销到的节点是普通的节点,并且当前的节点是分流节点,并且分流节点已经发送下去了. #region 如果当前是协作组长模式,就要考虑当前是否是会签节点,如果是会签节点,就要处理。 if (cancelToNode.TodolistModel == TodolistModel.TeamupGroupLeader || cancelToNode.TodolistModel == TodolistModel.Teamup) { sql = "SELECT ActionType FROM ND" + int.Parse(this.FlowNo) + "Track WHERE NDFrom=" + cancelToNodeID + " AND EmpFrom='" + WebUser.No + "' AND WorkID=" + this.WorkID; DataTable dt = DBAccess.RunSQLReturnTable(sql); foreach (DataRow dr in dt.Rows) { int ac = int.Parse(dr[0].ToString()); ActionType at = (ActionType)ac; if (at == ActionType.TeampUp) { /*如果是写作人员,就不允许他撤销 */ throw new Exception("@您是节点[" + cancelToNode.Name + "]的会签人,您不能执行撤销。"); } } } #endregion 如果当前是协作组长模式 WorkNode wnOfCancelTo = new WorkNode(this.WorkID, cancelToNodeID); // 调用撤消发送前事件。 string msg = nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneBefore, nd, wn.HisWork, null); #region 除当前节点数据。 // 删除产生的工作列表。 GenerWorkerLists wls = new GenerWorkerLists(); wls.Delete(GenerWorkerListAttr.WorkID, this.WorkID, GenerWorkerListAttr.FK_Node, gwf.FK_Node); // 删除工作信息,如果是按照ccflow格式存储的。 if (this.HisFlow.HisDataStoreModel == BP.WF.Template.DataStoreModel.ByCCFlow) { wn.HisWork.Delete(); } // 删除附件信息。 DBAccess.RunSQL("DELETE FROM Sys_FrmAttachmentDB WHERE FK_MapData='ND" + gwf.FK_Node + "' AND RefPKVal='" + this.WorkID + "'"); #endregion 除当前节点数据。 // 更新. gwf.FK_Node = cancelToNode.NodeID; gwf.NodeName = cancelToNode.Name; //恢复上一步发送人 DataTable dtPrevTrack = Dev2Interface.Flow_GetPreviousNodeTrack(this.WorkID, cancelToNode.NodeID); if (dtPrevTrack != null && dtPrevTrack.Rows.Count > 0) { gwf.Sender = dtPrevTrack.Rows[0]["EmpFrom"].ToString(); } if (cancelToNode.IsEnableTaskPool && Glo.IsEnableTaskPool) { gwf.TaskSta = TaskSta.Takeback; } else { gwf.TaskSta = TaskSta.None; } gwf.TodoEmps = WebUser.No + "," + WebUser.Name + ";"; gwf.Update(); if (cancelToNode.IsEnableTaskPool && Glo.IsEnableTaskPool) { //设置全部的人员不可用。 BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0, IsEnable=-1 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node); //设置当前人员可用。 BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0, IsEnable=1 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node + " AND FK_Emp='" + WebUser.No + "'"); } else { BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node + " AND FK_Emp='" + WebUser.No + "'"); } //更新当前节点,到rpt里面。 BP.DA.DBAccess.RunSQL("UPDATE " + this.HisFlow.PTable + " SET FlowEndNode=" + gwf.FK_Node + " WHERE OID=" + this.WorkID); // 记录日志.. wn.AddToTrack(ActionType.UnSend, WebUser.No, WebUser.Name, cancelToNode.NodeID, cancelToNode.Name, "无"); //删除审核组件设置“协作模式下操作员显示顺序”为“按照接受人员列表先后顺序(官职大小)”,而生成的待审核轨迹信息 FrmWorkCheck fwc = new FrmWorkCheck(nd.NodeID); if (fwc.FWCSta == FrmWorkCheckSta.Enable && fwc.FWCOrderModel == FWCOrderModel.SqlAccepter) { BP.DA.DBAccess.RunSQL("DELETE FROM ND" + int.Parse(nd.FK_Flow) + "Track WHERE WorkID = " + this.WorkID + " AND ActionType = " + (int)ActionType.WorkCheck + " AND NDFrom = " + nd.NodeID + " AND NDTo = " + nd.NodeID + " AND (Msg = '' OR Msg IS NULL)"); } // 删除数据. if (wn.HisNode.IsStartNode) { DBAccess.RunSQL("DELETE FROM WF_GenerWorkFlow WHERE WorkID=" + this.WorkID); DBAccess.RunSQL("DELETE FROM WF_GenerWorkerlist WHERE WorkID=" + this.WorkID + " AND FK_Node=" + nd.NodeID); } else { DBAccess.RunSQL("DELETE FROM WF_GenerWorkerlist WHERE WorkID=" + this.WorkID + " AND FK_Node=" + nd.NodeID); } //首先删除当前节点的,审核意见. string delTrackSQl = "DELETE FROM ND" + int.Parse(nd.FK_Flow) + "Track WHERE WorkID=" + this.WorkID + " AND NDFrom=" + nd.NodeID + " AND ActionType =22 "; DBAccess.RunSQL(delTrackSQl); if (wn.HisNode.IsEval) { /*如果是质量考核节点,并且撤销了。*/ DBAccess.RunSQL("DELETE FROM WF_CHEval WHERE FK_Node=" + wn.HisNode.NodeID + " AND WorkID=" + this.WorkID); } #region 恢复工作轨迹,解决工作抢办。 if (cancelToNode.IsStartNode == false && cancelToNode.IsEnableTaskPool == false) { WorkNode ppPri = wnOfCancelTo.GetPreviousWorkNode(); GenerWorkerList wl = new GenerWorkerList(); wl.Retrieve(GenerWorkerListAttr.FK_Node, wnOfCancelTo.HisNode.NodeID, GenerWorkerListAttr.WorkID, this.WorkID); // BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerList SET IsPass=0 WHERE FK_Node=" + backtoNodeID + " AND WorkID=" + this.WorkID); RememberMe rm = new RememberMe(); rm.Retrieve(RememberMeAttr.FK_Node, wnOfCancelTo.HisNode.NodeID, RememberMeAttr.FK_Emp, ppPri.HisWork.Rec); string[] empStrs = rm.Objs.Split('@'); foreach (string s in empStrs) { if (s == "" || s == null) { continue; } if (s == wl.FK_Emp) { continue; } GenerWorkerList wlN = new GenerWorkerList(); wlN.Copy(wl); wlN.FK_Emp = s; WF.Port.WFEmp myEmp = new Port.WFEmp(s); wlN.FK_EmpText = myEmp.Name; wlN.Insert(); } } #endregion 恢复工作轨迹,解决工作抢办。 #region 如果是开始节点, 检查此流程是否有子流程,如果有则删除它们。 if (nd.IsStartNode) { /*要检查一个是否有 子流程,如果有,则删除它们。*/ GenerWorkFlows gwfs = new GenerWorkFlows(); gwfs.Retrieve(GenerWorkFlowAttr.PWorkID, this.WorkID); if (gwfs.Count > 0) { foreach (GenerWorkFlow item in gwfs) { /*删除每个子线程.*/ BP.WF.Dev2Interface.Flow_DoDeleteFlowByReal(item.FK_Flow, item.WorkID, true); } } } #endregion //调用撤消发送后事件。 msg += nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneAfter, nd, wn.HisWork, null); if (wnOfCancelTo.HisNode.IsStartNode) { switch (wnOfCancelTo.HisNode.HisFormType) { case NodeFormType.FoolForm: case NodeFormType.FreeForm: return("@撤消执行成功." + msg); break; default: return("@撤销成功." + msg); break; } } else { // 更新是否显示。 // DBAccess.RunSQL("UPDATE WF_ForwardWork SET IsRead=1 WHERE WORKID=" + this.WorkID + " AND FK_Node=" + cancelToNode.NodeID); switch (wnOfCancelTo.HisNode.HisFormType) { case NodeFormType.FoolForm: case NodeFormType.FreeForm: return("@撤消执行成功. " + msg); break; default: return("撤销成功:" + msg); break; } } return("工作已经被您撤销到:" + cancelToNode.Name); }
/// <summary> /// 执行撤销发送 /// </summary> /// <param name="gwf"></param> /// <returns></returns> public string DoUnSendHeiLiu_Main(GenerWorkFlow gwf) { Node currNode = new Node(gwf.FK_Node); Node priFLNode = currNode.HisPriFLNode; GenerWorkerList wl = new GenerWorkerList(); //判断改操作人员是否是分流节点上的人员. int i = wl.Retrieve(GenerWorkerListAttr.FK_Node, priFLNode.NodeID, GenerWorkerListAttr.FK_Emp, BP.Web.WebUser.No); if (i == 0) { return("@不是您把工作发送到当前节点上,所以您不能撤消。"); } WorkNode wn = this.GetCurrentWorkNode(); WorkNode wnPri = new WorkNode(this.WorkID, priFLNode.NodeID); // 记录日志.. wnPri.AddToTrack(ActionType.UnSend, WebUser.No, WebUser.Name, wnPri.HisNode.NodeID, wnPri.HisNode.Name, "无"); //删除当前节点的流程 GenerWorkerLists wls = new GenerWorkerLists(); wls.Delete(GenerWorkerListAttr.WorkID, this.WorkID, GenerWorkerListAttr.FK_Node, gwf.FK_Node.ToString()); if (this.HisFlow.HisDataStoreModel == BP.WF.Template.DataStoreModel.ByCCFlow) { wn.HisWork.Delete(); } //更改流程信息 gwf.FK_Node = wnPri.HisNode.NodeID; gwf.NodeName = wnPri.HisNode.Name; gwf.Update(); BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node); //删除子线程的功能 foreach (Node ndNext in wnPri.HisNode.HisToNodes) { i = DBAccess.RunSQL("DELETE FROM WF_GenerWorkerList WHERE FID=" + this.WorkID + " AND FK_Node=" + ndNext.NodeID); if (i == 0) { continue; } if (ndNext.HisRunModel == RunModel.SubThread) { /*如果到达的节点是子线程,就查询出来发起的子线程。*/ GenerWorkFlows gwfs = new GenerWorkFlows(); gwfs.Retrieve(GenerWorkFlowAttr.FID, this.WorkID); foreach (GenerWorkFlow en in gwfs) { BP.WF.Dev2Interface.Flow_DeleteSubThread(gwf.FK_Flow, en.WorkID, "合流节点撤销发送前,删除子线程."); } continue; } // 删除工作记录。 Works wks = ndNext.HisWorks; if (this.HisFlow.HisDataStoreModel == BP.WF.Template.DataStoreModel.ByCCFlow) { wks.Delete(GenerWorkerListAttr.FID, this.WorkID); } } ShiftWorks fws = new ShiftWorks(); fws.Delete(ShiftWorkAttr.FK_Node, wn.HisNode.NodeID.ToString(), ShiftWorkAttr.WorkID, this.WorkID.ToString()); #region 恢复工作轨迹,解决工作抢办。 if (wnPri.HisNode.IsStartNode == false) { WorkNode ppPri = wnPri.GetPreviousWorkNode(); wl = new GenerWorkerList(); wl.Retrieve(GenerWorkerListAttr.FK_Node, wnPri.HisNode.NodeID, GenerWorkerListAttr.WorkID, this.WorkID); RememberMe rm = new RememberMe(); rm.Retrieve(RememberMeAttr.FK_Node, wnPri.HisNode.NodeID, RememberMeAttr.FK_Emp, ppPri.HisWork.Rec); string[] empStrs = rm.Objs.Split('@'); foreach (string s in empStrs) { if (s == "" || s == null) { continue; } if (s == wl.FK_Emp) { continue; } GenerWorkerList wlN = new GenerWorkerList(); wlN.Copy(wl); wlN.FK_Emp = s; WF.Port.WFEmp myEmp = new Port.WFEmp(s); wlN.FK_EmpText = myEmp.Name; wlN.Insert(); } } #endregion 恢复工作轨迹,解决工作抢办。 // 删除以前的节点数据. wnPri.DeleteToNodesData(priFLNode.HisToNodes); if (wnPri.HisNode.IsStartNode) { if (wnPri.HisNode.HisFormType != NodeFormType.SDKForm) { return("@撤消执行成功."); } else { return("@撤销成功."); } } else { return("@撤消执行成功."); } }
public void AutoCC() { if (this.HisWorkNode.HisNode.HisCCRole == CCRole.AutoCC || this.HisWorkNode.HisNode.HisCCRole == CCRole.HandAndAuto) { } else { return; } /*如果是自动抄送*/ CC cc = this.HisWorkNode.HisNode.HisCC; #region 替换节点变量 cc.CCSQL = cc.CCSQL.Replace("@FK_Node", this.HisNode.NodeID + ""); cc.CCSQL = cc.CCSQL.Replace("@FK_Flow", this.HisNode.FK_Flow); cc.CCSQL = cc.CCSQL.Replace("@OID", this.HisWorkNode.WorkID + ""); #endregion // 执行抄送. DataTable dt = cc.GenerCCers(this.HisWorkNode.rptGe); if (dt.Rows.Count == 0) { return; } string ccMsg = "@消息自动抄送给"; string basePath = BP.WF.Glo.HostURL; string mailTemp = BP.DA.DataType.ReadTextFile2Html(BP.Sys.SystemConfig.PathOfDataUser + "\\EmailTemplete\\CC_" + WebUser.SysLang + ".txt"); GenerWorkerLists gwls = null; if (this.HisWorkNode.town != null) { //取出抄送集合,如果待办里有此人就取消该人员的抄送. gwls = new GenerWorkerLists(this.WorkID, this.HisWorkNode.town.HisNode.NodeID); } foreach (DataRow dr in dt.Rows) { string toUserNo = dr[0].ToString(); //如果待办包含了它. if (gwls != null && gwls.Contains(GenerWorkerListAttr.FK_Emp, toUserNo) == true) { continue; } string toUserName = dr[1].ToString(); //生成标题与内容. string ccTitle = cc.CCTitle.Clone() as string; ccTitle = BP.WF.Glo.DealExp(ccTitle, this.rptGe, null); string ccDoc = cc.CCDoc.Clone() as string; ccDoc = BP.WF.Glo.DealExp(ccDoc, this.rptGe, null); ccDoc = ccDoc.Replace("@Accepter", toUserNo); ccTitle = ccTitle.Replace("@Accepter", toUserNo); //抄送信息. ccMsg += "(" + toUserNo + " - " + toUserName + ");"; #region 如果是写入抄送列表. if (this.HisNode.CCWriteTo == CCWriteTo.All || this.HisNode.CCWriteTo == CCWriteTo.CCList) { /*如果要求写入抄送列表.*/ CCList list = new CCList(); list.MyPK = this.HisWorkNode.WorkID + "_" + this.HisWorkNode.HisNode.NodeID + "_" + dr[0].ToString(); list.FK_Flow = this.HisWorkNode.HisNode.FK_Flow; list.FlowName = this.HisWorkNode.HisNode.FlowName; list.FK_Node = this.HisWorkNode.HisNode.NodeID; list.NodeName = this.HisWorkNode.HisNode.Name; list.Title = ccTitle; list.Doc = ccDoc; list.CCTo = dr[0].ToString(); list.CCToName = dr[1].ToString(); list.RDT = DataType.CurrentDataTime; list.Rec = WebUser.No; list.WorkID = this.HisWorkNode.WorkID; list.FID = this.HisWorkNode.HisWork.FID; try { list.Insert(); } catch { list.Update(); } } #endregion 如果是写入抄送列表. #region 如果要写入待办. if (this.HisNode.CCWriteTo == CCWriteTo.All || this.HisNode.CCWriteTo == CCWriteTo.Todolist) { /*如果要写入待办*/ GenerWorkerList gwl = (GenerWorkerList)gwls[0]; gwl.FK_Emp = dr[0].ToString(); gwl.FK_EmpText = dr[1].ToString(); gwl.IsCC = true; try { gwl.Insert(); } catch { /*这里有可能,抄送人与待办人重复.*/ } } #endregion 如果要写入待办. if (BP.WF.Glo.IsEnableSysMessage == true) { // //写入消息提示. // ccMsg += list.CCTo + "(" + dr[1].ToString() + ");"; // BP.WF.Port.WFEmp wfemp = new Port.WFEmp(list.CCTo); // string sid = list.CCTo + "_" + list.WorkID + "_" + list.FK_Node + "_" + list.RDT; // string url = basePath + "WF/Do.aspx?DoType=OF&SID=" + sid; // string urlWap = basePath + "WF/Do.aspx?DoType=OF&SID=" + sid + "&IsWap=1"; // string mytemp = mailTemp.Clone() as string; // mytemp = string.Format(mytemp, wfemp.Name, WebUser.Name, url, urlWap); // string title = string.Format("工作抄送:{0}.工作:{1},发送人:{2},需您查阅", //this.HisNode.FlowName, this.HisNode.Name, WebUser.Name); // BP.WF.Dev2Interface.Port_SendMsg(wfemp.No, title, mytemp, null, BP.Sys.SMSMsgType.CC, list.FK_Flow, list.FK_Node, list.WorkID, list.FID); } } this.HisWorkNode.addMsg(SendReturnMsgFlag.CCMsg, ccMsg); //写入日志. this.HisWorkNode.AddToTrack(ActionType.CC, WebUser.No, WebUser.Name, this.HisNode.NodeID, this.HisNode.Name, ccMsg, this.HisNode); }
/// <summary> /// 执行撤销发送 /// </summary> /// <param name="gwf"></param> /// <returns></returns> public string DoUnSendHeiLiu_Main(GenerWorkFlow gwf) { Node currNode = new Node(gwf.FK_Node); Node priFLNode = currNode.HisPriFLNode; GenerWorkerList wl = new GenerWorkerList(); int i = wl.Retrieve(GenerWorkerListAttr.FK_Node, priFLNode.NodeID, GenerWorkerListAttr.FK_Emp, BP.Web.WebUser.No); if (i == 0) { return("@不是您把工作发送到当前节点上,所以您不能撤消。"); } WorkNode wn = this.GetCurrentWorkNode(); WorkNode wnPri = new WorkNode(this.WorkID, priFLNode.NodeID); // 记录日志.. wnPri.AddToTrack(ActionType.UnSend, WebUser.No, WebUser.Name, wnPri.HisNode.NodeID, wnPri.HisNode.Name, "无"); GenerWorkerLists wls = new GenerWorkerLists(); wls.Delete(GenerWorkerListAttr.WorkID, this.WorkID, GenerWorkerListAttr.FK_Node, gwf.FK_Node.ToString()); if (this.HisFlow.HisDataStoreModel == BP.WF.Template.DataStoreModel.ByCCFlow) { wn.HisWork.Delete(); } gwf.FK_Node = wnPri.HisNode.NodeID; gwf.NodeName = wnPri.HisNode.Name; gwf.Update(); BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node); BP.DA.DBAccess.RunSQL("UPDATE WF_GenerFH SET FK_Node=" + gwf.FK_Node + " WHERE FID=" + this.WorkID); ShiftWorks fws = new ShiftWorks(); fws.Delete(ShiftWorkAttr.FK_Node, wn.HisNode.NodeID.ToString(), ShiftWorkAttr.WorkID, this.WorkID.ToString()); #region 恢复工作轨迹,解决工作抢办。 if (wnPri.HisNode.IsStartNode == false) { WorkNode ppPri = wnPri.GetPreviousWorkNode(); wl = new GenerWorkerList(); wl.Retrieve(GenerWorkerListAttr.FK_Node, wnPri.HisNode.NodeID, GenerWorkerListAttr.WorkID, this.WorkID); // BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerList SET IsPass=0 WHERE FK_Node=" + backtoNodeID + " AND WorkID=" + this.WorkID); RememberMe rm = new RememberMe(); rm.Retrieve(RememberMeAttr.FK_Node, wnPri.HisNode.NodeID, RememberMeAttr.FK_Emp, ppPri.HisWork.Rec); string[] empStrs = rm.Objs.Split('@'); foreach (string s in empStrs) { if (s == "" || s == null) { continue; } if (s == wl.FK_Emp) { continue; } GenerWorkerList wlN = new GenerWorkerList(); wlN.Copy(wl); wlN.FK_Emp = s; WF.Port.WFEmp myEmp = new Port.WFEmp(s); wlN.FK_EmpText = myEmp.Name; wlN.Insert(); } } #endregion 恢复工作轨迹,解决工作抢办。 // 删除以前的节点数据. wnPri.DeleteToNodesData(priFLNode.HisToNodes); if (wnPri.HisNode.IsStartNode) { if (BP.Web.WebUser.IsWap) { if (wnPri.HisNode.HisFormType != NodeFormType.SDKForm) { return("@撤消执行成功,您可以点这里<a href='" + this.VirPath + this.AppType + "/MyFlow.aspx?FK_Flow=" + this.FlowNo + "&WorkID=" + this.WorkID + "&FK_Node=" + gwf.FK_Node + "'><img src='" + VirPath + "WF/Img/Btn/Do.gif' border=0/>执行工作</A> , <a href='" + this.VirPath + this.AppType + "/MyFlowInfo.aspx?DoType=DeleteFlow&WorkID=" + wn.HisWork.OID + "&FK_Flow=" + this.FlowNo + "' /><img src='" + VirPath + "WF/Img/Btn/Delete.gif' border=0/>此流程已经完成(删除它)</a>。"); } else { return("@撤销成功."); } } else { if (wnPri.HisNode.HisFormType != NodeFormType.SDKForm) { return("@撤消执行成功,您可以点这里<a href='" + this.VirPath + this.AppType + "/MyFlow.aspx?FK_Flow=" + this.FlowNo + "&WorkID=" + this.WorkID + "&FK_Node=" + gwf.FK_Node + "'><img src='" + VirPath + "WF/Img/Btn/Do.gif' border=0/>执行工作</A> , <a href='" + this.VirPath + this.AppType + "/MyFlowInfo.aspx?DoType=DeleteFlow&WorkID=" + wn.HisWork.OID + "&FK_Flow=" + this.FlowNo + "' /><img src='" + VirPath + "WF/Img/Btn/Delete.gif' border=0/>此流程已经完成(删除它)</a>。"); } else { return("@撤销成功."); } } } else { // 更新是否显示。 #warning // DBAccess.RunSQL("UPDATE WF_ForwardWork SET IsRead=1 WHERE WORKID=" + this.WorkID + " AND FK_Node=" + wnPri.HisNode.NodeID); if (BP.Web.WebUser.IsWap == false) { return("@撤消执行成功,您可以点这里<a href='" + this.VirPath + this.AppType + "/MyFlow.aspx?FK_Flow=" + this.FlowNo + "&WorkID=" + this.WorkID + "&FK_Node=" + gwf.FK_Node + "'><img src='" + VirPath + "WF/Img/Btn/Do.gif' border=0/>执行工作</A>。"); } else { return("@撤消执行成功,您可以点这里<a href='" + this.VirPath + this.AppType + "/MyFlow.aspx?FK_Flow=" + this.FlowNo + "&WorkID=" + this.WorkID + "&FK_Node=" + gwf.FK_Node + "'><img src='" + VirPath + "WF/Img/Btn/Do.gif' border=0/>执行工作</A>。"); } } }
/// <summary> /// 执行撤消 /// </summary> public string DoUnSend() { GenerWorkFlow gwf = new GenerWorkFlow(this.WorkID); if (gwf.FID != 0) { /* * 说明该流程是一个子线程,如果子线程的撤销,就需要删除该子线程。 */ BP.WF.Dev2Interface.Flow_DeleteSubThread(this.FlowNo, this.WorkID, "撤销方式删除"); return("@子线程已经被删除."); } // 如果停留的节点是分合流。 Node nd = new Node(gwf.FK_Node); if (nd.HisCancelRole == CancelRole.None) { /*该节点不允许退回.*/ throw new Exception("当前节点,不允许撤销。"); } switch (nd.HisNodeWorkType) { case NodeWorkType.WorkFHL: throw new Exception("分合流点不允许撤消。"); case NodeWorkType.WorkFL: /*判断权限,当前的发送人是谁,如果是自己,就可以撤销.*/ if (gwf.Sender != WebUser.No) { throw new Exception("@分流点不是您发送的,您不能执行撤销。"); } return(this.DoUnSendFeiLiu(gwf)); case NodeWorkType.StartWorkFL: return(this.DoUnSendFeiLiu(gwf)); case NodeWorkType.WorkHL: if (this.IsMainFlow) { /* 首先找到与他最近的一个分流点,并且判断当前的操作员是不是分流点上的工作人员。*/ return(this.DoUnSendHeiLiu_Main(gwf)); } else { return(this.DoUnSendSubFlow(gwf)); //是子流程时. } break; case NodeWorkType.SubThreadWork: break; default: break; } if (nd.IsStartNode) { throw new Exception("当前节点是开始节点,所以您不能撤销。"); } //定义当前的节点. WorkNode wn = this.GetCurrentWorkNode(); #region 求的撤销的节点. int cancelToNodeID = 0; if (nd.HisCancelRole == CancelRole.SpecNodes) { /*指定的节点可以撤销,首先判断当前人员是否有权限.*/ NodeCancels ncs = new NodeCancels(); ncs.Retrieve(NodeCancelAttr.FK_Node, wn.HisNode.NodeID); if (ncs.Count == 0) { throw new Exception("@流程设计错误, 您设置了当前节点(" + wn.HisNode.Name + ")可以让指定的节点人员撤销,但是您没有设置指定的节点."); } /* 查询出来. */ string sql = "SELECT FK_Node FROM WF_GenerWorkerList WHERE FK_Emp='" + WebUser.No + "' AND IsPass=1 AND IsEnable=1 AND WorkID=" + wn.HisWork.OID + " ORDER BY RDT DESC "; DataTable dt = DBAccess.RunSQLReturnTable(sql); if (dt.Rows.Count == 0) { throw new Exception("@撤销流程错误,您没有权限执行撤销发送."); } // 找到将要撤销到的NodeID. foreach (DataRow dr in dt.Rows) { foreach (NodeCancel nc in ncs) { if (nc.CancelTo == int.Parse(dr[0].ToString())) { cancelToNodeID = nc.CancelTo; break; } } if (cancelToNodeID != 0) { break; } } if (cancelToNodeID == 0) { throw new Exception("@撤销流程错误,您没有权限执行撤销发送,没有找到可以撤销的节点."); } } if (nd.HisCancelRole == CancelRole.OnlyNextStep) { /*如果仅仅允许撤销上一步骤.*/ WorkNode wnPri = wn.GetPreviousWorkNode(); GenerWorkerList wl = new GenerWorkerList(); int num = wl.Retrieve(GenerWorkerListAttr.FK_Emp, BP.Web.WebUser.No, GenerWorkerListAttr.FK_Node, wnPri.HisNode.NodeID); if (num == 0) { throw new Exception("@您不能执行撤消发送,因为当前工作不是您发送的或下一步工作已处理。"); } cancelToNodeID = wnPri.HisNode.NodeID; } if (cancelToNodeID == 0) { throw new Exception("@没有求出要撤销到的节点."); } #endregion 求的撤销的节点. /********** 开始执行撤销. **********************/ Node cancelToNode = new Node(cancelToNodeID); WorkNode wnOfCancelTo = new WorkNode(this.WorkID, cancelToNodeID); // 调用撤消发送前事件。 string msg = nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneBefore, nd, wn.HisWork, null); #region 除当前节点数据。 // 删除产生的工作列表。 GenerWorkerLists wls = new GenerWorkerLists(); wls.Delete(GenerWorkerListAttr.WorkID, this.WorkID, GenerWorkerListAttr.FK_Node, gwf.FK_Node); // 删除工作信息,如果是按照ccflow格式存储的。 if (this.HisFlow.HisDataStoreModel == BP.WF.Template.DataStoreModel.ByCCFlow) { wn.HisWork.Delete(); } // 删除附件信息。 DBAccess.RunSQL("DELETE FROM Sys_FrmAttachmentDB WHERE FK_MapData='ND" + gwf.FK_Node + "' AND RefPKVal='" + this.WorkID + "'"); #endregion 除当前节点数据。 // 更新. gwf.FK_Node = cancelToNode.NodeID; gwf.NodeName = cancelToNode.Name; if (cancelToNode.IsEnableTaskPool && Glo.IsEnableTaskPool) { gwf.TaskSta = TaskSta.Takeback; } else { gwf.TaskSta = TaskSta.None; } gwf.TodoEmps = WebUser.No + "," + WebUser.Name; gwf.Update(); if (cancelToNode.IsEnableTaskPool && Glo.IsEnableTaskPool) { //设置全部的人员不可用。 BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0, IsEnable=-1 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node); //设置当前人员可用。 BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0, IsEnable=1 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node + " AND FK_Emp='" + WebUser.No + "'"); } else { BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node); } //更新当前节点,到rpt里面。 BP.DA.DBAccess.RunSQL("UPDATE " + this.HisFlow.PTable + " SET FlowEndNode=" + gwf.FK_Node + " WHERE OID=" + this.WorkID); // 记录日志.. wn.AddToTrack(ActionType.UnSend, WebUser.No, WebUser.Name, cancelToNode.NodeID, cancelToNode.Name, "无"); // 删除数据. if (wn.HisNode.IsStartNode) { DBAccess.RunSQL("DELETE FROM WF_GenerFH WHERE FID=" + this.WorkID); DBAccess.RunSQL("DELETE FROM WF_GenerWorkFlow WHERE WorkID=" + this.WorkID); DBAccess.RunSQL("DELETE FROM WF_GenerWorkerlist WHERE WorkID=" + this.WorkID + " AND FK_Node=" + nd.NodeID); } if (wn.HisNode.IsEval) { /*如果是质量考核节点,并且撤销了。*/ DBAccess.RunSQL("DELETE FROM WF_CHEval WHERE FK_Node=" + wn.HisNode.NodeID + " AND WorkID=" + this.WorkID); } #region 恢复工作轨迹,解决工作抢办。 if (cancelToNode.IsStartNode == false && cancelToNode.IsEnableTaskPool == false) { WorkNode ppPri = wnOfCancelTo.GetPreviousWorkNode(); GenerWorkerList wl = new GenerWorkerList(); wl.Retrieve(GenerWorkerListAttr.FK_Node, wnOfCancelTo.HisNode.NodeID, GenerWorkerListAttr.WorkID, this.WorkID); // BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerList SET IsPass=0 WHERE FK_Node=" + backtoNodeID + " AND WorkID=" + this.WorkID); RememberMe rm = new RememberMe(); rm.Retrieve(RememberMeAttr.FK_Node, wnOfCancelTo.HisNode.NodeID, RememberMeAttr.FK_Emp, ppPri.HisWork.Rec); string[] empStrs = rm.Objs.Split('@'); foreach (string s in empStrs) { if (s == "" || s == null) { continue; } if (s == wl.FK_Emp) { continue; } GenerWorkerList wlN = new GenerWorkerList(); wlN.Copy(wl); wlN.FK_Emp = s; WF.Port.WFEmp myEmp = new Port.WFEmp(s); wlN.FK_EmpText = myEmp.Name; wlN.Insert(); } } #endregion 恢复工作轨迹,解决工作抢办。 #region 如果是开始节点, 检查此流程是否有子线程,如果有则删除它们。 if (nd.IsStartNode) { /*要检查一个是否有 子流程,如果有,则删除它们。*/ GenerWorkFlows gwfs = new GenerWorkFlows(); gwfs.Retrieve(GenerWorkFlowAttr.PWorkID, this.WorkID); if (gwfs.Count > 0) { foreach (GenerWorkFlow item in gwfs) { /*删除每个子线程.*/ BP.WF.Dev2Interface.Flow_DoDeleteFlowByReal(item.FK_Flow, item.WorkID, true); } } } #endregion //调用撤消发送后事件。 msg += nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneAfter, nd, wn.HisWork, null); if (wnOfCancelTo.HisNode.IsStartNode) { if (BP.Web.WebUser.IsWap) { if (wnOfCancelTo.HisNode.HisFormType != NodeFormType.SDKForm) { return("@撤消发送执行成功,您可以点这里<a href='" + VirPath + "WF/Wap/MyFlow.aspx?FK_Flow=" + this.FlowNo + "&WorkID=" + this.WorkID + "&FK_Node=" + gwf.FK_Node + "'><img src='" + VirPath + "WF/Img/Btn/Do.gif' border=0/>执行工作</A> , <a href='" + VirPath + "WF/Wap/MyFlowInfo.aspx?DoType=DeleteFlow&WorkID=" + wn.HisWork.OID + "&FK_Flow=" + this.FlowNo + "' /><img src='" + VirPath + "WF/Img/Btn/Delete.gif' border=0/>此流程已经完成(删除它)</a>。" + msg); } else { return("@撤销成功." + msg); } } else { switch (wnOfCancelTo.HisNode.HisFormType) { case NodeFormType.FixForm: case NodeFormType.FreeForm: return("@撤消执行成功,您可以点这里<a href='" + this.VirPath + this.AppType + "/MyFlow.aspx?FK_Flow=" + this.FlowNo + "&WorkID=" + this.WorkID + "&FK_Node=" + gwf.FK_Node + "'><img src='" + VirPath + "WF/Img/Btn/Do.gif' border=0/>执行工作</A> , <a href='" + this.VirPath + this.AppType + "/Do.aspx?ActionType=DeleteFlow&WorkID=" + wn.HisWork.OID + "&FK_Flow=" + this.FlowNo + "' /><img src='" + VirPath + "WF/Img/Btn/Delete.gif' border=0/>此流程已经完成(删除它)</a>。" + msg); break; default: return("撤销成功" + msg); break; } } } else { // 更新是否显示。 // DBAccess.RunSQL("UPDATE WF_ForwardWork SET IsRead=1 WHERE WORKID=" + this.WorkID + " AND FK_Node=" + cancelToNode.NodeID); switch (wnOfCancelTo.HisNode.HisFormType) { case NodeFormType.FixForm: case NodeFormType.FreeForm: return("@撤消执行成功,您可以点这里<a href='" + this.VirPath + this.AppType + "/MyFlow.aspx?FK_Flow=" + this.FlowNo + "&WorkID=" + this.WorkID + "&FK_Node=" + gwf.FK_Node + "'><img src='" + VirPath + "WF/Img/Btn/Do.gif' border=0/>执行工作</A> . " + msg); break; default: return("撤销成功:" + msg); break; } } return("工作已经被您撤销到:" + cancelToNode.Name); }
/// <summary> /// 执行子线程的撤销. /// </summary> /// <returns></returns> private string DoThreadUnSend() { //定义当前的节点. WorkNode wn = this.GetCurrentWorkNode(); GenerWorkFlow gwf = new GenerWorkFlow(this.WorkID); Node nd = new Node(gwf.FK_Node); #region 求的撤销的节点. int cancelToNodeID = 0; if (nd.HisCancelRole == CancelRole.SpecNodes) { /*指定的节点可以撤销,首先判断当前人员是否有权限.*/ NodeCancels ncs = new NodeCancels(); ncs.Retrieve(NodeCancelAttr.FK_Node, wn.HisNode.NodeID); if (ncs.Count == 0) { throw new Exception("@流程设计错误, 您设置了当前节点(" + wn.HisNode.Name + ")可以让指定的节点人员撤销,但是您没有设置指定的节点."); } /* 查询出来. */ string sql = "SELECT FK_Node FROM WF_GenerWorkerList WHERE FK_Emp='" + WebUser.No + "' AND IsPass=1 AND IsEnable=1 AND WorkID=" + wn.HisWork.OID + " ORDER BY RDT DESC "; DataTable dt = DBAccess.RunSQLReturnTable(sql); if (dt.Rows.Count == 0) { throw new Exception("@撤销流程错误,您没有权限执行撤销发送."); } // 找到将要撤销到的NodeID. foreach (DataRow dr in dt.Rows) { foreach (NodeCancel nc in ncs) { if (nc.CancelTo == int.Parse(dr[0].ToString())) { cancelToNodeID = nc.CancelTo; break; } } if (cancelToNodeID != 0) { break; } } if (cancelToNodeID == 0) { throw new Exception("@撤销流程错误,您没有权限执行撤销发送,没有找到可以撤销的节点."); } } if (nd.HisCancelRole == CancelRole.OnlyNextStep) { /*如果仅仅允许撤销上一步骤.*/ WorkNode wnPri = wn.GetPreviousWorkNode(); GenerWorkerList wl = new GenerWorkerList(); int num = wl.Retrieve(GenerWorkerListAttr.FK_Emp, BP.Web.WebUser.No, GenerWorkerListAttr.FK_Node, wnPri.HisNode.NodeID); if (num == 0) { throw new Exception("@您不能执行撤消发送,因为当前工作不是您发送的或下一步工作已处理。"); } cancelToNodeID = wnPri.HisNode.NodeID; } if (cancelToNodeID == 0) { throw new Exception("@没有求出要撤销到的节点."); } #endregion 求的撤销的节点. /********** 开始执行撤销. **********************/ Node cancelToNode = new Node(cancelToNodeID); WorkNode wnOfCancelTo = new WorkNode(this.WorkID, cancelToNodeID); // 调用撤消发送前事件。 string msg = nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneBefore, nd, wn.HisWork, null); #region 除当前节点数据。 // 删除产生的工作列表。 GenerWorkerLists wls = new GenerWorkerLists(); wls.Delete(GenerWorkerListAttr.WorkID, this.WorkID, GenerWorkerListAttr.FK_Node, gwf.FK_Node); // 删除工作信息,如果是按照ccflow格式存储的。 if (this.HisFlow.HisDataStoreModel == BP.WF.Template.DataStoreModel.ByCCFlow) { wn.HisWork.Delete(); } // 删除附件信息。 DBAccess.RunSQL("DELETE FROM Sys_FrmAttachmentDB WHERE FK_MapData='ND" + gwf.FK_Node + "' AND RefPKVal='" + this.WorkID + "'"); #endregion 除当前节点数据。 // 更新. gwf.FK_Node = cancelToNode.NodeID; gwf.NodeName = cancelToNode.Name; //如果不启动自动记忆,删除tonodes,用于 选择节点发送。撤消后,可重新选择节点发送 if (cancelToNode.IsRememberMe == false) { gwf.Paras_ToNodes = ""; } if (cancelToNode.IsEnableTaskPool && Glo.IsEnableTaskPool) { gwf.TaskSta = TaskSta.Takeback; } else { gwf.TaskSta = TaskSta.None; } gwf.TodoEmps = WebUser.No + "," + WebUser.Name + ";"; gwf.Update(); if (cancelToNode.IsEnableTaskPool && Glo.IsEnableTaskPool) { //设置全部的人员不可用。 BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0, IsEnable=-1 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node); //设置当前人员可用。 BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0, IsEnable=1 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node + " AND FK_Emp='" + WebUser.No + "'"); } else { BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerlist SET IsPass=0 WHERE WorkID=" + this.WorkID + " AND FK_Node=" + gwf.FK_Node); } //更新当前节点,到rpt里面。 BP.DA.DBAccess.RunSQL("UPDATE " + this.HisFlow.PTable + " SET FlowEndNode=" + gwf.FK_Node + " WHERE OID=" + this.WorkID); // 记录日志.. wn.AddToTrack(ActionType.UnSend, WebUser.No, WebUser.Name, cancelToNode.NodeID, cancelToNode.Name, "无"); // 删除数据. if (wn.HisNode.IsStartNode) { DBAccess.RunSQL("DELETE FROM WF_GenerWorkFlow WHERE WorkID=" + this.WorkID); DBAccess.RunSQL("DELETE FROM WF_GenerWorkerlist WHERE WorkID=" + this.WorkID + " AND FK_Node=" + nd.NodeID); } if (wn.HisNode.IsEval) { /*如果是质量考核节点,并且撤销了。*/ DBAccess.RunSQL("DELETE FROM WF_CHEval WHERE FK_Node=" + wn.HisNode.NodeID + " AND WorkID=" + this.WorkID); } #region 恢复工作轨迹,解决工作抢办。 if (cancelToNode.IsStartNode == false && cancelToNode.IsEnableTaskPool == false) { WorkNode ppPri = wnOfCancelTo.GetPreviousWorkNode(); GenerWorkerList wl = new GenerWorkerList(); wl.Retrieve(GenerWorkerListAttr.FK_Node, wnOfCancelTo.HisNode.NodeID, GenerWorkerListAttr.WorkID, this.WorkID); // BP.DA.DBAccess.RunSQL("UPDATE WF_GenerWorkerList SET IsPass=0 WHERE FK_Node=" + backtoNodeID + " AND WorkID=" + this.WorkID); RememberMe rm = new RememberMe(); rm.Retrieve(RememberMeAttr.FK_Node, wnOfCancelTo.HisNode.NodeID, RememberMeAttr.FK_Emp, ppPri.HisWork.Rec); string[] empStrs = rm.Objs.Split('@'); foreach (string s in empStrs) { if (s == "" || s == null) { continue; } if (s == wl.FK_Emp) { continue; } GenerWorkerList wlN = new GenerWorkerList(); wlN.Copy(wl); wlN.FK_Emp = s; WF.Port.WFEmp myEmp = new Port.WFEmp(s); wlN.FK_EmpText = myEmp.Name; wlN.Insert(); } } #endregion 恢复工作轨迹,解决工作抢办。 #region 如果是开始节点, 检查此流程是否有子线程,如果有则删除它们。 if (nd.IsStartNode) { /*要检查一个是否有 子流程,如果有,则删除它们。*/ GenerWorkFlows gwfs = new GenerWorkFlows(); gwfs.Retrieve(GenerWorkFlowAttr.PWorkID, this.WorkID); if (gwfs.Count > 0) { foreach (GenerWorkFlow item in gwfs) { /*删除每个子线程.*/ BP.WF.Dev2Interface.Flow_DoDeleteFlowByReal(item.FK_Flow, item.WorkID, true); } } } #endregion //调用撤消发送后事件。 msg += nd.HisFlow.DoFlowEventEntity(EventListOfNode.UndoneAfter, nd, wn.HisWork, null); if (wnOfCancelTo.HisNode.IsStartNode) { return("@撤消执行成功. " + msg); } else { return("@撤消执行成功. " + msg); } return("工作已经被您撤销到:" + cancelToNode.Name); }