Ver código fonte

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

Murphy 2 anos atrás
pai
commit
087324b670
20 arquivos alterados com 770 adições e 256 exclusões
  1. 5 0
      MicroServices/Business/Business.Application.Contracts/Dto/LineStartDto.cs
  2. 2 2
      MicroServices/Business/Business.Application.Contracts/Dto/WorkOrdMstDto.cs
  3. 13 3
      MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/Dto/BomChildExamineDto.cs
  4. 37 0
      MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/Dto/PrPurchaseDto.cs
  5. 5 0
      MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/Dto/ProdExamineParamDto.cs
  6. 1 1
      MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/Dto/SRMPRDto.cs
  7. 3 3
      MicroServices/Business/Business.Application/ReplenishmentManagement/ReplenishmentAppService.cs
  8. 388 119
      MicroServices/Business/Business.Application/ResourceExamineManagement/CalcBomViewAppService.cs
  9. 5 14
      MicroServices/Business/Business.Application/ResourceExamineManagement/MorderAppService.cs
  10. 5 0
      MicroServices/Business/Business.Application/ResourceExamineManagement/PretreatmentAppService.cs
  11. 20 0
      MicroServices/Business/Business.Application/ResourceExamineManagement/ProductExamineAppService.cs
  12. 196 74
      MicroServices/Business/Business.Application/ResourceExamineManagement/ProductionScheduleAppService.cs
  13. 3 2
      MicroServices/Business/Business.Application/ResourceExamineManagement/PurchaseOrderAppService.cs
  14. 44 36
      MicroServices/Business/Business.Application/ResourceExamineManagement/ResourceExamineAppService.cs
  15. 12 0
      MicroServices/Business/Business.Domain/StructuredDB/Bang/b_bom_pretreatment.cs
  16. 5 0
      MicroServices/Business/Business.Domain/StructuredDB/MES/IC/NbrDetail.cs
  17. 1 1
      MicroServices/Business/Business.Domain/StructuredDB/MES/IC/NbrMaster.cs
  18. 12 0
      MicroServices/Business/Business.Domain/StructuredDB/Production/WorkOrdDetail.cs
  19. 6 0
      MicroServices/Business/Business.Domain/StructuredDB/Production/WorkOrdMaster.cs
  20. 7 1
      MicroServices/Business/Business.Domain/StructuredDB/Production/WorkOrdRouting.cs

+ 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; }
     }
 }

+ 13 - 3
MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/Dto/BomChildExamineDto.cs

@@ -197,12 +197,12 @@ namespace Business.ResourceExamineManagement.Dto
         public DateTime? satisfy_time { get; set; }
 
         /// <summary>
-        /// 自制时长(天)
+        /// 生产准备提前期
         /// </summary>
         public int? make_time { get; set; }
 
         /// <summary>
-        /// 采购前置(需加上自制)
+        /// 供应欠缺时间
         /// </summary>
         public int? pre_time { get; set; }
 
@@ -247,7 +247,7 @@ namespace Business.ResourceExamineManagement.Dto
         public int substitute_mode { get; set; }
 
         /// <summary>
-        /// 物料状态-- -1.无需求 0.缺料 1.充足 2.可制,时间满足 3.可制,时间不满足 4.采购 5.委外
+        /// 物料状态-- -1.无需求 0.缺料 1.充足 2.可制,时间满足 3.可制,时间不满足 4.采购 5.委外 99,无货源清单
         /// </summary>
         public int stock_state { get; set; }
 
@@ -265,6 +265,16 @@ namespace Business.ResourceExamineManagement.Dto
         /// 工序
         /// </summary>
         public int Op { get; set; }
+
+        /// <summary>
+        /// 物料前处理天数
+        /// </summary>
+        public decimal? clean_leadtime { get; set; }
+
+        /// <summary>
+        /// 供应提前期
+        /// </summary>
+        public int PurLT { get; set; }
     }
 
     /// <summary>

+ 37 - 0
MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/Dto/PrPurchaseDto.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Business.ResourceExamineManagement.Dto
+{
+    public class PrPurchaseDto
+    {
+        /// <summary>
+        /// 供应商id
+        /// </summary>
+        public long? pr_purchaseid { get; set; }
+
+        /// <summary>
+        /// 数量
+        /// </summary>
+        public decimal num { get; set; }
+
+        /// <summary>
+        /// 占比
+        /// </summary>
+        public decimal ratio { get; set; }
+
+        /// <summary>
+        /// 优先级
+        /// </summary>
+        public int quota_priority { get; set; }
+
+        /// <summary>
+        /// 配额比例
+        /// </summary>
+        public decimal quota_rate { get; set; }
+
+    }
+}

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

@@ -25,5 +25,10 @@ namespace Business.ResourceExamineManagement.Dto
         /// 计划开始时间
         /// </summary>
         public DateTime PlanStart { get; set; }
+
+        /// <summary>
+        /// 工厂ID
+        /// </summary>
+        public string Domain { get; set; }
     }
 }

+ 1 - 1
MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/Dto/SRMPRDto.cs

@@ -28,7 +28,7 @@ namespace Business.ResourceExamineManagement.Dto
         /// <summary>
         /// 总共提前期
         /// </summary>
-        public decimal? totalLeadTime { get; set; }
+        public int? totalLeadTime { get; set; }
 
         /// <summary>
         /// 订单价格(含税)

+ 3 - 3
MicroServices/Business/Business.Application/ReplenishmentManagement/ReplenishmentAppService.cs

@@ -1602,7 +1602,7 @@ namespace Business.Replenishment
                 _CalcBomViewAppService.BomStock(getBomList, stocklist, bangid);
 
                 //计算
-                _CalcBomViewAppService.CalcView(getBomList, bangid, item.need_number.GetValueOrDefault(), item.start_time, sklist, sentry, item.urgent, icitemlist);
+                _CalcBomViewAppService.CalcView(getBomList, bangid, item.need_number.GetValueOrDefault(), item.start_time, sklist, sentry, icitemlist);
 
                 //TODO:最晚开始时间
                 var curFacDtl = leadTimeList.FirstOrDefault(p => p.item_id == childBom.icitem_id);
@@ -1660,7 +1660,7 @@ namespace Business.Replenishment
                     morder.moentry_sys_etime = wod.DueDate;
 
                     /*var exa = rtn.examines.Find(s => s.morder_no == wod.WorkOrd);
-                    exa.latest_times = morder.moentry_sys_etime.GetValueOrDefault().Date.AddDays(1);*/
+                    exa.latest_times = morder.moentry_sys_etime.GetValueOrDefault().Date.AddDays(1);
                     //根据排产后得日期,反推PR。
                     var wkordPrList = prmainlist.Where(s => s.pr_mono == wod.WorkOrd).ToList();
 
@@ -1678,7 +1678,7 @@ namespace Business.Replenishment
                         {
                             pr.pr_ssend_date = DateTime.Now.Date.AddDays(1);
                         }
-                    });
+                    });*/
                 }
                 using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
                 {

+ 388 - 119
MicroServices/Business/Business.Application/ResourceExamineManagement/CalcBomViewAppService.cs

@@ -2,11 +2,14 @@
 using Business.Core.Utilities;
 using Business.Domain;
 using Business.ResourceExamineManagement.Dto;
+using MathNet.Numerics.RootFinding;
 using MongoDB.Driver.Linq;
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
 using Volo.Abp.Application.Services;
+using static Spire.Pdf.General.Render.Decode.Jpeg2000.j2k.codestream.HeaderInfo;
 
 namespace Business.ResourceExamineManagement
 {
@@ -40,6 +43,20 @@ namespace Business.ResourceExamineManagement
         public crm_seorder seorder = new crm_seorder();
 
         public mes_morder mes_morder = new mes_morder();
+        public List<mo_srm_pr_main> quarter_srm_pr_mains = new List<mo_srm_pr_main>();
+
+        public DateTime quarter_starttime;
+        public DateTime quarter_endtime;
+
+        /// <summary>
+        /// 是否倒排
+        /// </summary>
+        public bool IsInverted = false;
+
+        /// <summary>
+        /// 工单类型
+        /// </summary>
+        public string morder_type;
 
         SnowFlake help = new SnowFlake();
 
@@ -139,7 +156,7 @@ namespace Business.ResourceExamineManagement
         /// <param name="plan_date"></param>
         /// <param name="checkflag">是否生成工单、委外、采购</param>
         public void CalcView(List<BomChildExamineDto> returnlist, long bangid, decimal count, DateTime
-            ? plan_date, List<mo_ic_item_stockoccupy> sklist, crm_seorderentry sentrys,int urgent, List<mo_ic_item> icitemlist)
+            ? plan_date, List<mo_ic_item_stockoccupy> sklist, crm_seorderentry sentrys, List<mo_ic_item> icitemlist)
         {
             ProductionTimeDay = 0;
             //第一级
@@ -254,12 +271,20 @@ namespace Business.ResourceExamineManagement
                     //先设定在制的齐套时间
                     //level1Dto.satisfy_time = mooccupylist[0]?.moo_etime;
                     level1Dto.stock_state = 0;
-
                     if (param.checkflag || (!param.checkflag && param.checkPlan))
                     {
+                        ProdExamineParamDto prodExamine = new ProdExamineParamDto()
+                        {
+                            ItemNum = level1Dto.item_number,
+                            PlanStart = plan_date.GetValueOrDefault(),
+                            QtyOrd = level1Dto.lack_qty,
+                            Domain = param.factoryId.ToString()
+                        };
+                        int make_time = _productExamineAppService.ProductTime(prodExamine);
                         //根据成品属性来判断是自制还是委外还是外购,需要考虑这种场景
                         if (level1Dto.erp_cls == 1 && param.checkflag)
                         {
+                            //设置成品的生产时长为子物料的提前准备期
                             //param.checkflag=true 销售订单产生工单
                             level1Dto.make_qty = level1Dto.lack_qty;
                             //生成主工单
@@ -272,12 +297,12 @@ namespace Business.ResourceExamineManagement
                                 version = level1Dto.version,
                                 number = level1Dto.item_number,
                                 Quantity = level1Dto.lack_qty,
-                                morder_type = MorderEnum.XsMorder,
+                                morder_type = morder_type,
                                 work_order_type = MorderEnum.CgMorder,
                                 morder_state = MorderEnum.Initial_state,
                                 bang_id = bangid
                             };
-                            CreateMainOrder(generateMorderDto, level1Dto, childList, returnlist, bangid, plan_date, sklist, sentrys, urgent, icitemlist);
+                            CreateMainOrder(generateMorderDto, level1Dto, childList, returnlist, bangid, plan_date, sklist, sentrys, icitemlist, make_time);
                         }
                         else if (level1Dto.erp_cls == 3)
                         {
@@ -290,7 +315,7 @@ namespace Business.ResourceExamineManagement
                                 {
                                     level1Dto.lack_qty = level1Dto.lack_qty - itemPRQty;
                                     //采购申请
-                                    PackageSRMPR(level1Dto, bangid, sentrys);
+                                    PackageSRMPR(level1Dto, bangid, sentrys, plan_date);
                                 }
                             }
                         }
@@ -300,14 +325,18 @@ namespace Business.ResourceExamineManagement
                             CalcInTransit(sentrys, level1Dto, bangid, plan_date.GetValueOrDefault());
                             if (level1Dto.lack_qty > 0)
                             {
+                                //1.先生成委外工单。
+                                var mesorder = CreateMesOOder(level1Dto, param.company_id, param.factoryId, bangid, leadTimeList, supplierList, plan_date.Value);
+                                mesorder.ooentry_etime = plan_date.GetValueOrDefault().AddDays(-1);
+                                var srmprDto = PackageSRMPR(level1Dto, bangid, sentrys, plan_date);
+                                mesorder.ooentry_stime = plan_date.GetValueOrDefault().AddDays(-srmprDto.totalLeadTime.GetValueOrDefault());
+
                                 //先计算末级数据的齐套时间。
                                 if (childList.Count > 0)
                                 {
                                     MatterTileDevelop(level1Dto, childList, returnlist, sklist, bangid, plan_date, sentrys, icitemlist);
-                                    level1Dto.kitting_time = childList.Max(s => s.kitting_time);
+                                    level1Dto.kitting_time = childList.Max(s => s.kitting_time).GetValueOrDefault().AddDays(srmprDto.totalLeadTime.GetValueOrDefault());//加上物料的采购提前期
                                 }
-                                //1.先生成委外工单。
-                                var mesorder = CreateMesOOder(level1Dto, param.company_id, param.factoryId, bangid, leadTimeList, supplierList, plan_date.Value);
 
                                 //2.生成采购申请
                                 //采购申请
@@ -316,7 +345,7 @@ namespace Business.ResourceExamineManagement
                                 {
                                     level1Dto.lack_qty = level1Dto.lack_qty - itemPRQty;
                                     //采购申请
-                                    PackageSRMPR(level1Dto, bangid, sentrys);
+                                    PackageSRMPR(level1Dto, bangid, sentrys, plan_date);
                                 }
                                 //PackageSRMPR(level1Dto, bangid, sentrys);
 
@@ -329,7 +358,7 @@ namespace Business.ResourceExamineManagement
                                 oo.production_unit_code = mesorder.production_unit_code;
                                 oo.ooentry_prdname = mesorder.ooentry_prdname;
                                 oo.ooentry_stime = mesorder.ooentry_stime;
-                                oo.ooentry_etime = level1Dto.kitting_time;
+                                oo.ooentry_etime = mesorder.ooentry_etime;
                                 oo.oorder_date = mesorder.oorder_date;
                                 oo.oorder_no = mesorder.oorder_no;
                                 level1Dto.subcontracting_list.Add(oo);
@@ -344,7 +373,7 @@ namespace Business.ResourceExamineManagement
                     else {
                         MatterTileDevelop(level1Dto, childList, returnlist, sklist, bangid, plan_date, sentrys, icitemlist);
                     }
-                    CalcLevelMakeTime(returnlist);
+                    //CalcLevelMakeTime(returnlist);
                 }
             }
             else
