Selaa lähdekoodia

排产逻辑复核

heteng 2 vuotta sitten
vanhempi
commit
c9bb90957a

+ 390 - 365
MicroServices/Business/Business.Application/ResourceExamineManagement/ProductionScheduleAppService.cs

@@ -857,6 +857,13 @@ namespace Business.ResourceExamineManagement
                     secWOMasters.Clear();
                     //获取当天的产能
                     LineScheduledDto dto = GetScheduledPoint(lineStart, workStartTime, mLCalendars, mlqtyWorkDtls);
+                    //获取当天的工作时间段
+                    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);
                     //正常工单排产第一天没有特殊工单,第一天之后才需要考虑是否有特殊工单
                     if (!isFstDay)
                     {
@@ -886,27 +893,22 @@ namespace Business.ResourceExamineManagement
                         if (dto.EffTime > lineStart.setupTime * 60 - sumTimes)
                         {
                             //当天剩余时长(分钟)
-                            decimal residueTime = dto.EffTime - lineStart.setupTime * 60 - sumTimes;
+                            decimal residueTime = dto.EffTime - (lineStart.setupTime * 60 - sumTimes);
                             //产线提前期安排完之后,需要考虑当前是否存在特殊工单:
                             //1、如果当天是排产的最后一天,则先排完正常工单,再安排特殊工单;
                             //2、如果是排产中间日期,则先安排特殊工单排产
                             //当天剩余产能
-                            decimal sumAmount = dto.ProductQty - Math.Floor(dto.Rate * (lineStart.setupTime - sumTimes / 60));
-                            //判断已排产数量+当天的产能是否超过工单数量
-                            if (sumQty + sumAmount <= workOrd.QtyOrded)//当天的产能需要全部排产
+                            decimal sumAmount = Math.Floor(dto.Rate * residueTime / 60);
+                            //已排产数量+当天的剩余产能小于工单数量,当天的产能需要全部排产
+                            if (sumQty + sumAmount < workOrd.QtyOrded)
                             {
-                                if (sumTsTimes > 0)//当天有特殊工单,先排特殊工单
+                                //当天有特殊工单,且当天的产能不能满足工单剩余需排产数量,则优先排特殊工单
+                                if (sumTsTimes > 0)
                                 {
                                     DateTime beginTime = workStartTime;//排产开始时间
                                     DateTime endTime = dto.EndTime;//排产结束时间
-                                    //获取当天的工作时间段
-                                    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);
-                                    if (residueTime > sumTsTimes)//当天的可用产能满足特殊工单生产时长
+                                    //当天的可用生产时长满足特殊工单生产时长
+                                    if (residueTime > sumTsTimes)
                                     {
                                         //特殊工单排产
                                         foreach (var item in workDtos)
@@ -922,7 +924,8 @@ namespace Business.ResourceExamineManagement
                                             span = curPoint.EndPoint - beginTime;
                                             //当天工作时间段的有效生产时间(分钟)
                                             decimal effMins = (decimal)span.TotalMinutes;
-                                            if (effMins >= needTime)//当前工作时间段即可满足产能
+                                            //当前工作时间段即可满足产能
+                                            if (effMins >= needTime)
                                             {
                                                 endTime = beginTime.AddMinutes((double)needTime);
                                             }
@@ -973,11 +976,13 @@ namespace Business.ResourceExamineManagement
                                             });
                                             //下一工单开始时间=当前工单结束时间,如果位于工作区间结尾,则为下一工作区间开始时间
                                             curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
-                                            if (endTime == curPoint.EndPoint)//结束时间位于工作区间结尾
+                                            //结束时间位于工作区间结尾
+                                            if (endTime == curPoint.EndPoint)
                                             {
                                                 //获取后续生产时间段
                                                 var nextPoint = workPoints.Where(p => p.Level == curPoint.Level + 1).FirstOrDefault();
-                                                if (nextPoint != null)//存在后续工作区间
+                                                //存在后续工作区间
+                                                if (nextPoint != null)
                                                 {
                                                     endTime = nextPoint.StartPoint;
                                                 }
@@ -986,23 +991,12 @@ namespace Business.ResourceExamineManagement
                                             //工单排产完成,排产时长=工单工作时长
                                             item.Worked = item.LbrVar;
                                             item.QtyWorked = item.QtyOrded;
-                                            sumTsTimes -= needTime;
                                         }
 
                                         //处理正常工单开工时间
                                         workStartTime = endTime;
-                                        var point = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
-                                        if (endTime == point.EndPoint)
-                                        {
-                                            var nextPoint = workPoints.FirstOrDefault(p => p.Level == point.Level + 1);
-                                            if (nextPoint != null)
-                                            {
-                                                workStartTime = nextPoint.StartPoint;
-                                            }
-                                        }
-
                                         //剩余产能继续排正常工单
-                                        sumAmount = dto.ProductQty - Math.Floor(dto.Rate * (lineStart.setupTime - (sumTimes + sumTsTimes) / 60));
+                                        sumAmount = Math.Floor(dto.Rate * (residueTime - sumTsTimes) / 60);
                                         //记录生产周期
                                         curSequences.Add(new PeriodSequenceDet
                                         {
@@ -1041,7 +1035,8 @@ namespace Business.ResourceExamineManagement
                                         //排产完毕,特殊工单时长置0
                                         sumTsTimes = 0;
                                     }
-                                    else//当天的可用产能不满足或者刚好满足特殊工单生产时长
+                                    //当天的可用产能不满足或者刚好满足特殊工单生产时长
+                                    else
                                     {
                                         foreach (var item in workDtos)
                                         {
@@ -1051,14 +1046,16 @@ namespace Business.ResourceExamineManagement
                                             }
                                             //当前工单剩余待排产时长(分钟)
                                             decimal needTime = item.LbrVar - item.Worked;
-                                            if (residueTime >= needTime)//当天剩余产能满足当前工单的剩余待排产时长
+                                            //当天剩余产能满足当前工单的剩余待排产时长
+                                            if (residueTime >= needTime)
                                             {
                                                 //计算工单排产结束时间
                                                 var curPoint = workPoints.Find(p => p.StartPoint <= beginTime && beginTime <= p.EndPoint);
                                                 span = curPoint.EndPoint - beginTime;
                                                 //当前工作时间段的有效生产时间(分钟)
                                                 decimal effMins = (decimal)span.TotalMinutes;
-                                                if (effMins >= needTime)//当前工作时间段即可满足产能
+                                                //当前工作时间段即可满足产能
+                                                if (effMins >= needTime)
                                                 {
                                                     endTime = beginTime.AddMinutes((double)needTime);
                                                 }
@@ -1127,7 +1124,8 @@ namespace Business.ResourceExamineManagement
                                                     break;
                                                 }
                                             }
-                                            else//当天剩余产能不满足当前工单的剩余待排产时长
+                                            //当天剩余产能不满足当前工单的剩余待排产时长
+                                            else
                                             {
                                                 //计算生产数量
                                                 decimal qty = Math.Ceiling(residueTime / item.LbrVar * item.QtyOrded);
@@ -1172,8 +1170,9 @@ namespace Business.ResourceExamineManagement
                                         isFstDay = false;
                                     }
                                 }
-                                else { //当天没有特殊工单
-                                    #region 正常工单排产-开始
+                                //当天没有特殊工单,直接进行正常工单排产
+                                else
+                                { 
                                     //记录生产周期
                                     curSequences.Add(new PeriodSequenceDet
                                     {
@@ -1208,29 +1207,23 @@ namespace Business.ResourceExamineManagement
                                     //继续排下一个工作日
                                     workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
                                     isFstDay = false;
-                                    #endregion 正常工单排产-结束
                                 }
                             }
-                            else// 当天的产能正常工单只能占用一部分
+                            //当天的剩余产能可满足正常工单剩余待排产数量,则先排正常工单,如果有特殊工单,则后排
+                            else
                             {
                                 #region 正常工单排产-开始
                                 //剩余需要排产的数量
                                 decimal residueQty = workOrd.QtyOrded - sumQty;
                                 //剩余数量生产需要时长(分钟)
                                 decimal workTime = Math.Ceiling(residueQty / dto.Rate * 60);
-                                //获取当天的工作时间段
-                                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);
                                 var curPoint = workPoints.Find(p => p.StartPoint <= workStartTime && workStartTime <= p.EndPoint);
                                 span = curPoint.EndPoint - workStartTime;
                                 //当天工作时间段的有效生产时间
                                 decimal effMins = (decimal)span.TotalMinutes;
                                 DateTime workEndTime = workStartTime;
-                                if (effMins >= workTime)//当前工作时间段即可满足产能
+                                //当前工作时间段即可满足产能
+                                if (effMins >= workTime)
                                 {
                                     workEndTime = workStartTime.AddMinutes((double)workTime);
                                 }
@@ -1282,114 +1275,45 @@ namespace Business.ResourceExamineManagement
                                 });
                                 #endregion 正常工单排产-结束
 
-                                #region 特殊工单排产-开始
-                                //当天剩余产能
-                                decimal restTime = residueTime - workTime;
+                                //处理正常工单排产结束时间<=>特殊工单排产开始时间
+                                curPoint = workPoints.Find(p => p.StartPoint <= workEndTime && workEndTime <= p.EndPoint);
+                                if (workEndTime == curPoint.EndPoint)
+                                {
+                                    var nextPoint = workPoints.FirstOrDefault(p => p.Level == curPoint.Level + 1);
+                                    if (nextPoint != null)
+                                    {
+                                        workEndTime = nextPoint.StartPoint;
+                                    }
+                                }
+                                //当天排完正常工单后的剩余生产时长(分钟)
+                                decimal restTime = (residueTime - workTime) < 0 ? 0 : (residueTime - workTime);
+                                //当天存在特殊工单
                                 if (sumTsTimes > 0)
                                 {
-                                    DateTime beginTime = workEndTime;//排产开始时间
-                                    DateTime endTime = dto.EndTime;//排产结束时间
-                                    if (restTime >= sumTsTimes)//当天的可用产能满足特殊工单生产时长
+                                    //当天剩余生产时长大于0,特殊工单排产
+                                    if (restTime > 0)
                                     {
-                                        foreach (var item in workDtos)
+                                        #region 特殊工单排产-开始
+                                        DateTime beginTime = workEndTime;//排产开始时间
+                                        DateTime endTime = dto.EndTime;//排产结束时间
+                                        //当天的剩余生产时长满足特殊工单生产时长
+                                        if (restTime >= sumTsTimes)
                                         {
-                                            if (item.LbrVar == item.Worked)//当前工单已排产,跳过
-                                            {
-                                                continue;
-                                            }
-                                            //当前工单还需工作时长
-                                            decimal needTime = item.LbrVar - item.Worked;
-                                            //计算工单排产结束时间
-                                            curPoint = workPoints.Find(p => p.StartPoint <= beginTime && beginTime <= p.EndPoint);
-                                            span = curPoint.EndPoint - beginTime;
-                                            //当天工作时间段的有效生产时间(分钟)
-                                            effMins = (decimal)span.TotalMinutes;
-                                            if (effMins >= needTime)//当前工作时间段即可满足产能
-                                            {
-                                                endTime = beginTime.AddMinutes((double)needTime);
-                                            }
-                                            else
-                                            {
-                                                //获取后续生产时间段
-                                                var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).OrderBy(p => p.Level).ToList();
-                                                //剩余需要工作时长
-                                                decimal nextMins = needTime - effMins;
-                                                foreach (var p in nextPoints)
-                                                {
-                                                    if (p.WorkMinutes >= nextMins)
-                                                    {
-                                                        endTime = p.StartPoint.AddMinutes((double)nextMins);
-                                                        break;
-                                                    }
-                                                    nextMins -= p.WorkMinutes;
-                                                }
-                                            }
-                                            //记录生产周期
-                                            curSequences.Add(new PeriodSequenceDet
+                                            foreach (var item in workDtos)
                                             {
-                                                Domain = domain,
-                                                Line = lineStart.Line,
-                                                ItemNum = item.ItemNum,
-                                                PlanDate = beginTime.Date,
-                                                Period = dto.Period,
-                                                OrdQty = item.QtyOrded - item.QtyWorked,
-                                                WorkOrds = item.WorkOrd,
-                                                Op = item.Op,
-                                                IsActive = true,
-                                                Status = "",
-                                                CreateTime = DateTime.Now
-                                            });
-                                            //记录排产记录
-                                            curScheduleRsts.Add(new ScheduleResultOpMaster
-                                            {
-                                                Domain = domain,
-                                                WorkOrd = item.WorkOrd,
-                                                Line = lineStart.Line,
-                                                ItemNum = item.ItemNum,
-                                                Op = item.Op,
-                                                WorkDate = beginTime.Date,
-                                                WorkQty = item.QtyOrded - item.QtyWorked,
-                                                WorkStartTime = beginTime,
-                                                WorkEndTime = endTime,
-                                                CreateTime = DateTime.Now
-                                            });
-                                            //下一工单开始时间=当前工单结束时间,如果位于工作区间结尾,则为下一工作区间开始时间
-                                            curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
-                                            if (endTime == curPoint.EndPoint)//结束时间位于工作区间结尾
-                                            {
-                                                //获取后续生产时间段
-                                                var nextPoint = workPoints.Where(p => p.Level == curPoint.Level + 1).FirstOrDefault();
-                                                if (nextPoint != null)//存在后续工作区间
+                                                if (item.LbrVar == item.Worked)//当前工单已排产
                                                 {
-                                                    endTime = nextPoint.StartPoint;
+                                                    continue;
                                                 }
-                                            }
-                                            beginTime = endTime;
-                                            //工单排产完成,排产时长=工单工作时长
-                                            item.Worked = item.LbrVar;
-                                            item.QtyWorked = item.QtyOrded;
-                                            sumTsTimes -= needTime;
-                                        }
-                                        sumTsTimes = 0;//排产完毕,特殊工单时长置0
-                                    }
-                                    else//当天的可用产能不满足特殊工单生产时长
-                                    {
-                                        foreach (var item in workDtos)
-                                        {
-                                            if (item.LbrVar == item.Worked)//当前工单已排产
-                                            {
-                                                continue;
-                                            }
-                                            //当前工单剩余待排产时长(分钟)
-                                            decimal needTime = item.LbrVar - item.Worked;
-                                            if (restTime >= needTime)//当天剩余产能满足当前工单的剩余待排产时长
-                                            {
+                                                //当前工单还需工作时长
+                                                decimal needTime = item.LbrVar - item.Worked;
                                                 //计算工单排产结束时间
                                                 curPoint = workPoints.Find(p => p.StartPoint <= beginTime && beginTime <= p.EndPoint);
                                                 span = curPoint.EndPoint - beginTime;
-                                                //当工作时间段的有效生产时间(分钟)
+                                                //当天工作时间段的有效生产时间(分钟)
                                                 effMins = (decimal)span.TotalMinutes;
-                                                if (effMins >= needTime)//当前工作时间段即可满足产能
+                                                //当前工作时间段即可满足产能
+                                                if (effMins >= needTime)
                                                 {
                                                     endTime = beginTime.AddMinutes((double)needTime);
                                                 }
@@ -1438,68 +1362,175 @@ namespace Business.ResourceExamineManagement
                                                     WorkEndTime = endTime,
                                                     CreateTime = DateTime.Now
                                                 });
-                                                beginTime = endTime;
-                                                //当前工单已排产完成,已排产时间=工单生产时长,已排产数量=工单数量
-                                                item.Worked = item.LbrVar;
-                                                item.QtyWorked = item.QtyWorked;
-                                                //当天剩余产能
-                                                restTime -= needTime;
-                                                if (restTime == 0)
+                                                //下一工单开始时间=当前工单结束时间,如果位于工作区间结尾,则为下一工作区间开始时间
+                                                curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
+                                                if (endTime == curPoint.EndPoint)//结束时间位于工作区间结尾
                                                 {
-                                                    break;
+                                                    //获取后续生产时间段
+                                                    var nextPoint = workPoints.Where(p => p.Level == curPoint.Level + 1).FirstOrDefault();
+                                                    if (nextPoint != null)//存在后续工作区间
+                                                    {
+                                                        endTime = nextPoint.StartPoint;
+                                                    }
                                                 }
+                                                beginTime = endTime;
+                                                //工单排产完成,排产时长=工单工作时长
+                                                item.Worked = item.LbrVar;
+                                                item.QtyWorked = item.QtyOrded;
+                                                sumTsTimes -= needTime;
                                             }
-                                            else//当天剩余产能不满足当前工单的剩余待排产时长
+                                            sumTsTimes = 0;//排产完毕,特殊工单时长置0
+                                        }
+                                        //当天的剩余生产时长不满足特殊工单生产时长
+                                        else
+                                        {
+                                            foreach (var item in workDtos)
                                             {
-                                                //计算生产数量
-                                                decimal qty = Math.Ceiling(restTime / item.LbrVar * item.QtyOrded);
-                                                //记录生产周期
-                                                curSequences.Add(new PeriodSequenceDet
+                                                if (item.LbrVar == item.Worked)//当前工单已排产
                                                 {
-                                                    Domain = domain,
-                                                    Line = lineStart.Line,
-                                                    ItemNum = item.ItemNum,
-                                                    PlanDate = beginTime.Date,
-                                                    Period = dto.Period,
-                                                    OrdQty = qty,
-                                                    WorkOrds = item.WorkOrd,
-                                                    Op = item.Op,
-                                                    IsActive = true,
-                                                    Status = "",
-                                                    CreateTime = DateTime.Now
-                                                });
-                                                //记录排产记录
-                                                curScheduleRsts.Add(new ScheduleResultOpMaster
+                                                    continue;
+                                                }
+                                                //当前工单剩余待排产时长(分钟)
+                                                decimal needTime = item.LbrVar - item.Worked;
+                                                //当天剩余产能满足当前工单的剩余待排产时长
+                                                if (restTime >= needTime)
                                                 {
-                                                    Domain = domain,
-                                                    WorkOrd = item.WorkOrd,
-                                                    Line = lineStart.Line,
-                                                    ItemNum = item.ItemNum,
-                                                    Op = item.Op,
-                                                    WorkDate = beginTime.Date,
-                                                    WorkQty = qty,
-                                                    WorkStartTime = beginTime,
-                                                    WorkEndTime = endTime,
-                                                    CreateTime = DateTime.Now
-                                                });
-                                                item.Worked += restTime;
-                                                item.QtyWorked += qty;
-                                                break;
+                                                    //计算工单排产结束时间
+                                                    curPoint = workPoints.Find(p => p.StartPoint <= beginTime && beginTime <= p.EndPoint);
+                                                    span = curPoint.EndPoint - beginTime;
+                                                    //当前工作时间段的有效生产时间(分钟)
+                                                    effMins = (decimal)span.TotalMinutes;
+                                                    //当前工作时间段即可满足产能
+                                                    if (effMins >= needTime)
+                                                    {
+                                                        endTime = beginTime.AddMinutes((double)needTime);
+                                                    }
+                                                    else
+                                                    {
+                                                        //获取后续生产时间段
+                                                        var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).OrderBy(p => p.Level).ToList();
+                                                        //剩余需要工作时长
+                                                        decimal nextMins = needTime - effMins;
+                                                        foreach (var p in nextPoints)
+                                                        {
+                                                            if (p.WorkMinutes >= nextMins)
+                                                            {
+                                                                endTime = p.StartPoint.AddMinutes((double)nextMins);
+                                                                break;
+                                                            }
+                                                            nextMins -= p.WorkMinutes;
+                                                        }
+                                                    }
+                                                    //记录生产周期
+                                                    curSequences.Add(new PeriodSequenceDet
+                                                    {
+                                                        Domain = domain,
+                                                        Line = lineStart.Line,
+                                                        ItemNum = item.ItemNum,
+                                                        PlanDate = beginTime.Date,
+                                                        Period = dto.Period,
+                                                        OrdQty = item.QtyOrded - item.QtyWorked,
+                                                        WorkOrds = item.WorkOrd,
+                                                        Op = item.Op,
+                                                        IsActive = true,
+                                                        Status = "",
+                                                        CreateTime = DateTime.Now
+                                                    });
+                                                    //记录排产记录
+                                                    curScheduleRsts.Add(new ScheduleResultOpMaster
+                                                    {
+                                                        Domain = domain,
+                                                        WorkOrd = item.WorkOrd,
+                                                        Line = lineStart.Line,
+                                                        ItemNum = item.ItemNum,
+                                                        Op = item.Op,
+                                                        WorkDate = beginTime.Date,
+                                                        WorkQty = item.QtyOrded - item.QtyWorked,
+                                                        WorkStartTime = beginTime,
+                                                        WorkEndTime = endTime,
+                                                        CreateTime = DateTime.Now
+                                                    });
+                                                    curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
+                                                    if (endTime == curPoint.EndPoint)
+                                                    {
+                                                        var nextPoint = workPoints.FirstOrDefault(p=>p.Level == curPoint.Level + 1);
+                                                        if (nextPoint != null)
+                                                        {
+                                                            endTime = nextPoint.StartPoint;
+                                                        }
+                                                    }
+                                                    beginTime = endTime;
+                                                    //当前工单已排产完成,已排产时间=工单生产时长,已排产数量=工单数量
+                                                    item.Worked = item.LbrVar;
+                                                    item.QtyWorked = item.QtyWorked;
+                                                    //当天剩余产能
+                                                    restTime -= needTime;
+                                                    if (restTime == 0)
+                                                    {
+                                                        break;
+                                                    }
+                                                }
+                                                //当天剩余产能不满足当前工单的剩余待排产时长
+                                                else
+                                                {
+                                                    //计算生产数量
+                                                    decimal qty = Math.Ceiling(restTime / item.LbrVar * item.QtyOrded);
+                                                    //记录生产周期
+                                                    curSequences.Add(new PeriodSequenceDet
+                                                    {
+                                                        Domain = domain,
+                                                        Line = lineStart.Line,
+                                                        ItemNum = item.ItemNum,
+                                                        PlanDate = beginTime.Date,
+                                                        Period = dto.Period,
+                                                        OrdQty = qty,
+                                                        WorkOrds = item.WorkOrd,
+                                                        Op = item.Op,
+                                                        IsActive = true,
+                                                        Status = "",
+                                                        CreateTime = DateTime.Now
+                                                    });
+                                                    //记录排产记录
+                                                    curScheduleRsts.Add(new ScheduleResultOpMaster
+                                                    {
+                                                        Domain = domain,
+                                                        WorkOrd = item.WorkOrd,
+                                                        Line = lineStart.Line,
+                                                        ItemNum = item.ItemNum,
+                                                        Op = item.Op,
+                                                        WorkDate = beginTime.Date,
+                                                        WorkQty = qty,
+                                                        WorkStartTime = beginTime,
+                                                        WorkEndTime = endTime,
+                                                        CreateTime = DateTime.Now
+                                                    });
+                                                    item.Worked += restTime;
+                                                    item.QtyWorked += qty;
+                                                    break;
+                                                }
                                             }
