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

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

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

+ 77 - 143
MicroServices/Business/Business.Application/ResourceExamineManagement/ProductionScheduleAppService.cs

@@ -8,11 +8,14 @@ using Business.StructuredDB.Production;
 using System;
 using System.Collections.Generic;
 using System.Collections.Immutable;
+using System.Configuration;
 using System.Linq;
 using System.Threading.Tasks;
 using System.Transactions;
 using Volo.Abp.Application.Services;
 using Volo.Abp.MultiTenancy;
+using Microsoft.Extensions.Configuration;
+using MongoDB.Driver.Linq;
 
 namespace Business.ResourceExamineManagement
 {
@@ -80,6 +83,10 @@ namespace Business.ResourceExamineManagement
         /// </summary>
         private ISqlRepository<ResourceOccupancyTime> _resourceOccupancyTime;
         /// <summary>
+        /// 加班设置表
+        /// </summary>
+        private ISqlRepository<GeneralizedCodeMaster> _generalizedCodeMaster;
+        /// <summary>
         /// 节假日记录表
         /// </summary>
         private ISqlRepository<HolidayMaster> _holidayMaster;
@@ -130,6 +137,7 @@ namespace Business.ResourceExamineManagement
             ISqlRepository<ShopCalendarWorkCtr> shopCalendarWorkCtr,
             ISqlRepository<QualityLineWorkDetail> qualityLineWorkDetail,
             ISqlRepository<HolidayMaster> holidayMaster,
+            ISqlRepository<GeneralizedCodeMaster> generalizedCodeMaster,
             ICurrentTenant currentTenant
             )
         {
@@ -146,6 +154,7 @@ namespace Business.ResourceExamineManagement
             _shopCalendarWorkCtr = shopCalendarWorkCtr;
             _qualityLineWorkDetail = qualityLineWorkDetail;
             _holidayMaster = holidayMaster;
+            _generalizedCodeMaster = generalizedCodeMaster;
             _currentTenant = currentTenant;
         }
         #endregion
@@ -155,8 +164,21 @@ namespace Business.ResourceExamineManagement
         /// </summary>
         public async void DoExt()
         {
-            List<WorkOrdMaster> workOrds = new List<WorkOrdMaster>();
-            domain = "1001";//定时任务跑资源检查,需要定义工厂id
+            //定时任务排产:获取工厂id
+            IConfiguration configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build();
+            domain = configuration.GetConnectionString("Factory_id");
+
+            //获取提前期
+            var generalizedCodeMaster = _generalizedCodeMaster.Select(x => x.FldName == "SystemConfig" && x.Val == "WorkOrderLockPeriod" && x.Domain == domain).FirstOrDefault();
+            decimal Udecil = 0;
+            if (generalizedCodeMaster != null)
+            {
+                Udecil = generalizedCodeMaster.UDeci1;
+            }
+            //排产取4周工单排产
+            DateTime dateTime = DateTime.Now.AddDays(30);
+            DateTime date = DateTime.Now.AddDays((double)Udecil);
+            var workOrds = _workOrdMaster.Select(x => x.IsActive && x.Domain == domain && x.OrdDate < dateTime && x.OrdDate > date && x.Status == "初始").ToList();
             await DoProductShcedule(workOrds, domain);
         }
 
@@ -168,30 +190,18 @@ namespace Business.ResourceExamineManagement
         /// <returns></returns>
         public async Task DoProductShcedule(List<WorkOrdMaster> workOrds, string factoryid)
         {
+            //记录工厂id
             domain = factoryid;
-            if (workOrds.Count == 0)//定时任务调用时,需要获取工单数据
-            {
-                //1、获取需要排产的工单:Status为空且IsActive==1
-                workOrds = _workOrdMaster.Select(p => string.IsNullOrEmpty(p.Status) && p.IsActive && p.Domain == domain);
-            }
             if (workOrds.Count == 0)//没有工单需要排产
             {
                 return;
             }
             //获取排产工单的最早计划开工日期
-            DateTime earlist;
-            if (workOrds.Min(p => p.OrdDate) == null)
-            {
-                earlist = DateTime.Now.Date.AddDays(7);
-            }
-            else
-            {
-                earlist = workOrds.Min(p => p.OrdDate.GetValueOrDefault()).Date;
-            }
+            DateTime earlist = workOrds.Min(p => p.OrdDate.GetValueOrDefault()).Date;
 
             //2、获取数据
             //获取工单工艺路径数据
-            List<WorkOrdRouting> workOrdRoutings = _workOrdRouting.Select(p => workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd) && p.Domain == domain && p.Status != "C" && p.IsActive);
+            List<WorkOrdRouting> workOrdRoutings = _workOrdRouting.Select(p => workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd) && p.ParentOp == 0 && p.Domain == domain && p.Status != "C" && p.IsActive);
             //获取物料对应的生产线信息:物料、工序对应的生产线
             List<ProdLineDetail> prodLines = _prodLineDetail.Select(p => workOrds.Select(m => m.ItemNum).Contains(p.Part) && p.Domain == domain && p.IsActive);
             List<string> lines = prodLines.Select(p => p.Line).ToList();