@@ -358,7 +387,7 @@ namespace Business.ResourceExamineManagement
             }
         }
 
-        //计算每层物料倒排时,需要根据半成品的工作时长倒排。
+        /*//计算每层物料倒排时,需要根据半成品的工作时长倒排。
         public void CalcLevelMakeTime(List<BomChildExamineDto> returnlist)
         {
             for (int level = 3; level <= returnlist.Max(s => s.level); level++)
@@ -372,14 +401,14 @@ namespace Business.ResourceExamineManagement
                     }
                 });
             }
-        }
+        }*/
 
 
         /// <summary>
         /// 生成主工单
         /// </summary>
         public void CreateMainOrder(GenerateMorderDto generateMorderDto, BomChildExamineDto level1Dto, List<BomChildExamineDto> childList, List<BomChildExamineDto> returnlist, long bangid, DateTime
-            ? plan_date, List<mo_ic_item_stockoccupy> sklist, crm_seorderentry sentrys,int urgent, List<mo_ic_item> icitemlist)
+            ? plan_date, List<mo_ic_item_stockoccupy> sklist, crm_seorderentry sentrys, List<mo_ic_item> icitemlist,int make_time)
         {
             //生成主工单
             _morderAppService.prodLines = prodLines;
@@ -389,7 +418,7 @@ namespace Business.ResourceExamineManagement
             _morderAppService.qualityLineWorks = qualityLineWorks;
             _morderAppService.holidays = holidays;
             _morderAppService.param = param;
-            Mes_MorderDto mes_MorderDto = _morderAppService.GenerateMorder(generateMorderDto, urgent);
+            Mes_MorderDto mes_MorderDto = _morderAppService.GenerateMorder(generateMorderDto);
             //这里更新产品得满足时间。
             if (mes_MorderDto != null)
             {
@@ -398,12 +427,24 @@ namespace Business.ResourceExamineManagement
                 if (mes_Morders != null)
                 {
                     mes_morder = ObjectMapper.Map<mo_mes_morder, mes_morder>(mes_Morders);
-                    MatterTileDevelop(level1Dto, childList, returnlist, sklist, bangid, plan_date, sentrys, icitemlist);
+                    var plan = icitemlist.Find(x => x.mysql_id == level1Dto.item_id);
+                    //结束日期=开始时间+生产时长+自检提前期+入库提前期+发运提前期;
+                    decimal LeadTime = 0;
+                    if (plan != null)
+                    {
+                        //减去提前期
+                        LeadTime = plan.self_inspection_date.GetValueOrDefault() + plan.Warehousing_date.GetValueOrDefault() + plan.Shipping_date.GetValueOrDefault();
+                    }
+                    mes_Morders.moentry_sys_etime = plan_date.GetValueOrDefault().AddDays(-(int)Math.Floor(LeadTime));
+
+                    mes_Morders.moentry_sys_stime = mes_Morders.moentry_sys_etime.GetValueOrDefault().AddDays(-(make_time - 1));
+                    MatterTileDevelop(level1Dto, childList, returnlist, sklist, bangid, mes_Morders.moentry_sys_stime, sentrys, icitemlist);
                     if (!string.IsNullOrEmpty(mes_Morders.bom_number))
                     {
-                        mes_Morders.moentry_sys_stime = childList.Max(s => s.kitting_time.GetValueOrDefault()).AddDays(1).Date;//数据齐套完成后隔天开始生产;
-                        //var ProductiveDate = ProductiveExamine(mes_Morders.bom_number, level1Dto.version, (int)mes_Morders.morder_production_number.Value);
-                        ProdExamineParamDto prodExamine = new ProdExamineParamDto()
+                        mes_Morders.mat_start_date = childList.Max(s => s.kitting_time.GetValueOrDefault()).AddDays(1).Date;//数据齐套完成后隔天开始生产;
+                        mes_Morders.mat_end_date = mes_Morders.mat_start_date.GetValueOrDefault().AddDays(make_time);
+
+                        /*ProdExamineParamDto prodExamine = new ProdExamineParamDto()
                         {
                             ItemNum = mes_Morders.bom_number,
                             PlanStart = mes_Morders.moentry_sys_stime.Value,
@@ -416,28 +457,15 @@ namespace Business.ResourceExamineManagement
                         _productExamineAppService.qualityLineWorks = qualityLineWorks;
                         _productExamineAppService.holidays = holidays;
 
-                        var plan = icitemlist.Find(x => x.mysql_id == level1Dto.item_id);
+                        
                         var ProductiveDate = _productExamineAppService.ProductiveExamine(prodExamine);
-                        //var Day = ProductiveDate / (60 * 10); //返回的分钟除以十个小时得出工作天数;
 
-                        //结束日期=开始时间+生产时长+自检提前期+入库提前期+发运提前期;
-                        DateTime LeadTime;
-                        if (plan != null)
-                        {
-                            var TQdate = plan.self_inspection_date.GetValueOrDefault() + plan.Warehousing_date.GetValueOrDefault()+ plan.Shipping_date.GetValueOrDefault();
-                            LeadTime = ProductiveDate.AddDays((double)TQdate);
-                        }
-                        else
-                        {
-                            LeadTime = ProductiveDate;
-                        }
-                        //ProductionTimeDay = LeadTime;
                         mes_Morders.moentry_sys_etime = LeadTime;
                         TimeSpan span = ProductiveDate - mes_Morders.moentry_sys_stime.Value;
-                        mes_Morders.morder_need_time = (decimal)span.TotalMinutes;
+                        mes_Morders.morder_need_time = (decimal)span.TotalMinutes;*/
 
                         //满足资源检查的时间需加上提前期
-                        level1Dto.satisfy_time = LeadTime;
+                        level1Dto.satisfy_time = mes_Morders.moentry_sys_etime;
                         if (sentrys != null)
                         {
                             sentrys.sys_capacity_date = level1Dto.satisfy_time;
@@ -645,6 +673,7 @@ namespace Business.ResourceExamineManagement
             var parent = returnlist.Find(s => s.fid == item.parent_id);
             if (item.lack_qty > 0)
             {
+                //item.make_time = parent.make_time.GetValueOrDefault();
                 var cilList = returnlist.Where(s => s.parent_id == item.fid && s.type == item.type).OrderBy(k => k.num_order).ToList();
                 //如果缺料,占用库存,然后走采购或自制
                 if (item.sqty > 0)
@@ -656,22 +685,33 @@ namespace Business.ResourceExamineManagement
                 item.use_qty = item.sqty;
                 if (item.erp_cls == 1)
                 {
-                    /*var ic_item = icitemlist.Find(s => s.Id == item.item_id);
-                    var mooccupylist = _morderAppService.CheckMorder(item.bom_number, item.lack_qty, plan_date.GetValueOrDefault(), sentrys, ic_item).Result;
+                    var ic_item = icitemlist.Find(s => s.mysql_id == item.item_id);
+                    List<mo_mes_mooccupy> mooccupylist = new List<mo_mes_mooccupy>();
+                    if (param.checkflag)
+                    {
+                        mooccupylist = _morderAppService.CheckMorder(item.bom_number, item.lack_qty, plan_date.GetValueOrDefault(), sentrys, ic_item, bangid);
+                    }  
                     decimal moo_qty = mooccupylist.Sum(s => s.moo_qty.GetValueOrDefault());
                     item.mo_qty = moo_qty;
-                    item.mo_occupy_list = new List<mo_occupy>();
-                    mooccupylist.ForEach(s =>
+                    
+                    if (mooccupylist.Any())
                     {
-                        mo_occupy mooc = new mo_occupy();
-                        mooc.moo_mo = s.moo_mo;
-                        mooc.moo_stime = s.moo_ctime;
-                        mooc.moo_etime = s.moo_etime;
-                        mooc.moo_qty = s.moo_qty;
-                        item.mo_occupy_list.Add(mooc);
-                    });*/
-                    decimal moo_qty = 0;
-                    if (moo_qty == returnlist[0].lack_qty)
+                        mooccupyAllList.AddRange(mooccupylist);
+                        mooccupyAllInsertList.AddRange(mooccupylist);
+                        //在制占用明细
+                        item.mo_occupy_list = new List<mo_occupy>();
+                        mooccupylist.ForEach(s =>
+                        {
+                            mo_occupy mooc = new mo_occupy();
+                            mooc.id = s.Id;
+                            mooc.moo_mo = s.moo_mo;
+                            mooc.moo_stime = s.moo_ctime;
+                            mooc.moo_etime = s.moo_etime;
+                            mooc.moo_qty = s.moo_qty;
+                            item.mo_occupy_list.Add(mooc);
+                        });
+                    }
+                    if (moo_qty == item.lack_qty)
                     {
                         //在制完全足够
                         item.lack_qty = 0;
@@ -683,17 +723,78 @@ namespace Business.ResourceExamineManagement
                     {
                         item.lack_qty -= moo_qty;
                         item.kitting_time = DateTime.Now;
-                        //先计算末级数据的齐套时间。
-                        if (cilList.Count > 0)
+                        //TODO:需要按标准UPH来计算生产时长
+                        //生成主工单
+                        GenerateMorderDto generateMorderDto = new GenerateMorderDto()
                         {
-                            CalcIcitem(cilList, returnlist, bangid, sklist, plan_date, icitemlist, sentrys, childidList);
-                            
-                            item.kitting_time = cilList.Max(s => s.kitting_time);
-                        }
+                            seorderentry = sentrys,
+                            seorder = seorder,
+                            ic_Item = ic_item,
+                            BomNumber = item.bom_number,
+                            version = item.version,
+                            number = item.item_number,
+                            Quantity = item.lack_qty,
+                            morder_type = morder_type,
+                            work_order_type = MorderEnum.CgMorder,
+                            morder_state = MorderEnum.Initial_state,
+                            bang_id = bangid
+                        };
+                        Mes_MorderDto mes_MorderDto = _morderAppService.GenerateMorder(generateMorderDto);
+                        ProdExamineParamDto prodExamine = new ProdExamineParamDto()
+                        {
+                            ItemNum = item.item_number,
+                            PlanStart = plan_date.GetValueOrDefault(),
+                            QtyOrd = item.lack_qty,
+                            Domain = param.factoryId.ToString()
+                        };
+                        int make = _productExamineAppService.ProductTime(prodExamine);
                         item.make_qty = item.lack_qty;
-                        //默认中间件需要1天的制造周期
-                        item.make_time = 1;
-                        item.kitting_time = item.kitting_time.Value.AddDays(1);
+                        if (mes_MorderDto != null)
+                        {
+                            //主工单最后计算满足日期
+                            var mes_Morders = mes_MorderDto.mes_Morders.Where(x => x.parent_id == null).FirstOrDefault();
+                            if (mes_Morders != null)
+                            {
+                                //子工单生成的检查明细,还是挂接到主工单上。
+                                mes_Morders.moentry_sys_etime = plan_date.GetValueOrDefault().AddDays(-1);
+                                mes_Morders.moentry_sys_stime = mes_Morders.moentry_sys_etime.GetValueOrDefault().AddDays(-(make - 1));
+                                item.make_list = new List<moorder>();
+                                mes_MorderDto.mes_Morders.ForEach(me =>
+                                {
+                                    moorder mo = new moorder();
+                                    mo.Id = me.Id;
+                                    mo.moentry_stime = me.moentry_stime;
+                                    mo.moentry_etime = me.moentry_etime;
+                                    mo.moentry_wrkcname = me.moentry_wrkcname;
+                                    mo.moentry_sys_stime = me.moentry_sys_stime;
+                                    mo.moentry_sys_etime = me.moentry_sys_etime;
+                                    mo.moentry_prdname = me.moentry_prdname;
+                                    mo.morder_need_time = me.morder_need_time;
+                                    mo.morder_no = me.morder_no;
+                                    mo.morder_production_number = me.morder_production_number;
+                                    mo.need_number = me.need_number;
+                                    mo.reality_end_time = me.reality_end_time;
+                                    mo.reality_start_time = me.reality_start_time;
+                                    item.make_list.Add(mo);
+                                });
+                                //批量保存 后期考虑子工单
+                                mordersList.AddRange(mes_MorderDto.mes_Morders);
+                                mordersInsertList.AddRange(mes_MorderDto.mes_Morders);
+                                moentriesList.AddRange(mes_MorderDto.mes_Moentries);
+                                moentriesInsertList.AddRange(mes_MorderDto.mes_Moentries);
+                                //先计算末级数据的齐套时间。
+                                if (cilList.Count > 0)
+                                {
+                                    CalcIcitem(cilList, returnlist, bangid, sklist, mes_Morders.moentry_sys_stime, icitemlist, sentrys, childidList);
+
+                                    item.kitting_time = cilList.Max(s => s.kitting_time);
+                                }
+                                mes_Morders.mat_start_date = item.kitting_time.GetValueOrDefault().AddDays(1).Date;//数据齐套完成后隔天开始生产;
+                                mes_Morders.mat_end_date = mes_Morders.mat_start_date.GetValueOrDefault().AddDays(make);
+                                item.kitting_time = mes_Morders.mat_end_date;
+                            }
+                        }
+                        
                         /*//走自制
                         ProdExamineParamDto prodExamine = new ProdExamineParamDto()
                         {
@@ -728,29 +829,30 @@ namespace Business.ResourceExamineManagement
                         if (item.lack_qty > 0)
                         {
                             //采购申请
-                            PackageSRMPR(item, bangid, sentrys);
+                            PackageSRMPR(item, bangid, sentrys, plan_date);
                         }
                     }
                 }
                 else if (item.erp_cls == 2)
                 {
+
                     if (param.checkflag || param.checkPlan)
                     {
                         //先找在途
                         CalcInTransit(sentrys, item, bangid, plan_date.GetValueOrDefault());
                         if (item.lack_qty > 0)
                         {
+                            //1.先生成委外工单。
+                            var mesorder = CreateMesOOder(item, param.company_id, param.factoryId, bangid, leadTimeList, supplierList, plan_date.GetValueOrDefault());
+                            mesorder.ooentry_etime = plan_date.GetValueOrDefault().AddDays(-1);
+                            var srmprDto = PackageSRMPR(item, bangid, sentrys, plan_date);
+                            mesorder.ooentry_stime = mesorder.ooentry_etime.GetValueOrDefault().AddDays(-(srmprDto.totalLeadTime.GetValueOrDefault() - 1));
                             //先计算末级数据的齐套时间。
                             if (cilList.Count > 0)
                             {
-                                CalcIcitem(cilList, returnlist, bangid, sklist, plan_date, icitemlist, sentrys, childidList);
-                                item.kitting_time = cilList.Max(s => s.kitting_time);
+                                CalcIcitem(cilList, returnlist, bangid, sklist, mesorder.ooentry_stime, icitemlist, sentrys, childidList);
+                                item.kitting_time = cilList.Max(s => s.kitting_time).GetValueOrDefault().AddDays(srmprDto.totalLeadTime.GetValueOrDefault());//加上物料的采购提前期
                             }
-                            //1.先生成委外工单。
-                            var mesorder = CreateMesOOder(item, param.company_id, param.factoryId, bangid, leadTimeList, supplierList, plan_date.Value);
-                            //2.生成采购申请
-                            //采购申请
-                            PackageSRMPR(item, bangid, sentrys);
                             item.subcontracting_qty = item.lack_qty;
                             item.subcontracting_list = new List<ooder>();
                             ooder oo = new ooder();
@@ -1114,36 +1216,117 @@ namespace Business.ResourceExamineManagement
 
                         if (sct.erp_cls == 1)
                         {
-                            //先计算末级数据的齐套时间。
-                            if (cilList.Count > 0)
+                            var ic_item = icitemlist.Find(s => s.mysql_id == sct.item_id);
+                            List<mo_mes_mooccupy> mooccupylist = new List<mo_mes_mooccupy>();
+                            if (param.checkflag)
                             {
-                                CalcIcitem(cilList, returnlist, bangid, sklist, plan_date, icitemlist, sentrys, childidList);
-                                sct.kitting_time = cilList.Max(s => s.kitting_time);
+                                mooccupylist = _morderAppService.CheckMorder(sct.bom_number, sct.lack_qty, plan_date.GetValueOrDefault(), sentrys, ic_item, bangid);
                             }
-                            sct.make_qty = sct.lack_qty;
-                            //默认中间件需要1天的制造周期
-                            sct.make_time = 1;
-                            sct.kitting_time = sct.kitting_time.Value.AddDays(1);
+                            decimal moo_qty = mooccupylist.Sum(s => s.moo_qty.GetValueOrDefault());
+                            sct.mo_qty = moo_qty;
 
-                            /*//走自制
-                            ProdExamineParamDto prodExamine = new ProdExamineParamDto()
+                            if (mooccupylist.Any())
                             {
-                                bom_number = sct.bom_number,
-                                version = sct.version,
-                                packages = (int)sct.lack_qty
-                            };
-                            _productExamineAppService.process = process;
-                            _productExamineAppService.techs = techs;
-                            _productExamineAppService.tech_Processes = tech_Processes;
-                            _productExamineAppService.tech_Proc_Workshops = tech_Proc_Workshops;
-
-                            var minute = _productExamineAppService.ProductiveExamine(prodExamine);
-                            //系统建议完工日期为 开工日期+产能检查时间=完工日期
-                            var Day = minute / (60 * 10); //返回的分钟除以十个小时得出工作天数;
-                            sct.kitting_time = sct.kitting_time.Value.AddDays((double)Day);
-                            sct.make_qty = sct.lack_qty;*/
-                            //todo:
-                            sct.make_list = new List<moorder>();
+                                mooccupyAllList.AddRange(mooccupylist);
+                                mooccupyAllInsertList.AddRange(mooccupylist);
+                                //在制占用明细
+                                sct.mo_occupy_list = new List<mo_occupy>();
+                                mooccupylist.ForEach(s =>
+                                {
+                                    mo_occupy mooc = new mo_occupy();
+                                    mooc.id = s.Id;
+                                    mooc.moo_mo = s.moo_mo;
+                                    mooc.moo_stime = s.moo_ctime;
+                                    mooc.moo_etime = s.moo_etime;
+                                    mooc.moo_qty = s.moo_qty;
+                                    sct.mo_occupy_list.Add(mooc);
+                                });
+                            }
+                            if (moo_qty == sct.lack_qty)
+                            {
+                                //在制完全足够
+                                sct.lack_qty = 0;
+                                //item.kitting_time = mooccupylist[0].moo_etime;
+                                sct.kitting_time = DateTime.Now;
+                                sct.stock_state = 1;
+                            }
+                            else {
+                                sct.lack_qty -= moo_qty;
+                                sct.kitting_time = DateTime.Now;
+                                //TODO:需要按标准UPH来计算生产时长
+                                //生成主工单
+                                GenerateMorderDto generateMorderDto = new GenerateMorderDto()
+                                {
+                                    seorderentry = sentrys,
+                                    seorder = seorder,
+                                    ic_Item = ic_item,
+                                    BomNumber = sct.bom_number,
+                                    version = sct.version,
+                                    number = sct.item_number,
+                                    Quantity = sct.lack_qty,
+                                    morder_type = morder_type,
+                                    work_order_type = MorderEnum.CgMorder,
+                                    morder_state = MorderEnum.Initial_state,
+                                    bang_id = bangid
+                                };
+                                Mes_MorderDto mes_MorderDto = _morderAppService.GenerateMorder(generateMorderDto);
+                                ProdExamineParamDto prodExamine = new ProdExamineParamDto()
+                                {
+                                    ItemNum = sct.item_number,
+                                    PlanStart = plan_date.GetValueOrDefault(),
+                                    QtyOrd = sct.lack_qty,
+                                    Domain = param.factoryId.ToString()
+                                };
+                                int make = _productExamineAppService.ProductTime(prodExamine);
+                                sct.make_qty = sct.lack_qty;
+                                if (mes_MorderDto != null)
+                                {
+                                    //主工单最后计算满足日期
+                                    var mes_Morders = mes_MorderDto.mes_Morders.Where(x => x.parent_id == null).FirstOrDefault();
+                                    if (mes_Morders != null)
+                                    {
+                                        //子工单生成的检查明细,还是挂接到主工单上。
+                                        //mes_morder = ObjectMapper.Map<mo_mes_morder, mes_morder>(mes_Morders);
+                                        mes_Morders.moentry_sys_etime = plan_date.GetValueOrDefault().AddDays(-1);
+                                        mes_Morders.moentry_sys_stime = mes_Morders.moentry_sys_etime.GetValueOrDefault().AddDays(-(make - 1));
+                                        sct.make_list = new List<moorder>();
+                                        mes_MorderDto.mes_Morders.ForEach(me =>
+                                        {
+                                            moorder mo = new moorder();
+                                            mo.Id = me.Id;
+                                            mo.moentry_stime = me.moentry_stime;
+                                            mo.moentry_etime = me.moentry_etime;
+                                            mo.moentry_wrkcname = me.moentry_wrkcname;
+                                            mo.moentry_sys_stime = me.moentry_sys_stime;
+                                            mo.moentry_sys_etime = me.moentry_sys_etime;
+                                            mo.moentry_prdname = me.moentry_prdname;
+                                            mo.morder_need_time = me.morder_need_time;
+                                            mo.morder_no = me.morder_no;
+                                            mo.morder_production_number = me.morder_production_number;
+                                            mo.need_number = me.need_number;
+                                            mo.reality_end_time = me.reality_end_time;
+                                            mo.reality_start_time = me.reality_start_time;
+                                            sct.make_list.Add(mo);
+                                        });
+                                        //批量保存 后期考虑子工单
+                                        mordersList.AddRange(mes_MorderDto.mes_Morders);
+                                        mordersInsertList.AddRange(mes_MorderDto.mes_Morders);
+                                        moentriesList.AddRange(mes_MorderDto.mes_Moentries);
+                                        moentriesInsertList.AddRange(mes_MorderDto.mes_Moentries);
+                                        
+                                        //先计算末级数据的齐套时间。
+                                        if (cilList.Count > 0)
+                                        {
+                                            CalcIcitem(cilList, returnlist, bangid, sklist, mes_Morders.moentry_sys_stime, icitemlist, sentrys, childidList);
+                                            sct.kitting_time = cilList.Max(s => s.kitting_time);
+                                        }
+                                        mes_Morders.mat_start_date = sct.kitting_time.GetValueOrDefault().AddDays(1).Date;//数据齐套完成后隔天开始生产;
+                                        mes_Morders.mat_end_date = mes_Morders.mat_start_date.GetValueOrDefault().AddDays(make);
+                                        sct.kitting_time = mes_Morders.mat_end_date;
+                                    }
+                                }
+                                
+                            }
                         }
                         else if (sct.erp_cls == 3)
                         {
@@ -1154,7 +1337,7 @@ namespace Business.ResourceExamineManagement
                                 if (sct.lack_qty > 0)
                                 {
                                     //采购申请
-                                    PackageSRMPR(sct, bangid, sentrys);
+                                    PackageSRMPR(sct, bangid, sentrys, plan_date);
                                 }
                             }
                         }
@@ -1166,16 +1349,18 @@ namespace Business.ResourceExamineManagement
                                 CalcInTransit(sentrys, sct, bangid, plan_date.GetValueOrDefault());
                                 if (sct.lack_qty > 0)
                                 {
+                                    //1.先生成委外工单。
+                                    var mesorder = CreateMesOOder(sct, param.company_id, param.factoryId, bangid, leadTimeList, supplierList, plan_date.GetValueOrDefault());
+                                    mesorder.ooentry_etime = plan_date.GetValueOrDefault().AddDays(-1);
+                                    var srmprDto = PackageSRMPR(sct, bangid, sentrys, plan_date);
+                                    mesorder.start_time = mesorder.ooentry_etime.GetValueOrDefault().AddDays(-(srmprDto.totalLeadTime.GetValueOrDefault() - 1));
+
                                     //先计算末级数据的齐套时间。
                                     if (cilList.Count > 0)
                                     {
-                                        CalcIcitem(cilList, returnlist, bangid, sklist, plan_date, icitemlist, sentrys, childidList);
-                                        sct.kitting_time = cilList.Max(s => s.kitting_time);
+                                        CalcIcitem(cilList, returnlist, bangid, sklist, mesorder.ooentry_stime, icitemlist, sentrys, childidList);
+                                        sct.kitting_time = cilList.Max(s => s.kitting_time).GetValueOrDefault().AddDays(srmprDto.totalLeadTime.GetValueOrDefault());//加上物料的采购提前期
                                     }
-                                    //1.先生成委外工单。
-                                    var mesorder = CreateMesOOder(sct, param.company_id, param.factoryId, bangid, leadTimeList, supplierList, plan_date.Value);
-                                    //采购申请
-                                    PackageSRMPR(sct, bangid, sentrys);
                                     sct.subcontracting_qty = sct.lack_qty;
                                     sct.subcontracting_list = new List<ooder>();
                                     ooder oo = new ooder();
@@ -1185,7 +1370,7 @@ namespace Business.ResourceExamineManagement
                                     oo.production_unit_code = mesorder.production_unit_code;
                                     oo.ooentry_prdname = mesorder.ooentry_prdname;
                                     oo.ooentry_stime = mesorder.ooentry_stime;
-                                    oo.ooentry_etime = sct.kitting_time;
+                                    oo.ooentry_etime = mesorder.ooentry_etime;
                                     oo.oorder_date = mesorder.oorder_date;
                                     oo.oorder_no = mesorder.oorder_no;
                                     item.subcontracting_list.Add(oo);
@@ -1227,24 +1412,95 @@ namespace Business.ResourceExamineManagement
             item.stock_state = item.lack_qty > 0 ? 0 : 1;
         }
 
+
         /// <summary>
         /// 生成采购申请单,颗粒度是一个物料一个单,没必要弄列表
         /// </summary>
         /// <param name="returnlist"></param>
         /// <param name="factoryid"></param>
         /// <param name="orderType">2委外采购申请单,3采购申请单</param>
-        private SRMPRDto CreateSRMPR(BomChildExamineDto returnlist, long? companyId, long factoryid, long bangId, int orderType, List<ICItemLeadTimeDto> iCItemLeadTimes, List<mo_srm_purchase> supplierList, List<mo_ic_item> planList, crm_seorderentry sentrys)
+        private SRMPRDto CreateSRMPR(BomChildExamineDto returnlist, long? companyId, long factoryid, long bangId, int orderType, List<ICItemLeadTimeDto> iCItemLeadTimes, List<mo_srm_purchase> supplierList, List<mo_ic_item> planList, crm_seorderentry sentrys, DateTime? plan_date)
         {
             SRMPRDto sRMPR = new SRMPRDto();
-            var supplier = supplierList.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
+            mo_srm_purchase supplier = null;
             var plan = planList.Find(x => x.mysql_id == returnlist.item_id);
-            sRMPR.srm_Pr_Main = new List<mo_srm_pr_main>();
-            if (supplier == null || plan == null)
+            var supplist = supplierList.Where(s => s.icitem_id == returnlist.item_id).ToList();
+            decimal day = 0;
+            if (!supplist.Any() || plan == null)
             {
+                returnlist.stock_state = 99;
                 sRMPR.lastStartTmie = DateTime.Now.AddDays(7);//默认采购提前期
+                sRMPR.totalLeadTime = 7;
                 return sRMPR;
-                //throw new NotImplementedException("未找到物料ic_factory_details或ic_item_pur或ic_plan信息!");
             }
+            if (plan_date != null && returnlist.erp_cls == 3)
+            {
+                //判断当前时间与交期还剩余多少天
+                var timesp = plan_date.GetValueOrDefault() - DateTime.Now.Date;
+                //交期-生产时长-物料前处理周期
+                day = Math.Floor(timesp.Days - returnlist.clean_leadtime.GetValueOrDefault());
+                if (day > 0)
+                {
+                    supplist = supplist.Where(s => s.lead_time.GetValueOrDefault() < day).ToList();
+                    if (supplist.Any())
+                    {
+                        //TODO:走配额管理
+                        List<mo_srm_pr_main> itemPrlist = quarter_srm_pr_mains.Where(s => s.icitem_id == returnlist.item_id).ToList();
+                        if (itemPrlist.Any())
+                        {
+                            decimal qtyCount = itemPrlist.Sum(x => x.pr_aqty).GetValueOrDefault();
+                            //按配额比例,计算使用哪个供应商。
+                            List<PrPurchaseDto> PrPurchaseDtoList = new List<PrPurchaseDto>();
+                            supplist.ForEach(s => {
+                                PrPurchaseDto purDto = new PrPurchaseDto();
+                                purDto.pr_purchaseid = s.supplier_id;
+                                purDto.num = itemPrlist.Where(x => x.pr_purchaseid == s.supplier_id).Sum(c => c.pr_aqty.GetValueOrDefault());
+                                purDto.ratio = Math.Round(purDto.num / qtyCount, 2, MidpointRounding.AwayFromZero);
+                                purDto.quota_priority = s.quota_priority;
+                                purDto.quota_rate = s.quota_rate.GetValueOrDefault();
+                                PrPurchaseDtoList.Add(purDto);
+                            });
+
+                            //首先取出占比还小于配额比的数据
+                            var priorityPurlist = PrPurchaseDtoList.Where(s => s.quota_rate - s.ratio > 2).ToList();
+                            if (!priorityPurlist.Any())
+                            {
+                                //没有则取出当前集合中的供应商的数据,计算差额
+                                priorityPurlist = PrPurchaseDtoList;
+                            }
+                            //还没有达到配额比的供应商,优先分配
+                            decimal difference = 0;
+                            PrPurchaseDto dto1 = priorityPurlist[0];
+                            priorityPurlist.ForEach(s => {
+                                decimal diff = s.quota_rate - s.ratio;
+                                if (diff > difference)
+                                {
+                                    difference = diff;
+                                    dto1 = s;
+                                }
+                            });
+                            supplier = supplist.Find(s => s.supplier_id == dto1.pr_purchaseid);
+                        }
+                        else {
+                            supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
+                        }
+                    }
+                    else
+                    {
+                        supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
+                    }
+                }
+                else
+                {
+                    supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
+                }
+            }
+            else
+            {
+                //委外暂时不做配额处理
+                supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
+            }
+            sRMPR.srm_Pr_Main = new List<mo_srm_pr_main>();
             mo_srm_pr_main srm_Pr = new mo_srm_pr_main();
             srm_Pr.GenerateNewId(help.NextId());
             srm_Pr.mysql_id = help.NextId();
@@ -1270,19 +1526,30 @@ namespace Business.ResourceExamineManagement
             srm_Pr.icitem_id = returnlist.item_id;//物料id
             srm_Pr.icitem_name = returnlist.item_name;//物料名称
             srm_Pr.num = returnlist.num;
-            var tomorrow = DateTime.Now.Date.AddDays(1);
+            
             srm_Pr.pr_order_type = 1;//单据类型
-            srm_Pr.pr_ssend_date = tomorrow;//系统建议下单日期
-            srm_Pr.pr_sarrive_date = DateTime.Now.AddDays((double)plan.order_leadtime).AddDays((double)plan.transportation_leadtime);//系统建议到达日期(建议到货日期)
-            srm_Pr.pr_psend_date = tomorrow;//计划下单日期
-            srm_Pr.pr_parrive_date = DateTime.Now.AddDays((double)plan.order_leadtime).AddDays((double)plan.transportation_leadtime);//计划到达日期
-            srm_Pr.pr_rarrive_date = DateTime.Now.AddDays((double)plan.order_leadtime).AddDays((double)plan.transportation_leadtime);//需求到货日期
+
+            if (plan_date != null && IsInverted)
+            {
+                //-1为提前一天准备
+                int d = ((int)Math.Floor(-1 - returnlist.clean_leadtime.GetValueOrDefault()));
+                srm_Pr.pr_sarrive_date = plan_date.GetValueOrDefault().AddDays(d);
+                srm_Pr.pr_ssend_date = srm_Pr.pr_sarrive_date.Value.AddDays(-(int)Math.Floor(supplier.lead_time.GetValueOrDefault()));//系统建议下单日期
+                if (srm_Pr.pr_ssend_date < DateTime.Now.AddDays(1))
+                {
+                    //如果建议下单日期为今天或者过去,则代表物料需求供应时间不够,则需要标记此物料时间不足。
+                    var timeSp = DateTime.Now - srm_Pr.pr_ssend_date.Value;
+                    returnlist.pre_time = timeSp.Days + 1;
+                }
+            }
+            else {
+                srm_Pr.pr_ssend_date = DateTime.Now.Date.AddDays(1);//系统建议下单日期
+                srm_Pr.pr_sarrive_date = DateTime.Now.AddDays((double)supplier.lead_time.GetValueOrDefault());//系统建议到达日期(建议到货日期)
+            }
+            sRMPR.totalLeadTime = (int)Math.Floor(supplier.lead_time.GetValueOrDefault());
             srm_Pr.pr_sysprice = supplier.order_price;//系统价格(含税)
             srm_Pr.pr_orderprice = qty * supplier.order_price;//订单价格(含税)
             srm_Pr.pr_price = supplier.netpurchase_price;//采购净价(不含税)
-            /*srm_Pr.pr_sysprice = qty * x.netpurchase_price * (1 + x.taxrate);//系统价格(含税)
-            srm_Pr.pr_orderprice = qty * x.netpurchase_price * (1 + x.taxrate);//订单价格(含税)
-            srm_Pr.pr_price = x.netpurchase_price;//采购净价(不含税)*/
             srm_Pr.pr_rate = supplier.taxrate;//税率
             srm_Pr.pr_unit = returnlist.unit;//单位
             srm_Pr.state = 1;//状态
@@ -1298,13 +1565,14 @@ namespace Business.ResourceExamineManagement
             {
                 srm_Pr.sentry_id = sentrys.Id;
             }
-            decimal? totalLeadTime = plan.transportation_leadtime + plan.stock_leadtime + plan.production_leadtime + plan.order_leadtime;
+            decimal? totalLeadTime = supplier.lead_time.GetValueOrDefault();//plan.transportation_leadtime + plan.stock_leadtime + plan.production_leadtime + plan.order_leadtime;
             srm_Pr.totalLeadTime = totalLeadTime;
             srm_Pr.create_time = DateTime.Now;
             srm_Pr.create_by_name = "admin";
             srm_Pr.update_time = DateTime.Now;
             srm_Pr.update_by_name = "admin";
             sRMPR.srm_Pr_Main.Add(srm_Pr);
+
             if (sRMPR.srm_Pr_Main.Any())
             {
                 sRMPR.srm_Pr_Main.OrderBy(x => x.totalLeadTime.GetValueOrDefault()).ThenBy(x => x.pr_orderprice.GetValueOrDefault()).First().isbestoptions = true;
@@ -1345,8 +1613,8 @@ namespace Business.ResourceExamineManagement
             oOrder.ooentry_wrkcname = "10001";//工作中心名称
             oOrder.planner_num = "wwww";//计划员工号
             oOrder.planner_name = "qqq";//计划员名称
-            oOrder.ooentry_stime = returnlist.kitting_time == null ? DateTime.Now.AddDays(1) : returnlist.kitting_time.GetValueOrDefault().AddDays(1);//计划开工日期
-            oOrder.ooentry_etime = oOrder.ooentry_stime.GetValueOrDefault().AddDays(7);//计划完工日期
+            
+            oOrder.ooentry_etime = deliveryDate.AddDays(-1);//计划完工日期
             oOrder.product_code = returnlist.item_number;//产品代码
             oOrder.ffms_number = "1000";//fms旧料号
             oOrder.product_name = returnlist.item_name;//产品名称
@@ -1390,6 +1658,7 @@ namespace Business.ResourceExamineManagement
         {
             _purchaseOrderAppService.mo_Srm_Po_Lists = srm_Po_Lists; //采购明细
             _purchaseOrderAppService.srm_Po_Occupies = srm_Po_Occupies; //采购明细
+
             var occupylist = _purchaseOrderAppService.CheckPurchaseOrder(sentrys, item.item_id, item.lack_qty, plan_date, ic_item_List, bangid);
             if (occupylist.Any())
             {
@@ -1422,10 +1691,10 @@ namespace Business.ResourceExamineManagement
             }
         }
 
-        public void PackageSRMPR(BomChildExamineDto item,long bangid, crm_seorderentry sentrys)
+        public SRMPRDto PackageSRMPR(BomChildExamineDto item,long bangid, crm_seorderentry sentrys, DateTime? plan_date)
         {
             //采购申请
-            var SRMPRDto = CreateSRMPR(item, param.company_id, param.factoryId, bangid, item.erp_cls, leadTimeList, supplierList, ic_item_List, sentrys);
+            var SRMPRDto = CreateSRMPR(item, param.company_id, param.factoryId, bangid, item.erp_cls, leadTimeList, supplierList, ic_item_List, sentrys, plan_date);
             item.purchase_list = new List<purchase>();
             if (SRMPRDto.srm_Pr_Main != null)
             {
@@ -1454,10 +1723,10 @@ namespace Business.ResourceExamineManagement
             {
                 item.purchase_qty = item.lack_qty;
                 item.purchase_list = new List<purchase>();
-                
             }
             item.kitting_time = SRMPRDto.lastStartTmie;
             SRMPRDtoList.Add(SRMPRDto);
+            return SRMPRDto;
         }
     }
 }

+ 5 - 14
MicroServices/Business/Business.Application/ResourceExamineManagement/MorderAppService.cs

@@ -133,7 +133,7 @@ namespace Business.ResourceExamineManagement
         /// <param name="number">物料编码</param>
         /// <param name="Quantity"></param>
         /// <param name="ParentId"></param>
-        public Mes_MorderDto GenerateMorder(GenerateMorderDto generateMorderDto, int urgent)
+        public Mes_MorderDto GenerateMorder(GenerateMorderDto generateMorderDto)
         {
             //1.库存、在制工单检查完成后 当前BOM需要自制时 产生工单。
 
@@ -153,7 +153,7 @@ namespace Business.ResourceExamineManagement
             mes_Morder.fms_number = generateMorderDto.ic_Item.fms_number;
             mes_Morder.bom_number = generateMorderDto.BomNumber;
             mes_Morder.fmodel = generateMorderDto.ic_Item.model;
-            mes_Morder.urgent = urgent;
+            mes_Morder.urgent = 0;//暂时不用这个字段
             if (generateMorderDto.ParentId != null && generateMorderDto.moentry_sys_stime != null)
             {
                 //最早的开工时间3天后、 最晚时间为订单承诺时间 - 采购提前期 - 质检提前期 - 入库提前期 - 发料提前期 = 最晚开工时间  最早或最晚为系统建议开工日期
@@ -182,7 +182,6 @@ namespace Business.ResourceExamineManagement
                     mes_Morder.morder_need_time = (decimal)span.TotalMinutes;
                 }
             }
-
             mes_Morder.moentry_startup_status = 0;
             mes_Morder.tenant_id = param.company_id.GetValueOrDefault();
             mes_Morder.factory_id = param.factoryId;
@@ -238,15 +237,7 @@ namespace Business.ResourceExamineManagement
                 mes_Moentry.fbill_no = generateMorderDto.seorderentry.bill_no;
                 mes_Moentry.fentry_id = generateMorderDto.seorderentry.entry_seq.Value;
             }
-
             return mes_MorderDto;
-
-            //using (TransactionScope scope = new TransactionScope())
-            // {
-            //_mes_morder.InsertOne(mes_Morder);
-            //_mes_moentry.InsertOne(mes_Moentry);
-            //scope.Complete();
-            //}
         }
 
         /// <summary>
@@ -257,7 +248,7 @@ namespace Business.ResourceExamineManagement
         /// <param name="DeliverDate">交付日期</param>
         /// <param name="seorderentry_id">销售订单子表ID</param>
         /// <returns></returns>
-        public virtual List<mo_mes_mooccupy> CheckMorder(string bomNumber, decimal Quantity, DateTime DeliverDate, crm_seorderentry seorderentry, mo_ic_item ic_Item, long bang_id)
+        public List<mo_mes_mooccupy> CheckMorder(string bomNumber, decimal Quantity, DateTime DeliverDate, crm_seorderentry seorderentry, mo_ic_item ic_Item, long bang_id)
         {
             if (string.IsNullOrEmpty(bomNumber))
             {
@@ -289,7 +280,7 @@ namespace Business.ResourceExamineManagement
             var moentrys = mo_Mes_Moentry.Where(s => s.soentry_id == seorderentry.Id);
             //找到当前订单行生成的主工单
             var toMid = moentrys.Select(s => s.moentry_moid).ToList();
-            var morderDataList = mo_Mes_Morders.Where(x => x.bom_number == bomNumber && x.morder_type == MorderEnum.JhMorder && x.moentry_sys_etime.GetValueOrDefault().AddDays(-1) < DeliverDate &&
+            var morderDataList = mo_Mes_Morders.Where(x => x.bom_number == bomNumber && x.morder_type == MorderEnum.JhMorder && x.moentry_sys_etime.GetValueOrDefault() < DeliverDate &&
             (x.morder_production_number - x.inventory_number - mes_mooccupyList.Where(p => p.moo_moid.GetValueOrDefault() == x.mysql_id)?.Sum(m => m.moo_qty)) > Quantity)
              .OrderByDescending(x => x.planner_end_date).ToList();
 
@@ -297,7 +288,7 @@ namespace Business.ResourceExamineManagement
             //当数量或日期不满足的时候,寻找最早日期的工单
             if (morderDataList.Count == 0)
             {
-                morderDataList = mo_Mes_Morders.Where(x => x.bom_number == bomNumber && (x.morder_type == MorderEnum.JhMorder || toMid.Contains(x.mysql_id)) && x.moentry_sys_etime.GetValueOrDefault().AddDays(-1) < DeliverDate).OrderByDescending(x => x.planner_end_date).ToList();
+                morderDataList = mo_Mes_Morders.Where(x => x.bom_number == bomNumber && (x.morder_type == MorderEnum.JhMorder || toMid.Contains(x.mysql_id)) && x.moentry_sys_etime.GetValueOrDefault() < DeliverDate).OrderByDescending(x => x.planner_end_date).ToList();
             }
             var QuantityNumber = 0.00m;
             //存在此数据满足当前BOM交付找到最早日期工单,则返回无需后续继续检查。

+ 5 - 0
MicroServices/Business/Business.Application/ResourceExamineManagement/PretreatmentAppService.cs

@@ -126,6 +126,8 @@ namespace Business.ResourceExamineManagement
                     cdto.bom_id = childBom.mysql_id;
                     cdto.bom_number = childBom.bom_number;
                     cdto.Op = c.Op;
+                    cdto.clean_leadtime = icitem.clean_leadtime;
+                    cdto.PurLT = icitem.PurLT;
                     //递归寻找子级
                     GetBomList(bomlist, bomchildlist, icitemlist, cdto, returnlist, type);
                 }
@@ -159,6 +161,7 @@ namespace Business.ResourceExamineManagement
                         childDto.type = type;
                         childDto.item_number = icitem.number;
                         childDto.Op = c.Op;
+                        childDto.clean_leadtime = icitem.clean_leadtime;
                         returnlist.Add(childDto);
                     }
                 }
@@ -275,6 +278,7 @@ namespace Business.ResourceExamineManagement
             dto.substitute_all_num = sal.order_num;//群组优先级
             //先按标准料的工序给替代料赋值。
             dto.Op = toDto.Op;
+            dto.clean_leadtime = icitem.clean_leadtime;
             if (bom != null)
             {
                 dto.bom_id = bom.mysql_id;
@@ -285,6 +289,7 @@ namespace Business.ResourceExamineManagement
                 dto.haveicsubs = 0;
                 dto.substitute_code = "";
                 dto.icitem_ids = "";
+                dto.PurLT = icitem.PurLT;
                 GetBomList(bomlist, bomchildlist, icitemlist, dto, returnlist, type);
             }
             else

+ 20 - 0
MicroServices/Business/Business.Application/ResourceExamineManagement/ProductExamineAppService.cs

@@ -54,6 +54,26 @@ namespace Business.ResourceExamineManagement
         {
         }
 
+        /// <summary>
+        /// 根据标准工艺获取生产时长(天)
+        /// </summary>
+        /// <param name="param"></param>
+        /// <returns></returns>
+        public int ProductTime(ProdExamineParamDto param)
+        {
+            var rtOps = routingOps.Where(s => s.RoutingCode == param.ItemNum && s.Domain == param.Domain && s.MilestoneOp == true).ToList();
+            if (rtOps.Any())
+            { 
+                decimal maxRt = rtOps.Max(s => s.RunTime);
+                decimal sumRt = rtOps.Sum(s => s.RunTime);
+                decimal totalTime = (param.QtyOrd - 1) * maxRt + sumRt;//总计生产小时
+                return (int)(Math.Floor(totalTime / 8));
+            }
+            return 1;
+        }
+
+
+
         /// <summary>
         /// 产能计算-批量
         /// </summary>

+ 196 - 74
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
 {
@@ -135,6 +136,11 @@ namespace Business.ResourceExamineManagement
         /// </summary>
         private List<ResourceOccupancyTime> resourceOccupancyTimes;
 
+        /// <summary>
+        /// 领料单
+        /// </summary>
+        private ISqlRepository<NbrMaster> _nbrMaster;
+
         /// <summary>
         /// 工厂id
         /// </summary>
@@ -161,13 +167,15 @@ namespace Business.ResourceExamineManagement
             ISqlRepository<HolidayMaster> holidayMaster,
             ISqlRepository<GeneralizedCodeMaster> generalizedCodeMaster,
             ICurrentTenant currentTenant,
-            ISqlRepository<ScheduleExceptionMaster> scheduleExceptionMaster
+            ISqlRepository<ScheduleExceptionMaster> scheduleExceptionMaster,
+            ISqlRepository<NbrMaster> nbrMaster
             )
         {
             _itemMaster = itemMaster;
             _workOrdMaster = workOrdMaster;
             _workOrdDetail = workOrdDetail;
             _workOrdRouting = workOrdRouting;
+            _nbrMaster = nbrMaster;
             _prodLineDetail = prodLineDetail;
             _prodLineDetailRunCrew = prodLineDetailRunCrew;
             _resourceOccupancyTime = resourceOccupancyTime;
@@ -192,15 +200,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 +247,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 +285,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 +317,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 +363,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);
@@ -355,6 +377,9 @@ namespace Business.ResourceExamineManagement
                     scope.Dispose();
                 }
             }
+
+            //领料单重新处理
+            AdjustNbrDate(workOrds);
         }
 
         /// <summary>
