heteng před 2 roky
rodič
revize
ecf7a2710e

+ 10 - 0
MicroServices/Business/Business.Application.Contracts/Dto/WorkOrdMstDto.cs

@@ -16,6 +16,16 @@ namespace Business.Dto
         /// </summary>
         public string WorkOrd { get; set; }
 
+        /// <summary>
+        /// 工单计划开始时间
+        /// </summary>
+        public DateTime OrdDate { get; set; }
+
+        /// <summary>
+        /// 特殊工单产线
+        /// </summary>
+        public string ProdLine { get; set; }
+
         /// <summary>
         /// 物料编号
         /// </summary>

+ 174 - 19
MicroServices/Business/Business.Application/ResourceExamineManagement/ProductionScheduleAppService.cs

@@ -217,9 +217,8 @@ namespace Business.ResourceExamineManagement
             {
                 return;
             }
-            //获取排产工单的最早计划开工日期
+            //工单排产的最早日期
             DateTime earlist = DateTime.Now.Date.AddDays(1);
-
             //特殊工单指定时间开工,不需要计算产能,只需要计算时长即可
             var tsWorkOrds = workOrds.Where(p => !string.IsNullOrEmpty(p.Typed)).ToList();
             //正常工单
@@ -294,8 +293,38 @@ namespace Business.ResourceExamineManagement
                 List<ScheduleResultOpMaster> scheduleList = scheduleMasters.Where(s => s.WorkOrd == item.WorkOrd).ToList();
                 if (scheduleList.Any())
                 {
-                    item.OrdDate = scheduleList.Min(s => s.WorkStartTime.Date);
-                    item.DueDate = scheduleList.Max(s => s.WorkEndTime.Date);
+                    item.OrdDate = scheduleList.Min(s => s.WorkStartTime);
+                    item.DueDate = scheduleList.Max(s => s.WorkEndTime);
+                }
+            }
+            //判断是否有特殊工单没有排产,如果有,则对剩余特殊工单排产
+            var notSchedules = tsWorkOrds.Where(p => !ypcWorkOrds.Contains(p.WorkOrd)).ToList();
+            List<WorkOrdMstDto> workDtos = new List<WorkOrdMstDto>();
+            foreach (var item in notSchedules)
+            {
+                int op = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First().OP;
+                workDtos.Add(new WorkOrdMstDto
+                {
+                    WorkOrd = item.WorkOrd,
+                    ItemNum = item.ItemNum,
+                    QtyOrded = item.QtyOrded,
+                    OrdDate = item.OrdDate.GetValueOrDefault(),
+                    ProdLine = item.ProdLine,
+                    LbrVar = item.LbrVar,
+                    Worked = 0,
+                    QtyWorked = 0,
+                    Op = op
+                });
+            }
+            TsLineSchedule(workDtos, periodSequenceDtls, scheduleMasters);
+            //处理特殊工单计划开始日期、计划结束日期
+            foreach (var item in tsWorkOrds)
+            {
+                List<ScheduleResultOpMaster> scheduleList = scheduleMasters.Where(s => s.WorkOrd == item.WorkOrd).ToList();
+                if (scheduleList.Any())
+                {
+                    item.OrdDate = scheduleList.Min(s => s.WorkStartTime);
+                    item.DueDate = scheduleList.Max(s => s.WorkEndTime);
                 }
             }
             using (TransactionScope scope = new TransactionScope())
@@ -514,8 +543,6 @@ namespace Business.ResourceExamineManagement
                 var secWOMasters = new List<WorkOrdMaster>();
                 //特殊工单工作时长(分钟)
                 decimal sumTsTimes = fstWOMasters.Sum(p => p.LbrVar) * 60;
-                //特殊工单排产结束当天占用的产能时长(分钟)
-                decimal dayOccupyTimes = 0m;
                 while (sumTsTimes > 0) //产线排产开始当天安排了特殊工单,则先安排特殊工单
                 {
                     secWOMasters.Clear();
@@ -550,7 +577,7 @@ namespace Business.ResourceExamineManagement
                                 Op = op
                             });
                         }
-                        //特殊工单待排产时长增加新增带排产特殊工单生产时长
+                        //特殊工单待排产时长增加新增特殊工单生产时长
                         sumTsTimes += secWOMasters.Sum(p => p.LbrVar) * 60;
                     }
                     if (dto.EffTime * 60 >= sumTsTimes)//当天的可用产能满足特殊工单生产时长
