Просмотр исходного кода

Merge branch 'dev' of http://123.60.180.165:4647/ZZYDOP/DOPCore into dev

tangdi 2 лет назад
Родитель
Сommit
cb14435dc4

+ 224 - 72
MicroServices/Business/Business.Application/ResourceExamineManagement/ProductionScheduleAppService.cs

@@ -155,7 +155,12 @@ namespace Business.ResourceExamineManagement
         /// <summary>
         /// 新增工序准备开始时间记录
         /// </summary>
-        private List<WorkOrdSetupTimeRecord> inserts=new List<WorkOrdSetupTimeRecord>();
+        private List<WorkOrdSetupTimeRecord> inserts = new List<WorkOrdSetupTimeRecord>();
+
+        /// <summary>
+        /// 更新工序准备开始时间记录
+        /// </summary>
+        private List<WorkOrdSetupTimeRecord> updates = new List<WorkOrdSetupTimeRecord>();
 
         /// <summary>
         /// 生产工单主表
@@ -341,7 +346,6 @@ namespace Business.ResourceExamineManagement
                 var curRoutings = workOrdRoutings.Where(p =>p.WorkOrd == item.WorkOrd && p.ItemNum == item.ItemNum && p.ParentOp == 0 && p.MilestoneOp).OrderBy(p=>p.OP).ToList();
                 //当前工单的产线明细
                 var curProdLines = prodLines.Where(p => p.Part == item.ItemNum).ToList();
-                
                 //产线排产
                 LineSchedule(item, curRoutings, curProdLines, periodSequenceDtls, scheduleMasters, allResults, tsWorkOrds, ypcWorkOrds, tsWoRoutings);
             }
@@ -433,10 +437,28 @@ namespace Business.ResourceExamineManagement
                     {
                         _workOrdSetupTimeRecord.Insert(inserts);
                     }
-                    
-                    //TODO:当天日计划数据调整
+                    //更新工单工序准备开始时间记录
+                    if (updates.Any())
+                    {
+                        _workOrdSetupTimeRecord.Update(updates);
+                    }
 
-                    //保存排产记录
+                    //当天日计划数据调整
+                    //获取当天重新排产的工单日计划
+                    var tdSeqDtls = periodSequenceDtls.Where(p => p.PlanDate == scheTime.Date).ToList();
+                    var tdSchMsts = scheduleMasters.Where(p => p.WorkDate == scheTime.Date).ToList();
+                    //删除数据库中的已存在的日计划
+                    _periodSequenceDet.Delete(p=>p.Domain == domain && tdSeqDtls.Select(m => m.WorkOrds).Contains(p.WorkOrds) && p.PlanDate == scheTime.Date);
+                    _scheduleResultOpMaster.Delete(p=>p.Domain == domain && tdSchMsts.Select(m => m.WorkOrd).Contains(p.WorkOrd) && p.WorkDate == scheTime.Date);
+                    //更新当天日计划的计划数量,排产数量
+                    foreach (var item in periodSequenceDtls)
+                    {
+                        item.UDeci1 = item.OrdQty.GetValueOrDefault();
+                        //获取历史排产数据
+                        var curDtl = dbPeriodSequences.FirstOrDefault(p => p.WorkOrds == item.WorkOrds && p.Line == item.Line && p.PlanDate == scheTime.Date);
+                        item.OrdQty = curDtl == null ? item.OrdQty : curDtl.OrdQty;
+                    }
+                    //保存日计划数据
                     _periodSequenceDet.Insert(periodSequenceDtls);
                     _scheduleResultOpMaster.Insert(scheduleMasters);
                     scope.Complete();