@@ -545,22 +570,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 +598,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 +608,37 @@ 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 qtyNeed = item.QtyOrded - curOp.QtyComplete;
+                        //剩余工作时长(分钟)
+                        decimal usedTime = Math.Ceiling(qtyNeed / item.QtyOrded * item.LbrVar * 60);
                         workDtos.Add(new WorkOrdMstDto
                         {
                             WorkOrd = item.WorkOrd,
                             ItemNum = item.ItemNum,
-                            QtyOrded = item.QtyOrded,
-                            LbrVar = item.LbrVar * 60,
+                            QtyOrded = qtyNeed,
+                            LbrVar = 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 +658,47 @@ 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 qtyNeed = item.QtyOrded - curOp.QtyComplete;
+                                //剩余工作时长(分钟)
+                                decimal usedTime = Math.Ceiling(qtyNeed / item.QtyOrded * item.LbrVar * 60);
                                 workDtos.Add(new WorkOrdMstDto
                                 {
                                     WorkOrd = item.WorkOrd,
                                     ItemNum = item.ItemNum,
-                                    QtyOrded = item.QtyOrded,
-                                    LbrVar = item.LbrVar * 60,
+                                    QtyOrded = qtyNeed,
+                                    LbrVar = usedTime,
                                     Worked = 0,
                                     QtyWorked = 0,
                                     Op = curOp.OP,
                                     WaitTime = curOp.WaitTime * 60,
-                                    PlanDate = item.OrdDate.Value
+                                    Priority = item.Priority
                                 });
+                                sumLbrVar += 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;
                         }
                     }
                     //特殊工单排序
