Procházet zdrojové kódy

特殊工单独立产线排产调整

heteng před 2 roky
rodič
revize
dfcc63a985

+ 5 - 0
MicroServices/Business/Business.Application.Contracts/Dto/LineStartDto.cs

@@ -45,5 +45,10 @@ namespace Business.Dto
         /// 产线UPH
         /// </summary>
         public decimal Rate { get; set; }
+
+        /// <summary>
+        /// 工序剩余待排产数量
+        /// </summary>
+        public decimal QtyRemain { get; set; }
     }
 }

+ 2 - 2
MicroServices/Business/Business.Application.Contracts/Dto/WorkOrdMstDto.cs

@@ -62,8 +62,8 @@ namespace Business.Dto
         public decimal WaitTime { get; set; }
 
         /// <summary>
-        /// 工单计划开始时间
+        /// 工单优先级
         /// </summary>
-        public DateTime PlanDate { get; set; }
+        public decimal Priority { get; set; }
     }
 }

+ 125 - 73
MicroServices/Business/Business.Application/ResourceExamineManagement/ProductionScheduleAppService.cs

@@ -19,6 +19,7 @@ using MongoDB.Driver.Linq;
 using Amazon.Runtime.Internal.Util;
 using IdentityModel.Client;
 using Amazon.Runtime;
+using Magicodes.ExporterAndImporter.Core.Extension;
 
 namespace Business.ResourceExamineManagement
 {
@@ -192,15 +193,12 @@ namespace Business.ResourceExamineManagement
             IConfiguration configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build();
             domain = configuration.GetConnectionString("Factory_id");
 
-            //获取排产锁定期
-            var generalizedCodeMaster = _generalizedCodeMaster.Select(p => p.FldName == "SystemConfig" && p.Val == "WorkOrderLockPeriod" && p.Domain == domain && p.IsActive).FirstOrDefault();
-            decimal lockDays = generalizedCodeMaster != null ? generalizedCodeMaster.UDeci1 : 0;
-            
             //获取需要排产的工单(获取四周的工单:正常工单+已审批通过的特殊工单)
             DateTime endDate = DateTime.Now.Date.AddDays(28).AddDays(1);
-            //取数开始时间需要排除掉锁定期内的工单
-            DateTime startDate = DateTime.Now.Date.AddDays(1).AddDays((double)lockDays);
-            var workOrds = _workOrdMaster.Select(p => p.IsActive && p.Domain == domain && p.OrdDate < endDate && p.OrdDate >= startDate && string.IsNullOrEmpty(p.Status) && (string.IsNullOrEmpty(p.Typed) || (!string.IsNullOrEmpty(p.Typed) && p.BusinessID >0 ))).ToList();
+            //取数开始时间为当前天的下一天
+            DateTime startDate = DateTime.Now.Date.AddDays(1);
+            //尚未开始生产的工单+正在生产的工单
+            var workOrds = _workOrdMaster.Select(p => p.IsActive && p.Domain == domain && ((p.OrdDate < endDate && p.OrdDate >= startDate && (string.IsNullOrEmpty(p.Typed) || (!string.IsNullOrEmpty(p.Typed) && p.BusinessID >0 ))) || p.Status.ToLower() == "w")).ToList();
             await DoProductSchedule(workOrds, domain, 1);
         }
 
@@ -242,11 +240,11 @@ namespace Business.ResourceExamineManagement
             List<PeriodSequenceDet> dbPeriodSequences = _periodSequenceDet.Select(p => lines.Contains(p.Line) && p.PlanDate >= earlist && p.Domain == domain && p.IsActive);
             //获取当前日期往后的排产记录数据
             List<ScheduleResultOpMaster> dbSchedules = _scheduleResultOpMaster.Select(p => lines.Contains(p.Line) && p.WorkDate >= earlist && p.Domain == domain);
