1.业务场景:用户登录,收到消息通知,审批业务,根据配置的流程继续流转,最终审核发送回给申请人(终审同意结束,终审不同意申请人可以继续修改提交)。
2.思路过程:
--用户登录首先获取未处理的消息记录,提醒处理预审批记录。 --1.配置流程主表和关联的步骤明细表(根据序号流转) --2.提交业务审批的时候创建预审批记录(关联流程和步骤),发送消息到第一步骤的评审人,修改业务主表状态, --3.步骤评审人同意:更新这个节点所有人的审批记录、如果流程明细还有下一步审批则继续发送消息给下一个,创建下一个预审批记录,修改业务主表状态,更新自己和这个节点所有人的消息记录状态 --4.步骤评审人不同意:终止发送下一个,发送回给申请人,更新自己和这个节点所有人的消息记录状态和审批记录 -- 每一个节点可以配置多个审批人,第一个审批节点必须是同一个部门的才可以审批(可以配置多个部门领导,但是申请发送的时候只发送给同部门的领导) -- 登录人审批要根据预审批记录表查询是否有要审批的记录和判断是否有下一个步骤,审批完成后继续向下一个发送
3..数据库设计:
-------------------流程审批设计--------------------------创建流程表 Flow:ID、编号、流程名称、类别、制定人、制定日期、状态(是否启用)、备注 SELECT * FROM [dbo].[Flow] --创建流程审批明细表(关联流程表,一对多) FlowDetail:ID、流程主表编号、序号、步骤名称、评审人账号(多个)、评审人名字(多个)、状态(是否启用)、 select * from FlowDetail --创建审批记录表 FlowRecords:ID、流程主表编号、流程步骤序号、业务编号、评审人账号、评审人名字、审批状态(1同意,2不同意,3审核中)、审批日期、备注、 select * from FlowRecords where BusinessNum='4C4CED8E3F8D42C997E2424D83C447B8' --创建消息通知表 Message :ID、标题、内容、业务编号、接收人账号、接收人名字、发送人账号、发送人名字、发送时间、状态(1未处理,2已处理) select * from FlowMessage where BusinessNum='4C4CED8E3F8D42C997E2424D83C447B8' --业务主表 (增加字段关联审批流程:流程主表编号、流程明细序号)
4.代码过程:
/// <summary> /// 审核单据 /// </summary> /// <param name="entity"></param> /// <returns></returns> public override string Audite(ReceiveOrderEntity entity) { using (TransactionScope ts = new TransactionScope()) { //1.获取自己当前业务需要审核的记录,没有则不能审核 FlowRecordsEntity record = new FlowRecordsEntity(); record.IncludeAll(); record.Where(a => a.BusinessNum == entity.SnNum).And(a => a.ApproverUserNum == entity.UserName); var myRecord = this.FlowRecords.GetList(record).FirstOrDefault(); if (myRecord == null) return "1003"; if(myRecord.ApproverResult!=3) return "1004"; //2.获取是否有下一步的流程步骤 FlowProvider provider = new FlowProvider(CompanyID); List<FlowDetailEntity> FlowDetails = provider .GetFlowDetail(new FlowDetailEntity {FlowSnNum = entity.FlowSnNum}).OrderBy(x => x.Seq).ToList(); FlowDetailEntity nextFlowDeail = null; int line = 0; if (FlowDetails != null && FlowDetails.Count > 0) { int count = 0; foreach (var obj in FlowDetails) { if (obj.Seq == myRecord.FlowDtlSeq) break; else count++; } //是否有下一步的流程 if (FlowDetails.Count > count && FlowDetails.Count!=count+1) { nextFlowDeail = FlowDetails[count + 1]; } } #region 不同意流程 if (entity.Status == (int) EAudite.NotPass) { entity.FlowDtlSeq = myRecord.FlowDtlSeq; entity.IncludeStatus(true).IncludeReason(true).IncludeFlowDtlSeq(true) .Where(a => a.SnNum == entity.SnNum) .And(a => a.CompanyID == this.CompanyID) ; line += this.ReceiveOrder.Update(entity); //1.更新自己的审批记录 myRecord.ApproverResult = 2; myRecord.ApproverDate = DateTime.Now; myRecord.IncludeApproverResult(true).IncludeApproverDate(true); line += this.FlowRecords.Update(myRecord); //2.更新自己(这一个步骤所有人)的消息记录 FlowMessageEntity msg = new FlowMessageEntity(); msg.Status = 2; msg.IncludeStatus(true); msg.Where(a => a.BusinessNum == entity.SnNum).And(a => a.FlowSnNum == entity.FlowSnNum) .And(a => a.FlowDtlSeq == myRecord.FlowDtlSeq); line += this.FlowMessage.Update(msg); //3.只发送消息回给申请人 FlowMessageEntity nextMsg = new FlowMessageEntity() { SendUserNum = entity.UserName, SendUserName = entity.RealName, AcceptUserNum = entity.CusNum, AcceptUserName = entity.CusName, BusinessNum = entity.SnNum, FlowSnNum = entity.FlowSnNum, FlowDtlSeq = myRecord.FlowDtlSeq, Status = 1, SendDate = DateTime.Now, Title = "物品领用申请审核", Notice = "您的编号为:"+entity.OrderNum+"的物品领用申审核已被拒绝!" }; nextMsg.IncludeAll(); line += this.FlowMessage.Add(nextMsg); ts.Complete(); return line > 0 ? "1000" : string.Empty; } #endregion #region 同意流程 else if (entity.Status == (int) EAudite.Pass) { //1.更新自己的审批记录 myRecord.ApproverResult = 1; myRecord.ApproverDate = DateTime.Now; myRecord.IncludeApproverResult(true).IncludeApproverDate(true); line += this.FlowRecords.Update(myRecord); //2.更新自己(这一个步骤所有人)的消息记录 FlowMessageEntity msg = new FlowMessageEntity(); msg.Status = 2; msg.IncludeStatus(true); msg.Where(a => a.BusinessNum == entity.SnNum).And(a => a.FlowSnNum == entity.FlowSnNum) .And(a => a.FlowDtlSeq == myRecord.FlowDtlSeq); line += this.FlowMessage.Update(msg); //如果有下一步的审核 if (nextFlowDeail != null) { //1.修改业务状态 entity.Status = 5; //2.获取下一步骤的审批人账号列表 var users = nextFlowDeail.ApproverUserNum.Split(',') .Where(x => string.IsNullOrEmpty(x) == false).ToList(); List<AdminEntity> sendUser = new List<AdminEntity>(); users.ForEach(x => { AdminEntity model = new AdminEntity(); model.IncludeAll(); model.Where(a => a.IsDelete == (int)EIsDelete.NotDelete).And(item => item.UserName == x); var user = this.Admin.GetSingle(model); if (user != null) { sendUser.Add(user); } }); foreach (var user in sendUser) { //3.创建下一个审批人的预审批记录 FlowRecordsEntity nextRecord = new FlowRecordsEntity() { ApproverUserName = user.RealName, ApproverUserNum = user.UserName, BusinessNum = entity.SnNum, FlowSnNum = entity.FlowSnNum, FlowDtlSeq = nextFlowDeail.Seq, ApproverResult = 3 }; nextRecord.IncludeAll(); line += this.FlowRecords.Add(nextRecord); //4.发送下一个审批人的消息通知 FlowMessageEntity nextMsg = new FlowMessageEntity() { SendUserNum = entity.UserName, SendUserName = entity.RealName, AcceptUserNum = user.UserName, AcceptUserName = user.RealName, BusinessNum = entity.SnNum, FlowSnNum = entity.FlowSnNum, FlowDtlSeq = nextFlowDeail.Seq, Status = 1, SendDate = DateTime.Now, Title = "物品领用申请审核", Notice = "有编号为:" + entity.OrderNum + "的物品领用申请需要您审核!" }; nextMsg.IncludeAll(); line += this.FlowMessage.Add(nextMsg); } } else { //流程结束 entity.Status = (int) EAudite.Pass; //发送消息回给申请人 FlowMessageEntity fristMsg = new FlowMessageEntity() { SendUserNum = entity.UserName, SendUserName = entity.RealName, AcceptUserNum = entity.CusNum, AcceptUserName = entity.CusName, BusinessNum = entity.SnNum, FlowSnNum = entity.FlowSnNum, FlowDtlSeq = myRecord.FlowDtlSeq, Status = 1, SendDate = DateTime.Now, Title = "物品领用申请审核", Notice = "您的编号为:" + entity.OrderNum + "的物品领用申审核已经通过!" }; fristMsg.IncludeAll(); line += this.FlowMessage.Add(fristMsg); } entity.FlowDtlSeq = myRecord.FlowDtlSeq; entity.AuditeTime = DateTime.Now; entity.Include(a => new {a.Status, a.AuditUser, a.AuditeTime, a.Reason, a.Remark,a.FlowDtlSeq}); entity.Where(a => a.SnNum == entity.SnNum).And(a => a.CompanyID == this.CompanyID); line += this.ReceiveOrder.Update(entity); ts.Complete(); return line > 0 ? EnumHelper.GetEnumDesc<EReturnStatus>(EReturnStatus.Success) : string.Empty; } #endregion } return string.Empty; }