-                    workDtos = workDtos.OrderBy(p => p.PlanDate).ToList();
+                    workDtos = workDtos.OrderBy(p => p.Priority).ToList();
                     //当天的可用生产时长满足特殊工单生产时长+清场时间(最后一个工单清场时间除外)
                     if (dto.EffTime >= sumTsTimes)
                     {
@@ -803,35 +846,42 @@ 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 qtyNeed = item.QtyOrded - curOp.QtyComplete;
+                                    //剩余工作时长(分钟)
+                                    decimal usedTime = Math.Ceiling(qtyNeed / item.QtyOrded * item.LbrVar * 60);
                                     workDtos.Add(new WorkOrdMstDto
                                     {
                                         WorkOrd = item.WorkOrd,
                                         ItemNum = item.ItemNum,
-                                        QtyOrded = item.QtyOrded,
-                                        LbrVar = item.LbrVar * 60,
+                                        QtyOrded = qtyNeed,
+                                        LbrVar = usedTime,
                                         Worked = 0,
                                         QtyWorked = 0,
                                         Op = curOp.OP,
                                         WaitTime = curOp.WaitTime * 60,
-                                        PlanDate = item.OrdDate.Value
+                                        Priority = item.Priority
                                     });
                                     sumCleanTimes += curOp.WaitTime * 60;
+                                    sumLbrVar += usedTime;
                                 }
                                 //获取最后一个特殊工单的清场时长
                                 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 +1097,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 +1115,38 @@ 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 qtyNeed = item.QtyOrded - curOp.QtyComplete;