-            //获取锁定期之外的工单排产数据
-            List<PeriodSequenceDet> delPeriodSequences = dbPeriodSequences.Where(p => workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrds)).ToList();
-            List<ScheduleResultOpMaster> delSchedules = dbSchedules.Where(p => workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd)).ToList();
-            //产线占用记录排除锁定期之前的工单
-            dbSchedules = dbSchedules.Where(p => !workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd)).ToList();
+            ////获取锁定期之外的工单排产数据
+            //List<PeriodSequenceDet> delPeriodSequences = dbPeriodSequences.Where(p => workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrds)).ToList();
+            //List<ScheduleResultOpMaster> delSchedules = dbSchedules.Where(p => workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd)).ToList();
+            ////产线占用记录排除锁定期之前的工单
+            //dbSchedules = dbSchedules.Where(p => !workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd)).ToList();
             //获取工作日历数据:产线的工作日历+默认的工作日历
             calendars = _shopCalendarWorkCtr.Select(p => (lines.Contains(p.ProdLine) || string.IsNullOrEmpty(p.ProdLine)) && p.Domain == domain && p.IsActive);
             //获取产线休息记录数据
@@ -280,11 +278,13 @@ namespace Business.ResourceExamineManagement
             List<PeriodSequenceDet> periodSequenceDtls = new List<PeriodSequenceDet>();
             //排产记录表
             List<ScheduleResultOpMaster> scheduleMasters = new List<ScheduleResultOpMaster>();
-            //排产结果
+            //记录排产结果
             List<ScheduleResultOpMaster> allResults = new List<ScheduleResultOpMaster>();
-            allResults.AddRange(dbSchedules);
+            //allResults.AddRange(dbSchedules);
             //记录特殊工单排产结果
             List<string> ypcWorkOrds = new List<string>();
