进度节点录入控制

     以前做过一个项目监管系统,该系统主要对项目单位用户在项目建设过程中主要工程节点进行监控,比如项目在建设过程中需要季度资金上报、招投标合同审核、进度节点数据报审、中央下达资金支出情况填报等等,项目的主要进度节点有资金管理阶段、未开工阶段、在建阶段、验收阶段,在每个阶段下有很多关键的节点,比如:开工、交工、验收、竣工时间节点等。有下面这样的场景:
1、节点分为普通节点和关键节点,关键节点要求按照一定的顺序填报数据;
2、节点数据要求填报节点时间、附件、备注、和特殊说明,各个节点有的要求附件必填,有的限制说明或备注必填,即是填报的节点控制要求不一样;
3、需求不确定,一开始要求所有的节点不区分关键节点,按照项目进度节点所在的阶段按顺序填报;中途要求放开部分节点,限制部分节点的填报;
4、阶段会根据项目建设过程中实际情况添加,也会新加节点,新加关键节点、更改普通节点为关键节点等;
5、节点填报后可以编辑、删除,重新填报;
   现在有这样的一个录入控制要求:
  (1)新加了几个关键节点,填报时按照一定的顺序控制;
  (2)当填报第四个关键节点时第一个或第二个关键节点被删除,该节点不可填报,并给与某节点未填报提醒;