+                                //剩余工作时长(分钟)
+                                decimal usedTime = Math.Ceiling(qtyNeed / item.QtyOrded * item.LbrVar * 60);
                                 workDtos.Add(new WorkOrdMstDto
                                 {
                                     WorkOrd = item.WorkOrd,
                                     ItemNum = item.ItemNum,
-                                    QtyOrded = item.QtyOrded,
-                                    LbrVar = item.LbrVar * 60,
+                                    QtyOrded = qtyNeed,
+                                    LbrVar = usedTime,
                                     Worked = 0,
                                     QtyWorked = 0,
                                     Op = curOp.OP,
                                     WaitTime = curOp.WaitTime * 60,
-                                    PlanDate = item.OrdDate.Value
+                                    Priority = item.Priority
                                 });
+                                sumLbrVar += 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 +1163,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 +1590,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 +1622,8 @@ namespace Business.ResourceExamineManagement
                                         nextMins -= p.WorkMinutes;
                                     }
                                 }
-                                //工单排产完成,已排产数量=工单数量
-                                sumQty = workOrd.QtyOrded;
+                                //工单排产完成,已排产数量=工单需排产数量数量
+                                sumQty = lineStart.QtyRemain;
                                 //当天剩余可用生产时长
                                 residueTime -= workTime;
                                 //处理清场时间,两种场景:
