审批代码 -> 审批环节 -> 审批岗位 ->在数据库中创建各个节点保存审核记录

一个审批代码表示一个业务需要审批,通过审批代码得到审批中需要流转的环节,每个环节对应着一个或是多个审批岗位



#region 各个审核步骤定义并实现,每个审核步骤均对应一个代码,通过代码得到审核所需的环节,从而得到审批岗位
    public class ProgressHelper
    {
        #region 流程流转顺序(一个流程顺序包含多个流转(Progress))定义(一个流转(Progress)可以有多个审核节点(Step))
        public static List<OrderAudiProgressTemplate> GFanDanOrderAudiProgressTest
        {
            get
            {
                var progress1 = new OrderAudiProgressTemplate
                       {

                           ProgressName = "翻单订单导SAP审核过程1",
                           PreviousProgress = null,
                           Steps = new List<OrderAudiStepTemplate>
                           {
                                //三个并行审核过程
                                new OrderAudiStepTemplate{ UserSpecial = "财务-不合理欠款" , Remark = "1查询客户是否有不合理欠款"},
                                new OrderAudiStepTemplate{ UserSpecial = "财务-库存是否过剩" , Remark = "2查询客户该机型是否有不合理库存"},
                                new OrderAudiStepTemplate{ UserSpecial = "财务-订金是否到" , Remark = "3查询客户订金是否到帐"}
                           }

                       };
                var progress2 = new OrderAudiProgressTemplate
                       {
                           ProgressName = "翻单订单导SAP审核过程2",
                           PreviousProgress = progress1,
                           Steps = new List<OrderAudiStepTemplate>
                           {
                                //三个并行审核过程
                                new OrderAudiStepTemplate{ UserSpecial = "财务-不合理欠款" , Remark = "4查询客户是否有不合理欠款"},
                                new OrderAudiStepTemplate{ UserSpecial = "财务-库存是否过剩" , Remark = "5查询客户该机型是否有不合理库存"},
                                new OrderAudiStepTemplate{ UserSpecial = "财务-订金是否到" , Remark = "6查询客户订金是否到帐"}
                           }

                       };

                var progress3 = new OrderAudiProgressTemplate
                {
                    ProgressName = "翻单订单导SAP审核过程3",
                    PreviousProgress = progress2,
                    Steps = new List<OrderAudiStepTemplate>
                           {
                                //三个并行审核过程
                                new OrderAudiStepTemplate{ UserSpecial = "财务-不合理欠款" , Remark = "7查询客户是否有不合理欠款"},
                                new OrderAudiStepTemplate{ UserSpecial = "财务-库存是否过剩" , Remark = "8查询客户该机型是否有不合理库存"},
                                new OrderAudiStepTemplate{ UserSpecial = "财务-订金是否到" , Remark = "9查询客户订金是否到帐"}
                           }

                };
                return new List<OrderAudiProgressTemplate> 
                {
                      progress2,progress1,progress3
                };
            }
        }

        public static List<OrderAudiProgressTemplate> FanDanOrderAudiProgress
        {
            get
            {

                var progress1 = new OrderAudiProgressTemplate
                {
                    ProgressName = "翻单订单导SAP前审核过程",
                    ProgressCode = PendingCode.FandanAudiProgressCode,
                    PreviousProgress = null,
                    Steps = new List<OrderAudiStepTemplate>
                           {
                                //三个并行审核过程
                                new OrderAudiStepTemplate{ UserSpecial = "财务-不合理欠款" , Remark = "查询客户是否有不合理欠款" ,StepCode = "Ac1"},
                                new OrderAudiStepTemplate{ UserSpecial = "财务-库存是否过剩" , Remark = "查询客户该机型是否有不合理库存",StepCode = "Ac2"},
                                new OrderAudiStepTemplate{ UserSpecial = "财务-订金是否到" , Remark = "查询客户订金是否到帐",StepCode = "Ac3"}
                           }

                };
                return new List<OrderAudiProgressTemplate> 
                {
                      progress1
                };
            }
        }
        #endregion
        private static List<OrderAudiProgressTemplate> GetAudiProgressByCode(string code)
        {
            var codeTitles = new Dictionary<string, List<OrderAudiProgressTemplate>>();
            codeTitles.Add(PendingCode.TestAudiProgressCode, GFanDanOrderAudiProgressTest);
            codeTitles.Add(PendingCode.FandanAudiProgressCode, FanDanOrderAudiProgress);
            if (codeTitles.ContainsKey(code))
            {
                return codeTitles[code];
            }
            return null;
        }

        public static void SetAllOrderProgresMoved(int orderId, string progressCode)
        {
           
            using (var db = new DataContext.OverSeaOrderEntities())
            {
                foreach (var item in db.OrderPendingState.Where(p => p.OrderID == orderId && p.ProgressCode == progressCode))
                {
                    item.ProgressCode = item.ProgressCode + "_";
                }
                db.SaveChanges();
            }
        }

        public static void CreateProgressForOrder(int orderId,string progressCode)
        {
            var template = GetAudiProgressByCode(progressCode);
            if (template == null) return;
            var currentgress = template.FirstOrDefault(p => p.PreviousProgress == null);
            if (currentgress == null) return;
            var stateId = 0;

            using (var db = new DataContext.OverSeaOrderEntities())
            {
                if (db.OrderPendingState.Any(p => p.OrderID == orderId && p.ProgressCode == progressCode))
                {
                    return;
                }
                var state = new OrderPendingState
                {
                    CreateDate = System.DateTime.Now,
                    LastUpdateDate = null,
                    OrderID = orderId,
                    PendingResult = (int)OrderPendingResult.Pending,
                    ProgressCode = progressCode
                };
                db.OrderPendingState.Add(state);
                db.SaveChanges();
                stateId = state.ID;
            }
            OrderAudiProgress predbgress = null;
            do
            {
                //创建新的Progress项目
                var curdb = CreateSaveingProgress(currentgress, orderId, predbgress, stateId);
                //查找下一个
                predbgress = curdb;
                currentgress = template.FirstOrDefault(p => p.PreviousProgress == currentgress);
            }
            while (currentgress != null);
            //为所有的流转创建一个状态项
           
        }
        /// <summary>
        /// 保存用户保存结果
        /// </summary>
        public static void SetStepPendingResult(int userId,int progressStepId, bool result)
        {
            using (var db = new DataContext.OverSeaOrderEntities())
            {
                var step = db.ProgressStep.FirstOrDefault(p => p.ID == progressStepId);
                if (step == null) return;
                step.Passed = result;
                //判断每个步骤是否都已经执行
                var allsteps = db.ProgressStep.Where(p => p.ProgressID == step.ProgressID && p.ID != progressStepId).ToList();
                //此处需等所有人【步骤】都审核完成才执行,是否结果为false时就直接判断结束
                if (allsteps.All(p => p.Passed.HasValue) || result == false )
                {
                    //所有人已经填写,总结下是否都通过
                    var progressResult = result;
                    if (result && allsteps.All(p => p.Passed == true))
                    {
                        progressResult = true;
                    }
//按总结情况更新主状态,是下一步,还是退回
                    var progress = db.OrderAudiProgress.FirstOrDefault(p => p.ID == step.ProgressID);
                    if (progress == null) return;
                    var orderstat = db.OrderPendingState.FirstOrDefault(p => progress.OrderID  == p.OrderID && p.ProgressCode == progress.ProgerssCode);
                    if (orderstat == null) return;
                    progress.IsPassed = progressResult;
                    progress.PassedDate = System.DateTime.Now;
                    if (progressResult) //下一步或是完成
                    {
                        progress.IsRuning = false;
                        //查找下一步progress
                        var nextProgress = db.OrderAudiProgress.FirstOrDefault(p => p.PreviousProgressID == progress.ID);
                        if (nextProgress == null)
                        {
                            //流程已走完
                            orderstat.PendingResult = (int)OrderPendingResult.Successed;
                            orderstat.LastUpdateDate = System.DateTime.Now;
                        }
                        else
                        {
                            //更新下一个progress开始进行
                            nextProgress.IsRuning = true;
                        }
                    }
                    else
                    {
                        //有审核人员意见不通过
                        orderstat.PendingResult = (int)OrderPendingResult.Backed;
                        orderstat.LastUpdateDate = System.DateTime.Now;
                    }
                }
                db.SaveChanges();
            }
        }

        /// <summary>
        /// 为每一个流程顺序创建一个数据库对应项并指定流转顺序
        /// </summary>
        /// <param name="gressTemplate"></param>
        /// <param name="orderId"></param>
        /// <param name="predbgress"></param>
        /// <returns></returns>
        static OrderAudiProgress CreateSaveingProgress(OrderAudiProgressTemplate gressTemplate, int orderId, OrderAudiProgress predbgress,int stateId)
        {
            using (var db = new DataContext.OverSeaOrderEntities())
            {
                OrderAudiProgress item = new OrderAudiProgress
                {
                    CreateDate = System.DateTime.Now,
                    IsPassed = null,
                    OrderID = orderId,
                    PassedDate = null,
                    ProgressName = gressTemplate.ProgressName,
                    ProgressStep = new List<ProgressStep>(),
                    ProgerssCode = gressTemplate.ProgressCode,
                    PendingStateID = stateId
                };
                if (predbgress == null)
                {
                    item.PreviousProgressID = null;
                    item.IsRuning = true; //如果没有前续表明该流转为第一个开始的
                }
                else
                {
                    item.PreviousProgressID = predbgress.ID;
                    item.IsRuning = false;
                }
                db.OrderAudiProgress.Add(item);
                foreach (var step in gressTemplate.Steps)
                {
                    var dbstep = new ProgressStep
                    {
                        AudiorID = 0,
                        CreateDate = System.DateTime.Now,
                        StepTitle = step.Remark,
                        StepCode = step.StepCode
                    };
                    /****  审核员查找代码  ***/
                    var audio = db.User.OrderByDescending(p => p.ID).FirstOrDefault(p => p.AudiSpecial == step.UserSpecial);
                    if (audio != null)
                    {
                        dbstep.AudiorID = audio.ID;
                    }
                    /****-完毕-*/
                    item.ProgressStep.Add(dbstep);
                    db.ProgressStep.Add(dbstep);
                }
                db.SaveChanges();
                return item;
            }
        }

        /// <summary>
        /// 获取用户的审核列表
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public static List<ProgressStep> GetUserPendingList(int userId)
        {
            using (var db = new DataContext.OverSeaOrderEntities())
            {
                return db.ProgressStep.Where(p => p.AudiorID == userId && p.OrderAudiProgress.IsRuning == true && p.Passed == null).ToList();
            }
        }
    }
    #endregion

    #region 定义审核及审核结果枚举[前提:每个订单对应几个审核情况,如,在导入ERP前有前置审批,在导入后的出货有出货相关流种审批,每个审批对应几个环节,每个环节对应几个岗位]
    public enum OrderPendingResult
    {
         Pending = 0 ,Backed = 4 ,Successed = 8
    }

    public class PendingCode
    {
        public const string TestAudiProgressCode = "FDTest";
        public const string FandanAudiProgressCode = "FD001";
        public static string GetPendingCodeTitle(string code)
        {
            var codeTitles = new Dictionary<string, string>();
            codeTitles.Add(PendingCode.TestAudiProgressCode, "测试时使用流程");
            codeTitles.Add(PendingCode.FandanAudiProgressCode, "翻单导SAP流程");
            if (codeTitles.ContainsKey(code))
            {
                return codeTitles[code];
            }
            return string.Empty;
        }
    }
    #endregion

    #region 定义审核过程及每个过程包含的审核步骤类
    //订单审核过程 (1个过程(progress)中包含多个步骤(step) 过程是有先后顺序,步骤则没有但需全部完成) 
    public class OrderAudiProgressTemplate
    {
        public string ProgressName { get; set; }
        public string ProgressCode { get; set; }
        public List<OrderAudiStepTemplate> Steps { get; set; }
        public OrderAudiProgressTemplate PreviousProgress { get; set; }
    }

    //订单审核
    public class OrderAudiStepTemplate
    {
        //public User Audior { get; set; }
        public string UserSpecial { get; set; }  //用户岗位 [通过用户岗位描述来查找审核员]
        public string Remark { get; set; }

        public string StepCode { get; set; }
    }
    #endregion

    #region 各种情况判定帮助类
    public class OrderAudiStateHelper
    {

        public static bool IsOrderProgressCreated(int orderId, string progressCode)
        {
            return PendingSateAny(p => p.OrderID == orderId && p.ProgressCode == progressCode);
        }

        public static bool IsOrderProgressSuccess(int orderId, string progressCode)
        {
            var resutl = (int)OrderPendingResult.Successed;
            return PendingSateAny(p => p.OrderID == orderId && p.ProgressCode == progressCode && p.PendingResult == resutl);
        }
        public static bool IsOrderProgressBacked(int orderId, string progressCode)
        {
            var resutl = (int)OrderPendingResult.Successed;
            return PendingSateAny(p => p.OrderID == orderId && p.ProgressCode == progressCode && p.PendingResult == resutl);
        }

        private static bool PendingSateAny(Expression<Func<OrderPendingState, bool>> func)
        {
            using (var db = new DataContext.OverSeaOrderEntities())
            {
                return db.OrderPendingState.Any(func);
            }
        }


    }
    #endregion