+                                            //特殊工单剩余待排产时长(分钟)
+                                            sumTsTimes -= restTime;
+                                            //获取下一个工作日
+                                            workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
+                                            isFstDay = false;
                                         }
-                                        //特殊工单剩余待排产时长(分钟)
-                                        sumTsTimes -= restTime;
-                                        //获取下一个工作日
+                                        #endregion 特殊工单排产-结束
+                                    }
+                                    //当天剩余生产时长为0,由于存在特殊工单,则循环下一个工作日进行排产
+                                    else 
+                                    {
+                                        //继续排下一个工作日
                                         workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
                                         isFstDay = false;
                                     }
                                 }
-                                #endregion 特殊工单排产-结束
                             }
                             //记录提前期
                             sumTimes = lineStart.setupTime * 60;
                         }
-                        else//当天可用生产时长不能满足或者刚好满足提前期
+                        //当天可用生产时长不能满足或者刚好满足提前期
+                        else
                         {
                             //当天的可用生产时长不能满足提前期
                             sumTimes += dto.EffTime;
@@ -1510,28 +1541,23 @@ namespace Business.ResourceExamineManagement
                     }
                     else
                     {
-                        //判断已排产数量+当天的产能是否超过工单数量
-                        if (sumQty + dto.ProductQty <= workOrd.QtyOrded)//当天的产能需要全部排产
+                        //已排产数量+当天的产能小于或者等于工单数量,当天的产能需要全部排产
+                        if (sumQty + dto.ProductQty <= workOrd.QtyOrded)
                         {
-                            if (sumTsTimes > 0)//当天有特殊工单,先排特殊工单
+                            //当天有特殊工单,先排特殊工单
+                            if (sumTsTimes > 0)
                             {
                                 //当天剩余产能(分钟)
                                 decimal residueTime = dto.EffTime;
                                 DateTime beginTime = workStartTime;//排产开始时间
                                 DateTime endTime = dto.EndTime;//排产结束时间
-                                //获取当天的工作时间段
-                                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);
-                                if (residueTime > sumTsTimes)//当天的可用产能满足特殊工单生产时长
+                                //当天的可用产能满足特殊工单生产时长
+                                if (residueTime > sumTsTimes)
                                 {
                                     //特殊工单排产
                                     foreach (var item in workDtos)
                                     {
-                                        if (item.LbrVar == item.Worked)//当前工单已排产,跳过
+                                        if (item.LbrVar == item.Worked)//当前工单已排产
                                         {
                                             continue;
                                         }
@@ -1596,7 +1622,7 @@ namespace Business.ResourceExamineManagement
                                         if (endTime == curPoint.EndPoint)//结束时间位于工作区间结尾
                                         {
                                             //获取后续生产时间段
-                                            var nextPoint = workPoints.Where(p => p.Level == curPoint.Level + 1).FirstOrDefault();
+                                            var nextPoint = workPoints.FirstOrDefault(p => p.Level == curPoint.Level + 1);
                                             if (nextPoint != null)//存在后续工作区间
                                             {
                                                 endTime = nextPoint.StartPoint;
@@ -1611,18 +1637,8 @@ namespace Business.ResourceExamineManagement
 
                                     //处理正常工单开工时间
                                     workStartTime = endTime;
-                                    var point = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
-                                    if (endTime == point.EndPoint)
-                                    {
-                                        var nextPoint = workPoints.FirstOrDefault(p => p.Level == point.Level + 1);
-                                        if (nextPoint != null)
-                                        {
-                                            workStartTime = nextPoint.StartPoint;
-                                        }
-                                    }
-
                                     //剩余产能继续排正常工单
-                                    decimal sumAmount = dto.ProductQty - Math.Floor(dto.Rate * (dto.EffTime - sumTsTimes) / 60);
+                                    decimal sumAmount = Math.Floor(dto.Rate * (dto.EffTime - sumTsTimes) / 60);
                                     //记录生产周期
                                     curSequences.Add(new PeriodSequenceDet
                                     {
@@ -1661,7 +1677,8 @@ namespace Business.ResourceExamineManagement
                                     //排产完毕,特殊工单时长置0
                                     sumTsTimes = 0;
                                 }
-                                else//当天的可用产能不满足或者刚好满足特殊工单生产时长
+                                //当天的可用产能不满足或者刚好满足特殊工单生产时长
+                                else
                                 {
                                     foreach (var item in workDtos)
                                     {
@@ -1671,7 +1688,8 @@ namespace Business.ResourceExamineManagement
                                         }
                                         //当前工单剩余待排产时长(分钟)
                                         decimal needTime = item.LbrVar - item.Worked;
-                                        if (residueTime >= needTime)//当天剩余产能满足当前工单的剩余待排产时长
+                                        //当天剩余产能满足当前工单的剩余待排产时长
+                                        if (residueTime >= needTime)
                                         {
                                             //计算工单排产结束时间
                                             var curPoint = workPoints.Find(p => p.StartPoint <= beginTime && beginTime <= p.EndPoint);
@@ -1792,7 +1810,9 @@ namespace Business.ResourceExamineManagement
                                     isFstDay = false;
                                 }
                             }
-                            else {//不存在特殊工单
+                            //不存在特殊工单
+                            else
+                            {
                                 //记录生产周期
                                 curSequences.Add(new PeriodSequenceDet
                                 {
@@ -1833,13 +1853,6 @@ namespace Business.ResourceExamineManagement
                         {
                             decimal workTime = 0m;
                             DateTime workEndTime = workStartTime;
-                            //获取当天的工作时间段
-                            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);
                             if (sumQty < workOrd.QtyOrded)
                             {
                                 #region 正常工单排产-开始
@@ -1851,7 +1864,8 @@ namespace Business.ResourceExamineManagement
                                 span = curPoint.EndPoint - workStartTime;
                                 //当天工作时间段的有效生产时间
                                 decimal effMins = (decimal)span.TotalMinutes;
-                                if (effMins >= workTime)//当前工作时间段即可满足产能
+                                //当前工作时间段即可满足产能
+                                if (effMins >= workTime)
                                 {
                                     workEndTime = workStartTime.AddMinutes((double)workTime);
                                 }
@@ -1904,112 +1918,30 @@ namespace Business.ResourceExamineManagement
                                 #endregion 正常工单排产-结束
                             }
 
-                            #region 特殊工单排产-开始
                             //当天剩余产能(分钟)
-                            decimal restTime = dto.EffTime - workTime;
+                            decimal restTime = (dto.EffTime - workTime) < 0 ? 0 : (dto.EffTime - workTime);
                             if (sumTsTimes > 0)//存在特殊工单
                             {
-                                DateTime beginTime = workEndTime;//排产开始时间
-                                DateTime endTime = dto.EndTime;//排产结束时间
-                                if (restTime >= sumTsTimes)//当天的可用产能满足特殊工单生产时长
+                                if (restTime > 0)
                                 {
-                                    foreach (var item in workDtos)
+                                    #region 特殊工单排产-开始
+                                    DateTime beginTime = workEndTime;//排产开始时间
+                                    DateTime endTime = dto.EndTime;//排产结束时间
+                                    //当天的可用产能满足特殊工单生产时长
+                                    if (restTime >= sumTsTimes)
                                     {
-                                        if (item.LbrVar == item.Worked)//当前工单已排产,跳过
-                                        {
-                                            continue;
-                                        }
-                                        //当前工单还需工作时长
-                                        decimal needTime = item.LbrVar - item.Worked;
-                                        //计算工单排产结束时间
-                                        var curPoint = workPoints.Find(p => p.StartPoint <= beginTime && beginTime <= p.EndPoint);
-                                        span = curPoint.EndPoint - beginTime;
-                                        //当天工作时间段的有效生产时间(分钟)
-                                        decimal effMins = (decimal)span.TotalMinutes;
-                                        if (effMins >= needTime)//当前工作时间段即可满足产能
-                                        {
-                                            endTime = beginTime.AddMinutes((double)needTime);
-                                        }
-                                        else
-                                        {
-                                            //获取后续生产时间段
-                                            var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).OrderBy(p => p.Level).ToList();
-                                            //剩余需要工作时长
-                                            decimal nextMins = needTime - effMins;
-                                            foreach (var p in nextPoints)
-                                            {
-                                                if (p.WorkMinutes >= nextMins)
-                                                {
-                                                    endTime = p.StartPoint.AddMinutes((double)nextMins);
-                                                    break;
-                                                }
-                                                nextMins -= p.WorkMinutes;
-                                            }
-                                        }
-                                        //记录生产周期
-                                        curSequences.Add(new PeriodSequenceDet
-                                        {
-                                            Domain = domain,
-                                            Line = lineStart.Line,
-                                            ItemNum = item.ItemNum,
-                                            PlanDate = beginTime.Date,
-                                            Period = dto.Period,
-                                            OrdQty = item.QtyOrded - item.QtyWorked,
-                                            WorkOrds = item.WorkOrd,
-                                            Op = item.Op,
-                                            IsActive = true,
-                                            Status = "",
-                                            CreateTime = DateTime.Now
-                                        });
-                                        //记录排产记录
-                                        curScheduleRsts.Add(new ScheduleResultOpMaster
-                                        {
-                                            Domain = domain,
-                                            WorkOrd = item.WorkOrd,
-                                            Line = lineStart.Line,
-                                            ItemNum = item.ItemNum,
-                                            Op = item.Op,
-                                            WorkDate = beginTime.Date,
-                                            WorkQty = item.QtyOrded - item.QtyWorked,
-                                            WorkStartTime = beginTime,
-                                            WorkEndTime = endTime,
-                                            CreateTime = DateTime.Now
-                                        });
-                                        //下一工单开始时间=当前工单结束时间,如果位于工作区间结尾,则为下一工作区间开始时间
-                                        curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
-                                        if (endTime == curPoint.EndPoint)//结束时间位于工作区间结尾
+                                        foreach (var item in workDtos)
                                         {
-                                            //获取后续生产时间段
-                                            var nextPoint = workPoints.Where(p => p.Level == curPoint.Level + 1).FirstOrDefault();
-                                            if (nextPoint != null)//存在后续工作区间
+                                            if (item.LbrVar == item.Worked)//当前工单已排产
                                             {
-                                                endTime = nextPoint.StartPoint;
+                                                continue;
                                             }
-                                        }
-                                        beginTime = endTime;
-                                        //工单排产完成,排产时长=工单工作时长
-                                        item.Worked = item.LbrVar;
-                                        item.QtyWorked = item.QtyOrded;
-                                        sumTsTimes -= needTime;
-                                    }
-                                    sumTsTimes = 0;//排产完毕,特殊工单时长置0
-                                }
-                                else//当天的可用产能不满足特殊工单生产时长
-                                {
-                                    foreach (var item in workDtos)
-                                    {
-                                        if (item.LbrVar == item.Worked)//当前工单已排产
-                                        {
-                                            continue;
-                                        }
-                                        //当前工单剩余待排产时长(分钟)
-                                        decimal needTime = item.LbrVar - item.Worked;
-                                        if (restTime >= needTime)//当天剩余产能满足当前工单的剩余待排产时长
-                                        {
+                                            //当前工单还需工作时长
+                                            decimal needTime = item.LbrVar - item.Worked;
                                             //计算工单排产结束时间
                                             var curPoint = workPoints.Find(p => p.StartPoint <= beginTime && beginTime <= p.EndPoint);
                                             span = curPoint.EndPoint - beginTime;
-                                            //当工作时间段的有效生产时间(分钟)
+                                            //当天工作时间段的有效生产时间(分钟)
                                             decimal effMins = (decimal)span.TotalMinutes;
                                             if (effMins >= needTime)//当前工作时间段即可满足产能
                                             {
@@ -2060,72 +1992,165 @@ namespace Business.ResourceExamineManagement
                                                 WorkEndTime = endTime,
                                                 CreateTime = DateTime.Now
                                             });
+                                            //下一工单开始时间=当前工单结束时间,如果位于工作区间结尾,则为下一工作区间开始时间
                                             curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
-                                            if (endTime == curPoint.EndPoint) 
+                                            if (endTime == curPoint.EndPoint)//结束时间位于工作区间结尾
                                             {
-                                                var nextPoint = workPoints.FirstOrDefault(p=>p.Level == curPoint.Level +1);
-                                                if (nextPoint != null)
+                                                //获取后续生产时间段
+                                                var nextPoint = workPoints.Where(p => p.Level == curPoint.Level + 1).FirstOrDefault();
+                                                if (nextPoint != null)//存在后续工作区间
                                                 {
                                                     endTime = nextPoint.StartPoint;
                                                 }
                                             }
                                             beginTime = endTime;
-                                            //当前工单已排产完成,已排产时间=工单生产时长,已排产数量=工单数量
+                                            //工单排产完成,排产时长=工单工作时长
                                             item.Worked = item.LbrVar;
-                                            item.QtyWorked = item.QtyWorked;
-                                            //当天剩余产能
-                                            restTime -= needTime;
-                                            if (restTime == 0)
-                                            {
-                                                break;
-                                            }
+                                            item.QtyWorked = item.QtyOrded;
+                                            sumTsTimes -= needTime;
                                         }
-                                        else//当天剩余产能不满足当前工单的剩余待排产时长
+                                        sumTsTimes = 0;//排产完毕,特殊工单时长置0
+                                    }
+                                    //当天的可用产能不满足特殊工单生产时长
+                                    else
+                                    {
+                                        foreach (var item in workDtos)
                                         {
-                                            //计算生产数量
-                                            decimal qty = Math.Ceiling(restTime / item.LbrVar * item.QtyOrded);
-                                            //记录生产周期
-                                            curSequences.Add(new PeriodSequenceDet
+                                            if (item.LbrVar == item.Worked)//当前工单已排产
                                             {
-                                                Domain = domain,
-                                                Line = lineStart.Line,
-                                                ItemNum = item.ItemNum,
-                                                PlanDate = beginTime.Date,
-                                                Period = dto.Period,
-                                                OrdQty = qty,
-                                                WorkOrds = item.WorkOrd,
-                                                Op = item.Op,
-                                                IsActive = true,
-                                                Status = "",
-                                                CreateTime = DateTime.Now
-                                            });
-                                            //记录排产记录
-                                            curScheduleRsts.Add(new ScheduleResultOpMaster
+                                                continue;
+                                            }
+                                            //当前工单剩余待排产时长(分钟)
+                                            decimal needTime = item.LbrVar - item.Worked;
+                                            //当天剩余产能满足当前工单的剩余待排产时长
+                                            if (restTime >= needTime)
                                             {
-                                                Domain = domain,
-                                                WorkOrd = item.WorkOrd,
-                                                Line = lineStart.Line,
-                                                ItemNum = item.ItemNum,
-                                                Op = item.Op,
-                                                WorkDate = beginTime.Date,
-                                                WorkQty = qty,
-                                                WorkStartTime = beginTime,
-                                                WorkEndTime = endTime,
-                                                CreateTime = DateTime.Now
-                                            });
-                                            item.Worked += restTime;
-                                            item.QtyWorked += qty;
-                                            break;
+                                                //计算工单排产结束时间
+                                                var curPoint = workPoints.Find(p => p.StartPoint <= beginTime && beginTime <= p.EndPoint);
+                                                span = curPoint.EndPoint - beginTime;
+                                                //当前工作时间段的有效生产时间(分钟)
+                                                decimal effMins = (decimal)span.TotalMinutes;
+                                                if (effMins >= needTime)//当前工作时间段即可满足产能
+                                                {
+                                                    endTime = beginTime.AddMinutes((double)needTime);
+                                                }
+                                                else
+                                                {
+                                                    //获取后续生产时间段
+                                                    var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).OrderBy(p => p.Level).ToList();
+                                                    //剩余需要工作时长
+                                                    decimal nextMins = needTime - effMins;
+                                                    foreach (var p in nextPoints)
+                                                    {
+                                                        if (p.WorkMinutes >= nextMins)
+                                                        {
+                                                            endTime = p.StartPoint.AddMinutes((double)nextMins);
+                                                            break;
+                                                        }
+                                                        nextMins -= p.WorkMinutes;
+                                                    }
+                                                }
+                                                //记录生产周期
+                                                curSequences.Add(new PeriodSequenceDet
+                                                {
+                                                    Domain = domain,
+                                                    Line = lineStart.Line,
+                                                    ItemNum = item.ItemNum,
+                                                    PlanDate = beginTime.Date,
+                                                    Period = dto.Period,
+                                                    OrdQty = item.QtyOrded - item.QtyWorked,
+                                                    WorkOrds = item.WorkOrd,
+                                                    Op = item.Op,
+                                                    IsActive = true,
+                                                    Status = "",
+                                                    CreateTime = DateTime.Now
+                                                });
+                                                //记录排产记录
+                                                curScheduleRsts.Add(new ScheduleResultOpMaster
+                                                {
+                                                    Domain = domain,
+                                                    WorkOrd = item.WorkOrd,
+                                                    Line = lineStart.Line,
+                                                    ItemNum = item.ItemNum,
+                                                    Op = item.Op,
+                                                    WorkDate = beginTime.Date,
+                                                    WorkQty = item.QtyOrded - item.QtyWorked,
+                                                    WorkStartTime = beginTime,
+                                                    WorkEndTime = endTime,
+                                                    CreateTime = DateTime.Now
+                                                });
+                                                curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
+                                                if (endTime == curPoint.EndPoint)
+                                                {
+                                                    var nextPoint = workPoints.FirstOrDefault(p => p.Level == curPoint.Level + 1);
+                                                    if (nextPoint != null)
+                                                    {
+                                                        endTime = nextPoint.StartPoint;
+                                                    }
+                                                }
+                                                beginTime = endTime;
+                                                //当前工单已排产完成,已排产时间=工单生产时长,已排产数量=工单数量
+                                                item.Worked = item.LbrVar;
+                                                item.QtyWorked = item.QtyWorked;
+                                                //当天剩余产能
+                                                restTime -= needTime;
+                                                if (restTime == 0)
+                                                {
+                                                    break;
+                                                }
+                                            }
+                                            else//当天剩余产能不满足当前工单的剩余待排产时长
+                                            {
+                                                //计算生产数量
+                                                decimal qty = Math.Ceiling(restTime / item.LbrVar * item.QtyOrded);
+                                                //记录生产周期
+                                                curSequences.Add(new PeriodSequenceDet
+                                                {
+                                                    Domain = domain,
+                                                    Line = lineStart.Line,
+                                                    ItemNum = item.ItemNum,
+                                                    PlanDate = beginTime.Date,
+                                                    Period = dto.Period,
+                                                    OrdQty = qty,
+                                                    WorkOrds = item.WorkOrd,
+                                                    Op = item.Op,
+                                                    IsActive = true,
+                                                    Status = "",
+                                                    CreateTime = DateTime.Now
+                                                });
+                                                //记录排产记录
+                                                curScheduleRsts.Add(new ScheduleResultOpMaster
+                                                {
+                                                    Domain = domain,
+                                                    WorkOrd = item.WorkOrd,
+                                                    Line = lineStart.Line,
+                                                    ItemNum = item.ItemNum,
+                                                    Op = item.Op,
+                                                    WorkDate = beginTime.Date,
+                                                    WorkQty = qty,
+                                                    WorkStartTime = beginTime,
+                                                    WorkEndTime = endTime,
+                                                    CreateTime = DateTime.Now
+                                                });
+                                                item.Worked += restTime;
+                                                item.QtyWorked += qty;
+                                                break;
+                                            }
                                         }
+                                        //特殊工单剩余待排产时长(分钟)
+                                        sumTsTimes -= restTime;
+                                        //获取下一个工作日
+                                        workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
+                                        isFstDay = false;
                                     }
-                                    //特殊工单剩余待排产时长(分钟)
-                                    sumTsTimes -= restTime;
-                                    //获取下一个工作日
+                                    #endregion 特殊工单排产-结束
+                                }
+                                else {
+                                    //继续排下一个工作日
                                     workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
                                     isFstDay = false;
                                 }
                             }
-                            #endregion 特殊工单排产-结束
                         }
                     }
                 }