using System; using System.Data; using BP.DA; using System.Net.Mail; using BP.En; using BP.Port; using BP.Sys; using BP.WF.Template; using BP.Web; using BP.Difference; namespace BP.WF.DTS { /// /// ccbpm服务 /// public class ccbpmServices : Method { /// /// ccbpm服务 /// public ccbpmServices() { this.Title = "ccbpm流程服务 "; this.Help = "1,自动发送邮件. 2,自动发起流程. 3,自动执行节点任务.."; this.Help += "所有自动任务的综合."; this.GroupName = "流程自动执行定时任务"; } public override void Init() { } /// /// 当前的操纵员是否可以执行这个方法 /// public override bool IsCanDo { get { return true; } } /// /// 开始执行方法. /// /// public override object Do() { BP.WF.Dev2Interface.Port_Login("admin"); //自动发起流程. AutoRunStratFlows fls = new AutoRunStratFlows(); fls.Do(); //执行自动任务,机器执行的节点. AutoRun_WhoExeIt myen = new AutoRun_WhoExeIt(); myen.Do(); //扫描触发式自动发起流程表. //自动发起流程. AutoRunWF_Task wf_task = new AutoRunWF_Task(); wf_task.Do(); //扫描消息表,想外发送消息. DoSendMsg(); //扫描逾期流程数据,处理逾期流程. DTS_DealDeferredWork en = new DTS_DealDeferredWork(); en.Do(); //同步待办时间戳 DTS_GenerWorkFlowTimeSpan en2 = new DTS_GenerWorkFlowTimeSpan(); en2.Do(); //更新WF_GenerWorkerFlow.TodoSta状态. DTS_GenerWorkFlowTodoSta en3 = new DTS_GenerWorkFlowTodoSta(); en3.Do(); //执行自动任务. Auto_Rpt_Dtl_DTS dtRpts = new Auto_Rpt_Dtl_DTS(); dtRpts.Do(); return "执行完成..."; } /// /// 逾期流程 /// private void DoOverDueFlow() { //特殊处理天津的需求. if (BP.Difference.SystemConfig.CustomerNo == "") DoTianJinSpecFunc(); # region 流程逾期 //判断是否有流程逾期的消息设置 DataTable dt = null; string sql = "SELECT a.FK_Flow,a.WorkID,a.Title,a.FK_Node,a.SDTOfNode,a.Starter,a.TodoEmps "; sql += "FROM WF_GenerWorkFlow a, WF_Node b"; sql += " WHERE a.SDTOfFlow<='" + DataType.CurrentDateTime + "' "; sql += " AND WFState=2 and b.OutTimeDeal!=0"; sql += " AND a.FK_Node=b.NodeID"; dt = DBAccess.RunSQLReturnTable(sql); // 遍历循环,逾期表进行处理. foreach (DataRow dr in dt.Rows) { string fk_flow = dr["FK_Flow"] + ""; int fk_node = int.Parse(dr["FK_Node"] + ""); long workid = long.Parse(dr["WorkID"] + ""); string title = dr["Title"] + ""; //判断流程是否设置逾期消息 PushMsg pushMsg = new PushMsg(); int count = pushMsg.Retrieve(PushMsgAttr.FK_Flow, fk_flow, PushMsgAttr.FK_Node, 0, PushMsgAttr.FK_Event, EventListNode.FlowOverDue); if (count != 0) { Node node = new Node(fk_node); pushMsg.DoSendMessage(node, node.HisWork, null, null, null, null); } continue; } #endregion 流程逾期 # region 流程预警 sql = "SELECT a.FK_Flow,a.WorkID,a.Title,a.FK_Node,a.SDTOfNode,a.Starter,a.TodoEmps "; sql += "FROM WF_GenerWorkFlow a, WF_Node b"; sql += " WHERE a.SDTOfFlowWarning<='" + DataType.CurrentDateTime + "' "; sql += " AND WFState=2 and b.OutTimeDeal!=0"; sql += " AND a.FK_Node=b.NodeID"; dt = DBAccess.RunSQLReturnTable(sql); // 遍历循环,预警表进行处理. foreach (DataRow dr in dt.Rows) { string fk_flow = dr["FK_Flow"] + ""; int fk_node = int.Parse(dr["FK_Node"] + ""); long workid = long.Parse(dr["WorkID"] + ""); string title = dr["Title"] + ""; //判断流程是否设置逾期消息 PushMsg pushMsg = new PushMsg(); int count = pushMsg.Retrieve(PushMsgAttr.FK_Flow, fk_flow, PushMsgAttr.FK_Node, 0, PushMsgAttr.FK_Event, EventListNode.FlowWarning); if (count != 0) { Node node = new Node(fk_node); pushMsg.DoSendMessage(node, node.HisWork, null, null, null, null); } continue; } #endregion 流程预警 DataTable generTab = null; #region 节点预警 sql = "SELECT a.FK_Flow,a.WorkID,a.Title,a.FK_Node,a.SDTOfNode,a.Starter,a.TodoEmps "; sql += "FROM WF_GenerWorkFlow a, WF_Node b"; sql += " WHERE a.SDTOfNode>='" + DataType.CurrentDateTime + "' "; sql += " AND WFState=2 and b.OutTimeDeal!=0"; sql += " AND a.FK_Node=b.NodeID"; generTab = DBAccess.RunSQLReturnTable(sql); foreach (DataRow row in generTab.Rows) { string fk_flow = row["FK_Flow"] + ""; int fk_node = int.Parse(row["FK_Node"] + ""); long workid = long.Parse(row["WorkID"] + ""); string title = row["Title"] + ""; string compleateTime = row["SDTOfNode"] + ""; string starter = row["Starter"] + ""; Node node = new Node(fk_node); if (node.ItIsStartNode) continue; PushMsgs pushMsgs = new PushMsgs(); int count = pushMsgs.Retrieve(PushMsgAttr.FK_Flow, node.FlowNo, PushMsgAttr.FK_Node, node.NodeID, PushMsgAttr.FK_Event, EventListNode.NodeWarning); int maxHour = 0; int minHour = 0; if (count != 0) { foreach (PushMsg pushMsg in pushMsgs) { if (pushMsg.GetParaInt("NoticeType") == 0) { pushMsg.DoSendMessage(node, node.HisWork, null, null, null, null); continue; } else { if (pushMsg.GetParaInt("NoticeHour") > maxHour) maxHour = pushMsg.GetParaInt("NoticeHour"); if (pushMsg.GetParaInt("NoticeHour") < minHour) minHour = pushMsg.GetParaInt("NoticeHour"); } } //计算当天时间和节点应完成日期的时间差 int hours = DataType.SpanHours(compleateTime, DataType.CurrentDate); int noticeHour = 0; if (hours > minHour)//如果小于最新提醒天数则不发消息 { foreach (PushMsg pushMsg in pushMsgs) { if (pushMsg.GetParaInt("NoticeType") == 1) { noticeHour = pushMsg.GetParaInt("NoticeHour"); if (noticeHour == hours) { pushMsg.DoSendMessage(node, node.HisWork, null, null, null, null); continue; } } } } } } #endregion 节点预警 #region 找到要节点逾期的数据. sql = "SELECT a.FK_Flow,a.WorkID,a.Title,a.FK_Node,a.SDTOfNode,a.Starter,a.TodoEmps "; sql += "FROM WF_GenerWorkFlow a, WF_Node b"; sql += " WHERE a.SDTOfNode<='" + DataType.CurrentDateTime + "' "; sql += " AND WFState=2 and b.OutTimeDeal!=0"; sql += " AND a.FK_Node=b.NodeID"; generTab = DBAccess.RunSQLReturnTable(sql); #endregion 找到要逾期的数据. // 遍历循环,逾期表进行处理. string msg = ""; string info = ""; foreach (DataRow row in generTab.Rows) { string fk_flow = row["FK_Flow"] + ""; int fk_node = int.Parse(row["FK_Node"] + ""); long workid = long.Parse(row["WorkID"] + ""); string title = row["Title"] + ""; string compleateTime = row["SDTOfNode"] + ""; string starter = row["Starter"] + ""; GenerWorkerLists gwls = new GenerWorkerLists(); gwls.Retrieve(GenerWorkerListAttr.WorkID, workid, GenerWorkerListAttr.FK_Node, fk_node); bool isLogin = false; foreach (GenerWorkerList item in gwls) { if (item.ItIsEnable == false) continue; BP.Port.Emp emp = new Emp(item.EmpNo); BP.Web.WebUser.SignInOfGener(emp); isLogin = true; } if (isLogin == false) { BP.Port.Emp emp = new Emp("admin"); BP.Web.WebUser.SignInOfGener(emp); } try { Node node = new Node(fk_node); if (node.ItIsStartNode) continue; #region 启动逾期消息设置 PushMsgs pushMsgs = new PushMsgs(); int count = pushMsgs.Retrieve(PushMsgAttr.FK_Flow, node.FlowNo, PushMsgAttr.FK_Node, node.NodeID, PushMsgAttr.FK_Event, EventListNode.NodeOverDue); int maxDay = 0; int minDay = 0; if (count != 0) { foreach (PushMsg pushMsg in pushMsgs) { if (pushMsg.GetParaInt("NoticeType") == 0) { pushMsg.DoSendMessage(node, node.HisWork, null, null, null, null); continue; } else { if (pushMsg.GetParaInt("NoticeDay") > maxDay) maxDay = pushMsg.GetParaInt("NoticeDay"); if (pushMsg.GetParaInt("NoticeDay") < minDay) minDay = pushMsg.GetParaInt("NoticeDay"); } } //计算当天时间和节点应完成日期的时间差 int days = DataType.SpanDays(DataType.CurrentDate, compleateTime); int noticeDay = 0; if (days > minDay)//如果小于最新提醒天数则不发消息 { foreach (PushMsg pushMsg in pushMsgs) { if (pushMsg.GetParaInt("NoticeType") == 1) { noticeDay = pushMsg.GetParaInt("NoticeDay"); if (noticeDay == days || days > maxDay) { pushMsg.DoSendMessage(node, node.HisWork, null, null, null, null); continue; } } } } } #endregion 启动逾期消息设置 //获得该节点的处理内容. string doOutTime = node.GetValStrByKey(NodeAttr.DoOutTime); switch (node.HisOutTimeDeal) { case OutTimeDeal.None: //逾期不处理. continue; case OutTimeDeal.AutoJumpToSpecNode: //跳转到指定的节点. try { int jumpNode = int.Parse(doOutTime); Node jumpToNode = new Node(jumpNode); //设置默认同意. BP.WF.Dev2Interface.Node_WriteWorkCheck(workid,"同意(预期自动审批)", null, null); //执行发送. info = BP.WF.Dev2Interface.Node_SendWork(fk_flow, workid, null, null, jumpToNode.NodeID, null).ToMsgOfText(); msg = "流程 '" + node.FlowName + "',标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'自动跳转'," + info; BP.DA.Log.DebugWriteInfo(msg); } catch (Exception ex) { msg = "流程 '" + node.FlowName + "',WorkID=" + workid + ",标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'自动跳转',跳转异常:" + ex.Message; BP.DA.Log.DebugWriteError(msg); } break; case OutTimeDeal.AutoShiftToSpecUser: //走动移交给. // 判断当前的处理人是否是. Emp empShift = new Emp(doOutTime); try { BP.WF.Dev2Interface.Node_Shift(workid, empShift.UserID, "流程节点已经逾期,系统自动移交"); msg = "流程 '" + node.FlowName + "',标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'移交到指定的人',已经自动移交给'" + empShift.Name + "."; BP.DA.Log.DebugWriteInfo(msg); } catch (Exception ex) { msg = "流程 '" + node.FlowName + "' ,标题:'" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'移交到指定的人',移交异常:" + ex.Message; BP.DA.Log.DebugWriteError(msg); } break; case OutTimeDeal.AutoTurntoNextStep: try { GenerWorkerList workerList = new GenerWorkerList(); workerList.RetrieveByAttrAnd(GenerWorkerListAttr.WorkID, workid, GenerWorkFlowAttr.FK_Node, fk_node); WebUser.SignInOfGener(workerList.HisEmp); WorkNode firstwn = new WorkNode(workid, fk_node); string sendIfo = firstwn.NodeSend().ToMsgOfText(); msg = "流程 '" + node.FlowName + "',标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'自动发送到下一节点',发送消息为:" + sendIfo; BP.DA.Log.DebugWriteInfo(msg); } catch (Exception ex) { msg = "流程 '" + node.FlowName + "',标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'自动发送到下一节点',发送异常:" + ex.Message; BP.DA.Log.DebugWriteError(msg); } break; case OutTimeDeal.DeleteFlow: info = BP.WF.Dev2Interface.Flow_DoDeleteFlowByReal(workid, true); msg = "流程 '" + node.FlowName + "',标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'删除流程'," + info; BP.DA.Log.DebugWriteInfo(msg); break; case OutTimeDeal.RunSQL: try { BP.WF.Work wk = node.HisWork; wk.OID = workid; wk.Retrieve(); doOutTime = BP.WF.Glo.DealExp(doOutTime, wk, null); //替换字符串 doOutTime.Replace("@OID", workid + ""); doOutTime.Replace("@FK_Flow", fk_flow); doOutTime.Replace("@FK_Node", fk_node.ToString()); doOutTime.Replace("@Starter", starter); if (doOutTime.Contains("@")) { msg = "流程 '" + node.FlowName + "',标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'执行SQL'.有未替换的SQL变量."; BP.DA.Log.DebugWriteInfo(msg); break; } //执行sql. DBAccess.RunSQL(doOutTime); } catch (Exception ex) { msg = "流程 '" + node.FlowName + "',标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'执行SQL'.运行SQL出现异常:" + ex.Message; BP.DA.Log.DebugWriteError(msg); } break; case OutTimeDeal.SendMsgToSpecUser: try { Emp myemp = new Emp(doOutTime); bool boo = BP.WF.Dev2Interface.Port_WriteToSMS(myemp.UserID, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), "系统发送逾期消息", "您的流程:'" + title + "'的完成时间应该为'" + compleateTime + "',流程已经逾期,请及时处理!", "系统消息", workid); if (boo) msg = "'" + title + "'逾期消息已经发送给:'" + myemp.Name + "'"; else msg = "'" + title + "'逾期消息发送未成功,发送人为:'" + myemp.Name + "'"; BP.DA.Log.DebugWriteInfo(msg); } catch (Exception ex) { msg = "流程 '" + node.FlowName + "',标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'执行SQL'.运行SQL出现异常:" + ex.Message; BP.DA.Log.DebugWriteError(msg); } break; default: msg = "流程 '" + node.FlowName + "',标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'没有找到相应的超时处理规则."; BP.DA.Log.DebugWriteError(msg); break; } } catch (Exception ex) { BP.DA.Log.DebugWriteError(ex.ToString()); } } BP.DA.Log.DebugWriteInfo("结束扫描逾期流程数据."); } /// /// 特殊处理天津的流程 /// 当指定的节点,到了10号,15号自动向下发送. /// private void DoTianJinSpecFunc() { if (DateTime.Now.Day == 10 || DateTime.Now.Day == 15) { /* 一个是10号自动审批,一个是15号自动审批. */ } else { return; } #region 找到要逾期的数据. DataTable generTab = null; string sql = "SELECT a.FK_Flow,a.WorkID,a.Title,a.FK_Node,a.SDTOfNode,a.Starter,a.TodoEmps "; sql += "FROM WF_GenerWorkFlow a, WF_Node b"; sql += " WHERE "; sql += " a.FK_Node=b.NodeID "; if (DateTime.Now.Day == 10) sql += " AND b.NodeID=13304 "; if (DateTime.Now.Day == 15) sql += "AND b.NodeID=13302 "; generTab = DBAccess.RunSQLReturnTable(sql); #endregion 找到要逾期的数据. // 遍历循环,逾期表进行处理. string msg = ""; foreach (DataRow row in generTab.Rows) { string fk_flow = row["FK_Flow"] + ""; string fk_node = row["FK_Node"] + ""; long workid = long.Parse(row["WorkID"] + ""); string title = row["Title"] + ""; string compleateTime = row["SDTOfNode"] + ""; string starter = row["Starter"] + ""; try { Node node = new Node(int.Parse(fk_node)); try { GenerWorkerList workerList = new GenerWorkerList(); workerList.RetrieveByAttrAnd(GenerWorkerListAttr.WorkID, workid, GenerWorkFlowAttr.FK_Node, fk_node); WebUser.SignInOfGener(workerList.HisEmp); WorkNode firstwn = new WorkNode(workid, int.Parse(fk_node)); string sendIfo = firstwn.NodeSend().ToMsgOfText(); msg = "流程 '" + node.FlowName + "',标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'自动发送到下一节点',发送消息为:" + sendIfo; //输出消息. BP.DA.Log.DebugWriteInfo(msg); } catch (Exception ex) { msg = "流程 '" + node.FlowName + "',标题: '" + title + "'的应该完成时间为'" + compleateTime + "',当前节点'" + node.Name + "'超时处理规则为'自动发送到下一节点',发送异常:" + ex.Message; BP.DA.Log.DebugWriteError(msg); } } catch (Exception ex) { BP.DA.Log.DebugWriteError(ex.ToString()); } } BP.DA.Log.DebugWriteInfo("结束扫描逾期流程数据."); } /// /// 发送消息 /// private void DoSendMsg() { int idx = 0; #region 发送消息 SMSs sms = new SMSs(); BP.En.QueryObject qo = new BP.En.QueryObject(sms); sms.Retrieve(SMSAttr.EmailSta, (int)MsgSta.UnRun); foreach (SMS sm in sms) { if (sm.Email.Length == 0) { sm.HisEmailSta = MsgSta.RunOK; sm.Update(); continue; } try { this.SendMail(sm); } catch (Exception ex) { BP.DA.Log.DebugWriteError(ex.Message); } } #endregion 发送消息 } /// /// 发送邮件。 /// /// public void SendMail(SMS sms) { #region 发送邮件. if (string.IsNullOrEmpty(sms.Email)) { BP.Port.Emp emp = null;// new BP.WF.Port.WFEmp(sms.SendToEmpNo); if (SystemConfig.CCBPMRunModel == CCBPMRunModel.SAAS) { emp = new BP.Port.Emp(WebUser.OrgNo + "_" + sms.SendToEmpNo); } else { emp = new BP.Port.Emp(sms.SendToEmpNo); } sms.Email = emp.Email; } System.Net.Mail.MailMessage myEmail = new System.Net.Mail.MailMessage(); myEmail.From = new MailAddress("ccbpmtester@tom.com", "ccbpm123", System.Text.Encoding.UTF8); myEmail.To.Add(sms.Email); myEmail.Subject = sms.Title; myEmail.SubjectEncoding = System.Text.Encoding.UTF8;//邮件标题编码 myEmail.Body = sms.DocOfEmail; myEmail.BodyEncoding = System.Text.Encoding.UTF8;//邮件内容编码 myEmail.IsBodyHtml = true;//是否是HTML邮件 myEmail.Priority = MailPriority.High;//邮件优先级 SmtpClient client = new SmtpClient(); //邮件地址. string emailAddr = BP.Difference.SystemConfig.GetValByKey("SendEmailAddress", null); if (emailAddr == null) emailAddr = "ccbpmtester@tom.com"; string emailPassword = BP.Difference.SystemConfig.GetValByKey("SendEmailPass", null); if (emailPassword == null) emailPassword = "ccbpm123"; //是否启用ssl? bool isEnableSSL = false; string emailEnableSSL = BP.Difference.SystemConfig.GetValByKey("SendEmailEnableSsl", null); if (emailEnableSSL == null || emailEnableSSL == "0") isEnableSSL = false; else isEnableSSL = true; client.Credentials = new System.Net.NetworkCredential(emailAddr, emailPassword); //上述写你的邮箱和密码 client.Port = BP.Difference.SystemConfig.GetValByKeyInt("SendEmailPort", 25); //使用的端口 client.Host = BP.Difference.SystemConfig.GetValByKey("SendEmailHost", "smtp.tom.com"); //是否启用加密,有的邮件服务器发送配置不成功就是因为此参数的错误。 client.EnableSsl = BP.Difference.SystemConfig.GetValByKeyBoolen("SendEmailEnableSsl", isEnableSSL); object userState = myEmail; try { client.SendAsync(myEmail, userState); sms.HisEmailSta = MsgSta.RunOK; sms.Update(); } catch (System.Net.Mail.SmtpException ex) { BP.DA.Log.DebugWriteError(ex.Message); throw ex; } #endregion 发送邮件. } } }