heteng 2 rokov pred
rodič
commit
57cf4ffb80

+ 193 - 40
MicroServices/Business/Business.Application/ResourceExamineManagement/ProductionScheduleAppService.cs

@@ -411,6 +411,7 @@ namespace Business.ResourceExamineManagement
                 decimal planQty = Math.Ceiling(sumTimes / (item.LbrVar * 60) * item.QtyOrded);
                 //剩余排产数量 = 工单数量 - 已报工数量 - 计划数量
                 decimal qtyNeed = item.QtyOrded - curOp.QtyComplete - planQty;
+                qtyNeed = qtyNeed < 0 ? 0 : qtyNeed;
                 //剩余工作时长(分钟)
                 decimal usedTime = Math.Ceiling(qtyNeed / item.QtyOrded * item.LbrVar * 60);
                 
@@ -491,15 +492,15 @@ namespace Business.ResourceExamineManagement
                     //获取当天重新排产的工单日计划
                     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);
+                    //删除数据库中的已存在的当天日计划
+                    _periodSequenceDet.Delete(p=>p.Domain == domain && tdSeqDtls.Select(m => m.Op).Contains(p.Op) && tdSeqDtls.Select(m => m.WorkOrds).Contains(p.WorkOrds) && p.PlanDate == scheTime.Date);
+                    _scheduleResultOpMaster.Delete(p=>p.Domain == domain && tdSchMsts.Select(m => m.Op).Contains(p.Op) && 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);
+                        var curDtl = dbPeriodSequences.FirstOrDefault(p => p.Op == item.Op && p.WorkOrds == item.WorkOrds && p.Line == item.Line && p.PlanDate == scheTime.Date);
                         item.OrdQty = curDtl == null ? item.OrdQty : curDtl.OrdQty;
                     }
                     //保存日计划数据