@@ -635,7 +662,6 @@ namespace Business.ResourceExamineManagement
                             item.Worked = item.LbrVar;
                             sumTsTimes -= needTime;
                         }
-                        dayOccupyTimes = sumTsTimes;
                         if (dto.EffTime * 60 == sumTsTimes)//当天产能完全占用
                         {
                             sumTsTimes = 0;//排产完毕,特殊工单时长置0
@@ -662,7 +688,6 @@ namespace Business.ResourceExamineManagement
                             }
                             //特殊工单待排产时长增加新增带排产特殊工单生产时长
                             sumTsTimes += secWOMasters.Sum(p => p.LbrVar) * 60;
-                            dayOccupyTimes = 0m;
                         }
                         else {
                             sumTsTimes = 0;//排产完毕,特殊工单时长置0
@@ -818,12 +843,6 @@ namespace Business.ResourceExamineManagement
                     secWOMasters.Clear();
                     //获取当天的产能
                     LineScheduledDto dto = GetScheduledPoint(lineStart, workStartTime, mLCalendars, mlqtyWorkDtls);
-                    //当天产能被特殊工单占用部分,需要先剔除
-                    if (dayOccupyTimes > 0)
-                    {
-                        dto.EffTime -= Math.Ceiling(dayOccupyTimes / 60);
-                        dayOccupyTimes = 0;
-                    }
                     //正常工单排产第一天没有特殊工单,第一天之后才需要考虑是否有特殊工单
                     if (!isFstDay)
                     {
@@ -2071,6 +2090,145 @@ namespace Business.ResourceExamineManagement
             scheduleResults.AddRange(curScheduleRsts);
         }
 
+        /// <summary>
+        /// 特殊工单排产:和正常工单不共用产线的特殊工单
+        /// </summary>
+        /// <param name="workOrds">特殊工单</param>
+        /// <param name="periodsDet">生产周期</param>
+        /// <param name="scheduleResults">排产结果</param>
+        public void TsLineSchedule(List<WorkOrdMstDto> workOrds, List<PeriodSequenceDet> periodsDet, List<ScheduleResultOpMaster> scheduleResults)
+        {
+            foreach (var item in workOrds)
+            {
+                //工单的生产时长(小时)
+                decimal sumTimes = item.LbrVar;
+                //工单的排产开始时间
+                DateTime workStartTime = item.OrdDate;
+                //当前产线的工作日历
+                var mLCalendars = calendars.Where(p => p.ProdLine == item.ProdLine || string.IsNullOrEmpty(p.ProdLine)).ToList();
+                //当前产线的休息时间设置
+                var mlqtyWorkDtls = qualityLines.Where(p => p.ProdLine == item.ProdLine).ToList();
+                LineStartDto lineStart = new LineStartDto();
+                lineStart.Line = item.ProdLine;
+                lineStart.Op = item.Op;
+                lineStart.StartTime = workStartTime;
+                lineStart.Rate = 0;
+                while (sumTimes > 0)
+                {
+                    //获取当天的工作时间段
+                    var curCalendar = mLCalendars.FirstOrDefault(p => !string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)workStartTime.DayOfWeek);
+                    if (curCalendar == null)
+                    {
+                        curCalendar = mLCalendars.FirstOrDefault(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)workStartTime.DayOfWeek);
+                    }
+                    List<LineWorkPointDto> workPoints = DealWorkDayToLevels(lineStart.Line, workStartTime, curCalendar, mlqtyWorkDtls);
+                    //获取当天的产能
+                    LineScheduledDto dto = GetScheduledPoint(lineStart, workStartTime, mLCalendars, mlqtyWorkDtls);
+                    //当天的可用生产时长不能满足特殊工单生产时长
+                    if (dto.EffTime <= sumTimes)
+                    {
+                        decimal qty = Math.Ceiling(dto.EffTime / item.LbrVar * item.QtyOrded);
+                        //记录生产周期
+                        periodsDet.Add(new PeriodSequenceDet
+                        {
+                            Domain = domain,
+                            Line = item.ProdLine,
+                            ItemNum = item.ItemNum,
+                            PlanDate = workStartTime.Date,
+                            Period = dto.Period,
+                            OrdQty = qty,
+                            WorkOrds = item.WorkOrd,
+                            Op = item.Op,
+                            IsActive = true,
+                            Status = "",
+                            CreateTime = DateTime.Now
+                        });
+                        //记录排产记录
+                        scheduleResults.Add(new ScheduleResultOpMaster
+                        {
+                            Domain = domain,
+                            WorkOrd = item.WorkOrd,
+                            Line = item.ProdLine,
+                            ItemNum = item.ItemNum,
+                            Op = item.Op,
+                            WorkDate = workStartTime.Date,
+                            WorkQty = qty,
+                            WorkStartTime = dto.StartTime,
+                            WorkEndTime = dto.EndTime,
+                            CreateTime = DateTime.Now
+                        });
+                        //剩余待排产时长
+                        sumTimes -= dto.EffTime;
+                        //已排产数量
+                        item.QtyWorked += qty;
+                        //继续排下一个工作日
+                        workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
+                    }
+                    else// 最后一天的产能只能占用一部分
+                    {
+                        //剩余生产时长(分钟)
+                        decimal workTime = sumTimes * 60;
+                        var curPoint = workPoints.Find(p => p.StartPoint <= workStartTime && workStartTime <= p.EndPoint);
+                        TimeSpan span = curPoint.EndPoint - workStartTime;
+                        //当前工作时间段的有效生产时间
+                        decimal effMins = (decimal)span.TotalMinutes;
+                        DateTime workEndTime = workStartTime;
+                        if (effMins >= workTime)//当前工作时间段即可满足产能
+                        {
+                            workEndTime = workStartTime.AddMinutes((double)workTime);
+                        }
+                        else
+                        {
+                            //获取后续生产时间段
+                            var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).ToList();
+                            //剩余需要工作时长
+                            decimal nextMins = workTime - effMins;
+                            foreach (var p in nextPoints)
+                            {
+                                if (p.WorkMinutes >= nextMins)
+                                {
+                                    workEndTime = p.StartPoint.AddMinutes((double)nextMins);
+                                    break;
+                                }
+                                nextMins -= p.WorkMinutes;
+                            }
+                        }
+                        //记录生产周期
+                        periodsDet.Add(new PeriodSequenceDet
+                        {
+                            Domain = domain,
+                            Line = item.ProdLine,
+                            ItemNum = item.ItemNum,
+                            PlanDate = workStartTime.Date,
+                            Period = dto.Period,
+                            OrdQty = item.QtyOrded - item.QtyWorked,
+                            WorkOrds = item.WorkOrd,
+                            Op = item.Op,
+                            IsActive = true,
+                            Status = "",
+                            CreateTime = DateTime.Now
+                        });
+                        //记录排产记录
+                        scheduleResults.Add(new ScheduleResultOpMaster
+                        {
+                            Domain = domain,
+                            WorkOrd = item.WorkOrd,
+                            Line = item.ProdLine,
+                            ItemNum = item.ItemNum,
+                            Op = item.Op,
+                            WorkDate = workStartTime.Date,
+                            WorkQty = item.QtyOrded - item.QtyWorked,
+                            WorkStartTime = workStartTime,
+                            WorkEndTime = workEndTime,
+                            CreateTime = DateTime.Now
+                        });
+                        sumTimes = 0;
+                        item.QtyWorked = item.QtyOrded;
+                    }
+                }
+            }
+        }
+
         /// <summary>
         /// 获取产线当天的开工时间,结束时间,有效工作时长,生产数量
         /// </summary>
@@ -2108,9 +2266,6 @@ namespace Business.ResourceExamineManagement
                 span = item.EndPoint - item.StartPoint;
                 scheduledDto.EffTime += (decimal)span.TotalHours;
             }
-            ////判断产线当天有没有加班
-            //var curOccupyTimes = resourceOccupancyTimes.Where(p=> p.Resource == lineStart.Line && p.StartTime.GetValueOrDefault().Date == startTime.Date).ToList();
-            //scheduledDto.EffTime += curOccupyTimes.Sum(p=> Convert.ToDecimal(p.Ufld1));
             //判断当前产线的UPH
             var curRunCrews = prodLineDetailRunCrews.Where(p=>p.ProdLineDetailRecID == lineStart.RecID).ToList();
             //判断当前日期是否配置了UPH
@@ -2120,7 +2275,7 @@ namespace Business.ResourceExamineManagement
             //计算当天的产能(向下取整)
             scheduledDto.ProductQty = Math.Floor(scheduledDto.EffTime * rate);
             //计算班次
-            scheduledDto.Period = 1;//默认一
+            scheduledDto.Period = 1;//默认一
             if (shopCal.ShiftsStart2 != 0 && shopCal.ShiftsHours2 != 0)
             {
                 scheduledDto.Period = 2;