@@ -228,32 +238,39 @@ namespace Business.ResourceExamineManagement
                 //var curSchedules = dbSchedules.Where(p => curLines.Contains(p.Line)).ToList();
                 allResults.AddRange(scheduleMasters);
 
-                //工序预处理:确定每层级工序对应的产线
-                List<WorkOrdRoutingDto> routingDtos = ProcPretreatment(item, workOrdRoutings.Where(p => p.WorkOrd == item.WorkOrd).ToList(), prodLines, allResults);
-
-                //排产前的数据校验
-                if (routingDtos.Count == 0)//没有维护主工序
+                #region 校验
+                //工单工艺多产线关键工序、物料对应的生产线信息:物料,工序对应的生产线、工作日历数据
+                var workOrdRouting = workOrdRoutings.Where(x => x.WorkOrd == item.WorkOrd && x.ParentOp == 0).ToList();
+                if (workOrdRouting.Count == 0)
                 {
                     //记录排产异常原因
-                    new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的工序数据维护错误", _currentTenant.Id.ToString());
+                    new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的工单工艺流程数据维护为空", _currentTenant.Id.ToString());
                     continue;
                 }
-                //校验每层级工序是否都维护了产线
-                if (routingDtos.Exists(p => string.IsNullOrEmpty(p.Line)))
+                //TODO:多个关键工序校验
+
+                //物料对应生产线校验
+                var ProdLineDetails = prodLines.Where(x => x.Part == item.ItemNum).ToList();
+                if (ProdLineDetails.Count == 0)
                 {
                     //记录排产异常原因
-                    new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的产线数据维护错误", _currentTenant.Id.ToString());
+                    new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的生产线物料数据维护为空", _currentTenant.Id.ToString());
                     continue;
                 }
+                var calendarsList = calendars.Where(x => ProdLineDetails.Select(p => p.Line).Contains(x.ProdLine) || string.IsNullOrEmpty(x.ProdLine)).ToList();
                 //校验每个层级是否维护了工作日历
                 bool flag = false;