@@ -1648,7 +1705,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 +2082,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 +2233,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 +2280,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 +2311,7 @@ namespace Business.ResourceExamineManagement
                                             }
                                         }
                                         //工单排产完成,已排产数量=工单数量
-                                        sumQty = workOrd.QtyOrded;
+                                        sumQty = lineStart.QtyRemain;
 
                                         //剩余可用生产时长
                                         residueTime = (residueTime - workTime) < 0 ? 0 : (residueTime - workTime);
@@ -2531,7 +2588,7 @@ namespace Business.ResourceExamineManagement
                         //当天之前的特殊工单全部排产完毕
                         else {
                             //已排产数量+当天的产能小于工单数量,当天的产能需要全部排产
-                            if (sumQty + dto.ProductQty < workOrd.QtyOrded)
+                            if (sumQty + dto.ProductQty < lineStart.QtyRemain)
                             {
                                 //当天有特殊工单,先排特殊工单
                                 if (sumTsTimes > 0)
@@ -2540,7 +2597,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 +3020,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 +3055,7 @@ namespace Business.ResourceExamineManagement
                                         }
                                     }
                                     //工单排产完成,已排产数量=工单数量
-                                    sumQty = workOrd.QtyOrded;
+                                    sumQty = lineStart.QtyRemain;
                                     //剩余可用生产时长
                                     residueTime = (residueTime - workTime) < 0 ? 0 : (residueTime - workTime);
                                     //处理清场时间,两种场景:
@@ -3094,7 +3151,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 +3736,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 +3760,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 +3777,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 +3933,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 +3951,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 +3964,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;
         }
 
@@ -4109,5 +4180,56 @@ namespace Business.ResourceExamineManagement
             }
             return workPoints.OrderBy(p => p.Level).ToList();
         }
+
+        /// <summary>
+        /// 调整领料单时间
+        /// </summary>
+        /// <param name="workords"></param>
+        public void AdjustNbrDate(List<WorkOrdMaster> workords)
+        {
+            if (workords.Any())
+            {
+                //找出当前工单的所有领料单,更新领料单的前处理时间和完成日期。
+                //1.如果未生成领料单,则无需调整。
+                //2.已生成领料单,但是领料单已出库,也不调整。nbr.Status='C'
+                //3.当领料单未出库,则代表需要调整这个领料单的处理时间。
+                var nbrlist = _nbrMaster.Select(s => workords.Select(x => x.WorkOrd).Contains(s.WorkOrd) && s.Domain == workords[0].Domain).ToList();
+                if (nbrlist.Any())
+                {
+                    foreach (var work in workords)
+                    {
+                        var workNbr = nbrlist.Where(s => s.WorkOrd == work.WorkOrd).ToList();
+                        foreach (var nbr in workNbr)
+                        {
+                            if (string.IsNullOrEmpty(nbr.Status))
+                            {
+                                if (nbr.TransType == "PrevProcess")
+                                {
+                                    //前处理领料单
+                                    var ts = nbr.EffDate.GetValueOrDefault() - nbr.Date.GetValueOrDefault();
+                                    nbr.EffDate = work.OrdDate.GetValueOrDefault().AddDays(-1);
+                                    nbr.Date = nbr.EffDate.GetValueOrDefault().AddDays(-ts.Days);
+                                }
+                                else
+                                {
+                                    nbr.EffDate = work.OrdDate.GetValueOrDefault().AddDays(-1);
+                                    nbr.Date = nbr.EffDate;
+                                }
+                                if (nbr.Date.GetValueOrDefault().Date <= DateTime.Now.Date)
+                                {
+                                    nbr.Date = DateTime.Now.AddDays(1).Date;
+                                }
+                                if (nbr.EffDate.GetValueOrDefault().Date <= DateTime.Now.Date)
+                                {
+                                    nbr.EffDate = DateTime.Now.AddDays(1).Date;
+                                }
+                            }
+                        }
+                    }
+                    _nbrMaster.Update(nbrlist);
+                }
+            }
+        }
+    
     }
 }

+ 3 - 2
MicroServices/Business/Business.Application/ResourceExamineManagement/PurchaseOrderAppService.cs

@@ -80,13 +80,14 @@ namespace Business.ResourceExamineManagement
             var poDetailList = mo_Srm_Po_Lists.Where(x => x.icitem_id == icitem_id);
             //采购订单占用数据
             var poOccupys = srm_Po_Occupies.Where(x => poDetailList.Select(p => p.Id).ToList().Contains(x.polist_id));
+
             //先查询出满足日期,并且数量可满足占用的数据