@@ -724,11 +725,6 @@ namespace Business.ResourceExamineManagement
             //第一层级工序有几个关键工序,就有几条产线
             for (int i = 0; i < workOrdRoutings.Count; i++)
             {
-                //如果当前工序已经生产完成,则跳过
-                if (workOrdRoutings[i].QtyComplete == workOrd.QtyOrded)
-                {
-                    continue;
-                }
                 //产线实际排产开始时间
                 if (i == 0)//第一条产线
                 {
@@ -739,12 +735,18 @@ namespace Business.ResourceExamineManagement
                     //获取前一产线排产开始时间,通过提前期计算当前产线排产开始时间
                     lineStart = DealNextStartTime(workOrd, lineStart, workOrdRoutings[i], prodLines, allResults);
                 }
+                //如果当前工序已经生产完成,则跳过
+                if (lineStart.QtyRemain == 0)
+                {
+                    continue;
+                }
+
                 //当前产线的工作日历
                 var mLCalendars = calendars.Where(p => p.ProdLine == lineStart.Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
                 //当前产线的休息时间设置
                 var mlqtyWorkDtls = qualityLines.Where(p => p.ProdLine == lineStart.Line).ToList();
                 //产线排产开始时间
-                DateTime workStartTime = scheTime;
+                DateTime workStartTime = lineStart.StartTime;
                 //记录特殊工单:获取第一天是否有特殊工单
                 List<WorkOrdMaster> fstWOMasters = tsWorkOrds.Where(p => p.ProdLine == lineStart.Line && p.OrdDate.Value.Date == workStartTime.Date).OrderBy(p => p.Priority).ToList();
                 List<WorkOrdMstDto> workDtos = new List<WorkOrdMstDto>();
@@ -763,39 +765,86 @@ namespace Business.ResourceExamineManagement
                     foreach (var item in fstWOMasters)
                     {
                         //注:特殊工单暂时只考虑连续生产,不考虑暂停
+                        DateTime tsStartTime = workStartTime;
+                        var first = fstWOMasters.First();
+                        if (item != first)
+                        {
+                            tsStartTime = item.OrdDate.GetValueOrDefault();
+                        }
                         //特殊工单工序
                         var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
                         //获取特殊工单开始排产时间记录
                         var curRecord = timeRecords.FirstOrDefault(p => p.WorkOrd == item.WorkOrd && p.Op == curOp.OP);
-                        //if (curRecord == null)
-                        //{
-                        //    //添加记录
-                        //    inserts.Add(new WorkOrdSetupTimeRecord
-                        //    {
-                        //        Domain = item.Domain,
-                        //        WorkOrd = item.WorkOrd,
-                        //        ItemNum = item.ItemNum,
-                        //        Op = curOp.OP,
-                        //        Line = item.ProdLine,
-                        //        StartTime = tStartTime,
-                        //        CreateTime = DateTime.Now
-                        //    });
-                        //    //记录工序开始准备时间记录
-                        //    timeRecords.Add(new WorkOrdSetupTimeRecord
-                        //    {
-                        //        Domain = item.Domain,
-                        //        WorkOrd = item.WorkOrd,
-                        //        ItemNum = item.ItemNum,
-                        //        Op = curOp.OP,
-                        //        Line = item.ProdLine,
-                        //        StartTime = tStartTime,
-                        //        CreateTime = DateTime.Now
-                        //    });
-                        //}
-
-
-                        //剩余排产数量
-                        decimal qtyNeed = item.QtyOrded - curOp.QtyComplete;
+                        //如果产线有准备时间记录且准备开始时间在当前时间之前,说明已在排产中,此时不需要重新获取产线
+                        if (curRecord != null && curRecord.StartTime < tsStartTime)
+                        {
+                            tsStartTime = workStartTime;
+                        }
+                        else
+                        {
+                            if (curRecord == null)
+                            {
+                                //添加记录
+                                inserts.Add(new WorkOrdSetupTimeRecord
+                                {
+                                    Domain = item.Domain,
+                                    WorkOrd = item.WorkOrd,
+                                    ItemNum = item.ItemNum,
+                                    Op = curOp.OP,
+                                    Line = item.ProdLine,
+                                    StartTime = tsStartTime,
+                                    CreateTime = DateTime.Now
+                                });
+                                //记录工序开始准备时间记录
+                                timeRecords.Add(new WorkOrdSetupTimeRecord
+                                {
+                                    Domain = item.Domain,
+                                    WorkOrd = item.WorkOrd,
+                                    ItemNum = item.ItemNum,
+                                    Op = curOp.OP,
+                                    Line = item.ProdLine,
+                                    StartTime = tsStartTime,
+                                    CreateTime = DateTime.Now
+                                });
+                            }
+                            else
+                            {
+                                //更新准备开始时间记录
+                                timeRecords.ForEach(p =>
+                                {
+                                    p.StartTime = p.WorkOrd == curRecord.WorkOrd && p.Op == curRecord.Op ? tsStartTime : p.StartTime;
+                                });
+                                //存在开始准备时间记录,则更新
+                                curRecord.StartTime = tsStartTime;
+                                updates.Add(curRecord);
+                            }
+                        }
+                        //计算开始排产时间或者上次报工时间到当前时间点的预估产能
+                        decimal sumWorkTimes = 0m;
+                        //工单没有报工记录
+                        if (curOp.Last == null)
+                        {
+                            if (curRecord == null)
+                            {
+                                //工单没有开始时间记录,取预计开工时间到当前时间的有效时长
+                                sumWorkTimes = 0m;
+                            }
+                            else
+                            {
+                                //工单有开始时间记录,取开始时间到当前时间的有效时长
+                                sumWorkTimes = CalcTimeMins(curRecord.StartTime, workStartTime, item.ProdLine);
+                            }
+                        }
+                        else
+                        {
+                            //工单有报工记录,取最新报工时间到当前时间的有效时长
+                            sumWorkTimes = CalcTimeMins(curOp.Last.GetValueOrDefault(), workStartTime, item.ProdLine);
+                        }
+                        //计算预估数量
+                        decimal planQty = Math.Ceiling(sumWorkTimes / (item.LbrVar * 60) * item.QtyOrded);
+                        //剩余排产数量 = 工单数量 - 已报工数量 - 计划数量
+                        decimal qtyNeed = item.QtyOrded - curOp.QtyComplete - planQty;
+                        qtyNeed = qtyNeed < 0 ? 0 : qtyNeed;
                         //剩余工作时长(分钟)
                         decimal usedTime = Math.Ceiling(qtyNeed / item.QtyOrded * item.LbrVar * 60);
                         workDtos.Add(new WorkOrdMstDto
@@ -848,7 +897,35 @@ namespace Business.ResourceExamineManagement
                             //记录新增待排产特殊工单
                             foreach (var item in secWOMasters)
                             {
+                                //注:特殊工单暂时只考虑连续生产,不考虑暂停
                                 var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
+                                //获取特殊工单开始排产时间记录
+                                var curRecord = timeRecords.FirstOrDefault(p => p.WorkOrd == item.WorkOrd && p.Op == curOp.OP);
+                                if (curRecord == null)
+                                {
+                                    //添加记录
+                                    inserts.Add(new WorkOrdSetupTimeRecord
+                                    {
+                                        Domain = item.Domain,
+                                        WorkOrd = item.WorkOrd,
+                                        ItemNum = item.ItemNum,
+                                        Op = curOp.OP,
+                                        Line = item.ProdLine,
+                                        StartTime = item.OrdDate.GetValueOrDefault(),
+                                        CreateTime = DateTime.Now
+                                    });
+                                    //记录工序开始准备时间记录
+                                    timeRecords.Add(new WorkOrdSetupTimeRecord
+                                    {
+                                        Domain = item.Domain,
+                                        WorkOrd = item.WorkOrd,
+                                        ItemNum = item.ItemNum,
+                                        Op = curOp.OP,
+                                        Line = item.ProdLine,
+                                        StartTime = item.OrdDate.GetValueOrDefault(),
+                                        CreateTime = DateTime.Now
+                                    });
+                                }
                                 //剩余排产数量
                                 decimal qtyNeed = item.QtyOrded - curOp.QtyComplete;
                                 //剩余工作时长(分钟)
@@ -1037,6 +1114,33 @@ namespace Business.ResourceExamineManagement
                                 foreach (var item in secWOMasters)
                                 {
                                     var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
+                                    //获取特殊工单开始排产时间记录
+                                    var curRecord = timeRecords.FirstOrDefault(p => p.WorkOrd == item.WorkOrd && p.Op == curOp.OP);
+                                    if (curRecord == null)
+                                    {
+                                        //添加记录
+                                        inserts.Add(new WorkOrdSetupTimeRecord
+                                        {
+                                            Domain = item.Domain,
+                                            WorkOrd = item.WorkOrd,
+                                            ItemNum = item.ItemNum,
+                                            Op = curOp.OP,
+                                            Line = item.ProdLine,
+                                            StartTime = item.OrdDate.GetValueOrDefault(),
+                                            CreateTime = DateTime.Now
+                                        });
+                                        //记录工序开始准备时间记录
+                                        timeRecords.Add(new WorkOrdSetupTimeRecord
+                                        {
+                                            Domain = item.Domain,
+                                            WorkOrd = item.WorkOrd,
+                                            ItemNum = item.ItemNum,
+                                            Op = curOp.OP,
+                                            Line = item.ProdLine,
+                                            StartTime = item.OrdDate.GetValueOrDefault(),
+                                            CreateTime = DateTime.Now
+                                        });
+                                    }
                                     //剩余排产数量
                                     decimal qtyNeed = item.QtyOrded - curOp.QtyComplete;
                                     //剩余工作时长(分钟)
@@ -1302,6 +1406,33 @@ namespace Business.ResourceExamineManagement
                             foreach (var item in secWOMasters)
                             {
                                 var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
+                                //获取特殊工单开始排产时间记录
+                                var curRecord = timeRecords.FirstOrDefault(p => p.WorkOrd == item.WorkOrd && p.Op == curOp.OP);
+                                if (curRecord == null)
+                                {
+                                    //添加记录
+                                    inserts.Add(new WorkOrdSetupTimeRecord
+                                    {
+                                        Domain = item.Domain,
+                                        WorkOrd = item.WorkOrd,
+                                        ItemNum = item.ItemNum,
+                                        Op = curOp.OP,
+                                        Line = item.ProdLine,
+                                        StartTime = item.OrdDate.GetValueOrDefault(),
+                                        CreateTime = DateTime.Now
+                                    });
+                                    //记录工序开始准备时间记录
+                                    timeRecords.Add(new WorkOrdSetupTimeRecord
+                                    {
+                                        Domain = item.Domain,
+                                        WorkOrd = item.WorkOrd,
+                                        ItemNum = item.ItemNum,
+                                        Op = curOp.OP,
+                                        Line = item.ProdLine,
+                                        StartTime = item.OrdDate.GetValueOrDefault(),
+                                        CreateTime = DateTime.Now
+                                    });
+                                }
                                 //剩余排产数量
                                 decimal qtyNeed = item.QtyOrded - curOp.QtyComplete;
                                 //剩余工作时长(分钟)
@@ -3885,6 +4016,13 @@ namespace Business.ResourceExamineManagement
             scheduledDto.EndTime = workPoints.Last().EndPoint;
             //计算starttime处于那个工作时间段
             var curPoint = workPoints.Where(p => startTime >= p.StartPoint && startTime <= p.EndPoint).First();
+            //开始时间不在工作时间段
+            if (curPoint == null)
+            {
+                //获取离开始时间最近的时间段
+                curPoint = workPoints.Where(p => p.EndPoint < startTime).OrderBy(p => p.Level).Last();
+                startTime = curPoint.EndPoint;
+            }
             TimeSpan span = curPoint.EndPoint - startTime;
             scheduledDto.EffTime = (decimal)span.TotalMinutes;
             //获取后续工作时间段的有效工作时间
@@ -3900,7 +4038,15 @@ namespace Business.ResourceExamineManagement
             var curLevel = curRunCrews.FirstOrDefault(p => p.StartDate.GetValueOrDefault().Date <= startTime.Date && p.EndDate.GetValueOrDefault().Date >= startTime.Date);
             decimal rate = curLevel == null ? lineStart.Rate : curLevel.Rate;
             scheduledDto.Rate = rate;
-            //计算当天的产能(向下取整)
+            //产线当天加班设置
+            var curOccupyTimes = resourceOccupancyTimes.Where(p => p.Resource == lineStart.Line && p.StartTime.GetValueOrDefault().Date == startTime.Date).OrderBy(p => p.StartTime).ToList();
+            scheduledDto.EffTime += curOccupyTimes.Sum(p=> Convert.ToDecimal(p.Ufld1) * 60);
+            if (curOccupyTimes.Any())
+            {
+                var last = curOccupyTimes.Last();
+                scheduledDto.EndTime = last.StartTime.GetValueOrDefault().AddHours(Convert.ToDouble(last.Ufld1));
+            }
+            //计算当天的产能(向上取整)
             scheduledDto.ProductQty = Math.Ceiling(scheduledDto.EffTime / 60 * rate);
             //计算班次
             scheduledDto.Period = 1;//默认一班制
@@ -3934,6 +4080,11 @@ namespace Business.ResourceExamineManagement
             if (curRecord != null && curRecord.StartTime < actStart)
             {
                 var curLine = lines.First(p=>p.Line == curRecord.Line);
+                //计算产线实际开始时间
+                //产线工作日历:当前产线的工作日历 + 默认工作日历
+                var curCalendars = calendars.Where(p => p.ProdLine == curLine.Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
+                var curQtyDtls = qualityLines.Where(p => p.ProdLine == curLine.Line).ToList();
+                actStart = CalcActStartTime(curLine.Line, actStart, curCalendars, curQtyDtls);
                 lineStart.RecID = curLine.RecID;
                 lineStart.Line = curLine.Line;
                 lineStart.StartTime = actStart;
@@ -4049,6 +4200,7 @@ namespace Business.ResourceExamineManagement
             }
             //剩余待排产数量=工单数量-已报工数量-预估数量
             lineStart.QtyRemain = workOrd.QtyOrded - routing.QtyComplete - planQty;
+            lineStart.QtyRemain = lineStart.QtyRemain < 0 ? 0 : lineStart.QtyRemain;
             return lineStart;
         }
 
@@ -4436,6 +4588,7 @@ namespace Business.ResourceExamineManagement
             }
             //剩余待排产数量=工单数量-已报工数量-预估数量
             startDto.QtyRemain = workOrd.QtyOrded - routing.QtyComplete - planQty;
+            startDto.QtyRemain = startDto.QtyRemain < 0 ? 0 : startDto.QtyRemain;
             return startDto;
         }
 

+ 2 - 2
MicroServices/Business/Business.Domain/StructuredDB/Production/WorkOrdSetupTimeRecord.cs

@@ -52,9 +52,9 @@ namespace Business.StructuredDB.Production
         public int Op { get; set; }
 
         /// <summary>
-        /// 开始准备时间
+        /// 开始准备时间/开始时间
         /// </summary>
-        [Comment("开始准备时间")]
+        [Comment("开始准备时间/开始时间")]
         public DateTime StartTime { get; set; }
 
         /// <summary>