@@ -3824,47 +3846,98 @@ namespace Business.ResourceExamineManagement
         /// <returns></returns>
         public LineStartDto DealStartTime(WorkOrdMaster workOrd,WorkOrdRouting routing,List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults)
         {
+            LineStartDto lineStart = new LineStartDto();
+            //排产工序
             int op = routing.OP;
+            //排产任务执行时间
             DateTime actStart = scheTime;
-            LineStartDto lineStart = new LineStartDto();
             //获取工序对应的产线,根据优先级排序
             var lines = prodLines.Where(p => p.Part == workOrd.ItemNum && p.Op == op).OrderBy(p => p.Sequence).ToList();
-            //获取第一条产线排产结束时间
-            var schedule = allResults.Where(p => p.Line == lines[0].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
-            actStart = schedule == null ? actStart : (schedule.WorkEndTime >= actStart ? schedule.WorkEndTime : actStart);
-            //计算实际开工时间
-            //产线工作日历:当前产线的工作日历+默认工作日历
-            var curCalendars = calendars.Where(p => p.ProdLine == lines[0].Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
-            var curQtyDtls = qualityLines.Where(p=>p.ProdLine == lines[0].Line).ToList();
-            actStart = CalcActStartTime(lines[0].Line, actStart, curCalendars, curQtyDtls);
-            lineStart.RecID = lines[0].RecID;
-            lineStart.Line = lines[0].Line;
-            lineStart.StartTime = actStart;
-            lineStart.setupTime = lines[0].SetupTime;
-            lineStart.Rate = lines[0].Rate;
-            //循环其他产线
-            for (int i = 1; i < lines.Count; i++)
+            //获取工序开始准备时长记录
+            var curRecord = timeRecords.FirstOrDefault(p => p.Domain == domain && p.WorkOrd == workOrd.WorkOrd && p.Op == op);
+            //如果产线有准备时间记录且准备开始时间在当前时间之前,说明已在排产中,此时不需要重新获取产线
+            if (curRecord != null && curRecord.StartTime < actStart)
             {
-                schedule = allResults.Where(p => p.Line == lines[i].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
-                DateTime StartTime = schedule == null ? actStart : (schedule.WorkEndTime >= actStart ? schedule.WorkEndTime : actStart);
+                var curLine = lines.First(p=>p.Line == curRecord.Line);
+                lineStart.RecID = curLine.RecID;
+                lineStart.Line = curLine.Line;
+                lineStart.StartTime = actStart;
+                lineStart.setupTime = curLine.SetupTime;
+                lineStart.Rate = curLine.Rate;
+            }
+            else {
+                //获取第一条产线排产结束时间
+                var schedule = allResults.Where(p => p.Line == lines[0].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
+                actStart = schedule == null ? actStart : (schedule.WorkEndTime >= actStart ? schedule.WorkEndTime : actStart);
                 //计算实际开工时间
                 //产线工作日历:当前产线的工作日历+默认工作日历
-                curCalendars = calendars.Where(p => p.ProdLine == lines[i].Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
-                curQtyDtls = qualityLines.Where(p => p.ProdLine == lines[i].Line).ToList();
-                StartTime = CalcActStartTime(lines[0].Line, StartTime, curCalendars, curQtyDtls);
-                if (StartTime < lineStart.StartTime)
+                var curCalendars = calendars.Where(p => p.ProdLine == lines[0].Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
+                var curQtyDtls = qualityLines.Where(p => p.ProdLine == lines[0].Line).ToList();
+                actStart = CalcActStartTime(lines[0].Line, actStart, curCalendars, curQtyDtls);
+                lineStart.RecID = lines[0].RecID;
+                lineStart.Line = lines[0].Line;
+                lineStart.StartTime = actStart;
+                lineStart.setupTime = lines[0].SetupTime;
+                lineStart.Rate = lines[0].Rate;
+                //循环其他产线
+                for (int i = 1; i < lines.Count; i++)
                 {
-                    lineStart.RecID = lines[i].RecID;
-                    lineStart.Line = lines[i].Line;
-                    lineStart.StartTime = StartTime;
-                    lineStart.setupTime = lines[i].SetupTime;
-                    lineStart.Rate = lines[i].Rate;
+                    schedule = allResults.Where(p => p.Line == lines[i].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
+                    DateTime StartTime = schedule == null ? actStart : (schedule.WorkEndTime >= actStart ? schedule.WorkEndTime : actStart);
+                    //计算实际开工时间
+                    //产线工作日历:当前产线的工作日历+默认工作日历
+                    curCalendars = calendars.Where(p => p.ProdLine == lines[i].Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
+                    curQtyDtls = qualityLines.Where(p => p.ProdLine == lines[i].Line).ToList();
+                    StartTime = CalcActStartTime(lines[0].Line, StartTime, curCalendars, curQtyDtls);
+                    if (StartTime < lineStart.StartTime)
+                    {
+                        lineStart.RecID = lines[i].RecID;
+                        lineStart.Line = lines[i].Line;
+                        lineStart.StartTime = StartTime;
+                        lineStart.setupTime = lines[i].SetupTime;
+                        lineStart.Rate = lines[i].Rate;
+                    }
+                }
+                //当前工序没有开始准备时间记录
+                if (curRecord == null)
+                {
+                    //添加记录
+                    inserts.Add(new WorkOrdSetupTimeRecord
+                    {
+                        Domain = workOrd.Domain,
+                        WorkOrd = workOrd.WorkOrd,
+                        ItemNum = workOrd.ItemNum,
+                        Op = op,
+                        Line = lineStart.Line,
+                        StartTime = lineStart.StartTime,
+                        CreateTime = DateTime.Now
+                    });
+                    //记录工序开始准备时间记录
+                    timeRecords.Add(new WorkOrdSetupTimeRecord
+                    {
+                        Domain = workOrd.Domain,
+                        WorkOrd = workOrd.WorkOrd,
+                        ItemNum = workOrd.ItemNum,
+                        Op = op,
+                        Line = lineStart.Line,
+                        StartTime = lineStart.StartTime,
+                        CreateTime = DateTime.Now
+                    });
+                }
+                else {
+                    //更新准备开始时间记录
+                    timeRecords.ForEach(p => {
+                        p.Line = p.WorkOrd == workOrd.WorkOrd && p.Op == curRecord.Op ? lineStart.Line : p.Line;
+                        p.StartTime = p.WorkOrd == workOrd.WorkOrd && p.Op == curRecord.Op ? lineStart.StartTime : p.StartTime;
+                    });
+                    //存在开始准备时间记录,则更新
+                    curRecord.Line = lineStart.Line;
+                    curRecord.StartTime = lineStart.StartTime;
+                    updates.Add(curRecord);
                 }
             }
             //计算准备开始时间点与当前时间点的有效时长
             decimal sumTimes = 0m;
-            //获取工序开始准备时长记录
-            var curRecord = timeRecords.FirstOrDefault(p =>p.Domain == domain && p.WorkOrd == workOrd.WorkOrd && p.Op == op);
             if (curRecord != null)
             {
                 sumTimes = CalcTimeMins(curRecord.StartTime, lineStart.StartTime, lineStart.Line);
@@ -3874,35 +3947,30 @@ namespace Business.ResourceExamineManagement
                     sumTimes = 0m;
                 }
             }
-            //工单没有准备开始时间记录
-            else
-            {
-                inserts.Add(new WorkOrdSetupTimeRecord
-                {
-                    Domain = workOrd.Domain,
-                    WorkOrd = workOrd.WorkOrd,
-                    ItemNum = workOrd.ItemNum,
-                    Op = op,
-                    StartTime = lineStart.StartTime,
-                    CreateTime = DateTime.Now
-                });
-            }
             //产线准备完成之后到当前时间点剩余时长(小时)
             decimal restTime = lineStart.setupTime - sumTimes / 60;
             lineStart.setupTime = restTime <= 0 ? 0 : restTime;
             lineStart.Op = op;
             lineStart.WaitTime = routing.WaitTime * 60;
+
+            //判断当前产线的UPH
+            var curRunCrews = prodLineDetailRunCrews.Where(p => p.ProdLineDetailRecID == lineStart.RecID).ToList();
+            //判断当前日期是否配置了UPH
+            var curLevel = curRunCrews.FirstOrDefault(p => p.StartDate.GetValueOrDefault().Date <= lineStart.StartTime.Date && p.EndDate.GetValueOrDefault().Date >= lineStart.StartTime.Date);
+            //当天的实际UPH
+            decimal rate = curLevel == null ? lineStart.Rate : curLevel.Rate;
+
             //计算上次报工到当前时间点的预估生产数量,如果没有报工记录,则计算产线准备时间完成到当前时间点的预估生产数量
             decimal planQty = 0m;
             if (routing.Last == null && Math.Abs(restTime)>0)
             {
                 //工序没有报工,使用产线准备完成之后到当前时间点剩余时长计算预估生产数量
-                planQty = Math.Floor(Math.Abs(restTime) * lineStart.Rate);
+                planQty = Math.Floor(Math.Abs(restTime) * rate);
             }
             else {
                 //工序存在报工记录,计算报工时间点到当前时间点的有效生产时长,然后计算预估生产数量
                 sumTimes = CalcTimeMins(routing.Last.GetValueOrDefault(), lineStart.StartTime, lineStart.Line);
-                planQty = Math.Floor(sumTimes / 60 * lineStart.Rate);
+                planQty = Math.Floor(sumTimes / 60 * rate);
             }
             //剩余待排产数量=工单数量-已报工数量-预估数量
             lineStart.QtyRemain = workOrd.QtyOrded - routing.QtyComplete - planQty;
@@ -4170,6 +4238,7 @@ namespace Business.ResourceExamineManagement
             int op = routing.OP;
             //获取上序实际开工时间
             DateTime preStartTime = lineStart.StartTime;
+            //上序的开始准备时间记录
             var preRecord = timeRecords.FirstOrDefault(p=>p.WorkOrd == workOrd.WorkOrd && p.Domain == domain && p.Op == lineStart.Op);
             if (preRecord != null)
             {
@@ -4178,37 +4247,120 @@ namespace Business.ResourceExamineManagement
             LineStartDto startDto = new LineStartDto();
             //获取产线
             var lines = prodLines.Where(p => p.Part == workOrd.ItemNum && p.Op == op).OrderBy(p=>p.Sequence).ToList();
-            //获取第一条产线排产结束时间
-            var schedule = allResults.Where(p => p.Line == lines[0].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
-            DateTime startTime = CalcStartTimeWithSetUpTime(lines[0], preStartTime, lineStart.setupTime + lines[0].OverlapTime);
-            startDto.RecID = lines[0].RecID;
-            startDto.Line = lines[0].Line;
-            startDto.setupTime = lines[0].SetupTime;
-            startDto.StartTime = schedule == null ? startTime : (startTime < schedule.WorkEndTime ? schedule.WorkEndTime : startTime);
-            startDto.Rate = lines[0].Rate;
-            //循环剩余产线,找到最早可开工产线
-            for (int i = 1; i < lines.Count(); i++)
+            //当前工序的开始准备时间记录
+            var curRecord = timeRecords.FirstOrDefault(p=>p.Domain == domain && p.WorkOrd == workOrd.WorkOrd && p.Op == op);
+            //如果产线有准备时间记录且准备开始时间在当前时间之前,说明已在排产中,此时不需要重新获取产线
+            if (curRecord != null && curRecord.StartTime < scheTime)
             {
-                schedule = allResults.Where(p => p.Line == lines[i].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
-                startTime = CalcStartTimeWithSetUpTime(lines[i], preStartTime, lineStart.setupTime + lines[i].OverlapTime);
-                startTime = schedule == null ? startTime : (startTime < schedule.WorkEndTime ? schedule.WorkEndTime : startTime);
-                if (startTime < startDto.StartTime)
+                var curLine = lines.First(p => p.Line == curRecord.Line);
+                startDto.RecID = curLine.RecID;
+                startDto.Line = curLine.Line;
+                startDto.StartTime = scheTime;
+                startDto.setupTime = curLine.SetupTime;
+                startDto.Rate = curLine.Rate;
+            }
+            else {
+                //获取第一条产线排产结束时间
+                var schedule = allResults.Where(p => p.Line == lines[0].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
+                DateTime startTime = CalcStartTimeWithSetUpTime(lines[0], preStartTime, lineStart.setupTime + lines[0].OverlapTime);
+                startDto.RecID = lines[0].RecID;
+                startDto.Line = lines[0].Line;
+                startDto.setupTime = lines[0].SetupTime;
+                startDto.StartTime = schedule == null ? startTime : (startTime < schedule.WorkEndTime ? schedule.WorkEndTime : startTime);
+                startDto.Rate = lines[0].Rate;
+                //循环剩余产线,找到最早可开工产线
+                for (int i = 1; i < lines.Count(); i++)
                 {
-                    startDto.RecID = lines[i].RecID;
-                    startDto.Line = lines[i].Line;
-                    startDto.setupTime = lines[i].SetupTime;
-                    startDto.StartTime = startTime;
-                    startDto.Rate = lines[i].Rate;
+                    schedule = allResults.Where(p => p.Line == lines[i].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
+                    startTime = CalcStartTimeWithSetUpTime(lines[i], preStartTime, lineStart.setupTime + lines[i].OverlapTime);
+                    startTime = schedule == null ? startTime : (startTime < schedule.WorkEndTime ? schedule.WorkEndTime : startTime);
+                    if (startTime < startDto.StartTime)
+                    {
+                        startDto.RecID = lines[i].RecID;
+                        startDto.Line = lines[i].Line;
+                        startDto.setupTime = lines[i].SetupTime;
+                        startDto.StartTime = startTime;
+                        startDto.Rate = lines[i].Rate;
+                    }
+                }
+                //当前工序没有开始准备时间记录
+                if (curRecord == null)
+                {
+                    //添加记录
+                    inserts.Add(new WorkOrdSetupTimeRecord
+                    {
+                        Domain = workOrd.Domain,
+                        WorkOrd = workOrd.WorkOrd,
+                        ItemNum = workOrd.ItemNum,
+                        Op = op,
+                        Line = lineStart.Line,
+                        StartTime = lineStart.StartTime,
+                        CreateTime = DateTime.Now
+                    });
+                    //记录工序开始准备时间记录
+                    timeRecords.Add(new WorkOrdSetupTimeRecord
+                    {
+                        Domain = workOrd.Domain,
+                        WorkOrd = workOrd.WorkOrd,
+                        ItemNum = workOrd.ItemNum,
+                        Op = op,
+                        Line = lineStart.Line,
+                        StartTime = lineStart.StartTime,
+                        CreateTime = DateTime.Now
+                    });
+                }
+                else
+                {
+                    //更新准备开始时间记录
+                    timeRecords.ForEach(p => {
+                        p.Line = p.WorkOrd == workOrd.WorkOrd && p.Op == curRecord.Op ? startDto.Line : p.Line;
+                        p.StartTime = p.WorkOrd == workOrd.WorkOrd && p.Op == curRecord.Op ? startDto.StartTime : p.StartTime;
+                    });
+                    //存在开始准备时间记录,则更新
+                    curRecord.Line = startDto.Line;
+                    curRecord.StartTime = startDto.StartTime;
+                    updates.Add(curRecord);
                 }
             }
-            //如果当前工单正在排产,且是连续排产时,重新排产不需要考虑产线准备时间
-            if (workOrd.Status.ToLower() == "w" && workOrd.JointTyped.ToUpper() != "B")
+            //计算准备开始时间点与当前时间点的有效时长
+            decimal sumTimes = 0m;
+            if (curRecord != null)
             {
-                startDto.setupTime = 0m;
+                sumTimes = CalcTimeMins(curRecord.StartTime, startDto.StartTime, startDto.Line);
+                //如果当前工单状态为生产中"W",但是,调整了日计划开工时间,则需要重新准备
+                if (workOrd.Status.ToUpper() == "W" && workOrd.JointTyped.ToUpper() == "B")
+                {
+                    sumTimes = 0m;
+                }
             }
+            //产线准备完成之后到当前时间点剩余时长(小时)
+            decimal restTime = startDto.setupTime - sumTimes / 60;
+            startDto.setupTime = restTime <= 0 ? 0 : restTime;
             startDto.Op = op;
             startDto.WaitTime = routing.WaitTime * 60;
-            startDto.QtyRemain = workOrd.QtyOrded - routing.QtyComplete;
+
+            //判断当前产线的UPH
+            var curRunCrews = prodLineDetailRunCrews.Where(p => p.ProdLineDetailRecID == startDto.RecID).ToList();
+            //判断当前日期是否配置了UPH
+            var curLevel = curRunCrews.FirstOrDefault(p => p.StartDate.GetValueOrDefault().Date <= startDto.StartTime.Date && p.EndDate.GetValueOrDefault().Date >= startDto.StartTime.Date);
+            //当天的实际UPH
+            decimal rate = curLevel == null ? startDto.Rate : curLevel.Rate;
+
+            //计算上次报工到当前时间点的预估生产数量,如果没有报工记录,则计算产线准备时间完成到当前时间点的预估生产数量
+            decimal planQty = 0m;
+            if (routing.Last == null && Math.Abs(restTime) > 0)
+            {
+                //工序没有报工,使用产线准备完成之后到当前时间点剩余时长计算预估生产数量
+                planQty = Math.Floor(Math.Abs(restTime) * rate);
+            }
+            else
+            {
+                //工序存在报工记录,计算报工时间点到当前时间点的有效生产时长,然后计算预估生产数量
+                sumTimes = CalcTimeMins(routing.Last.GetValueOrDefault(), startDto.StartTime, startDto.Line);
+                planQty = Math.Floor(sumTimes / 60 * rate);
+            }
+            //剩余待排产数量=工单数量-已报工数量-预估数量
+            startDto.QtyRemain = workOrd.QtyOrded - routing.QtyComplete - planQty;
             return startDto;
         }
 

+ 6 - 0
MicroServices/Business/Business.Domain/StructuredDB/Production/PeriodSequenceDet.cs

@@ -69,6 +69,12 @@ namespace Business.Domain
         [Comment("工序")]
         public int Op { get; set; }
 
+        /// <summary>
+        /// 日计划数量
+        /// </summary>
+        [Comment("日计划数量")]
+        public decimal UDeci1 { get; set; }
+
         /// <summary>
         /// 是否有效:1-有效;0-无效
         /// </summary>

+ 6 - 0
MicroServices/Business/Business.Domain/StructuredDB/Production/WorkOrdSetupTimeRecord.cs

@@ -39,6 +39,12 @@ namespace Business.StructuredDB.Production
         [Comment("物料编码")]
         public string ItemNum { get; set; }
 
+        /// <summary>
+        /// 产线
+        /// </summary>
+        [Comment("产线")]
+        public string Line { get; set; }
+
         /// <summary>
         /// 工序
         /// </summary>