-                foreach (var rut in routingDtos)
+                foreach (var rut in ProdLineDetails)
                 {
-                    var lineCals = calendars.Where(p => p.ProdLine == rut.Line).ToList();
+                    var lineCals = calendarsList.Where(p => p.ProdLine == rut.Line).ToList();
                     //当前产线未配置工作日历取标准无产线工作日历使用
                     if (lineCals.Count == 0)
                     {
                         lineCals = calendars.Where(p => string.IsNullOrEmpty(p.ProdLine)).ToList();
+                        if (lineCals.Count == 0)
+                        {
+                            break;
+                        }
                     }
                     if (lineCals.Select(p => p.WeekDay).Distinct().Count() != 7)
                     {
@@ -264,9 +281,14 @@ namespace Business.ResourceExamineManagement
                 if (flag)
                 {
                     //记录排产异常原因
-                    new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的产线工作日历数据维护错误", _currentTenant.Id.ToString());
+                    new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的<" + item.ProdLine + ">工作日历数据维护错误", _currentTenant.Id.ToString());
                     continue;
                 }
+                #endregion
+
+
+                //计算当前物料排产开始产线
+                List<WorkOrdRoutingDto> routingDtos = ProcPretreatment(item, workOrdRoutings.Where(p => p.WorkOrd == item.WorkOrd).ToList(), prodLines, allResults);
 
                 //产线排产
                 LineSchedule(item, routingDtos.OrderBy(p => p.level).ToList(), periodSequenceDtls, scheduleMasters);
@@ -860,130 +882,42 @@ namespace Business.ResourceExamineManagement
         /// <returns></returns>
         public List<WorkOrdRoutingDto> ProcPretreatment(WorkOrdMaster workOrd, List<WorkOrdRouting> woRuntings, List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> schedules)
         {
-            #region 注释旧逻辑
-            //List<WorkOrdRoutingDto> routingDtos = new List<WorkOrdRoutingDto>();
-            ////当前工单计划开始时间(默认加两天)
-            //DateTime planStart = workOrd.OrdDate.GetValueOrDefault().AddDays(2);
-            ////取主工序(第一层级工序)
-            //var firsts = woRuntings.Where(p => p.ParentOp == 0).OrderByDescending(p => p.OP).ToList();
-            //if (firsts.Count == 0)
-            //{
-            //    return routingDtos;
-            //}
-            //WorkOrdRoutingDto dto = new WorkOrdRoutingDto();
-            ////主工序按照Op排序,取最大Op
-            //var lastOp = firsts.First();
-            //dto.ParentOp = lastOp.ParentOp;
-            //dto.level = 1;
-            //dto.Op = lastOp.OP;
-            //dto.ChdParentOps = new List<int>();
-            ////获取当前层级工序中有子级的工序集合
-            //var childs = woRuntings.Where(p => firsts.Select(m => m.OP).Contains(p.ParentOp)).Select(m => m.ParentOp).Distinct().ToList();
-            //if (childs.Count > 0)
-            //{
-            //    dto.ChdParentOps = childs;
-            //}
-            ////主工序对应的产线(目前只考虑一个产品对应一条产线的情况)
-            //var line = prodLines.Where(p => p.Part == lastOp.ItemNum && p.Op == lastOp.OP).FirstOrDefault();
-            //if (line != null)
-            //{
-            //    dto.Line = line.Line;
-            //    dto.Rate = line.Rate;
-            //    dto.SetupTime = 0;
-            //    //获取产线占用结束时间
-            //    var schedule = schedules.Where(p => p.Line == line.Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
-            //    dto.StartTime = schedule == null ? planStart : schedule.WorkEndTime <= planStart ? planStart : schedule.WorkEndTime;
-            //}
-            //routingDtos.Add(dto);
-
-            ////递归处理其他层级工序
-            //RecursionProc(woRuntings, firsts, 1, routingDtos, prodLines);
-            #endregion
-            #region 新逻辑
             List<WorkOrdRoutingDto> routingDtos = new List<WorkOrdRoutingDto>();
             //当前工单计划开始时间(默认加两天)
-            DateTime planStart = workOrd.OrdDate.GetValueOrDefault().AddDays(2);
-
-            var firsts = woRuntings.Where(x => x.WorkOrd == workOrd.WorkOrd && x.MilestoneOp).ToList();
+            DateTime planStart = workOrd.OrdDate.GetValueOrDefault();
+            //取主工序(第一层级工序)
+            var firsts = woRuntings.Where(p => p.ParentOp == 0 && p.MilestoneOp).OrderByDescending(p => p.OP).ToList();
             if (firsts.Count == 0)
             {
                 return routingDtos;
             }
-            foreach (var item in firsts)
+            WorkOrdRoutingDto dto = new WorkOrdRoutingDto();
+            //主工序按照Op排序,取最大Op
+            var lastOp = firsts.First();
+            dto.ParentOp = lastOp.ParentOp;
+            dto.level = 1;
+            dto.Op = lastOp.OP;
+            dto.ChdParentOps = new List<int>();
+            //获取当前层级工序中有子级的工序集合
+            var childs = woRuntings.Where(p => firsts.Select(m => m.OP).Contains(p.ParentOp)).Select(m => m.ParentOp).Distinct().ToList();
+            if (childs.Count > 0)
             {
-                //多产线处理
-                var line = prodLines.Where(p => p.Part == item.ItemNum && p.Op == item.OP).ToList();
-                foreach (var data in line)
-                {
-                    WorkOrdRoutingDto dto = new WorkOrdRoutingDto();
-                    dto.Line = data.Line;
-                    dto.Rate = data.Rate;
-                    dto.SetupTime = data.SetupTime;
-                    dto.sequence = data.Sequence;
-                    dto.Op = data.Op.Value;
-                    //获取产线占用结束时间
-                    var schedule = schedules.Where(p => p.Line == data.Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
-                    dto.StartTime = schedule == null ? planStart : schedule.WorkEndTime <= planStart ? planStart : schedule.WorkEndTime;
-                    routingDtos.Add(dto);
-                }
+                dto.ChdParentOps = childs;
             }
-            //多生产线优先级处理
-             //var 
-            //var Lines = routingDtos.GroupBy(x => x.Line);
-            //递归处理其他层级工序
-            //RecursionProc(woRuntings, firsts, 1, routingDtos, prodLines);
-            #endregion
-            return routingDtos;
-        }
-
-        /// <summary>
-        /// 递归处理工序
-        /// </summary>
-        /// <param name="woRuntings">工单工序</param>
-        /// <param name="preLevels">上-层级工序</param>
-        /// <param name="level">层级</param>
-        /// <param name="routingDtos">返回结果</param>
-        /// <param name="prodLines">产线</param>
-        public void RecursionProc(List<WorkOrdRouting> woRuntings, List<WorkOrdRouting> preLevels, int level, List<WorkOrdRoutingDto> routingDtos, List<ProdLineDetail> prodLines)
-        {
-            //获取当前层级工序
-            var curLevels = woRuntings.Where(p => preLevels.Select(m => m.OP).Contains(p.ParentOp)).ToList();
-            if (curLevels.Count == 0)
+            //主工序对应的产线(目前只考虑一个产品对应一条产线的情况)
+            var line = prodLines.Where(p => p.Part == lastOp.ItemNum && p.Op == lastOp.OP).FirstOrDefault();
+            if (line != null)
             {
-                return;
+                dto.Line = line.Line;
+                dto.Rate = line.Rate;
+                dto.SetupTime = 0;
+                //获取产线占用结束时间
+                var schedule = schedules.Where(p => p.Line == line.Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
+                dto.StartTime = schedule == null ? planStart : schedule.WorkEndTime <= planStart ? planStart : schedule.WorkEndTime;
             }
-            //获取父级Op-当前层级有几条子产线
-            var parentOps = curLevels.Select(m => m.ParentOp).Distinct().ToList();
-            foreach (var item in parentOps)
-            {
-                var dto = new WorkOrdRoutingDto();
-                var lastOp = curLevels.Where(p => p.ParentOp == item).OrderByDescending(m => m.OP).FirstOrDefault();
-                if (lastOp == null)
-                {
-                    continue;
-                }
-                dto.Op = lastOp.OP;
-                dto.ParentOp = lastOp.ParentOp;
-                dto.level = level + 1;
-                dto.ChdParentOps = new List<int>();
-                //获取当前层级工序中有子级的工序集合
-                var childs = woRuntings.Where(p => curLevels.Where(p => p.ParentOp == item).Select(m => m.OP).Contains(p.ParentOp)).Select(m => m.ParentOp).Distinct().ToList();
-                if (childs.Count > 0)
-                {
-                    dto.ChdParentOps = childs;
-                }
-                //当前层级工序对应的产线
-                var maxRateLine = prodLines.Where(p => p.Part == lastOp.ItemNum && p.Op == lastOp.OP).OrderByDescending(p => p.Rate).FirstOrDefault();
-                if (maxRateLine != null)
-                {
-                    dto.Line = maxRateLine.Line;
-                    dto.Rate = maxRateLine.Rate;
-                    dto.SetupTime = maxRateLine.SetupTime;
-                }
-                routingDtos.Add(dto);
-            }
-            //递归
-            RecursionProc(woRuntings, curLevels, level + 1, routingDtos, prodLines);
+            routingDtos.Add(dto);
+
+            return routingDtos;
         }
     }
 }

+ 2 - 2
MicroServices/Business/Business.Application/ResourceExamineManagement/ResourceExamineAppService.cs

@@ -2962,7 +2962,7 @@ namespace Business.ResourceExamineManagement
                 //优先级排序
                 workOrdMasters = workOrdMasters.OrderBy(s => s.OrdDate).ToList();
                 //排产
-                await _productionScheduleAppService.DoProductShcedule(workOrdMasters, param.factoryId.ToString());
+                //await _productionScheduleAppService.DoProductShcedule(workOrdMasters, param.factoryId.ToString());
                 
                 foreach (var wod in workOrdMasters)
                 {
@@ -3544,7 +3544,7 @@ namespace Business.ResourceExamineManagement
                 return "当前工单已排产,无需重新排产。";
             }
             //排产
-            await _productionScheduleAppService.DoProductShcedule(workOrdMasters, workOrdMasters[0].Domain);
+            //await _productionScheduleAppService.DoProductShcedule(workOrdMasters, workOrdMasters[0].Domain);
             //AutoCreatePickBill(workOrdMasters.Select(p => p.WorkOrd).ToList());
             return "ok";
         }

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

@@ -40,7 +40,7 @@ namespace Business.Domain
         public string ItemNum { get; set; }
 
         /// <summary>
-        /// 计划日期
+        /// 计划日期开始日期
         /// </summary>
         [Comment("计划日期")]
         public DateTime? PlanDate { get; set; }

+ 2 - 1
MicroServices/Business/Business.Host/appsettings.json

@@ -17,7 +17,8 @@
     "DOPLog": "Server=123.60.180.165;Database=dopbiz;uid=sa;pwd=5h3n9)uN;Trusted_Connection=false;TrustServerCertificate=True",
     "DOPBang": "Server=123.60.180.165;Database=dopbiz;uid=sa;pwd=5h3n9)uN;Trusted_Connection=false;TrustServerCertificate=True",
     "DOPExt": "Server=123.60.180.165;Database=dopbiz;uid=sa;pwd=5h3n9)uN;Trusted_Connection=false;TrustServerCertificate=True",
-    "MongoDB": "mongodb://zzydop:h1Q$us3r@123.60.180.165/dopbase"
+    "MongoDB": "mongodb://zzydop:h1Q$us3r@123.60.180.165/dopbase",
+    "Factory_id": "1001"
   },
   "Redis": {
     "Configuration": "192.168.1.191"