+            //按照优先级排序
+            zcWorkOrds = zcWorkOrds.OrderBy(p=>p.Priority).ToList();
             foreach (var item in zcWorkOrds)
             {
                 //记录产线占用情况
@@ -310,14 +310,29 @@ namespace Business.ResourceExamineManagement
             foreach (var item in notSchedules)
             {
                 var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
+                //剩余排产数量
+                decimal qtyNeed = item.QtyOrded - curOp.QtyComplete;
+                //剩余工作时长(分钟)
+                decimal usedTime = Math.Ceiling(qtyNeed / item.QtyOrded * item.LbrVar * 60);
+                //特殊工单排产开始时间
+                DateTime startTime = item.OrdDate.GetValueOrDefault();
+                //如果当前特殊工单正在生产,则开工日期为当天的下一个工作日
+                if (item.Status.ToLower() == "w" && item.JointTyped.ToUpper() != "B")
+                {
+                    DateTime nowDate = DateTime.Now.Date;
+                    //当前产线的工作日历
+                    var mLCalendars = calendars.Where(p => p.ProdLine == item.ProdLine || string.IsNullOrEmpty(p.ProdLine)).ToList();
+                    //获取下一个工作日
+                    startTime = GetNextWorkDay((int)nowDate.DayOfWeek, nowDate, mLCalendars);
+                }
                 workDtos.Add(new WorkOrdMstDto
                 {
                     WorkOrd = item.WorkOrd,
                     ItemNum = item.ItemNum,
-                    QtyOrded = item.QtyOrded,
-                    OrdDate = item.OrdDate.GetValueOrDefault(),
+                    QtyOrded = qtyNeed,
+                    OrdDate = startTime,
                     ProdLine = item.ProdLine,
-                    LbrVar = item.LbrVar * 60,
+                    LbrVar = usedTime,
                     Worked = 0,
                     QtyWorked = 0,
                     Op = curOp.OP,
@@ -341,9 +356,9 @@ namespace Business.ResourceExamineManagement
                 {
                     //更新工单计划开工时间、计划结束时间
                     _workOrdMaster.Update(workOrds);
-                    //删除锁定期之外的工单排产记录
-                    _periodSequenceDet.Delete(delPeriodSequences);
-                    _scheduleResultOpMaster.Delete(delSchedules);
+                    //删除当前日期下一天开始的工单排产记录
+                    _periodSequenceDet.Delete(dbPeriodSequences);
+                    _scheduleResultOpMaster.Delete(dbSchedules);
                     //保存排产记录
                     _periodSequenceDet.Insert(periodSequenceDtls);
                     _scheduleResultOpMaster.Insert(scheduleMasters);
@@ -545,22 +560,27 @@ namespace Business.ResourceExamineManagement
             List<ScheduleResultOpMaster> curScheduleRsts = new List<ScheduleResultOpMaster>();
             //记录上一产线排产开始时间
             LineStartDto lineStart = new LineStartDto();
+            //产线开工时间默认为当前日期的下一天
+            lineStart.StartTime = DateTime.Now.Date.AddDays(1);
             TimeSpan span = TimeSpan.Zero;
             //第一层级工序有几个关键工序,就有几条产线
             for (int i = 0; i < workOrdRoutings.Count; i++)
             {
+                //如果当前工序已经生产完成,则跳过
+                if (workOrdRoutings[i].QtyComplete == workOrd.QtyOrded)
+                {
+                    continue;
+                }
                 //产线实际排产开始时间
                 if (i == 0)//第一条产线
                 {
-                    lineStart = DealStartTime(workOrd, workOrdRoutings[i].OP, prodLines, allResults);
+                    lineStart = DealStartTime(workOrd, workOrdRoutings[i], prodLines, allResults);
                 }
                 else
                 {
                     //获取前一产线排产开始时间,通过提前期计算当前产线排产开始时间
-                    lineStart = DealNextStartTime(workOrd, lineStart, workOrdRoutings[i].OP, prodLines, allResults);
+                    lineStart = DealNextStartTime(workOrd, lineStart, workOrdRoutings[i], prodLines, allResults);
                 }
-                //添加关键工序清场时长
-                lineStart.WaitTime = workOrdRoutings[i].WaitTime * 60;
                 //当前产线的工作日历
                 var mLCalendars = calendars.Where(p => p.ProdLine == lineStart.Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
                 //当前产线的休息时间设置
@@ -568,7 +588,7 @@ namespace Business.ResourceExamineManagement
                 //产线排产开始时间
                 DateTime workStartTime = lineStart.StartTime;
                 //记录特殊工单:获取第一天是否有特殊工单
-                List<WorkOrdMaster> fstWOMasters = tsWorkOrds.Where(p => p.ProdLine == lineStart.Line && p.OrdDate.Value.Date == workStartTime.Date).OrderBy(p => p.OrdDate).ToList();
+                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>();
                 //记录排产开始第二天及以后安排的特殊工单
                 var secWOMasters = new List<WorkOrdMaster>();
@@ -578,31 +598,35 @@ namespace Business.ResourceExamineManagement
                 decimal lstCleanTime = 0m;
                 //新增特殊工单最后一个清场时长
                 decimal secCleanTime = 0m;
+                //特殊工单排产需要考虑的时长
+                decimal sumTsTimes = 0m;
                 if (fstWOMasters.Any())
                 {
                     foreach (var item in fstWOMasters)
                     {
                         var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
+                        //计算已完成耗时(分钟)
+                        decimal usedTime = Math.Ceiling(curOp.QtyComplete / item.QtyOrded * item.LbrVar * 60);
                         workDtos.Add(new WorkOrdMstDto
                         {
                             WorkOrd = item.WorkOrd,
                             ItemNum = item.ItemNum,
-                            QtyOrded = item.QtyOrded,
-                            LbrVar = item.LbrVar * 60,
+                            QtyOrded = item.QtyOrded - curOp.QtyComplete,
+                            LbrVar = item.LbrVar * 60 - usedTime,
                             Worked = 0,
                             QtyWorked = 0,
                             Op = curOp.OP,
                             WaitTime = curOp.WaitTime * 60,
-                            PlanDate = item.OrdDate.Value
+                            Priority = item.Priority
                         });
                         sumCleanTimes += curOp.WaitTime * 60;
                     }
                     //获取最后一个特殊工单的清场时长
                     var last = fstWOMasters.Last();
                     lstCleanTime = tsWoRoutings.Where(p => p.WorkOrd == last.WorkOrd).OrderByDescending(p => p.OP).First().WaitTime * 60;
+                    //特殊工单排产需要考虑的时长=特殊工单工作时长(分钟)+除最后一个特殊工单之外的清场时长
+                    sumTsTimes = workDtos.Sum(p => p.LbrVar) + sumCleanTimes - lstCleanTime;
                 }
-                //特殊工单排产需要考虑的时长=特殊工单工作时长(分钟)+除最后一个特殊工单之外的清场时长
-                decimal sumTsTimes = fstWOMasters.Sum(p => p.LbrVar) * 60 + sumCleanTimes - lstCleanTime;
                 //工单排产第一天标识
                 bool isFstDay = true;
                 //产线排产开始当天安排了特殊工单,则先安排特殊工单
@@ -622,40 +646,45 @@ namespace Business.ResourceExamineManagement
                     if (dto.EffTime > sumTsTimes && !isFstDay)
                     {
                         //获取特殊工单
-                        secWOMasters = tsWorkOrds.Where(p => p.ProdLine == lineStart.Line && p.OrdDate.Value.Date == workStartTime.Date).OrderBy(p => p.OrdDate).ToList();
+                        secWOMasters = tsWorkOrds.Where(p => p.ProdLine == lineStart.Line && p.OrdDate.Value.Date == workStartTime.Date).OrderBy(p => p.Priority).ToList();
                         if (secWOMasters.Any())
                         {
                             sumCleanTimes = 0m;
                             //新增特殊工单最后一个清场时长
                             secCleanTime = 0m;
+                            //生产时长
+                            decimal sumLbrVar = 0m;
                             //记录新增待排产特殊工单
                             foreach (var item in secWOMasters)
                             {
                                 var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
+                                //计算已完成数量耗时(分钟)
+                                decimal usedTime = Math.Ceiling(curOp.QtyComplete / item.QtyOrded * item.LbrVar * 60);
                                 workDtos.Add(new WorkOrdMstDto
                                 {
                                     WorkOrd = item.WorkOrd,
                                     ItemNum = item.ItemNum,
-                                    QtyOrded = item.QtyOrded,
-                                    LbrVar = item.LbrVar * 60,
+                                    QtyOrded = item.QtyOrded - curOp.QtyComplete,
+                                    LbrVar = item.LbrVar * 60 - usedTime,
                                     Worked = 0,
                                     QtyWorked = 0,
                                     Op = curOp.OP,
                                     WaitTime = curOp.WaitTime * 60,
-                                    PlanDate = item.OrdDate.Value
+                                    Priority = item.Priority
                                 });
+                                sumLbrVar += item.QtyOrded - curOp.QtyComplete;
                                 sumCleanTimes += curOp.WaitTime * 60;
                             }
                             //获取最后一个特殊工单的清场时长
                             var last = secWOMasters.Last();
                             secCleanTime = tsWoRoutings.Where(p => p.WorkOrd == last.WorkOrd).OrderByDescending(p => p.OP).First().WaitTime * 60;
                             //特殊工单待排产时长=前一天特殊工单到最后一个清场时长+新增的特殊工单生产时长+新增特殊工单除最后一个清场时长之外的清场时长之和
-                            sumTsTimes += (lstCleanTime + secWOMasters.Sum(p => p.LbrVar) * 60 + sumCleanTimes - secCleanTime);
+                            sumTsTimes += (lstCleanTime + sumLbrVar + sumCleanTimes - secCleanTime);
                             lstCleanTime = secCleanTime;
                         }
                     }
                     //特殊工单排序
-                    workDtos = workDtos.OrderBy(p => p.PlanDate).ToList();
+                    workDtos = workDtos.OrderBy(p => p.Priority).ToList();
                     //当天的可用生产时长满足特殊工单生产时长+清场时间(最后一个工单清场时间除外)
                     if (dto.EffTime >= sumTsTimes)
                     {
@@ -803,27 +832,31 @@ namespace Business.ResourceExamineManagement
                             workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
                             isFstDay = true;
                             //特殊工单排产完成,占用了当天的全部产能,则需要判断下一个工作日是否存在特殊工单,如果存在,则需要继续排特殊工单
-                            secWOMasters = tsWorkOrds.Where(p => p.ProdLine == lineStart.Line && p.OrdDate.Value.Date == workStartTime.Date).OrderBy(p => p.OrdDate).ToList();
+                            secWOMasters = tsWorkOrds.Where(p => p.ProdLine == lineStart.Line && p.OrdDate.Value.Date == workStartTime.Date).OrderBy(p => p.Priority).ToList();
                             //记录新增待排产特殊工单
                             if (secWOMasters.Any())
                             {
                                 sumCleanTimes = 0m;
                                 //新增特殊工单最后一个清场时长(分钟)
                                 secCleanTime = 0m;
+                                //生产时长
+                                decimal sumLbrVar = 0m;
                                 foreach (var item in secWOMasters)
                                 {
                                     var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
+                                    //计算已完成数量耗时(分钟)
+                                    decimal usedTime = Math.Ceiling(curOp.QtyComplete / item.QtyOrded * item.LbrVar * 60);
                                     workDtos.Add(new WorkOrdMstDto
                                     {
                                         WorkOrd = item.WorkOrd,
                                         ItemNum = item.ItemNum,
-                                        QtyOrded = item.QtyOrded,
-                                        LbrVar = item.LbrVar * 60,
+                                        QtyOrded = item.QtyOrded - curOp.QtyComplete,
+                                        LbrVar = item.LbrVar * 60 - usedTime,
                                         Worked = 0,
                                         QtyWorked = 0,
                                         Op = curOp.OP,
                                         WaitTime = curOp.WaitTime * 60,
-                                        PlanDate = item.OrdDate.Value
+                                        Priority = item.Priority
                                     });
                                     sumCleanTimes += curOp.WaitTime * 60;
                                 }
@@ -831,7 +864,7 @@ namespace Business.ResourceExamineManagement
                                 var last = secWOMasters.Last();
                                 secCleanTime = tsWoRoutings.Where(p => p.WorkOrd == last.WorkOrd).OrderByDescending(p => p.OP).First().WaitTime * 60;
                                 //特殊工单待排产时长=前一天特殊工单到最后一个清场时长+新增的特殊工单生产时长+新增特殊工单除最后一个清场时长之外的清场时长之和
-                                sumTsTimes += (lstCleanTime + secWOMasters.Sum(p => p.LbrVar) * 60 + sumCleanTimes - secCleanTime);
+                                sumTsTimes += (lstCleanTime + sumLbrVar + sumCleanTimes - secCleanTime);
                                 lstCleanTime = secCleanTime;
                             }
                         }
@@ -1047,7 +1080,7 @@ namespace Business.ResourceExamineManagement
                 isFstDay = true;
                 //前一天是否有特殊工单未排产完全
                 bool isFullPC = true;
-                while (sumQty < workOrd.QtyOrded || sumTsTimes > 0)
+                while (sumQty < lineStart.QtyRemain || sumTsTimes > 0)
                 {
                     secWOMasters.Clear();
                     sumCleanTimes = 0m;
@@ -1065,31 +1098,36 @@ namespace Business.ResourceExamineManagement
                     if (!isFstDay)
                     {
                         //获取特殊工单
-                        secWOMasters = tsWorkOrds.Where(p => p.ProdLine == lineStart.Line && p.OrdDate.Value.Date == workStartTime.Date).OrderBy(p => p.OrdDate).ToList();
+                        secWOMasters = tsWorkOrds.Where(p => p.ProdLine == lineStart.Line && p.OrdDate.Value.Date == workStartTime.Date).OrderBy(p => p.Priority).ToList();
                         if (secWOMasters.Any())
                         {
+                            //生产时长
+                            decimal sumLbrVar = 0m;
                             foreach (var item in secWOMasters)
                             {
                                 var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
+                                //计算已完成数量耗时(分钟)
+                                decimal usedTime = Math.Ceiling(curOp.QtyComplete / item.QtyOrded * item.LbrVar * 60);
                                 workDtos.Add(new WorkOrdMstDto
                                 {
                                     WorkOrd = item.WorkOrd,
                                     ItemNum = item.ItemNum,
-                                    QtyOrded = item.QtyOrded,
-                                    LbrVar = item.LbrVar * 60,
+                                    QtyOrded = item.QtyOrded - curOp.QtyComplete,
+                                    LbrVar = item.LbrVar * 60 - usedTime,
                                     Worked = 0,
                                     QtyWorked = 0,
                                     Op = curOp.OP,
                                     WaitTime = curOp.WaitTime * 60,
-                                    PlanDate = item.OrdDate.Value
+                                    Priority = item.Priority
                                 });
+                                sumLbrVar += item.LbrVar * 60 - usedTime;
                                 sumCleanTimes += curOp.WaitTime * 60;
                             }
                             //获取最后一个特殊工单的清场时长
                             var last = secWOMasters.Last();
                             secCleanTime = tsWoRoutings.Where(p => p.WorkOrd == last.WorkOrd).OrderByDescending(p => p.OP).First().WaitTime * 60;
                             //特殊工单待排产时长=前一天特殊工单到最后一个清场时长+新增的特殊工单生产时长+新增特殊工单除最后一个清场时长之外的清场时长之和
-                            sumTsTimes += (lstCleanTime + secWOMasters.Sum(p => p.LbrVar) * 60 + sumCleanTimes - secCleanTime);
+                            sumTsTimes += (lstCleanTime + sumLbrVar + sumCleanTimes - secCleanTime);
                             lstCleanTime = secCleanTime;
                         }
                     }
@@ -1106,14 +1144,14 @@ namespace Business.ResourceExamineManagement
                             //2、如果是排产中间日期,则先安排特殊工单排产
                             //当天剩余产能
                             decimal sumAmount = Math.Floor(dto.Rate * residueTime / 60);
-                            //已排产数量+当天的剩余产能小于工单数量,当天的产能需要全部排产
-                            if (sumQty + sumAmount < workOrd.QtyOrded)
+                            //已排产数量+当天的剩余产能小于工单剩余需排产数量,当天的产能需要全部排产
+                            if (sumQty + sumAmount < lineStart.QtyRemain)
                             {
                                 //当天有特殊工单,且当天的产能不能满足工单剩余需排产数量,则优先排特殊工单
                                 if (sumTsTimes > 0)
                                 {
                                     //特殊工单排序
-                                    workDtos = workDtos.OrderBy(p => p.PlanDate).ToList();
+                                    workDtos = workDtos.OrderBy(p => p.Priority).ToList();
                                     DateTime beginTime = workStartTime;//排产开始时间
                                     DateTime endTime = dto.EndTime;//排产结束时间
                                     //当天的可用生产时长满足特殊工单生产时长+清场时长(最后一个特殊工单的清场时长除外)
@@ -1533,7 +1571,7 @@ namespace Business.ResourceExamineManagement
                             {
                                 #region 正常工单排产-开始
                                 //剩余需要排产的数量
-                                decimal residueQty = workOrd.QtyOrded - sumQty;
+                                decimal residueQty = lineStart.QtyRemain - sumQty;
                                 //剩余数量生产需要时长(分钟)
                                 decimal workTime = Math.Ceiling(residueQty / dto.Rate * 60);
                                 //处理工作时长:防止相上取整导致时间大于剩余可用时长
@@ -1565,8 +1603,8 @@ namespace Business.ResourceExamineManagement
                                         nextMins -= p.WorkMinutes;
                                     }
                                 }
-                                //工单排产完成,已排产数量=工单数量
-                                sumQty = workOrd.QtyOrded;
+                                //工单排产完成,已排产数量=工单需排产数量数量
+                                sumQty = lineStart.QtyRemain;
                                 //当天剩余可用生产时长
                                 residueTime -= workTime;
                                 //处理清场时间,两种场景:
@@ -1648,7 +1686,7 @@ namespace Business.ResourceExamineManagement
                                 //当天存在特殊工单
                                 if (sumTsTimes > 0)
                                 {
-                                    workDtos = workDtos.OrderBy(p => p.PlanDate).ToList();
+                                    workDtos = workDtos.OrderBy(p => p.Priority).ToList();
                                     //当天剩余生产时长大于0,特殊工单排产
                                     if (restTime > 0)
                                     {
@@ -2025,7 +2063,7 @@ namespace Business.ResourceExamineManagement
                             decimal residueTime = dto.EffTime;
                             DateTime beginTime = workStartTime;//排产开始时间
                             DateTime endTime = dto.EndTime;//排产结束时间
-                            workDtos = workDtos.OrderBy(p => p.PlanDate).ToList();
+                            workDtos = workDtos.OrderBy(p => p.Priority).ToList();
                             //当天的可用生产时长满足特殊工单生产时长+清场时长(最后一个工单清场时间除外)
                             if (residueTime >= sumTsTimes)
                             {
@@ -2176,13 +2214,13 @@ namespace Business.ResourceExamineManagement
                                 //剩余可用生产时长
                                 residueTime = residueTime < 0 ? 0 : residueTime;
                                 //特殊工单处理完成,剩余生产时长大于0且还有正常工单待排产,则继续排正常工单
-                                if (residueTime > 0 && sumQty < workOrd.QtyOrded)
+                                if (residueTime > 0 && sumQty < lineStart.QtyRemain)
                                 {
                                     workStartTime = beginTime;//排产开始时间
                                     //剩余产能继续排正常工单
                                     decimal sumAmount = Math.Floor(dto.Rate * residueTime / 60);
                                     //如果剩余产能不能满足正常工单,剩余产能全部排产
-                                    if (sumQty + sumAmount < workOrd.QtyOrded)
+                                    if (sumQty + sumAmount < lineStart.QtyRemain)
                                     {
                                         //记录生产周期
                                         curSequences.Add(new PeriodSequenceDet
@@ -2223,7 +2261,7 @@ namespace Business.ResourceExamineManagement
                                     else
                                     {
                                         //剩余需要排产的数量
-                                        decimal residueQty = workOrd.QtyOrded - sumQty;
+                                        decimal residueQty = lineStart.QtyRemain - sumQty;
                                         //剩余数量生产需要时长(分钟)
                                         decimal workTime = Math.Ceiling(residueQty / dto.Rate * 60);
                                         //处理剩余需要生产时长:防止向上取整导致超过residueTime
@@ -2254,7 +2292,7 @@ namespace Business.ResourceExamineManagement
                                             }
                                         }
                                         //工单排产完成,已排产数量=工单数量
-                                        sumQty = workOrd.QtyOrded;
+                                        sumQty = lineStart.QtyRemain;
 
                                         //剩余可用生产时长
                                         residueTime = (residueTime - workTime) < 0 ? 0 : (residueTime - workTime);
@@ -2531,7 +2569,7 @@ namespace Business.ResourceExamineManagement
                         //当天之前的特殊工单全部排产完毕
                         else {
                             //已排产数量+当天的产能小于工单数量,当天的产能需要全部排产
-                            if (sumQty + dto.ProductQty < workOrd.QtyOrded)
+                            if (sumQty + dto.ProductQty < lineStart.QtyRemain)
                             {
                                 //当天有特殊工单,先排特殊工单
                                 if (sumTsTimes > 0)
@@ -2540,7 +2578,7 @@ namespace Business.ResourceExamineManagement
                                     decimal residueTime = dto.EffTime;
                                     DateTime beginTime = workStartTime;//排产开始时间
                                     DateTime endTime = dto.EndTime;//排产结束时间
-                                    workDtos = workDtos.OrderBy(p => p.PlanDate).ToList();
+                                    workDtos = workDtos.OrderBy(p => p.Priority).ToList();
                                     //当天的可用产能满足特殊工单生产时长+清场时长(最后一个工单清场时间除外)
                                     if (residueTime >= sumTsTimes)
                                     {
@@ -2963,11 +3001,11 @@ namespace Business.ResourceExamineManagement
                                 //正常工单生产时长
                                 decimal workTime = 0m;
                                 DateTime workEndTime = workStartTime;
-                                if (sumQty < workOrd.QtyOrded)
+                                if (sumQty < lineStart.QtyRemain)
                                 {
                                     #region 正常工单排产-开始
                                     //剩余需要排产的数量
-                                    decimal residueQty = workOrd.QtyOrded - sumQty;
+                                    decimal residueQty = lineStart.QtyRemain - sumQty;
                                     //剩余数量生产需要时长(分钟)
                                     workTime = Math.Ceiling(residueQty / dto.Rate * 60);
                                     //处理需要生产时长
@@ -2998,7 +3036,7 @@ namespace Business.ResourceExamineManagement
                                         }
                                     }
                                     //工单排产完成,已排产数量=工单数量
-                                    sumQty = workOrd.QtyOrded;
+                                    sumQty = lineStart.QtyRemain;
                                     //剩余可用生产时长
                                     residueTime = (residueTime - workTime) < 0 ? 0 : (residueTime - workTime);
                                     //处理清场时间,两种场景:
@@ -3094,7 +3132,7 @@ namespace Business.ResourceExamineManagement
                                         #region 特殊工单排产-开始
                                         DateTime beginTime = workStartTime;//排产开始时间
                                         DateTime endTime = dto.EndTime;//排产结束时间
-                                        workDtos = workDtos.OrderBy(p => p.PlanDate).ToList();
+                                        workDtos = workDtos.OrderBy(p => p.Priority).ToList();
                                         //当天的可用产能满足特殊工单生产时长+清场时长(最后一个工单清场时间除外)
                                         if (residueTime >= sumTsTimes)
                                         {
@@ -3679,12 +3717,13 @@ namespace Business.ResourceExamineManagement
         /// 计算主产线实际排产开始时间
         /// </summary>
         /// <param name="workOrd">工单</param>
-        /// <param name="op">工序</param>
+        /// <param name="routing">工序</param>
         /// <param name="prodLines">生产线明细</param>
         /// <param name="allResults">产线占用记录</param>
         /// <returns></returns>
-        public LineStartDto DealStartTime(WorkOrdMaster workOrd,int op,List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults)
+        public LineStartDto DealStartTime(WorkOrdMaster workOrd,WorkOrdRouting routing,List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults)
         {
+            int op = routing.OP;
             DateTime actStart = DateTime.Now.Date.AddDays(1);
             LineStartDto lineStart = new LineStartDto();
             //获取工序对应的产线,根据优先级排序
@@ -3702,7 +3741,6 @@ namespace Business.ResourceExamineManagement
             lineStart.StartTime = actStart;
             lineStart.setupTime = lines[0].SetupTime;
             lineStart.Rate = lines[0].Rate;
-            lineStart.Op = op;
             //循环其他产线
             for (int i = 1; i < lines.Count; i++)
             {
@@ -3720,9 +3758,16 @@ namespace Business.ResourceExamineManagement
                     lineStart.StartTime = StartTime;
                     lineStart.setupTime = lines[i].SetupTime;
                     lineStart.Rate = lines[i].Rate;
-                    lineStart.Op = op;
                 }
             }
+            //如果当前工单正在排产,且是连续排产时,重新排产不需要考虑产线准备时间
+            if (workOrd.Status.ToLower() == "w" && workOrd.JointTyped.ToUpper() !="B")
+            {
+                lineStart.setupTime = 0m;
+            }
+            lineStart.Op = op;
+            lineStart.WaitTime = routing.WaitTime * 60;
+            lineStart.QtyRemain = workOrd.QtyOrded - routing.QtyComplete;
             return lineStart;
         }
 
@@ -3869,12 +3914,13 @@ namespace Business.ResourceExamineManagement
         /// </summary>
         /// <param name="workOrd">工单</param>
         /// <param name="lineStart">上一产线开始时间</param>
-        /// <param name="op">工序</param>
+        /// <param name="routing">工序</param>
         /// <param name="prodLines">产线明细</param>
         /// <param name="allResults">产线占用记录</param>
         /// <returns></returns>
-        public LineStartDto DealNextStartTime(WorkOrdMaster workOrd,LineStartDto lineStart,int op, List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults)
+        public LineStartDto DealNextStartTime(WorkOrdMaster workOrd,LineStartDto lineStart,WorkOrdRouting routing, List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults)
         {
+            int op = routing.OP;
             LineStartDto startDto = new LineStartDto();
             //获取产线
             var lines = prodLines.Where(p => p.Part == workOrd.ItemNum && p.Op == op).OrderBy(p=>p.Sequence).ToList();
@@ -3886,7 +3932,6 @@ namespace Business.ResourceExamineManagement
             startDto.setupTime = lines[0].SetupTime;
             startDto.StartTime = schedule == null ? startTime : (startTime < schedule.WorkEndTime ? schedule.WorkEndTime : startTime);
             startDto.Rate = lines[0].Rate;
-            startDto.Op = op;
             //循环剩余产线,找到最早可开工产线
             for (int i = 1; i < lines.Count(); i++)
             {
@@ -3900,9 +3945,16 @@ namespace Business.ResourceExamineManagement
                     startDto.setupTime = lines[i].SetupTime;
                     startDto.StartTime = startTime;
                     startDto.Rate = lines[i].Rate;
-                    startDto.Op = op;
                 }
             }
+            //如果当前工单正在排产,且是连续排产时,重新排产不需要考虑产线准备时间
+            if (workOrd.Status.ToLower() == "w" && workOrd.JointTyped.ToUpper() != "B")
+            {
+                startDto.setupTime = 0m;
+            }
+            startDto.Op = op;
+            startDto.WaitTime = routing.WaitTime * 60;
+            startDto.QtyRemain = workOrd.QtyOrded - routing.QtyComplete;
             return startDto;
         }
 

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

@@ -129,6 +129,12 @@ namespace Business.Domain
         [Comment("生产时长")]
         public decimal LbrVar { get; set; }
 
+        /// <summary>
+        /// 正在生产的工单重新排产是否需要考虑产线准备时间:A-连续生产不需要考虑;B-日计划日期调整需要考虑
+        /// </summary>
+        [Comment("生产时长")]
+        public string JointTyped { get; set; }
+
         /// <summary>
         /// 流程id
         /// </summary>

+ 1 - 1
MicroServices/Business/Business.Domain/StructuredDB/Production/WorkOrdRouting.cs

@@ -84,7 +84,7 @@ namespace Business.Domain
         /// 报工数量
         /// </summary>
         [Comment("报工数量")]
-        public decimal? QtyComplete { get; set; }
+        public decimal QtyComplete { get; set; }
         
 
         /// <summary>