如下图:

                                               
                                            (进度节点主页)

                                          
                                                    (节点数据录入页)
 


                                             (节点填报后可编辑删除操作)

    涉及到的业务表有三个,项目表(可以拿到项目的基础信息)、进度节点表(跟具体项目有关系的进度节点数据)、字典表(保存有各进度节点的名称和类别); 用户登录可以拿到当前用户负责的项目ID,到进度节点表可以获取到已经填报的节点数据,字典表中通过建设阶段buildStep和进度节点buildNode可以唯一确定一个节点,当然也可以拿到关键的节点。

    鉴于上面的要求:关键节点可以更改,可以调整阶段或节点;关键节点要求按照顺序填报且附件、说明、备注有的要求控制;填报第n个关键节点前,检查n-1个关键节点未填报的给与相应提示;
    当时的处理方法如下:
   1、先判断所有的关键节点是否存在;当录入节点数据时,判断当前填报的是哪一个节点,是关键节点且未填报,给与提醒;填报第n个节点时要检查n-1个节点是否填报,未填报给与提醒;要有一大堆的逻辑判断和提醒。
   2、先判断所有的关键节点是否存在;当录入节点数据时,填报第二个关键节点时与第一个关键节点做与位运算,产生一个bool值,决定下一个关键节点是否要填报,依次类推,第n个关键节点填报时,产生n-1个bool值,决定第n个节点是否填报。
   

     以上两个方法都会有不必要的if  else逻辑判断,还要提示特殊节点的备注、说明、附件必填,提出第三个方法:
 思路:定义一个类,有以下信息:关键节点的阶段、名称,存在标识,不存在提示信息,附件提示信息等;初始化所有关键节点(可以放在集合中),遍历该集合,从中若找到关键节点,检查该节点前面的节点有未填报的返回提示信息,找不到放弃;后面新加节点或移除关键节点,只需要操作集合即可。
     代码参考如下:
   //定义一个关键节点类
   public class ProcessNode
        {
            public int BuildNode { get; set; }//节点ID
            public int BuildStep { get; set; }//节点所在阶段
            public bool IsExist { get; set; }//该节点是否存在
            public string Msg { get; set; }//不存在提示信息
        }

              初始化关键节点集合
         /// <summary>
        /// 初始化进度节点  节点按照控制顺序,新增需要控制的节点,需要新驾到nodesList
        /// </summary>
        /// <param name="projectID">项目ID</param>
        /// <returns></returns>
        private List<ProcessNode> GetProcessNode(int projectID)
        {
            /*20140220 新需求填报限制:三个关键节点有顺序限制,且在在建阶段时项目实际开工时间节点未填报时 该阶段其他节点填报限制
             20140224 验收阶段又新增 项目完成投资(关键) 节点,要求:四个关键节点录入顺序限制*/
            List<B_BuildProcess> buildProcessList = proOpt.SelectFigureNodeMsg(projectID);
            List<ProcessNode> nodesList = new List<ProcessNode>();
            if (buildProcessList != null && buildProcessList.Count > 0)
            {//填报节点是在建阶段且不是 项目实际开工时间节点

                nodesList.Add(new ProcessNode()
                {
                    BuildNode = 38,
                    BuildStep = 37,
                    IsExist = buildProcessList.Exists(b => b.BuildStep == 37
                        && b.BuildNode == 38),
                    Msg = "请先填报项目实际开工时间!"
                });
                nodesList.Add(new ProcessNode()
                {
                    BuildNode = 45,
                    BuildStep = 37,
                    IsExist = buildProcessList.Exists(b => b.BuildStep == 37
                        && b.BuildNode == 45),
                    Msg = "请先填报项目交工验收时间!"
                });
                nodesList.Add(new ProcessNode()
                {
                    BuildNode = 382,
                    BuildStep = 44,
                    IsExist = buildProcessList.Exists(b => b.BuildStep == 44 && b.BuildNode == 382),
                    Msg = "请先填报投入使用(试生产)!"
                });
                nodesList.Add(new ProcessNode()
                {
                    BuildNode = 383,
                    BuildStep = 44,
                    IsExist = buildProcessList.Exists(b => b.BuildStep == 44 && b.BuildNode == 383),
                    Msg = "请先填报项目完成投资!"
                });

                nodesList.Add(new ProcessNode()
                {
                    BuildNode = 47,
                    BuildStep = 44,
                    IsExist = buildProcessList.Exists(b => b.BuildStep == 44 && b.BuildNode == 383),
                    Msg = "请先填报项目竣工验收时间!"
                });
            }
            return nodesList;
        }
 
        /// <summary>
        /// 根据填报的当前节点获取未填报节点的提示信息
        /// </summary>
        /// <param name="buildNode">节点id</param>
        /// <param name="buildStep">进度节点所处阶段</param>
        /// <param name="NodesList">初始化控制顺序的节点列表</param>
        /// <returns></returns>
        private string GetNotExistNodeMsg(int buildNode, int buildStep, List<ProcessNode> NodesList)
        {
            string msg = string.Empty;
            if (buildStep == 37 && buildNode != 38)
            {//在建阶段 填报非项目实际开工时间 节点时
                if (!NodesList[0].IsExist) return NodesList[0].Msg;
            }
            if (buildStep == 44 && buildNode == 47)
            {//填报验收阶段 项目竣工验收时间节点时 验证项目交工验收时间节点是否填报
                //20140226 限制:累计完成投资额不低于项目计划总投资60%
                if (!new FundBLL().IsCompletedGTTotalInvest(SessionManage.GetCurrentProjectID()))
                    msg = "填报的累计完成投资额不能低于项目计划总投资60%!";
            }
            int index = NodesList.FindIndex(n => n.BuildNode == buildNode && n.BuildStep == buildStep);//拿到关键节点所在的索引
            for (int i = 0; i < index; i++)
            {
                ProcessNode node = NodesList[i];
                if (!node.IsExist)
                {
                    msg = node.Msg;
                    break;
                }
            }
            return msg;
        }

      //最后在录入节点方法中调用:
       public ActionResult Create(B_BuildProcess b_Build)
        {
            try
            {
                int ProjectID = SessionManage.GetCurrentProjectID(); //项目ID
                b_Build.ProjectID = ProjectID;

                //进度节点填报顺序控制
                List<ProcessNode> nodesList = GetProcessNode(ProjectID);
                string msg = GetNotExistNodeMsg(b_Build.BuildNode, b_Build.BuildStep, nodesList);
                if (!string.IsNullOrWhiteSpace(msg)) return Json((new { ok = false, msg = msg }));
             }
          //业务处理
          ...
         }
   结论:
1、若要控制所有的节点按规定顺序填报并给与相应的提示(这包括未填报节点、备注、说明、附件信息)只要初始化关键节点集合即可;              
2、遇到这类问题:要求控制项多、每个项做的控制不同,可以类似这样解决问题;比如通用检索中,检索条件很多,需要拼接sql语句即拼接后面的where条件,先初始化好sql语句设置好默认条件,当传递过来的检索条件满足时加到该语句中,最后生成查询语句。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页