-            var poDetails = poDetailList.Where(x => x.rarrdate.GetValueOrDefault().AddDays(-(int)ic_Plan.self_inspection_date.GetValueOrDefault()) < DeliverDate && x.qty - x.rqty - x.esqty -
+            var poDetails = poDetailList.Where(x => x.rarrdate.GetValueOrDefault() < DeliverDate && x.qty - x.rqty - x.esqty -
                 poOccupys.Where(p => p.polist_id == x.mysql_id)?.Sum(m => m.qty) > Quantity).OrderByDescending(x => x.rarrdate).ToList();
             //未满足则查询出满足日期的订单
             if (poDetails.Count == 0)
             {
-                poDetails = poDetailList.Where(x => x.rarrdate.GetValueOrDefault().AddDays(-(int)ic_Plan.self_inspection_date.GetValueOrDefault()) < DeliverDate).OrderByDescending(x => x.rarrdate).ToList();
+                poDetails = poDetailList.Where(x => x.rarrdate.GetValueOrDefault() < DeliverDate).OrderByDescending(x => x.rarrdate).ToList();
             }
             var QuantityNumber = 0.00m;
             foreach (var item in poDetails)

+ 44 - 36
MicroServices/Business/Business.Application/ResourceExamineManagement/ResourceExamineAppService.cs

@@ -667,6 +667,8 @@ namespace Business.ResourceExamineManagement
             //记录订单行的物料齐套时间
             List<KittingTimeDto> kittingTimes = new List<KittingTimeDto>();
             DataInitialization(boms, bangid, icitemlist, stocklist, pretreatments, sklist);
+
+            _CalcBomViewAppService.morder_type = MorderEnum.XsMorder;
             foreach (var sorder in sorders)
             {
                 param.sorderId = sorder.Id;
@@ -676,13 +678,11 @@ namespace Business.ResourceExamineManagement
                 _morderAppService.param = param;
                 _purchaseOrderAppService.param = param;
                 _CalcBomViewAppService.param = param;
+                _CalcBomViewAppService.IsInverted = true;
                 _CalcBomViewAppService.seorder = sorder;//销售订单
                 var orderSentrys = sentrys.Where(s => s.seorder_id == sorder.Id).ToList();
                 foreach (var item in orderSentrys)
                 {
-                    //获取销售订单“是否加急”字段
-                    int urgent = sorder.urgent;
-
                     //工单资源检查信息
                     dtl = new ExamineResult();
                     dtl.sorderid = sorder.Id;
@@ -709,7 +709,7 @@ namespace Business.ResourceExamineManagement
                     _CalcBomViewAppService.BomStock(getBomList, stocklist, bangid);
                     _CalcBomViewAppService.newStockOccList = new List<mo_ic_item_stockoccupy>();
                     //计算
-                    _CalcBomViewAppService.CalcView(getBomList, bangid, item.qty.GetValueOrDefault(), item.plan_date, sklist, item, urgent, icitemlist);
+                    _CalcBomViewAppService.CalcView(getBomList, bangid, item.qty.GetValueOrDefault(), item.plan_date, sklist, item, icitemlist);
 
                     //TODO:最晚开始时间
                     var curFacDtl = leadTimeList.FirstOrDefault(p => p.item_id == childBom.icitem_id);
@@ -1036,9 +1036,9 @@ namespace Business.ResourceExamineManagement
             srm_Pr.pr_sqty = prlist.Sum(s => s.pr_sqty);//建议数量
             srm_Pr.pr_ssend_date= prlist.Min(s => s.pr_ssend_date);//系统建议下单日期
             srm_Pr.pr_sarrive_date = prlist.Min(s => s.pr_sarrive_date);//系统建议到达日期(建议到货日期)
-            srm_Pr.pr_psend_date = prlist.Min(s => s.pr_psend_date);//计划下单日期
+/*            srm_Pr.pr_psend_date = prlist.Min(s => s.pr_psend_date);//计划下单日期
             srm_Pr.pr_parrive_date = prlist.Min(s => s.pr_parrive_date);//计划到达日期
-            srm_Pr.pr_rarrive_date = prlist.Min(s => s.pr_rarrive_date);//需求到货日期
+            srm_Pr.pr_rarrive_date = prlist.Min(s => s.pr_rarrive_date);//需求到货日期*/
             //srm_Pr.pr_sysprice = prlist.Sum(s => s.pr_rqty) * prlist[0].pr_price * (1 + prlist[0].pr_rate);//系统价格(含税)
             srm_Pr.pr_orderprice = prlist.Sum(s => s.pr_aqty) * prlist[0].pr_sysprice;//订单价格(含税)
             /*srm_Pr.icitem_id = returnlist.item_id;//物料id
@@ -1115,18 +1115,12 @@ namespace Business.ResourceExamineManagement
                         newPr.pr_aqty = ilist.Sum(s => s.pr_aqty);//申请数量
                         newPr.pr_sqty = ilist.Sum(s => s.pr_sqty);//建议数量
 
-                        decimal day = 0;
-                        if (icitem != null)
-                        {
-                            //目前只加入了下单前置(天)
-                            day += icitem.order_leadtime.GetValueOrDefault();
-                        }
-                        newPr.pr_rarrive_date = starttime;//需求到货日期
-                        newPr.pr_ssend_date = newPr.pr_rarrive_date.Value.AddDays(-double.Parse(day.ToString()));//系统建议下单日期
-                        newPr.pr_psend_date = newPr.pr_ssend_date;//计划下单日期
-                        newPr.pr_sarrive_date = newPr.pr_rarrive_date;//系统建议到达日期(建议到货日期)
-                        newPr.pr_parrive_date = newPr.pr_rarrive_date;//计划到达日期
-                        
+                        newPr.pr_ssend_date = ilist.Min(s => s.pr_ssend_date);//系统建议下单日期
+                        newPr.pr_sarrive_date = ilist.Min(s => s.pr_sarrive_date);//系统建议到达日期(建议到货日期)
+                        /*            newPr.pr_psend_date = ilist.Min(s => s.pr_psend_date);//计划下单日期
+                                    newPr.pr_parrive_date = ilist.Min(s => s.pr_parrive_date);//计划到达日期
+                                    newPr.pr_rarrive_date = ilist.Min(s => s.pr_rarrive_date);//需求到货日期*/
+
                         //newPr.pr_sysprice = newPr.pr_rqty * pr.pr_price * (1 + pr.pr_rate);//系统价格(含税)
                         newPr.pr_orderprice = newPr.pr_aqty * pr.pr_sysprice;//订单价格(含税)
                         ilist.ForEach(s => { s.refer_pr_billno = newPr.pr_billno; });
@@ -1289,8 +1283,8 @@ namespace Business.ResourceExamineManagement
             DateTime toTime = new DateTime(2023, 7, 6);
             DateTime starttime = toTime.AddDays(1);
             DateTime endtime = toTime.AddDays(8);
-            List<srm_pr_main> prlist = _mysql_srm_pr_main.GetListAsync(s => s.company_id.ToString() == companyid && s.IsRequireGoods == 0 && s.pr_rarrive_date >= starttime &&
-            s.pr_rarrive_date <= endtime && (s.state == 1|| s.state == 2 || s.state == 3)).Result;
+            List<srm_pr_main> prlist = _mysql_srm_pr_main.GetListAsync(s => s.company_id.ToString() == companyid && s.IsRequireGoods == 0 && s.pr_sarrive_date >= starttime &&
+            s.pr_sarrive_date <= endtime && (s.state == 1|| s.state == 2 || s.state == 3)).Result;
 
             if (prlist.Any())
             {
@@ -1600,12 +1594,21 @@ namespace Business.ResourceExamineManagement
                         {
                             _workOrdMaster.Insert(workOrds);
                         }
+                        var DBworkOrdList = _workOrdMaster.Select(a => a.Domain == workOrds[0].Domain && workOrds.Select(c => c.WorkOrd).Contains(a.WorkOrd));
                         if (workOrdRoutings.Any())
                         {
+                            workOrdRoutings.ForEach(c =>
+                            {
+                                c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
+                            });
                             _workOrdRouting.Insert(workOrdRoutings);
                         }
                         if (workOrdDetails.Any())
                         {
+                            workOrdDetails.ForEach(c =>
+                            {
+                                c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
+                            });
                             _workOrdDetail.Insert(workOrdDetails);
                         }
                         if (WriteMoentry.Any())
@@ -2067,7 +2070,7 @@ namespace Business.ResourceExamineManagement
                     poDto.polist = new List<srm_po_list>();
                     pOGroupDtos.Add(poDto);
                 }
-                item.state = 0;
+                item.state = 4;
                 srm_po_list podetail = new srm_po_list();
                 podetail.GenerateNewId(help.NextId());
                 podetail.pr_id = item.Id;
@@ -2091,7 +2094,7 @@ namespace Business.ResourceExamineManagement
                 podetail.plan_qty = item.pr_aqty;
                 podetail.unit = item.pr_unit;
                 podetail.state = item.state;
-                podetail.rarrdate = item.pr_rarrive_date;
+                podetail.rarrdate = item.pr_sarrive_date;
                 podetail.rnumber = 0;
                 podetail.currencytype = item.currencytype;
                 podetail.create_time = DateTime.Now;
@@ -3009,6 +3012,7 @@ namespace Business.ResourceExamineManagement
             _morderAppService.param = param;
             _purchaseOrderAppService.param = param;
             _CalcBomViewAppService.param = param;
+            _CalcBomViewAppService.IsInverted = true;
             foreach (var item in mo_Mes_Morders)
             {
                 var moentry = mo_Mes_Moentries.Find(s => s.moentry_moid == item.Id);
@@ -3044,12 +3048,13 @@ namespace Business.ResourceExamineManagement
                     getBomList.ForEach(s => s.sentry_id = item.Id);
                 }
                 _CalcBomViewAppService.newStockOccList = new List<mo_ic_item_stockoccupy>();
+                _CalcBomViewAppService.morder_type = item.morder_type;
                 _CalcBomViewAppService.mes_morder = item;
                 //库存初始化
                 _CalcBomViewAppService.BomStock(getBomList, stocklist, bangid);
 
                 //计算
-                _CalcBomViewAppService.CalcView(getBomList, bangid, item.need_number.GetValueOrDefault(), item.start_time, sklist, sentry, item.urgent, icitemlist);
+                _CalcBomViewAppService.CalcView(getBomList, bangid, item.need_number.GetValueOrDefault(), item.start_time, sklist, sentry, icitemlist);
                 
                 //TODO:最晚开始时间
                 var curFacDtl = leadTimeList.FirstOrDefault(p => p.item_id == childBom.icitem_id);
@@ -3109,7 +3114,7 @@ namespace Business.ResourceExamineManagement
                     /*var exa = rtn.examines.Find(s => s.morder_no == wod.WorkOrd);
                     exa.latest_times = morder.moentry_sys_etime.GetValueOrDefault().Date.AddDays(1);*/
                     //根据排产后得日期,反推PR。
-                    var wkordPrList = prmainlist.Where(s => s.pr_mono == wod.WorkOrd).ToList();
+                    /*var wkordPrList = prmainlist.Where(s => s.pr_mono == wod.WorkOrd).ToList();
 
                     //反算所有的PR,根据时间减去提前期   //按最大预处理时间倒排
                     var moIcitems = icitemlist.Where(s => s.is_clean == 1 && wkordPrList.Select(c => c.icitem_id).Contains(s.mysql_id)).ToList();
@@ -3130,7 +3135,7 @@ namespace Business.ResourceExamineManagement
                         {
                             pr.pr_ssend_date = DateTime.Now.Date.AddDays(1);
                         }
-                    });
+                    });*/
                 }
                 using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
                 {
@@ -3251,6 +3256,10 @@ namespace Business.ResourceExamineManagement
             _CalcBomViewAppService.srm_Po_Occupies = poOccupys; //采购占用表
             _CalcBomViewAppService.ic_item_List = icitemlist; //物料表
             _CalcBomViewAppService.srm_Pr_Mains = srm_pr_mains;//PR
+            DateTime dt = DateTime.Now;
+            _CalcBomViewAppService.quarter_starttime = dt.AddMonths(0 - (dt.Month - 1) % 3).AddDays(1 - dt.Day).Date;
+            _CalcBomViewAppService.quarter_endtime = _CalcBomViewAppService.quarter_starttime.AddMonths(3);
+            _CalcBomViewAppService.quarter_srm_pr_mains = srm_pr_mains.Where(s => s.pr_psend_date >= _CalcBomViewAppService.quarter_starttime && s.pr_psend_date < _CalcBomViewAppService.quarter_endtime).ToList();//本季度PR
         }
 
         public void GenerateSort(List<BomChildExamineDto> returnlist)
@@ -3382,7 +3391,7 @@ namespace Business.ResourceExamineManagement
                 var Items = _mysql_ic_item.GetListAsync(s => workDetails.Select(c => c.ItemNum).Contains(s.number) && s.factory_id.ToString() == workOrdMasters[0].Domain).Result;
                 List<ItemMaster> itemMasterList = _itemMaster.Select(p => workDetails.Select(c => c.ItemNum).Contains(p.ItemNum) && p.Domain == workOrdMasters[0].Domain).Distinct().ToList();
 
-                //按照工单领料,一个工单一个领料单,之前是按照排产日期和产线分别领料
+                //按照工单领料,之前是按照排产日期和产线分别领料
                 foreach (var workord in workOrdMasters)
                 {
                     Dictionary<string, decimal> dictItemQty = new Dictionary<string, decimal>();
@@ -3487,7 +3496,7 @@ namespace Business.ResourceExamineManagement
         {
             var Nbr = GetMaxSerialNumber(417416915624005);
             DateTime eff = workord.OrdDate.GetValueOrDefault().Date.AddDays(-1);
-            DateTime start = eff.AddDays((double)(0 - cleanTime - 1));
+            DateTime start = eff.AddDays((double)(0 - cleanTime));
             if (start <= DateTime.Now.Date)
             {
                 start = DateTime.Now.Date;
@@ -3520,6 +3529,7 @@ namespace Business.ResourceExamineManagement
             nbrMasterList.Add(newNbr);
             List<string> headAccount = new List<string>();
             int i = 1;
+            bool typed = string.IsNullOrEmpty(workord.Typed);
             detail.ForEach(a =>
             {
                 var find = itemLocList?.Find(c => c.ItemNum == a.ItemNum);
@@ -3556,7 +3566,8 @@ namespace Business.ResourceExamineManagement
                             UpdateTime = DateTime.Now,
                             CreateUser = user?.Name,
                             UpdateUser = user?.Name,
-                            UM = find.UM
+                            UM = find.UM,
+                            LotSerial = typed ? a.LotSerial : ""
                         });
                         i++;
                     }
@@ -3864,7 +3875,7 @@ namespace Business.ResourceExamineManagement
                 workOrd.IsConfirm = true;
                 workOrd.CreateTime = DateTime.Now;
                 workOrd.Batch = item.morder_no;
-                workOrd.Typed = "s";
+                workOrd.Typed = "";
                 workOrds.Add(workOrd);
 
                 //添加工单工艺路线数据
@@ -4274,15 +4285,12 @@ namespace Business.ResourceExamineManagement
         /// <exception cref="NotImplementedException"></exception>
         public async Task<string> ProductionSchedule(string domain)
         {
-            //获取排产锁定期
-            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 _productionScheduleAppService.DoProductSchedule(workOrds, domain, 2);
             return "ok";
         }

+ 12 - 0
MicroServices/Business/Business.Domain/StructuredDB/Bang/b_bom_pretreatment.cs

@@ -176,5 +176,17 @@ namespace Business.Domain
         /// </summary>
         [Comment("工序")]
         public int Op { get; set; }
+
+        /// <summary>
+        /// 物料前处理天数
+        /// </summary>
+        public decimal? clean_leadtime { get; set; }
+
+        /// <summary>
+        /// 供应提前期
+        /// </summary>
+        [StringLength(80)]
+        [Comment("供应提前期")]
+        public int PurLT { get; set; }
     }
 }

+ 5 - 0
MicroServices/Business/Business.Domain/StructuredDB/MES/IC/NbrDetail.cs

@@ -133,5 +133,10 @@ namespace Business.Domain
         [Comment("修改人")]
         public string UpdateUser { get; set; }
 
+        /// <summary>
+        /// 批次序列
+        /// </summary>
+        [Comment("批次序列")]
+        public string LotSerial { get; set; }
     }
 }

+ 1 - 1
MicroServices/Business/Business.Domain/StructuredDB/MES/IC/NbrMaster.cs

@@ -52,7 +52,7 @@ namespace Business.Domain
         public DateTime? Date { get; set; }
 
         /// <summary>
-        /// 状态:C为不可用状态
+        /// 状态:C为已下架、出库
         /// </summary>
         [Comment("状态")]
         public string Status { get; set; }

+ 12 - 0
MicroServices/Business/Business.Domain/StructuredDB/Production/WorkOrdDetail.cs

@@ -86,5 +86,17 @@ namespace Business.Domain
         /// </summary>
         [Comment("创建时间")]
         public DateTime? CreateTime { get; set; }
+
+        /// <summary>
+        /// 批次序列
+        /// </summary>
+        [Comment("批次序列")]
+        public string LotSerial { get; set; }
+
+        /// <summary>
+        /// 工单主键
+        /// </summary>
+        [Comment("工单主键")]
+        public int WorkOrdMasterRecID { get; set; }
     }
 }

+ 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>

+ 7 - 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>
@@ -122,5 +122,11 @@ namespace Business.Domain
         /// </summary>
         [Comment("创建时间")]
         public DateTime? CreateTime { get; set; }
+
+        /// <summary>
+        /// 工单主键
+        /// </summary>
+        [Comment("工单主键")]
+        public int WorkOrdMasterRecID { get; set; }
     }
 }