Browse Source

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

heteng 2 years ago
parent
commit
71307d2b37
54 changed files with 3153 additions and 1753 deletions
  1. 4 0
      MicroServices/Business/Business.Application.Contracts/Business.Application.Contracts.csproj
  2. 44 2
      MicroServices/Business/Business.Application.Contracts/ReplenishmentManagement/IReplenishmentAppService.cs
  3. 13 3
      MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/Dto/BomChildExamineDto.cs
  4. 1 1
      MicroServices/Business/Business.Application.Contracts/ResourceExamineManagement/Dto/SRMPRDto.cs
  5. 0 20
      MicroServices/Business/Business.Application.Contracts/SaleForecast/IAnnualProductionOutlineAppService.cs
  6. 0 38
      MicroServices/Business/Business.Application.Contracts/SaleForecast/IMonthlyCapacityLoadAppService.cs
  7. 784 31
      MicroServices/Business/Business.Application/ReplenishmentManagement/ReplenishmentAppService.cs
  8. 348 120
      MicroServices/Business/Business.Application/ResourceExamineManagement/CalcBomViewAppService.cs
  9. 6 14
      MicroServices/Business/Business.Application/ResourceExamineManagement/MorderAppService.cs
  10. 5 0
      MicroServices/Business/Business.Application/ResourceExamineManagement/PretreatmentAppService.cs
  11. 3 2
      MicroServices/Business/Business.Application/ResourceExamineManagement/PurchaseOrderAppService.cs
  12. 39 26
      MicroServices/Business/Business.Application/ResourceExamineManagement/ResourceExamineAppService.cs
  13. 0 308
      MicroServices/Business/Business.Application/SaleForecastManagement/AnnualProductionOutlineAppService.cs
  14. 0 1034
      MicroServices/Business/Business.Application/SaleForecastManagement/MonthlyCapacityLoadAppService.cs
  15. 9 0
      MicroServices/Business/Business.Domain/MongoDB/MES/IC/mo_ic_item.cs
  16. 12 0
      MicroServices/Business/Business.Domain/StructuredDB/Bang/b_bom_pretreatment.cs
  17. 5 0
      MicroServices/Business/Business.Domain/StructuredDB/MES/IC/NbrDetail.cs
  18. 9 0
      MicroServices/Business/Business.Domain/StructuredDB/MES/IC/ic_item.cs
  19. 6 0
      MicroServices/Business/Business.Domain/StructuredDB/Production/WorkOrdDetail.cs
  20. 2 2
      MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentAnnualProduction.cs
  21. 176 0
      MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentMonthPlan.cs
  22. 3 3
      MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentROP.cs
  23. 3 3
      MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentServiceLevel.cs
  24. 193 0
      MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentWeekPlan.cs
  25. 2 2
      MicroServices/Business/Business.EntityFrameworkCore/EntityFrameworkCore/BusinessDbContextModelCreatingExtensions.cs
  26. 4 3
      MicroServices/Business/Business.EntityFrameworkCore/EntityFrameworkCore/DOP/BusinessDbContext.cs
  27. 0 47
      MicroServices/Business/Business.HttpApi/Controllers/AnnualProductionOutlineController.cs
  28. 0 73
      MicroServices/Business/Business.HttpApi/Controllers/MonthlyCapacityLoadController.cs
  29. 70 20
      MicroServices/Business/Business.HttpApi/Controllers/ReplenishmentController.cs
  30. 60 0
      MicroServices/Business/QuartzSettings/logs/logs.txt
  31. 1 1
      MicroServices/Business/QuartzSettings/task_job.json
  32. 51 0
      MicroServices/DopInterfacePlatform/ClientIpCheckActionFilter.cs
  33. 40 0
      MicroServices/DopInterfacePlatform/Controllers/TokenController.cs
  34. 73 0
      MicroServices/DopInterfacePlatform/Controllers/WeatherForecastController.cs
  35. 23 0
      MicroServices/DopInterfacePlatform/DopInterfacePlatform.csproj
  36. 8 0
      MicroServices/DopInterfacePlatform/DopInterfacePlatform.csproj.user
  37. 25 0
      MicroServices/DopInterfacePlatform/DopInterfacePlatform.sln
  38. 14 0
      MicroServices/DopInterfacePlatform/DopInterfacePlatformContext.cs
  39. 49 0
      MicroServices/DopInterfacePlatform/Entity/InterfacePlatformLog.cs
  40. 9 0
      MicroServices/DopInterfacePlatform/Interface/IJwtService.cs
  41. 55 0
      MicroServices/DopInterfacePlatform/IpWhiteListMiddleware.cs
  42. 28 0
      MicroServices/DopInterfacePlatform/JWTExtensions.cs
  43. 25 0
      MicroServices/DopInterfacePlatform/JwtOptions.cs
  44. 108 0
      MicroServices/DopInterfacePlatform/LogFilter.cs
  45. 65 0
      MicroServices/DopInterfacePlatform/Program.cs
  46. 21 0
      MicroServices/DopInterfacePlatform/Properties/PublishProfiles/FolderProfile.pubxml
  47. 11 0
      MicroServices/DopInterfacePlatform/Properties/PublishProfiles/FolderProfile.pubxml.user
  48. 31 0
      MicroServices/DopInterfacePlatform/Properties/launchSettings.json
  49. 21 0
      MicroServices/DopInterfacePlatform/Service/JwtService.cs
  50. 610 0
      MicroServices/DopInterfacePlatform/StringHelper.cs
  51. 44 0
      MicroServices/DopInterfacePlatform/SwaggerGenOptionsExtensions.cs
  52. 13 0
      MicroServices/DopInterfacePlatform/WeatherForecast.cs
  53. 8 0
      MicroServices/DopInterfacePlatform/appsettings.Development.json
  54. 19 0
      MicroServices/DopInterfacePlatform/appsettings.json

+ 4 - 0
MicroServices/Business/Business.Application.Contracts/Business.Application.Contracts.csproj

@@ -41,4 +41,8 @@
     <ProjectReference Include="..\Business.Domain\Business.Domain.csproj" />
   </ItemGroup>
 
+  <ItemGroup>
+    <Folder Include="SaleForecast\" />
+  </ItemGroup>
+
 </Project>

+ 44 - 2
MicroServices/Business/Business.Application.Contracts/ReplenishmentManagement/IReplenishmentAppService.cs

@@ -1,4 +1,5 @@
 using Business.Dto;
+using Microsoft.AspNetCore.Mvc;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -9,18 +10,59 @@ namespace Business.ReplenishmentManagement
 {
     public interface IReplenishmentAppService
     {
+        /// <summary>
+        /// 生成年度生产大纲
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        Task<string> SaveAnnualProductionOutline(InputDto input);
+
+        /// <summary>
+        /// 刷新年度销售预测
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        Task<string> DemandAnalysis(InputDto input);
+
+        /// <summary>
+        /// 定时任务长周期物料
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        Task<string> CalcLongPeriodItemPR(InputDto input);
+
+        /// <summary>
+        /// 生成整体需求计划
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        //Task<string> OverallDemandPlan(InputDto input);
+
+
         /// <summary>
         /// 调整ROP和最高库存水位
         /// </summary>
         Task<string> CalcROP(InputDto input);
 
+        /// <summary>
+        /// 根据月计划生产周计划
+        /// </summary>
+        /// <param name="companyId">工厂id</param>
+        /// <returns></returns>
+        Task<string> CalcWeekPlan(InputDto input);
+
+        /// <summary>
+        /// 根据月计划生产周计划
+        /// </summary>
+        /// <param name="companyId">工厂id</param>
+        /// <returns></returns>
+        Task<string> CalcDayPlan(InputDto input);
+
         /// <summary>
         /// 检查所有成品半成品原材料是否需要补货先判断SS再判断ROP
         /// </summary>
         /// <param name="input"></param>
         /// <returns></returns>
         Task<string> DayCheckAllByFinalGoods(InputDto input);
-
-        Task<string> LongPeriodItemPR(InputDto input, int month);
     }
 }

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

+ 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>
         /// 订单价格(含税)

+ 0 - 20
MicroServices/Business/Business.Application.Contracts/SaleForecast/IAnnualProductionOutlineAppService.cs

@@ -1,20 +0,0 @@
-using Business.Dto;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Volo.Abp.Application.Services;
-
-namespace Business.SaleForecast
-{
-    public interface IAnnualProductionOutlineAppService : IApplicationService
-    {
-        /// <summary>
-        /// 生成年度生产大纲
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        Task<string> SaveAnnualProductionOutline(InputDto input);
-    }
-}

+ 0 - 38
MicroServices/Business/Business.Application.Contracts/SaleForecast/IMonthlyCapacityLoadAppService.cs

@@ -1,38 +0,0 @@
-using Business.Dto;
-using Microsoft.AspNetCore.Mvc;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Volo.Abp.Application.Services;
-
-namespace Business.SaleForecast
-{
-    /// <summary>
-    /// 产能分析接口
-    /// </summary>
-    public interface IMonthlyCapacityLoadAppService: IApplicationService
-    {
-        ///// <summary>
-        ///// 产能分析
-        ///// </summary>
-        ///// <param name="input"></param>
-        ///// <returns></returns>
-        //Task<string> CapacityAnalysis(InputDto input);
-
-        /// <summary>
-        /// 月度需求分析
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        Task<string> DemandAnalysis(InputDto input);
-
-        /// <summary>
-        /// 生成整体需求计划
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        Task<string> OverallDemandPlan(InputDto input);
-    }
-}

File diff suppressed because it is too large
+ 784 - 31
MicroServices/Business/Business.Application/ReplenishmentManagement/ReplenishmentAppService.cs


+ 348 - 120
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
 {
@@ -32,6 +35,7 @@ namespace Business.ResourceExamineManagement
         public List<mo_ic_item> ic_item_List = new List<mo_ic_item>();
         public List<mo_srm_po_list> srm_Po_Lists = new List<mo_srm_po_list>();
         public List<mo_srm_po_occupy> srm_Po_Occupies = new List<mo_srm_po_occupy>();
+        public List<mo_srm_pr_main> srm_Pr_Mains = new List<mo_srm_pr_main>();
         public List<mo_srm_po_occupy> srm_Po_OccupiesInsert = new List<mo_srm_po_occupy>();
 
         public List<mo_ic_item_stockoccupy> newStockOccList = new List<mo_ic_item_stockoccupy>();
@@ -40,6 +44,16 @@ namespace Business.ResourceExamineManagement
 
         public mes_morder mes_morder = new mes_morder();
 
+        /// <summary>
+        /// 是否倒排
+        /// </summary>
+        public bool IsInverted = false;
+
+        /// <summary>
+        /// 工单类型
+        /// </summary>
+        public string morder_type;
+
         SnowFlake help = new SnowFlake();
 
         /// <summary>
@@ -138,7 +152,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;
             //第一级
@@ -253,12 +267,14 @@ namespace Business.ResourceExamineManagement
                     //先设定在制的齐套时间
                     //level1Dto.satisfy_time = mooccupylist[0]?.moo_etime;
                     level1Dto.stock_state = 0;
-
+                    
                     if (param.checkflag || (!param.checkflag && param.checkPlan))
                     {
                         //根据成品属性来判断是自制还是委外还是外购,需要考虑这种场景
                         if (level1Dto.erp_cls == 1 && param.checkflag)
                         {
+                            //设置成品的生产时长为子物料的提前准备期
+                            level1Dto.make_time = 7;
                             //param.checkflag=true 销售订单产生工单
                             level1Dto.make_qty = level1Dto.lack_qty;
                             //生成主工单
@@ -271,12 +287,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);
                         }
                         else if (level1Dto.erp_cls == 3)
                         {
@@ -284,8 +300,13 @@ namespace Business.ResourceExamineManagement
                             CalcInTransit(sentrys, level1Dto, bangid, plan_date.GetValueOrDefault());
                             if (level1Dto.lack_qty > 0)
                             {
-                                //采购申请
-                                PackageSRMPR(level1Dto, bangid, sentrys);
+                                decimal itemPRQty = srm_Pr_Mains.Where(x => x.icitem_id.Value == level1Dto.item_id && x.pr_parrive_date <= plan_date).Sum(y => y.pr_aqty.GetValueOrDefault());
+                                if (itemPRQty < level1Dto.lack_qty)
+                                {
+                                    level1Dto.lack_qty = level1Dto.lack_qty - itemPRQty;
+                                    //采购申请
+                                    PackageSRMPR(level1Dto, bangid, sentrys, plan_date);
+                                }
                             }
                         }
                         else if (level1Dto.erp_cls == 2)
@@ -294,18 +315,30 @@ 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);
+                                level1Dto.make_time = srmprDto.totalLeadTime;//加上物料的采购提前期
+                                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.生成采购申请
                                 //采购申请
-                                PackageSRMPR(level1Dto, bangid, sentrys);
+                                decimal itemPRQty = srm_Pr_Mains.Where(x => x.icitem_id.Value == level1Dto.item_id && x.pr_parrive_date <= plan_date).Sum(y => y.pr_aqty.GetValueOrDefault());
+                                if (itemPRQty < level1Dto.lack_qty)
+                                {
+                                    level1Dto.lack_qty = level1Dto.lack_qty - itemPRQty;
+                                    //采购申请
+                                    PackageSRMPR(level1Dto, bangid, sentrys, plan_date);
+                                }
+                                //PackageSRMPR(level1Dto, bangid, sentrys);
 
                                 level1Dto.subcontracting_qty = level1Dto.lack_qty;
                                 level1Dto.subcontracting_list = new List<ooder>();
@@ -316,7 +349,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);
@@ -325,13 +358,15 @@ namespace Business.ResourceExamineManagement
                         }
                         else
                         {
+                            level1Dto.make_time = 7;
                             MatterTileDevelop(level1Dto, childList, returnlist, sklist, bangid, plan_date, sentrys, icitemlist);
                         }
                     }
                     else {
+                        level1Dto.make_time = 7;
                         MatterTileDevelop(level1Dto, childList, returnlist, sklist, bangid, plan_date, sentrys, icitemlist);
                     }
-                    CalcLevelMakeTime(returnlist);
+                    //CalcLevelMakeTime(returnlist);
                 }
             }
             else
@@ -345,7 +380,7 @@ namespace Business.ResourceExamineManagement
             }
         }
 
-        //计算每层物料倒排时,需要根据半成品的工作时长倒排。
+        /*//计算每层物料倒排时,需要根据半成品的工作时长倒排。
         public void CalcLevelMakeTime(List<BomChildExamineDto> returnlist)
         {
             for (int level = 3; level <= returnlist.Max(s => s.level); level++)
@@ -359,14 +394,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)
         {
             //生成主工单
             _morderAppService.prodLines = prodLines;
@@ -376,7 +411,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)
             {
@@ -385,12 +420,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(-(level1Dto.make_time.GetValueOrDefault() - 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(level1Dto.make_time.GetValueOrDefault());
+
+                        /*ProdExamineParamDto prodExamine = new ProdExamineParamDto()
                         {
                             ItemNum = mes_Morders.bom_number,
                             PlanStart = mes_Morders.moentry_sys_stime.Value,
@@ -403,28 +450,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;
@@ -632,6 +666,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)
@@ -643,22 +678,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;
@@ -670,17 +716,72 @@ 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);
+                        int make = 7;
+                        item.make_time += make;
                         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()
                         {
@@ -715,29 +816,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();
@@ -1061,6 +1163,7 @@ namespace Business.ResourceExamineManagement
                 //对select执行补充(根据属性采购、外购、自制等)
                 foreach (var sct in select)
                 {
+                    sct.make_time = parent.make_time.GetValueOrDefault();
                     decimal sqty = sct.sqty - sct.use_qty;//这里得出前面混用使用后的库存。
                     decimal lack_Count = parent_lack * sct.qty;//混用后还缺的部分。
                     mo_ic_item_stockoccupy itemStockoccupyDto = new mo_ic_item_stockoccupy();
@@ -1101,36 +1204,111 @@ 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);
+                                int make = 7;
+                                sct.make_time += make;
+                                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)
                         {
@@ -1141,7 +1319,7 @@ namespace Business.ResourceExamineManagement
                                 if (sct.lack_qty > 0)
                                 {
                                     //采购申请
-                                    PackageSRMPR(sct, bangid, sentrys);
+                                    PackageSRMPR(sct, bangid, sentrys, plan_date);
                                 }
                             }
                         }
@@ -1153,16 +1331,19 @@ 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);
+                                    sct.make_time += srmprDto.totalLeadTime;//加上物料的采购提前期
+                                    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();
@@ -1172,7 +1353,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);
@@ -1214,24 +1395,58 @@ 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.make_time.GetValueOrDefault() - returnlist.clean_leadtime.GetValueOrDefault());
+                if (day > 0)
+                {
+                    supplist = supplist.Where(s => s.lead_time.GetValueOrDefault() < day).ToList();
+                    if (supplist.Any())
+                    {
+                        //TODO:走配额管理
+                        //按配额比例,计算使用哪个供应商。
+                        supplier = supplist.OrderByDescending(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();
@@ -1257,19 +1472,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;//状态
@@ -1285,13 +1511,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;
@@ -1332,8 +1559,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;//产品名称
@@ -1377,6 +1604,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())
             {
@@ -1409,10 +1637,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)
             {
@@ -1441,10 +1669,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;
         }
     }
 }

+ 6 - 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;
@@ -219,6 +218,7 @@ namespace Business.ResourceExamineManagement
             mes_Moentry.morder_production_number = generateMorderDto.Quantity;
             mes_Moentry.need_number = generateMorderDto.Quantity;
             mes_Moentry.remaining_number = 0;
+            mes_Moentry.tenant_id = param.company_id.GetValueOrDefault();
             mes_Moentry.factory_id = param.factoryId;
             mes_Moentry.company_id = param.company_id;
             mes_Moentry.org_id = param.org_id;
@@ -237,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>
@@ -256,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))
             {
@@ -288,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();
 
@@ -296,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

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

+ 39 - 26
MicroServices/Business/Business.Application/ResourceExamineManagement/ResourceExamineAppService.cs

@@ -459,7 +459,7 @@ namespace Business.ResourceExamineManagement
             IRepository<ic_substitute, long> mysql_ic_substitute,
             IRepository<ic_substitute_group, long> mysql_ic_substitute_group,
             IRepository<ic_substitute_group_detail, long> mysql_ic_substitute_group_detail,
-            IRepository<ReplenishmentModel, long> replenishmentModel,
+            IRepository<ReplenishmentROP, long> replenishmentROP,
             IRepository<DomesticTerminalFcst, long> domesticTerminalFcst,
             ISqlRepository<ASNBOLShipperDetail> ASNBOLShipperDetail,
             IRepository<StandardItemModelSet, long> standardItemModelSet,
@@ -666,6 +666,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;
@@ -675,13 +677,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;
@@ -708,7 +708,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);
@@ -1035,9 +1035,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
@@ -1114,18 +1114,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; });
@@ -1288,8 +1282,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())
             {
@@ -1886,6 +1880,15 @@ namespace Business.ResourceExamineManagement
                 moSrm_po_occupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; });
                 await _srm_po_occupy.InsertManyAsync(moSrm_po_occupy);
             }
+
+            //pr
+            var srm_pr_main = _mysql_srm_pr_main.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && itemIds.Contains(x.icitem_id.GetValueOrDefault())).Result;
+            if(srm_pr_main.Count>0)
+            {
+                var moSrm_pr_main = ObjectMapper.Map<List<srm_pr_main>, List<mo_srm_pr_main>>(srm_pr_main);
+                moSrm_pr_main.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; });
+                await _srm_pr_main.InsertManyAsync(moSrm_pr_main);
+            }
         }
 
         /// <summary>
@@ -1914,6 +1917,9 @@ namespace Business.ResourceExamineManagement
 
             //清除采购订单占用详情
             //await _srm_po_occupy.DeleteAsync(p => p.bang_id == bangid);
+
+            //清除PR
+            await _srm_pr_main.DeleteAsync(p => p.bang_id == bangid);
         }
 
         /// <summary>
@@ -2078,7 +2084,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;
@@ -2996,6 +3002,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);
@@ -3031,12 +3038,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);
@@ -3205,6 +3213,8 @@ namespace Business.ResourceExamineManagement
             var poDetailList = _srm_po_list.GetListAsync(x => icitemlist.Select(p => p.mysql_id).ToList().Contains(x.icitem_id.Value) && x.bang_id == bangid && x.state == 1 && x.rstate == 1 && !x.IsDeleted).Result;
             //采购订单占用数据
             var poOccupys = _srm_po_occupy.GetListAsync(x => poDetailList.Select(p => p.Id).ToList().Contains(x.polist_id) && x.bang_id == bangid && !x.IsDeleted).Result;
+
+            var srm_pr_mains = _srm_pr_main.GetListAsync(x => icitemlist.Select(p => p.mysql_id).ToList().Contains(x.icitem_id.Value) && x.bang_id == bangid && x.state == 0 && !x.IsDeleted).Result;
             #endregion
 
             //处理一下已经插入得占用记录
@@ -3235,6 +3245,7 @@ namespace Business.ResourceExamineManagement
             _CalcBomViewAppService.srm_Po_Lists = poDetailList; //采购明细
             _CalcBomViewAppService.srm_Po_Occupies = poOccupys; //采购占用表
             _CalcBomViewAppService.ic_item_List = icitemlist; //物料表
+            _CalcBomViewAppService.srm_Pr_Mains = srm_pr_mains;//PR
         }
 
         public void GenerateSort(List<BomChildExamineDto> returnlist)
@@ -3366,7 +3377,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>();
@@ -3504,6 +3515,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);
@@ -3540,7 +3552,8 @@ namespace Business.ResourceExamineManagement
                             UpdateTime = DateTime.Now,
                             CreateUser = user?.Name,
                             UpdateUser = user?.Name,
-                            UM = find.UM
+                            UM = find.UM,
+                            LotSerial = typed ? a.LotSerial : ""
                         });
                         i++;
                     }
@@ -3848,7 +3861,7 @@ namespace Business.ResourceExamineManagement
                 workOrd.IsConfirm = true;
                 workOrd.CreateTime = DateTime.Now;
                 workOrd.Batch = item.morder_no;
-                workOrd.Typed = "s";
+                workOrd.Typed = "";
                 workOrds.Add(workOrd);
 
                 //添加工单工艺路线数据

+ 0 - 308
MicroServices/Business/Business.Application/SaleForecastManagement/AnnualProductionOutlineAppService.cs

@@ -1,308 +0,0 @@
-using Business.Core.Enum;
-using Business.Core.Utilities;
-using Business.Domain;
-using Business.Dto;
-using Business.EntityFrameworkCore.SqlRepositories;
-using Business.SaleForecast;
-using Business.StructuredDB.SaleFcst;
-using Business.StructuredDB.WMS;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using NetTopologySuite.Algorithm;
-using RazorEngine;
-using Spire.Pdf.General.Render.Decode.Jpeg2000.j2k.wavelet.synthesis;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Volo.Abp.Application.Dtos;
-using Volo.Abp.Application.Services;
-using Volo.Abp.DependencyInjection;
-using Volo.Abp.Domain.Repositories;
-using Volo.Abp.MultiTenancy;
-using Volo.Abp.Uow;
-using ZstdSharp.Unsafe;
-using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
-
-namespace Business.SaleForecastManagement
-{
-    public class AnnualProductionOutlineAppService : ApplicationService, ITransientDependency, IAnnualProductionOutlineAppService
-    {
-        #region 服务
-        /// <summary>
-        /// 工作单元
-        /// </summary>
-        private readonly IUnitOfWorkManager _unitOfWorkManager;
-
-        /// <summary>
-        /// 日志
-        /// </summary>
-        private readonly ICurrentTenant _currentTenant;
-
-        /// <summary>
-        /// 年度销售预测
-        /// </summary>
-        private IRepository<YearDemandManagement, long> _yearDemandManagement;
-
-        /// <summary>
-        /// 年度销售预测历史记录
-        /// </summary>
-        private IRepository<YearDemandManagementHistory, long> _yearDemandManagementHistory;
-
-        /// <summary>
-        /// 年度生产大纲
-        /// </summary>
-        private IRepository<AnnualProductionOutline, long> _annualProductionOutline;
-
-        /// <summary>
-        /// 生产线明细
-        /// </summary>
-        private ISqlRepository<ProdLineDetail> _prodLineDetail;
-
-        /// <summary>
-        /// 标准工艺流程表
-        /// </summary>
-        private ISqlRepository<RoutingOpDetail> _routingOpDetail;
-        /// <summary>
-        /// 库存表
-        /// </summary>
-        private ISqlRepository<LocationDetail> _locationDetail;
-        /// <summary>
-        /// 平台库存表
-        /// </summary>
-        private readonly IRepository<WMS_PlatformInventory, long> _PlatformInventory;
-        /// <summary>
-        /// 已发货记录
-        /// </summary>
-        private ISqlRepository<ASNBOLShipperDetail> _ASNBOLShipperDetail;
-        /// <summary>
-        /// 工单工艺路线明细
-        /// </summary>
-        private ISqlRepository<WorkOrdRouting> _workOrdRouting;
-        /// <summary>
-        /// 补货模型
-        /// </summary>
-        private IRepository<ReplenishmentModel, long> _replenishmentModel;
-        /// <summary>
-        /// 主生产计划
-        /// </summary>
-        private IRepository<ProductionMasterPlan, long> _productionMasterPlan;
-
-
-        /// <summary>
-        /// 雪花算法
-        /// </summary>
-        SnowFlake help = new SnowFlake();
-        #endregion
-
-        #region 构造函数
-        /// <summary>
-        /// 构造函数
-        /// </summary>
-        public AnnualProductionOutlineAppService(
-
-            IUnitOfWorkManager unitOfWorkManager,
-            ICurrentTenant currentTenant,
-            IRepository<YearDemandManagement, long> yearDemandManagement,
-            IRepository<AnnualProductionOutline, long> annualProductionOutline,
-            IRepository<YearDemandManagementHistory, long> yearDemandManagementHistory,
-            ISqlRepository<ProdLineDetail> prodLineDetail,
-            IRepository<WMS_PlatformInventory, long> PlatformInventory,
-            ISqlRepository<RoutingOpDetail> routingOpDetail,
-            ISqlRepository<ASNBOLShipperDetail> ASNBOLShipperDetail,
-            ISqlRepository<WorkOrdRouting> workOrdRouting,
-            ISqlRepository<LocationDetail> locationDetail,
-            IRepository<ReplenishmentModel, long> replenishmentModel,
-            IRepository<ProductionMasterPlan, long> productionMasterPlan
-            )
-        {
-            _unitOfWorkManager = unitOfWorkManager;
-            _currentTenant = currentTenant;
-            _PlatformInventory = PlatformInventory;
-            _prodLineDetail = prodLineDetail;
-            _workOrdRouting = workOrdRouting;
-            _routingOpDetail = routingOpDetail;
-            _locationDetail = locationDetail;
-            _ASNBOLShipperDetail = ASNBOLShipperDetail;
-            _yearDemandManagement = yearDemandManagement;
-            _yearDemandManagementHistory = yearDemandManagementHistory;
-            _annualProductionOutline = annualProductionOutline;
-            _replenishmentModel = replenishmentModel;
-            _productionMasterPlan = productionMasterPlan;
-        }
-        #endregion
-        /// <summary>
-        /// 生成年度生产大纲
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        /// <exception cref="NotImplementedException"></exception>
-        public async Task<string> SaveAnnualProductionOutline(InputDto input)
-        {
-            //获取当前导入或修改数据
-            List<YearDemandManagement> yearDemands = _yearDemandManagement.GetListAsync(p => p.Year == input.year && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ThenBy(o => o.PlanMonth).ToList();
-            //标准工艺路径表
-            List<RoutingOpDetail> routingOps = _routingOpDetail.Select(p => yearDemands.Select(m => m.SAPItemNumber).Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
-            var routingOpList = routingOps.Where(x => x.Descr == "组装").ToList();
-            //生产线明细表
-            List<ProdLineDetail> prodLines = _prodLineDetail.Select(p => yearDemands.Select(m => m.SAPItemNumber).Contains(p.Part) && p.Domain == input.factory_id.ToString() && p.IsActive && routingOpList.Select(m => m.Op).Contains(p.Op)).OrderBy(x => x.Sequence).ToList();
-            List<LocationDetail> locations = _locationDetail.Select(x => yearDemands.Select(m => m.SAPItemNumber).Contains(x.ItemNum) && x.Domain == input.factory_id.ToString() && x.IsActive).ToList();
-            //平台库存
-            var platformInvList = _PlatformInventory.GetListAsync(a => yearDemands.Select(m => m.SAPItemNumber).Contains(a.SAPItemNumber) && a.tenant_id == input.tenant_id && a.factory_id == input.factory_id && !a.IsDeleted).Result;
-            var replenishmentModels = _replenishmentModel.GetListAsync(x => !x.IsDeleted && x.isparam && yearDemands.Select(m => m.SAPItemNumber).Contains(x.number)).Result.ToList();
-            // 获取某年某月的起始日期和结束日期
-            int year = input.year;
-            int month = DateTime.Now.Month;
-            DateTime start = new DateTime(year, month, 1);
-            DateTime end = start.AddMonths(1).AddDays(-1);
-            //取当月发货出库记录
-            var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && yearDemands.Select(p => p.SAPItemNumber).Contains(a.ContainerItem)).Where(s => s.ShipDate >= start && s.ShipDate <= end);
-            #region 在制数量
-            //获取在制数量 获取工单数取每年4月到12月底的工单
-            DateTime startYear = new DateTime(year, 4, 1);
-            DateTime endYear = new DateTime(year, 12, 31);
-            List<WorkOrdRouting> workOrdRoutings = _workOrdRouting.Select(x => x.IsActive && x.QtyComplete > 0 && x.Domain == input.factory_id.ToString()).Where(p => p.DueDate >= startYear && p.DueDate <= endYear).ToList();
-            decimal? InProductionQty = 0.00m;
-            var workOrds = workOrdRoutings.GroupBy(x => x.WorkOrd).ToList();
-            //按照工单循环
-            //某工单10-90工序   Max(10-80工序QtyComplete)-90工序QtyComplete =在制数量
-            foreach (var item in workOrds)
-            {
-                var workOrdRoutingList = workOrdRoutings.Where(x => x.WorkOrd == item.Key).OrderByDescending(o => o.OP).ToList();
-                //找出最大工序
-                var MaxOp = workOrdRoutingList.FirstOrDefault();
-                //查询出其他工序最大值
-                var MaxQtyComplete = workOrdRoutingList.Where(x => x.RecID != MaxOp.RecID).ToList().Max(o => o.QtyComplete);
-                InProductionQty += MaxQtyComplete - MaxOp.QtyComplete;
-            }
-            #endregion
-            //年度生产大纲实体
-            List<AnnualProductionOutline> annualProductionOutlines = new List<AnnualProductionOutline>();
-            List<YearDemandManagement> frontYearDemand = new List<YearDemandManagement>();
-            foreach (var item in yearDemands)
-            {
-                var routingOp = routingOps.Where(x => x.RoutingCode == item.SAPItemNumber).ToList();
-                //组装标准工时
-                var Assembly = routingOp.Where(x => x.Descr == "组装").FirstOrDefault();
-                //热封标准工时
-                var HeatSealing = routingOp.Where(x => x.Descr == "热封").FirstOrDefault();
-                //包装标准工时
-                var Packaging = routingOp.Where(x => x.Descr == "包装").FirstOrDefault();
-                var prodLine = prodLines.Where(x => x.Part == item.SAPItemNumber).OrderBy(x => x.Sequence).FirstOrDefault();
-                //不同库位库存数量
-                var locationList = locations.Where(x => x.ItemNum == item.SAPItemNumber).ToList();
-                //平台数据
-                var platformInvs = platformInvList.Where(x => x.SAPItemNumber == item.SAPItemNumber).ToList();
-                //销售预测 对应 Excel中公式 AVERAGE 如果预测为0不参与计算排产批量
-                var QtySum = yearDemands.Where(x => x.SAPItemNumber == item.SAPItemNumber && x.Qty > 0).ToList();
-                //排产批量:(AVG(1 - 12月销售预测)/ 100 )=(0.45 = 1 小数向上取整)  *100 = 100
-                var pcpl = Math.Ceiling(QtySum.Sum(p => p.Qty) / QtySum.Count()) * 100;
-                //库存合计 + 在制+已发货 + 灭菌中 TODO: 灭菌中取值待确定
-                var ship = shipList.Where(x => x.ContainerItem == item.SAPItemNumber).ToList();
-                var locationSum = (locationList.Count == 0 ? 0 : locationList.Sum(x => x.QtyOnHand)) + (platformInvs.Count == 0 ? 0 : platformInvs.Sum(x => x.InventoryQuantity)) + (ship.Count == 0 ? 0 : ship.Sum(x => x.RealQty)) + InProductionQty + 0;
-                //前面N个月的生产数量
-                var frontQtySum = annualProductionOutlines.Sum(x => x.Qty);
-                //生产数量:3月为例子,if((库存合计和前2月生产数量)-(前2个月销售预测数据+安全库存)-当月销售预测数据 / 2 < 0)
-                // { 排产批量 * ((-(库存合计+前2个月生产数量)) +  (安全库存+前2个月销售预测) + 当月销售预测 / 2 ) / 排产批量 ) } else {0}
-                decimal ProduceQty = 0.00m;
-                //判断库存是否满足需要,满足则不用生产
-                var num = (locationSum.Value + frontQtySum) - frontYearDemand.Sum(m => m.Qty) + 0 - item.Qty / 2;
-                if (num < 0)
-                {
-                    ProduceQty = pcpl * Math.Ceiling((-(locationSum.Value + frontQtySum)) + (frontYearDemand.Sum(m => m.Qty) + 0) + item.Qty / 2);
-                }
-                else
-                {
-                    ProduceQty = 0;
-                }
-
-                //生成年度生产大纲
-                AnnualProductionOutline annualProductionOutline = new AnnualProductionOutline();
-                annualProductionOutline.Year = item.Year;
-                annualProductionOutline.Area = item.Area;
-                annualProductionOutline.ProdLine = item.ProdLine;
-                annualProductionOutline.ProdRange = item.ProdRange;
-                annualProductionOutline.WorkshopLine = prodLine == null ? "" : prodLine.Line;
-                annualProductionOutline.SAPItemNumber = item.SAPItemNumber;
-                annualProductionOutline.Model = item.Model;
-                annualProductionOutline.Languages = item.Languages;
-                annualProductionOutline.PlanMonth = item.PlanMonth;
-                annualProductionOutline.Qty = ProduceQty;
-                annualProductionOutline.StandardHours = (Assembly == null ? 0 : Assembly.RunTime) + (HeatSealing == null ? 0 : HeatSealing.RunTime) + (Packaging == null ? 0 : Packaging.RunTime);
-                //组装热封包装工时乘以数量 =单月工时
-                annualProductionOutline.AssemblyHours = Assembly == null ? 0 : Assembly.RunTime * ProduceQty;
-                annualProductionOutline.HeatSealingHours = HeatSealing == null ? 0 : HeatSealing.RunTime * ProduceQty;
-                annualProductionOutline.PackagingHours = Packaging == null ? 0 : Packaging.RunTime * ProduceQty;
-                annualProductionOutline.Totalhours = annualProductionOutline.AssemblyHours + annualProductionOutline.HeatSealingHours + annualProductionOutline.Totalhours;
-                annualProductionOutline.OrderNum = item.OrderNum;
-                annualProductionOutlines.Add(annualProductionOutline);
-                frontYearDemand.Add(item);
-            }
-            //保存数据
-            using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
-            {
-                try
-                {
-                    //await _annualProductionOutline.InsertManyAsync(annualProductionOutlines);
-                    await unitOfWork.CompleteAsync();
-                }
-                catch (Exception e)
-                {
-                    unitOfWork.Dispose();
-                    new NLogHelper("AnnualProductionOutlineAppService").WriteLog("SaveAnnualProductionOutline", "【" + input.year + "年" + "】年度生成大纲生成失败:" + e.Message, _currentTenant.Id.ToString());
-                    return "NO|" + e.Message;
-                };
-            }
-            return "OK";
-        }
-
-        /// <summary>
-        /// 生成主计划
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        public async Task<string> SaveProductionMasterPlan(InputDto input)
-        {
-            //计算当前年月的N0,N+1,N+2
-            List<string> planMons = new List<string>();
-            string strN0 = input.year.ToString() + "-" + input.month.ToString("00");
-            planMons.Add(strN0);
-            int newYear = input.month == 12 ? input.year + 1 : input.year;
-            int newMonth = input.month == 12 ? 1 : input.month + 1;
-            string strN1 = newYear.ToString() + "-" + newMonth.ToString("00");
-            planMons.Add(strN1);
-            newYear = newMonth == 12 ? newYear + 1 : newYear;
-            newMonth = newMonth == 12 ? 1 : newMonth + 1;
-            string strN2 = newYear.ToString() + "-" + newMonth.ToString("00");
-            planMons.Add(strN2);
-            //N0,N+1,N+2月度发货计划
-            var productionMasterPlan = _productionMasterPlan.GetListAsync(x => x.Year == input.year && !x.IsDeleted && x.tenant_id == input.tenant_id && x.company_id == input.company_id && x.factory_id == input.factory_id && planMons.Contains(x.PlanMonth)).Result.OrderBy(p => p.OrderNum).ThenBy(o => o.PlanMonth).ToList();
-            foreach (var item in productionMasterPlan)
-            {
-
-            }
-
-
-
-
-
-            //保存数据
-            using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
-            {
-                try
-                {
-                    //await _annualProductionOutline.InsertManyAsync(annualProductionOutlines);
-                    await unitOfWork.CompleteAsync();
-                }
-                catch (Exception e)
-                {
-                    unitOfWork.Dispose();
-                    new NLogHelper("AnnualProductionOutlineAppService").WriteLog("SaveProductionMasterPlan", "【" + input.year + "年" + "】主计划生成失败:" + e.Message, _currentTenant.Id.ToString());
-                    return "NO|" + e.Message;
-                };
-            }
-            return "OK";
-
-        }
-    }
-}

+ 0 - 1034
MicroServices/Business/Business.Application/SaleForecastManagement/MonthlyCapacityLoadAppService.cs

@@ -1,1034 +0,0 @@
-using Business.Core.Utilities;
-using Business.Domain;
-using Business.Dto;
-using Business.EntityFrameworkCore.SqlRepositories;
-using Business.SaleForecast;
-using Business.StructuredDB.WMS;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Volo.Abp.Application.Services;
-using Volo.Abp.DependencyInjection;
-using Volo.Abp.Domain.Repositories;
-using Volo.Abp.MultiTenancy;
-using Volo.Abp.Uow;
-
-namespace Business.SaleForecastManagement
-{
-    /// <summary>
-    /// 产能分析
-    /// </summary>
-    public class ReplenishmentAppService : ApplicationService, IMonthlyCapacityLoadAppService, ITransientDependency
-    {
-        #region 服务
-        /// <summary>
-        /// 物料
-        /// </summary>
-        private IRepository<ic_item, long> _ic_item;
-
-        /// <summary>
-        /// 生产线明细
-        /// </summary>
-        private ISqlRepository<ProdLineDetail> _prodLineDetail;
-
-        /// <summary>
-        /// 工作日历数据
-        /// </summary>
-        private ISqlRepository<ShopCalendarWorkCtr> _shopCalendarWorkCtr;
-
-        /// <summary>
-        /// 产线休息时间记录表
-        /// </summary>
-        private ISqlRepository<QualityLineWorkDetail> _qualityLineWorkDetail;
-
-        /// <summary>
-        /// 节假日记录表
-        /// </summary>
-        private ISqlRepository<HolidayMaster> _holidayMaster;
-
-        /// <summary>
-        /// 工作单元
-        /// </summary>
-        private readonly IUnitOfWorkManager _unitOfWorkManager;
-
-        /// <summary>
-        /// 日志
-        /// </summary>
-        private readonly ICurrentTenant _currentTenant;
-
-        /// <summary>
-        /// 年度生产需求大纲
-        /// </summary>
-        private IRepository<YearDemandManagement, long> _yearDemandManagement;
-
-        /// <summary>
-        /// 年度生产需求大纲历史记录
-        /// </summary>
-        private IRepository<YearDemandManagementHistory, long> _yearDemandManagementHistory;
-
-        /// <summary>
-        /// 国内终端预测
-        /// </summary>
-        private IRepository<DomesticTerminalFcst, long> _domesticTerminalFcst;
-
-        /// <summary>
-        /// 海外销售预测
-        /// </summary>
-        private IRepository<OverseasSaleFcst, long> _overseasSaleFcst;
-
-        /// <summary>
-        /// 平台预测收集
-        /// </summary>
-        private IRepository<PlatformFcstCollect, long> _platformFcstCollect;
-
-        /// <summary>
-        /// 标准物料规格型号设置表
-        /// </summary>
-        private IRepository<StandardItemModelSet,long> _standardItemModelSet;
-
-        /// <summary>
-        /// 库存明细表
-        /// </summary>
-        private ISqlRepository<LocationDetail> _locationDetail;
-
-        /// <summary>
-        /// 工单
-        /// </summary>
-        private ISqlRepository<WorkOrdMaster> _workOrdMaster;
-
-        /// <summary>
-        /// 整体需求计划
-        /// </summary>
-        private IRepository<OverallDemandPlan, long> _overallDemandPlan;
-
-        /// <summary>
-        /// 月度产能共识表
-        /// </summary>
-        private IRepository<MonthlyProdCapacity, long> _monthlyProdCapacity;
-
-        /// <summary>
-        /// 月度产能共识明细表
-        /// </summary>
-        private IRepository<MonthlyProdCapacityDtl, long> _monthlyProdCapacityDtl;
-
-        /// <summary>
-        /// SKU版本维护表
-        /// </summary>
-        private IRepository<SkuVersionSet, long> _skuVersionSet;
-
-        /// <summary>
-        /// 计划订单表
-        /// </summary>
-        private IRepository<crm_planorder, long> _crm_planorder;
-
-        /// <summary>
-        /// 平台库存监控月份
-        /// </summary>
-        private IRepository<PlatStockMonitorSetting, long> _platStockMonitorSetting;
-
-        /// <summary>
-        /// 平台库存表
-        /// </summary>
-        private IRepository<WMS_PlatformInventory, long> _platformInventory;
-
-        /// <summary>
-        /// 参数设置表
-        /// </summary>
-        private ISqlRepository<GeneralizedCodeMaster> _generalizedCodeMaster;
-
-        /// <summary>
-        /// SAP库存表
-        /// </summary>
-        private ISqlRepository<SAPInv> _SAPInv;
-
-        /// <summary>
-        /// 雪花算法
-        /// </summary>
-        SnowFlake help = new SnowFlake();
-        #endregion
-
-        #region 构造函数
-        /// <summary>
-        /// 构造函数
-        /// </summary>
-        public ReplenishmentAppService(
-            IRepository<ic_item, long> ic_item,
-            ISqlRepository<ProdLineDetail> prodLineDetail,
-            ISqlRepository<ShopCalendarWorkCtr> shopCalendarWorkCtr,
-            ISqlRepository<QualityLineWorkDetail> qualityLineWorkDetail,
-            ISqlRepository<HolidayMaster> holidayMaster,
-            IRepository<MonthlyProdCapacity, long> monthlyProdCapacity,
-            IUnitOfWorkManager unitOfWorkManager,
-            ICurrentTenant currentTenant,
-            IRepository<StandardItemModelSet,long> standardItemModelSet,
-            IRepository<YearDemandManagement, long> yearDemandManagement,
-            IRepository<DomesticTerminalFcst, long> domesticTerminalFcst,
-            IRepository<OverseasSaleFcst, long> overseasSaleFcst,
-            IRepository<PlatformFcstCollect, long> platformFcstCollect,
-            IRepository<YearDemandManagementHistory, long> yearDemandManagementHistory,
-            ISqlRepository<LocationDetail> locationDetail,
-            ISqlRepository<WorkOrdMaster> workOrdMaster,
-            IRepository<OverallDemandPlan, long> overallDemandPlan,
-            IRepository<MonthlyProdCapacityDtl, long> monthlyProdCapacityDtl,
-            IRepository<SkuVersionSet, long> skuVersionSet,
-            IRepository<crm_planorder, long> crm_planorder,
-            IRepository<PlatStockMonitorSetting, long> platStockMonitorSetting,
-            IRepository<WMS_PlatformInventory, long> platformInventory,
-            ISqlRepository<GeneralizedCodeMaster> generalizedCodeMaster,
-            ISqlRepository<SAPInv> SAPInv
-            )
-        {
-            _ic_item = ic_item;
-            _prodLineDetail = prodLineDetail;
-            _shopCalendarWorkCtr = shopCalendarWorkCtr;
-            _qualityLineWorkDetail = qualityLineWorkDetail;
-            _holidayMaster = holidayMaster;
-            _monthlyProdCapacity = monthlyProdCapacity;
-            _unitOfWorkManager = unitOfWorkManager;
-            _currentTenant = currentTenant;
-            _standardItemModelSet = standardItemModelSet;
-            _yearDemandManagement= yearDemandManagement;
-            _domesticTerminalFcst= domesticTerminalFcst;
-            _overseasSaleFcst = overseasSaleFcst;
-            _platformFcstCollect= platformFcstCollect;
-            _yearDemandManagementHistory= yearDemandManagementHistory;
-            _locationDetail = locationDetail;
-            _workOrdMaster = workOrdMaster;
-            _overallDemandPlan = overallDemandPlan;
-            _monthlyProdCapacityDtl = monthlyProdCapacityDtl;
-            _skuVersionSet= skuVersionSet;
-            _crm_planorder= crm_planorder;
-            _platStockMonitorSetting = platStockMonitorSetting;
-            _platformInventory = platformInventory;
-            _generalizedCodeMaster = generalizedCodeMaster;
-            _SAPInv = SAPInv;
-        }
-        #endregion
-
-        /// <summary>
-        /// 月度需求预测更新
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        /// <exception cref="NotImplementedException"></exception>
-        public async Task<string> DemandAnalysis(InputDto input)
-        {
-            //1.0 获取当前年年度生产需求大纲
-            List<YearDemandManagement> yearDemands = _yearDemandManagement.GetListAsync(p => p.Year == input.year && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p=>p.OrderNum).ToList();
-            //1.0 获取下一年年度生产大纲
-            List<YearDemandManagement> nextYearDemands = _yearDemandManagement.GetListAsync(p => p.Year == (input.year+1) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ToList();
-            //记录历史版本:当前年+下一年
-            var updateMonth = input.year.ToString() + "-" + input.month.ToString("00");
-            var histories = ObjectMapper.Map<List<YearDemandManagement>, List<YearDemandManagementHistory>>(yearDemands);
-            histories.ForEach(p => {
-                p.UpdateMonth = updateMonth;
-            });
-            var nextHistories = ObjectMapper.Map<List<YearDemandManagement>, List<YearDemandManagementHistory>>(nextYearDemands);
-            nextHistories.ForEach(p => {
-                p.UpdateMonth = updateMonth;
-            });
-            //1.1、获取海外销售预测数据
-            List<OverseasSaleFcst> overseasSales = _overseasSaleFcst.GetListAsync(p => p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
-            //1.2、获取平台预测收集数据
-            List<PlatformFcstCollect> platformFcsts = _platformFcstCollect.GetListAsync(p => p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
-            //1.3、获取国内终端预测-T1汇总数据
-            List<DomesticTerminalFcst> domesticFcst = _domesticTerminalFcst.GetListAsync(p =>p.TypeEnum == 2 && p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
-            //1.3.1、获取T2-海王,T2-国科数据
-            List<DomesticTerminalFcst> T2Fcsts = _domesticTerminalFcst.GetListAsync(p => (p.TypeEnum == 4 || p.TypeEnum == 5) && p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
-            //1.4、根据年度生产大纲,获取规格型号对应的补货周期
-            List<string> allModels = yearDemands.Select(p=>p.Model).Distinct().ToList();
-            if (nextYearDemands.Any())
-            {
-                allModels.AddRange(nextYearDemands.Select(p => p.Model).ToList());
-                allModels = allModels.Distinct().ToList();
-            }
-            List<StandardItemModelSet> standards = _standardItemModelSet.GetListAsync(p => allModels.Contains(p.Model) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
-            //1.5、获取规格型号对应的标准SKU数据:获取最小包装单位
-            List<string> itemNums = standards.Select(p=>p.ItemNumber).Distinct().ToList();
-            List<ic_item> items = _ic_item.GetListAsync(p=> itemNums.Contains(p.number) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
-            //1.6、获取成品库存、灭菌库存、在制库存(会从SAP同步的库存表更新到LocationDetail、ic_item表中)
-            //List<SAPInv> sAPInvs = _SAPInv.Select(p => p.WERKS == input.factory_id.ToString() && itemNums.Contains(p.MATNR));
-            List<LocationDetail> locations = _locationDetail.Select(p => p.Domain == input.factory_id.ToString() && itemNums.Contains(p.ItemNum) && p.IsActive);
-            //1.7、获取节假日设置
-            List<HolidayMaster> holidays = _holidayMaster.Select(p => (p.Dated.Value.Year == input.year || p.Dated.Value.Year == (input.year + 1)) && p.Domain == input.factory_id.ToString() && p.IsActive);
-            //1.8、获取平台库存监控月份设置
-            List<PlatStockMonitorSetting> monitorSettings = _platStockMonitorSetting.GetListAsync(p => p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
-            //1.9、获取客户要求交期在N+1月的销售订单
-            //List<>
-            #region 数据校验
-            //1、校验当前年的年度生产大纲是否导入
-            if (!yearDemands.Any())
-            {
-                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年的年度生产需求后再操作!", _currentTenant.Id.ToString());
-                return "NO|请导入" + input.year + "年的年度生产需求后再操作!";
-            }
-            //2、如果当前月份大于10,则需校验下一年的年度生产大纲
-            if (input.month > 10 && !nextYearDemands.Any())
-            {
-                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + (input.year+1) + "年的年度生产需求后再操作!", _currentTenant.Id.ToString());
-                return "NO|请导入" + (input.year + 1) + "年的年度生产需求后再操作!";
-            }
-            //3、校验当前月份的海外销售预测是否导入
-            if (!overseasSales.Any())
-            {
-                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年" + input.month + "月海外销售预测后再操作!", _currentTenant.Id.ToString());
-                return "NO|请导入" + input.year + "年" + input.month + "月海外销售预测后再操作!";
-            }
-            //4、校验当前月份的平台预测收集是否导入
-            if (!platformFcsts.Any())
-            {
-                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年" + input.month + "月平台需求收集后再操作!", _currentTenant.Id.ToString());
-                return "NO|请导入" + input.year + "年" + input.month + "月平台需求收集后再操作!";
-            }
-            //5、校验当前月份的国内终端预测是否导入
-            if (!domesticFcst.Any())
-            {
-                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年" + input.month + "月国内终端预测后再操作!", _currentTenant.Id.ToString());
-                return "NO|请导入" + input.year + "年" + input.month + "月国内终端预测后再操作!";
-            }
-            //6、校验终端+平台导入的规格型号是否已维护标准SKU
-            if (allModels.Count() != standards.Count())
-            {
-                allModels.RemoveAll(standards.Select(p=>p.Model).ToList());
-                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "规格型号【" + string.Join(",",allModels) + "】没有维护标准SKU,请维护后再操作!", _currentTenant.Id.ToString());
-                return "NO|规格型号【" + string.Join(",", allModels) + "】没有维护标准SKU,请维护后再操作!";
-            }
-            //7、校验是否已维护补货周期
-            var zeros = standards.Where(p => p.ReplenishCycle == 0).ToList();
-            if (zeros.Any())
-            {
-                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "规格型号【" + string.Join(",", zeros.Select(p=>p.Model).ToList()) + "】没有维护补货周期,请维护后再操作!", _currentTenant.Id.ToString());
-                return "NO|规格型号【" + string.Join(",", zeros.Select(p => p.Model).ToList()) + "】没有维护补货周期,请维护后再操作!";
-            }
-            #endregion
-
-            //计算当前年月的N0,N+1,N+2
-            List<string> planMons = new List<string>();
-            int newYear = input.month == 12 ? input.year + 1 : input.year;
-            int newMonth = input.month == 12 ? 1 : input.month + 1;
-            string strN1 = newYear.ToString() + "-" + newMonth.ToString("00");
-            planMons.Add(strN1);
-            newYear = newMonth == 12 ? newYear + 1 : newYear;
-            newMonth = newMonth == 12 ? 1 : newMonth + 1;
-            string strN2 = newYear.ToString() + "-" + newMonth.ToString("00");
-            planMons.Add(strN2);
-
-            //需要回写的数据
-            List<YearDemandManagement> updates = new List<YearDemandManagement>();
-            #region 计算国内终端预测,回写年度生产大纲
-            //获取导入的T1、平台数据
-            List<string> gnModels = new List<string>();
-            if (domesticFcst.Any())
-            {
-                gnModels.AddRange(domesticFcst.Select(p => p.Model).ToList());
-            }
-            if (platformFcsts.Any())
-            {
-                gnModels.AddRange(platformFcsts.Select(p => p.Model).ToList());
-            }
-            gnModels = gnModels.Distinct().ToList();
-            foreach (var gnModel in gnModels)
-            {
-                //N+1月
-                YearDemandManagement monthN1 = new YearDemandManagement();
-                //N+2月
-                YearDemandManagement monthN2 = new YearDemandManagement();
-                //获取需要回写的数据
-                if (input.month < 11)
-                {
-                    monthN1 = yearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN1);
-                    monthN2 = yearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN2);
-                }
-                if (input.month == 11)
-                {
-                    monthN1 = yearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN1);
-                    monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN2);
-                }
-                if (input.month == 12)
-                {
-                    monthN1 = nextYearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN1);
-                    monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN2);
-                }
-                if (monthN1 == null || monthN2 == null)
-                {
-                    continue;
-                }
-                //T1
-                var sumT1N1 = domesticFcst.Where(p => p.Model == gnModel && p.PlanMonth == strN1).Sum(p=>p.Qty);
-                var sumT1N2 = domesticFcst.Where(p => p.Model == gnModel && p.PlanMonth == strN2).Sum(p => p.Qty);
-                //平台
-                var sumPN1 = platformFcsts.Where(p => p.Model == gnModel && p.PlanMonth == strN1).Sum(p => p.Qty);
-                var sumPN2 = platformFcsts.Where(p => p.Model == gnModel && p.PlanMonth == strN2).Sum(p => p.Qty);
-                //合计
-                var sumN1 = sumT1N1+ sumPN1;
-                var sumN2 = sumT1N2 + sumPN2;
-
-                //当前规格型号对应标准SKU的最小包装单位、补货周期
-                var curStd = standards.FirstOrDefault(p => p.Model == gnModel);
-                decimal packQty = 1m;//最小包装单位
-                decimal cycle = 0m;//补货周期
-                //获取成品库存、在制库存、灭菌库存,参与计算
-                decimal cpQty = 0m;
-                decimal zzQty = 0m;
-                decimal mjQty = 0m;
-                if (curStd != null)
-                {
-                    var curItem = items.FirstOrDefault(p => p.number == curStd.ItemNumber);
-                    packQty = curItem == null ? 1 : (curItem.minpackqty.GetValueOrDefault() == 0.0m ? 1 : curItem.minpackqty.Value);
-                    cycle = curStd.ReplenishCycle;
-                    //成品库存
-                    cpQty = locations.Where(p => p.ItemNum == curStd.ItemNumber && p.Location == "8001").Sum(p => Convert.ToDecimal(p.QtyOnHand));
-                    //在制库存
-                    zzQty = locations.Where(p => p.ItemNum == curStd.ItemNumber && p.Location == "8000").Sum(p => Convert.ToDecimal(p.QtyOnHand));
-                    //灭菌库存
-                    mjQty = locations.Where(p => p.ItemNum == curStd.ItemNumber && p.Location == "5008").Sum(p => Convert.ToDecimal(p.QtyOnHand));
-                }
-                //N+1月使用N+2月的再订货点参与计算
-                decimal rop = CalcRop(strN2+"-01", sumN2, packQty, holidays, cycle);
-                monthN1.Qty = Math.Ceiling((sumN1 / 2 + sumN2 / 2 + rop - cpQty - zzQty - mjQty) / packQty) * packQty;
-                //N+2月使用本月的需求量,下一月的工作天数
-                rop = CalcRop(Convert.ToDateTime(strN2 + "-01").AddMonths(1).ToString("yyyy-MM-dd"), sumN2, packQty, holidays, cycle);
-                monthN2.Qty = Math.Ceiling((sumN2 + rop - cpQty - zzQty - mjQty) / packQty) * packQty;
-                //负数置0
-                monthN1.Qty = monthN1.Qty < 0 ? 0m : monthN1.Qty;
-                monthN2.Qty = monthN2.Qty < 0 ? 0m : monthN2.Qty;
-                //记录需要回写的数据
-                updates.Add(monthN1);
-                updates.Add(monthN2);
-            }
-            #endregion
-
-            #region 海外销售预测,回写年度生产大纲
-            List<string> hwModels = overseasSales.Select(p => p.Model).Distinct().ToList();
-            foreach (var hwModel in hwModels)
-            {
-                //N+1月
-                YearDemandManagement monthN1 = new YearDemandManagement();
-                //N+2月
-                YearDemandManagement monthN2 = new YearDemandManagement();
-                //获取需要回写的数据
-                if (input.month < 11)
-                {
-                    monthN1 = yearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN1);
-                    monthN2 = yearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN2);
-                }
-                if (input.month == 11)
-                {
-                    monthN1 = yearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN1);
-                    monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN2);
-                }
-                if (input.month == 12)
-                {
-                    monthN1 = nextYearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN1);
-                    monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN2);
-                }
-                if (monthN1 == null || monthN2 == null) {
-                    continue;
-                }
-                var sumN1 = overseasSales.Where(p => p.Model == hwModel && p.PlanMonth == strN1).Sum(p => p.Qty);
-                var sumN2 = overseasSales.Where(p => p.Model == hwModel && p.PlanMonth == strN2).Sum(p => p.Qty);
-
-                //当前规格型号对应标准SKU的最小包装单位、补货周期
-                var curStd = standards.FirstOrDefault(p => p.Model == hwModel);
-                decimal packQty = 1m;//最小包装单位
-                //获取成品库存、在制库存、灭菌库存,参与计算
-                decimal cpQty = 0m;
-                decimal zzQty = 0m;
-                decimal mjQty = 0m;
-                if (curStd != null)
-                {
-                    var curItem = items.FirstOrDefault(p => p.number == curStd.ItemNumber);
-                    packQty = curItem == null ? 1 : (curItem.minpackqty.GetValueOrDefault() == 0.0m ? 1 : curItem.minpackqty.Value);
-                    //成品库存
-                    cpQty = locations.Where(p => p.ItemNum == curStd.ItemNumber && p.Location == "8001").Sum(p => Convert.ToDecimal(p.QtyOnHand));
-                    //在制库存
-                    zzQty = locations.Where(p => p.ItemNum == curStd.ItemNumber && p.Location == "8000").Sum(p => Convert.ToDecimal(p.QtyOnHand));
-                    //灭菌库存
-                    mjQty = locations.Where(p => p.ItemNum == curStd.ItemNumber && p.Location == "5008").Sum(p => Convert.ToDecimal(p.QtyOnHand));
-                }
-                //海外生产需求量=当月的50%+下一月的50%-成品库存-在制库存-灭菌库存
-                //TODO:获取成品库存、在制库存、灭菌库存,参与运算
-                //计算N+1月,N+2月
-                monthN1.Qty = Math.Ceiling((sumN1 / 2 + sumN2 / 2 - cpQty - zzQty - mjQty) / packQty) * packQty;
-                monthN2.Qty = Math.Ceiling((sumN2 - cpQty - zzQty - mjQty) / packQty) *packQty; ;
-                //负数置0
-                monthN1.Qty = monthN1.Qty < 0 ? 0m : monthN1.Qty;
-                monthN2.Qty = monthN2.Qty < 0 ? 0m : monthN2.Qty;
-                //记录需要回写的数据
-                updates.Add(monthN1);
-                updates.Add(monthN2);
-            }
-            #endregion
-
-            //生成月度产能共识
-            var capacityDto = CapacityAnalysis(input, updates, planMons);
-
-            //生成下一个月的补货计划
-            var nextMonPFcsts = platformFcsts.Where(p => p.PlanMonth == strN2).ToList();
-            var nextMonDFcsts = domesticFcst.Where(p => p.PlanMonth == strN2).ToList();
-            var nextMonT2Fcsts = T2Fcsts.Where(p => p.PlanMonth == strN2).ToList();
-            var nextMonMonitors = monitorSettings.Where(p => p.PlanMonth == strN1).ToList();
-            var replenishs = MonthlyReplenish(input,strN1, nextMonPFcsts, nextMonDFcsts, nextMonT2Fcsts, standards, items, holidays, nextMonMonitors, locations);
-
-            //保存数据
-            using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
-            {
-                try
-                {
-                    //判断是否存在当前年月的历史版本,不存在则插入
-                    var dbHistory =  _yearDemandManagementHistory.GetListAsync(p=>p.Year ==input.year && p.UpdateMonth == updateMonth && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id).Result;
-                    if (!dbHistory.Any())
-                    {
-                        await _yearDemandManagementHistory.InsertManyAsync(histories);
-                    }
-                    if (input.month > 10)
-                    {
-                        //判断是否存在下一年月的历史版本,不存在则插入
-                        dbHistory = _yearDemandManagementHistory.GetListAsync(p =>(p.Year == input.year + 1) && p.UpdateMonth == updateMonth && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id).Result;
-                        if (!dbHistory.Any())
-                        {
-                            await _yearDemandManagementHistory.InsertManyAsync(nextHistories);
-                        }
-                    }
-                    //回写年度生产大纲
-                    await _yearDemandManagement.UpdateManyAsync(updates);
-                    //先删除产能共识、产能共识明细
-                    await _monthlyProdCapacity.HardDeleteAsync(p=>p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id);
-                    await _monthlyProdCapacityDtl.HardDeleteAsync(p => p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id);
-                    await _monthlyProdCapacity.InsertManyAsync(capacityDto.mains);
-                    await _monthlyProdCapacityDtl.InsertManyAsync(capacityDto.details);
-                    //生成下一月的补货计划
-                    await _crm_planorder.HardDeleteAsync(p=>p.PlanMonth == strN1 && p.Source =="系统运算" && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id);
-                    await _crm_planorder.InsertManyAsync(replenishs);
-
-                    await unitOfWork.CompleteAsync();
-                }
-                catch (Exception e)
-                {
-                    unitOfWork.Dispose();
-                    new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "【" + input.year + "年" + input.month + "月】月度需求预测更新失败:" + e.Message, _currentTenant.Id.ToString());
-                    return "NO|" + e.Message;
-                };
-            }
-            return "OK|刷新成功!";
-        }
-
-        /// <summary>
-        /// 生成月度产能共识
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        public MonthlyCapacityDto CapacityAnalysis(InputDto input,List<YearDemandManagement> yearDemands, List<string> planMons)
-        {
-            //1、获取数据
-            //1.1 根据规格型号获取物料数据
-            List<string> models = yearDemands.Select(p => p.Model).Distinct().ToList();
-            List<StandardItemModelSet> standards = _standardItemModelSet.GetListAsync(p => models.Contains(p.Model) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id).Result;
-            //1.3 根据物料编码获取产线数据
-            List<ProdLineDetail> lineDtls = _prodLineDetail.Select(p => standards.Select(m => m.ItemNumber).Contains(p.Part) && p.Domain == input.factory_id.ToString() && p.IsActive).OrderBy(p => p.Line).ToList();
-            //1.4 根据产线获取工作日历数据和产线休息配置数据
-            List<ShopCalendarWorkCtr> calendars = _shopCalendarWorkCtr.Select(p => lineDtls.Select(m => m.Line).Contains(p.ProdLine) && p.Domain == input.factory_id.ToString() && p.IsActive);
-            List<QualityLineWorkDetail> lineWorks = _qualityLineWorkDetail.Select(p => lineDtls.Select(m => m.Line).Contains(p.ProdLine) && p.Domain == input.factory_id.ToString() && p.IsActive);
-            //1.5 获取当前年和下一年的节假日配置数据
-            List<HolidayMaster> holidays = _holidayMaster.Select(p => (p.Dated.Value.Year == input.year || p.Dated.Value.Year == (input.year + 1)) && p.Domain == input.factory_id.ToString() && p.IsActive);
-
-            //月度产能共识表
-            List<MonthlyProdCapacity> capacities = new List<MonthlyProdCapacity>();
-            //月度产能共识明细表
-            List<MonthlyProdCapacityDtl> capacityDtls = new List<MonthlyProdCapacityDtl>();
-
-            //产线
-            List<string> lines = lineDtls.Select(p => p.Line).Distinct().ToList();
-            foreach (var item in lines)
-            {
-                //计算每天工作时间
-                var curCal = calendars.FirstOrDefault(p => p.ProdLine == item);
-                if (curCal == null)
-                {
-                    continue;
-                }
-                foreach (var pm in planMons)
-                {
-                    //添加月度产能共识产能效率数据
-                    MonthlyProdCapacity dtl = new MonthlyProdCapacity();
-                    dtl.Year = input.year;
-                    dtl.Month = input.month;
-                    dtl.PlanMonth = pm;
-                    dtl.ProdLine = item;
-
-                    dtl.DailyWorks = curCal.ShiftsHours1 + curCal.ShiftsHours2 + curCal.ShiftsHours3 + curCal.ShiftsHours4;
-                    dtl.FlightQty = 1;
-                    //计算当月工作天数
-                    var curHoildays = holidays.Where(p => p.Dated.Value.Year == Convert.ToInt16(pm.Substring(0,4)) && p.Dated.Value.Month == Convert.ToInt16(pm.Substring(5, 2))).ToList();
-                    //当月天数
-                    int days = DateTime.DaysInMonth(input.year, input.month);
-                    //当月周末天数
-                    int weekDays = CalcWeekDays(days, Convert.ToDateTime(pm + "-01"));
-                    dtl.MonthWorks = days - weekDays - curHoildays.Where(p => p.Ufld1 == "休假").Count() + curHoildays.Where(p => p.Ufld1 == "调班").Count();
-                    dtl.AvailableTimes = dtl.DailyWorks * dtl.MonthWorks;
-                    //计算产线耗时
-                    var curLines = lineDtls.Where(p => p.Line == item).ToList();
-                    decimal sumTimes = 0.00m;
-                    List<ProdLineDto> lineDtos = new List<ProdLineDto>(); 
-                    foreach (var ld in curLines)
-                    {
-                        if (lineDtos.Exists(p=>p.Part == ld.Part && p.Line == ld.Line))
-                        {
-                            continue;
-                        }
-                        var curStand = standards.FirstOrDefault(p => p.ItemNumber == ld.Part);
-                        if (curStand == null)
-                        {
-                            continue;
-                        }
-                        var curDemands = yearDemands.Where(p => p.Model == curStand.Model && p.PlanMonth == pm).ToList();
-                        var line = curLines.Where(p=>p.Part == ld.Part && p.Line == ld.Line).OrderByDescending(p => p.Op).First();
-                        sumTimes += line.Rate == 0 ? 0 : (Math.Ceiling(curDemands.Sum(p => p.Qty) / line.Rate));
-
-                        MonthlyProdCapacityDtl capacityDtl = new MonthlyProdCapacityDtl();
-                        capacityDtl.Year = input.year;
-                        capacityDtl.Month = input.month;
-                        capacityDtl.PlanMonth = pm;
-                        capacityDtl.ProdLine = item;
-                        capacityDtl.Model = curStand.Model;
-                        capacityDtl.Qty = curDemands.Sum(p => p.Qty);
-                        capacityDtl.tenant_id = input.tenant_id;
-                        capacityDtl.company_id = input.company_id;
-                        capacityDtl.factory_id = input.factory_id;
-                        capacityDtl.org_id = input.org_id;
-                        capacityDtl.create_by = input.create_by;
-                        capacityDtl.create_by_name = input.create_by_name;
-                        capacityDtl.create_time = DateTime.Now;
-                        capacityDtls.Add(capacityDtl);
-
-                        lineDtos.Add(new ProdLineDto { 
-                            Part = ld.Part,
-                            Line= ld.Line
-                        });
-                    }
-
-                    dtl.NeedWorks = sumTimes;
-                    dtl.ProdRate = 100;
-                    dtl.Rate = dtl.AvailableTimes == 0 ? 0 : Math.Floor(dtl.NeedWorks / dtl.AvailableTimes * 100);
-                    dtl.IsOverTime = dtl.NeedWorks > dtl.AvailableTimes ? "是" : "否";
-                    dtl.OverTimes = dtl.IsOverTime == "是" ? (dtl.NeedWorks - dtl.AvailableTimes) : 0;
-                    dtl.tenant_id = input.tenant_id;
-                    dtl.company_id= input.company_id;
-                    dtl.factory_id = input.factory_id;
-                    dtl.org_id= input.org_id;
-                    dtl.create_by= input.create_by;
-                    dtl.create_by_name = input.create_by_name;
-                    dtl.create_time = DateTime.Now;
-                    capacities.Add(dtl);
-                }
-            }
-            return new MonthlyCapacityDto{ 
-                mains = capacities,
-                details = capacityDtls
-            };
-        }
-
-        /// <summary>
-        /// T1、平台自动补货
-        /// </summary>
-        /// <param name="input"></param>
-        /// <param name="strN1">计划补货月份:N+1月</param>
-        /// <param name="platformFcsts">平台预测</param>
-        /// <param name="domesticFcsts">T1预测</param>
-        /// <param name="standards">标准SKU设置</param>
-        /// <param name="items">物料</param>
-        /// <param name="holidays">节假日</param>
-        /// <param name="monitorSettings">库存监控月份设置</param>
-        /// <param name="locations">SAP同步库存</param>
-        /// <returns></returns>
-        public List<crm_planorder> MonthlyReplenish(InputDto input,string strN1, List<PlatformFcstCollect> platformFcsts, List<DomesticTerminalFcst> domesticFcsts, List<DomesticTerminalFcst> T2Fcsts, List<StandardItemModelSet> standards, List<ic_item> items, List<HolidayMaster> holidays, List<PlatStockMonitorSetting> monitorSettings, List<LocationDetail> locations)
-        { 
-            List<crm_planorder> planorders = new List<crm_planorder>();
-            //获取T1中规格型号对应的不同版本的物料编码
-            var T1Models = domesticFcsts.Select(p => p.Model).Distinct().ToList();
-            List<SkuVersionSet> skus = _skuVersionSet.GetListAsync(p=> T1Models.Contains(p.Model) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
-            //获取T1库存
-            //List<string> itemNums = skus.Select(p=>p.ItemNum).Distinct().ToList();
-            //List<LocationDetail> locationDetails = _locationDetail.Select(p=> itemNums.Contains(p.ItemNum) && p.Domain == input.factory_id.ToString() && p.IsActive);
-
-            //获取临期库存设置
-            GeneralizedCodeMaster master = _generalizedCodeMaster.Select(p => p.Domain == input.factory_id.ToString() && p.IsActive && p.Val == "LongPeriodItemPlanMonth").FirstOrDefault();
-            int month = master == null ? 0 : Convert.ToInt16(master.UDeci1);
-            DateTime strTime = Convert.ToDateTime(platformFcsts[0].PlanMonth + "-01").AddMonths(month);
-            //获取平台库存
-            var PModels = platformFcsts.Select(p => p.Model).Distinct().ToList();
-            List<WMS_PlatformInventory> pInventories = _platformInventory.GetListAsync(p=> PModels.Contains(p.SpecificationModel) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && p.PeriodOfValidity >= strTime).Result;
-            
-            //计算T1补货
-            foreach (var item in T1Models)
-            {
-                //获取当前规格型号对应的预测数据
-                var curFcsts = domesticFcsts.Where(p=>p.Model == item).ToList();
-                //当前规格型号对应的库存数量
-                decimal sumQty = 0.00m;
-                //当前的物料版本
-                var curSkus = skus.Where(p => p.Model == item).ToList();
-                if (curSkus.Any())
-                {
-                    //sumQty = sAPInvs.Where(p => curSkus.Select(p => p.ItemNum).Contains(p.MATNR)).Sum(p => Convert.ToDecimal(p.LABST));
-                    sumQty = locations.Where(p => curSkus.Select(p => p.ItemNum).Contains(p.ItemNum) && p.Location == "8001").Sum(p => p.QtyOnHand);
-                }
-                //计算Rop
-                //当前规格型号对应标准SKU的最小包装单位、补货周期
-                var curStd = standards.FirstOrDefault(p => p.Model == item);
-                decimal packQty = 1m;//最小包装单位
-                decimal cycle = 0m;//补货周期
-                if (curStd != null)
-                {
-                    var curItem = items.FirstOrDefault(p => p.number == curStd.ItemNumber);
-                    packQty = curItem == null ? 1 : (curItem.minpackqty.GetValueOrDefault() == 0.0m ? 1 : curItem.minpackqty.Value);
-                    cycle = curStd.ReplenishCycle;
-                }
-                //N+1月使用N+2月的再订货点参与计算
-                decimal rop = CalcRop(curFcsts[0].PlanMonth + "-01", curFcsts.Sum(p=>p.Qty), packQty, holidays, cycle);
-                if(sumQty < rop)
-                {
-                    planorders.Add(new crm_planorder { 
-                        PlanMonth = strN1,
-                        Model = curFcsts[0].Model,
-                        ItemNum = curStd?.ItemNumber,
-                        ProdLine = curFcsts[0].ProdLine,
-                        ProdType = "",
-                        Qty = rop,
-                        Type = "计划单-T1直发补货"
-                    });
-                }
-            }
-
-            //计算平台补货:海王
-            var hwFcsts = platformFcsts.Where(p => p.Platform == "海王").ToList();
-            var hwModels = hwFcsts.Select(p=>p.Model).Distinct().ToList();
-            foreach (var item in hwModels)
-            {
-                //获取当前规格型号对应的平台预测数据
-                var curFcsts = hwFcsts.Where(p => p.Model == item).ToList();
-                //当前规格型号对应的库存数量
-                decimal sumQty = 0.00m;
-                //当前规格型号对应标准SKU的最小包装单位、补货周期
-                var curStd = standards.FirstOrDefault(p => p.Model == item);
-                decimal packQty = 1m;//最小包装单位
-                decimal cycle = 0m;//补货周期
-                if (curStd != null)
-                {
-                    var curItem = items.FirstOrDefault(p => p.number == curStd.ItemNumber);
-                    packQty = curItem == null ? 1 : (curItem.minpackqty.GetValueOrDefault() == 0.0m ? 1 : curItem.minpackqty.Value);
-                    cycle = curStd.ReplenishCycle;
-                }
-                //T2海王预测数据
-                var curT2Hws = T2Fcsts.Where(p => p.Model == item && p.TypeEnum == 4).ToList();
-                //计算Rop:N+1月使用N+2月的再订货点参与计算
-                decimal rop = CalcRop(curFcsts[0].PlanMonth + "-01", curT2Hws.Sum(p => p.Qty), packQty, holidays, cycle);
-                //获取海王当前规格型号库存
-                sumQty = pInventories.Where(p => p.SpecificationModel == item && p.Code == "HW0001").Sum(p=>p.InventoryQuantity);
-                //获取N+1月的库存监控设置
-                var curMonitor = monitorSettings.FirstOrDefault(p => p.Platform == "海王" && p.ProdType == curFcsts[0].ProdType);
-                if (curMonitor == null)
-                {
-                    new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "海王未维护产品类型为【"+ curFcsts[0].ProdType + "】的库存监控月份", _currentTenant.Id.ToString());
-                    continue;
-                }
-                //最小覆盖月份库存
-                var minQty = rop * curMonitor.MinTimes;
-                //最大库存月份库存
-                var maxQty = rop * curMonitor.MaxTimes;
-                //需补货数量
-                decimal needQty = 0m;
-                if (sumQty >= minQty && sumQty < maxQty)//大于等于最低库存覆盖月,小于最高库存覆盖月
-                {
-                    planorders.Add(new crm_planorder
-                    {
-                        PlanMonth = strN1,
-                        Model = curFcsts[0].Model,
-                        ItemNum = curStd?.ItemNumber,
-                        ProdLine = curT2Hws[0].ProdLine,
-                        ProdType = "",
-                        Qty = maxQty - sumQty,
-                        Type = "计划单-T2平台补货"
-                    });
-                }
-                if (sumQty < minQty)//低于最低库存覆盖月
-                {
-                    while (sumQty < minQty) 
-                    {
-                        sumQty += rop;
-                        needQty += rop;
-                    }
-                    planorders.Add(new crm_planorder
-                    {
-                        PlanMonth = strN1,
-                        Model = curFcsts[0].Model,
-                        ItemNum = curStd?.ItemNumber,
-                        ProdLine = curT2Hws[0].ProdLine,
-                        ProdType = "",
-                        Qty = needQty,
-                        Type = "计划单-T2平台补货"
-                    });
-                }
-            }
-
-            //计算平台补货:国科
-            var gkFcsts = platformFcsts.Where(p => p.Platform == "国科").ToList();
-            var gkModels = gkFcsts.Select(p => p.Model).Distinct().ToList();
-            foreach (var item in gkModels)
-            {
-                //获取当前规格型号对应的预测数据
-                var curFcsts = gkFcsts.Where(p => p.Model == item).ToList();
-                //当前规格型号对应的库存数量
-                decimal sumQty = 0.00m;
-                //当前规格型号对应标准SKU的最小包装单位、补货周期
-                var curStd = standards.FirstOrDefault(p => p.Model == item);
-                decimal packQty = 1m;//最小包装单位
-                decimal cycle = 0m;//补货周期
-                if (curStd != null)
-                {
-                    var curItem = items.FirstOrDefault(p => p.number == curStd.ItemNumber);
-                    packQty = curItem == null ? 1 : (curItem.minpackqty.GetValueOrDefault() == 0.0m ? 1 : curItem.minpackqty.Value);
-                    cycle = curStd.ReplenishCycle;
-                }
-                //T2国科预测数据
-                var curT2Gks = T2Fcsts.Where(p => p.Model == item && p.TypeEnum == 5).ToList();
-                //计算Rop:N+1月使用N+2月的再订货点参与计算
-                decimal rop = CalcRop(curFcsts[0].PlanMonth + "-01", curT2Gks.Sum(p => p.Qty), packQty, holidays, cycle);
-                //获取国科当前规格型号库存
-                sumQty = pInventories.Where(p => p.SpecificationModel == item && p.Code == "GK0001").Sum(p => p.InventoryQuantity);
-                //获取N+1月的库存监控设置
-                var curMonitor = monitorSettings.FirstOrDefault(p => p.Platform == "国科" && p.ProdType == curFcsts[0].ProdType);
-                if (curMonitor == null)
-                {
-                    new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "国科未维护产品类型为【" + curFcsts[0].ProdType + "】的库存监控月份", _currentTenant.Id.ToString());
-                    continue;
-                }
-                //最小覆盖月份库存
-                var minQty = rop * curMonitor.MinTimes;
-                //最大库存月份库存
-                var maxQty = rop * curMonitor.MaxTimes;
-                //需补货数量
-                decimal needQty = 0m;
-                if (sumQty >= minQty && sumQty < maxQty)
-                {
-                    planorders.Add(new crm_planorder
-                    {
-                        PlanMonth = strN1,
-                        Model = curFcsts[0].Model,
-                        ItemNum = curStd?.ItemNumber,
-                        ProdLine = curT2Gks[0].ProdLine,
-                        ProdType = "",
-                        Qty = maxQty - sumQty,
-                        Type = "计划单-T2平台补货"
-                    });
-                }
-                if (sumQty < minQty)
-                {
-                    while (sumQty < minQty)
-                    {
-                        sumQty += rop;
-                        needQty += rop;
-                    }
-                    planorders.Add(new crm_planorder
-                    {
-                        PlanMonth = strN1,
-                        Model = curFcsts[0].Model,
-                        ItemNum = curStd?.ItemNumber,
-                        ProdLine = curT2Gks[0].ProdLine,
-                        ProdType = "",
-                        Qty = needQty,
-                        Type = "计划单-T2平台补货"
-                    });
-                }
-            }
-
-            planorders.ForEach(p => {
-                p.Source = "系统运算";
-                p.tenant_id = input.tenant_id;
-                p.company_id = input.company_id;
-                p.factory_id = input.factory_id;
-                p.org_id = input.org_id;
-                p.create_by = input.create_by;
-                p.create_by_name = input.create_by_name;
-                p.create_time = DateTime.Now;
-            });
-            return planorders;
-        }
-
-
-        /// <summary>
-        /// 计算再订货点
-        /// </summary>
-        /// <param name="planMonth">计划年月(yyyy-MM-dd)</param>
-        /// <param name="qty">需求量</param>
-        /// <param name="qty">最小包装数量</param>
-        /// <param name="holidays">节假日</param>
-        /// <param name="replenishCycle">补货周期</param>
-        /// <returns></returns>
-        private decimal CalcRop(string planMonth,decimal qty,decimal packQty,List<HolidayMaster> holidays,decimal replenishCycle)
-        {
-            decimal rop = 0.0m;
-            //获取当月天数
-            int year = Convert.ToInt16(planMonth.Substring(0, 4));
-            int month = Convert.ToInt16(planMonth.Substring(5, 2));
-            int days = DateTime.DaysInMonth(year, month);
-            //计算当前月的周末天数
-            int weeks = CalcWeekDays(days, Convert.ToDateTime(planMonth));
-            //获取当前年月的节假日设置
-            var curHolidays = holidays.Where(p => p.Dated.Value.Year == year && p.Dated.Value.Month == month).ToList();
-            //当月工作天数
-            int workDays = days - weeks - curHolidays.Where(p => p.Ufld1 == "休假").Count() + curHolidays.Where(p => p.Ufld1 == "调班").Count();
-            //rop = (需求量/月工作天数*补货周期)=>按照最小包装单位元整
-            rop = Math.Ceiling(qty / workDays * replenishCycle / packQty) * packQty;
-            return rop;
-        }
-
-        /// <summary>
-        /// 计算当月有多少个周末
-        /// </summary>
-        /// <param name="days"></param>
-        /// <param name="startDay"></param>
-        /// <returns></returns>
-        private int CalcWeekDays(int days, DateTime startDay)
-        {
-            int sumDays = 0;
-            for (int i = 0; i < days; i++)
-            {
-                int weekDays = (int)startDay.AddDays(i).DayOfWeek;
-                if (weekDays == 0 || weekDays == 6)
-                {
-                    sumDays++;
-                }
-            }
-            return sumDays;
-        }
-
-        /// <summary>
-        /// 生成整体需求计划
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        /// <exception cref="NotImplementedException"></exception>
-        public async Task<string> OverallDemandPlan(InputDto input)
-        {
-            //1.1、获取海外销售预测数据
-            List<OverseasSaleFcst> overseasSales = _overseasSaleFcst.GetListAsync(p => p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ToList();
-            //1.2、获取平台预测收集数据
-            List<PlatformFcstCollect> platformFcsts = _platformFcstCollect.GetListAsync(p => p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p=>p.OrderNum).ToList();
-            //1.3、获取国内终端预测-T1汇总数据
-            List<DomesticTerminalFcst> domesticFcsts = _domesticTerminalFcst.GetListAsync(p => p.TypeEnum == 2 && p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ToList();
-
-            //计算当前年月的N+1,N+2
-            string strN0 = input.year.ToString() + "-" + input.month.ToString("00");
-            int newYear = input.month == 12 ? input.year + 1 : input.year;
-            int newMonth = input.month == 12 ? 1 : input.month + 1;
-            string strN1 = newYear.ToString() + "-" + newMonth.ToString("00");
-            newYear = newMonth == 12 ? newYear + 1 : newYear;
-            newMonth = newMonth == 12 ? 1 : newMonth + 1;
-            string strN2 = newYear.ToString() + "-" + newMonth.ToString("00");
-
-            //整体需求计划
-            List<OverallDemandPlan> plans = new List<OverallDemandPlan>();
-            //计算海外
-            List<string> hwModels = overseasSales.Select(p => p.Model).Distinct().ToList();
-            int OrderNum = 1;
-            foreach (var item in hwModels)
-            {
-                var curFcsts = overseasSales.Where(p => p.Model == item).ToList();
-                OverallDemandPlan plan = new OverallDemandPlan();
-                plan.Area = "海外";
-                plan.Model = item;
-                plan.PlanMonth = strN0;
-                plan.Qty = curFcsts.Where(p => p.PlanMonth == strN0).Sum(p => p.Qty);
-                plan.OrderNum = OrderNum;
-                plans.Add(plan);
-
-                plan = new OverallDemandPlan();
-                plan.Area = "海外";
-                plan.Model = item;
-                plan.PlanMonth = strN1;
-                plan.Qty = curFcsts.Where(p => p.PlanMonth == strN1).Sum(p => p.Qty);
-                plan.OrderNum = OrderNum;
-                plans.Add(plan);
-
-                plan = new OverallDemandPlan();
-                plan.Area = "海外";
-                plan.Model = item;
-                plan.PlanMonth = strN2;
-                plan.Qty = curFcsts.Where(p => p.PlanMonth == strN2).Sum(p => p.Qty);
-                plan.OrderNum = OrderNum;
-                plans.Add(plan);
-
-                OrderNum += 1;
-            }
-            //计算国内
-            List<string> gnModels = domesticFcsts.Select(p=>p.Model).ToList();
-            gnModels.AddRange(platformFcsts.Select(p => p.Model).ToList());
-            gnModels = gnModels.Distinct().ToList();
-            OrderNum = 1;
-            foreach (var item in gnModels)
-            {
-                var curDFcsts = domesticFcsts.Where(p => p.Model == item).ToList();
-                var curPFcsts = platformFcsts.Where(p => p.Model == item).ToList();
-                OverallDemandPlan plan = new OverallDemandPlan();
-                plan.Area = "国内";
-                plan.Model = item;
-                plan.PlanMonth = strN0;
-                plan.Qty = curDFcsts.Where(p => p.PlanMonth == strN0).Sum(p => p.Qty) + curPFcsts.Where(p => p.PlanMonth == strN0).Sum(p => p.Qty);
-                plan.OrderNum = OrderNum;
-                plans.Add(plan);
-
-                plan = new OverallDemandPlan();
-                plan.Area = "国内";
-                plan.Model = item;
-                plan.PlanMonth = strN1;
-                plan.Qty = curDFcsts.Where(p => p.PlanMonth == strN1).Sum(p => p.Qty) + curPFcsts.Where(p => p.PlanMonth == strN1).Sum(p => p.Qty);
-                plan.OrderNum = OrderNum;
-                plans.Add(plan);
-
-                plan = new OverallDemandPlan();
-                plan.Area = "国内";
-                plan.Model = item;
-                plan.PlanMonth = strN2;
-                plan.Qty = curDFcsts.Where(p => p.PlanMonth == strN2).Sum(p => p.Qty) + curPFcsts.Where(p => p.PlanMonth == strN2).Sum(p => p.Qty);
-                plan.OrderNum = OrderNum;
-                plans.Add(plan);
-
-                OrderNum += 1;
-            }
-
-            plans.ForEach(p => {
-                p.Year= input.year;
-                p.Month= input.month;
-                p.tenant_id = input.tenant_id;
-                p.company_id = input.company_id;
-                p.factory_id= input.factory_id;
-                p.org_id= input.org_id;
-                p.create_by = input.create_by;
-                p.create_by_name= input.create_by_name;
-                p.create_time = DateTime.Now;
-            });
-
-            //保存数据
-            using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
-            {
-                try
-                {
-                    //先删除
-                    await _overallDemandPlan.HardDeleteAsync(p=>p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id);
-                    //保存整体需求计划
-                    await _overallDemandPlan.InsertManyAsync(plans);
-                    await unitOfWork.CompleteAsync();
-                }
-                catch (Exception e)
-                {
-                    unitOfWork.Dispose();
-                    new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("OverallDemandPlan", "生成【" + input.year + "年" + input.month + "月】整体需求计划失败:" + e.Message, _currentTenant.Id.ToString());
-                    return "NO|" + e.Message;
-                };
-            }
-            return "OK|刷新成功!";
-        }
-    }
-}

+ 9 - 0
MicroServices/Business/Business.Domain/MongoDB/MES/IC/mo_ic_item.cs

@@ -682,5 +682,14 @@ namespace Business.Domain
         [StringLength(80)]
         [Comment("物料类型")]
         public string item_type { get; set; }
+
+        /// <summary>
+        /// 供应提前期
+        /// </summary>
+        [Comment("供应提前期")]
+        [Required]
+        [DefaultValue(0)]
+        [Precision(23, 10)]
+        public int PurLT { get; set; }
     }
 }

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

+ 9 - 0
MicroServices/Business/Business.Domain/StructuredDB/MES/IC/ic_item.cs

@@ -687,5 +687,14 @@ namespace Business.Domain
         [StringLength(80)]
         [Comment("物料类型")]
         public string item_type { get; set; }
+
+        /// <summary>
+        /// 供应提前期
+        /// </summary>
+        [Comment("供应提前期")]
+        [Required]
+        [DefaultValue(0)]
+        [Precision(23, 10)]
+        public int PurLT { get; set; }
     }
 }

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

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

+ 2 - 2
MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/AnnualProductionOutline.cs → MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentAnnualProduction.cs

@@ -5,13 +5,13 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
-namespace Business.StructuredDB.SaleFcst
+namespace Business.StructuredDB.Replenishment
 {
 
     /// <summary>
     ///  年度生产大纲    
     /// </summary>
-    public class AnnualProductionOutline : BaseEntity
+    public class ReplenishmentAnnualProduction : BaseEntity
     {
         /// <summary>
         /// 年    

+ 176 - 0
MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentMonthPlan.cs

@@ -0,0 +1,176 @@
+using Business.Domain;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Business.StructuredDB.Replenishment
+{
+
+    /// <summary>
+    ///  月生产主计划    
+    /// </summary>
+    public class ReplenishmentMonthPlan : BaseEntity
+    {
+        /// <summary>
+        /// 市场    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("市场")]
+        public string Area { get; set; }
+
+        /// <summary>
+        /// 产品线    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("产品线")]
+        public string ProdLine { get; set; }
+
+        /// <summary>
+        /// 产品系列    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("产品系列")]
+        public string ProdRange { get; set; }
+
+        /// <summary>
+        /// 车间线体(产线)    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("车间线体(产线)    ")]
+        public string Line { get; set; }
+
+        /// <summary>
+        /// 物料编码   
+        /// </summary>
+        [StringLength(128)]
+        [Comment("物料编码")] 
+        public string ItemNumber { get; set; }
+
+        /// <summary>
+        /// 规格型号    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("规格型号")] 
+        public string Model { get; set; }
+
+        /// <summary>
+        /// 生命周期    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("产品线")]
+        public string LifeCycle { get; set; }
+
+        /// <summary>
+        /// 语种    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("语种")]
+        public string Languages { get; set; }
+
+        /// <summary>
+        /// 计划年月    
+        /// </summary>
+        [StringLength(7)]
+        [Comment("计划年月")] 
+        public string PlanMonth { get; set; }
+
+        /// <summary>
+        /// 计划发货数量    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("计划发货数量")] 
+        public decimal PlanShipQty { get; set; }
+
+        /// <summary>
+        /// 实际发货数量    
+        /// </summary>
+
+        [Precision(18, 5)]
+        [Comment("实际发货数量")] 
+        public decimal ActualShipQty { get; set; }
+
+
+        /// <summary>
+        /// 8001库存(灭菌完成检验合格转入的仓库)    
+        /// </summary>
+
+        [Precision(18, 5)]
+        [Comment("8001库存(灭菌完成检验合格转入的仓库)")] 
+        public decimal Inventory8001 { get; set; }
+
+
+        /// <summary>
+        /// 8000库存(委外灭菌仓)    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("8000库存(委外灭菌仓)")] 
+        public decimal Inventory8000 { get; set; }
+
+        /// <summary>
+        /// 5008库存(成品线边仓)    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("5008库存(成品线边仓)")] 
+        public decimal Inventory5008 { get; set; }
+
+        /// <summary>
+        /// 灭菌中数量    
+        /// </summary>
+        [Precision(18, scale: 5)]
+        [Comment("灭菌中数量")] 
+        public decimal DuringSterilizationQty { get; set; }
+
+        /// <summary>
+        /// 在制数量    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("在制数量")] 
+        public decimal InProductionQty { get; set; }
+
+        /// <summary>
+        /// 计划生产数量    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("计划生产数量")]
+        public decimal PlanProductQty { get; set; }
+
+        /// <summary>
+        /// 实际生产数量    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("实际生产数量")]
+        public decimal ActualProductQty { get; set; }
+
+        
+        /// <summary>
+        /// 期初库存    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("期初库存")] 
+        public decimal StartStockQty { get; set; }
+
+        /// <summary>
+        /// 期末库存    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("期末库存")] 
+        public decimal EndStockQty { get; set; }
+
+        /// <summary>
+        /// 经济批量    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("经济批量")] 
+        public decimal EconomicLotQty { get; set; }
+
+        /// <summary>
+        /// 排序编码    
+        /// </summary>
+        [Comment("排序编码")]
+        public int OrderNum { get; set; }
+    }
+}

+ 3 - 3
MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentModel.cs → MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentROP.cs

@@ -11,11 +11,11 @@ using ZstdSharp.Unsafe;
 namespace Business.Domain
 {
     /// <summary>
-    ///补货模型算法表
+    ///补货模型ROP
     /// </summary>
-    [Comment("补货模型算法表")]
+    [Comment("补货模型ROP")]
     [Index(nameof(number), nameof(tenant_id), nameof(fversion),nameof(long_period),nameof(short_period),nameof(isparam), nameof(seqno),nameof(zero_based_seqno), nameof(factory_id), IsUnique = true)]
-    public class ReplenishmentModel : BaseEntity
+    public class ReplenishmentROP : BaseEntity
     {
         /// <summary>
         /// 物料编码

+ 3 - 3
MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ItemABCFMR.cs → MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentServiceLevel.cs

@@ -11,11 +11,11 @@ using ZstdSharp.Unsafe;
 namespace Business.Domain
 {
     /// <summary>
-    ///补货模型物料abcfmr
+    ///补货模型物料Z服务水平
     /// </summary>
     [Comment("补货模型物料abcfmr")]
     [Index(nameof(number), nameof(tenant_id), nameof(fversion),nameof(isstandalone), nameof(factory_id), IsUnique = true)]
-    public class replenishmentabcfmr : BaseEntity
+    public class ReplenishmentServiceLevel : BaseEntity
     {
         /// <summary>
         /// 物料编码
@@ -118,7 +118,7 @@ namespace Business.Domain
         /// <summary>
         /// 是否独立计算,成品跟产品计算,原材料跟原材料计算
         /// </summary>
-        [Comment("Z服务水平参数")]
+        [Comment("是否独立计算,成品跟产品计算,原材料跟原材料计算")]
         public bool isstandalone { get; set; }
     }
 }

+ 193 - 0
MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentWeekPlan.cs

@@ -0,0 +1,193 @@
+using Business.Domain;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Business.StructuredDB.Replenishment
+{
+
+    /// <summary>
+    ///  周生产计划    
+    /// </summary>
+    public class ReplenishmentWeekPlan : BaseEntity
+    {
+        /// <summary>
+        /// 排序编码(优先级)    
+        /// </summary>
+        [Comment("排序编码(优先级)")]
+        public int OrderNum { get; set; }
+
+        /// <summary>
+        /// 市场    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("市场")]
+        public string Area { get; set; }
+
+        /// <summary>
+        /// 开工日期
+        /// </summary>
+        [Comment("开工日期")]
+        public DateTime PlanStartDate { get; set; }
+
+        /// <summary>
+        /// 开工日期星期
+        /// </summary>
+        [StringLength(128)]
+        [Comment("开工日期星期")]
+        public string Week { get; set; }
+
+        /// <summary>
+        /// 订单号
+        /// </summary>
+        [StringLength(128)]
+        [Comment("订单号")]
+        public string OrderNO { get; set; }
+
+        /// <summary>
+        /// 生产指令
+        /// </summary>
+        [StringLength(128)]
+        [Comment("生产指令")]
+        public string ProductionOrder { get; set; }
+
+        /// <summary>
+        /// SAP工单号
+        /// </summary>
+        [StringLength(128)]
+        [Comment("SAP工单号")]
+        public string SAPOrderNO { get; set; }
+
+
+        /// <summary>
+        /// 指令类型
+        /// </summary>
+        [StringLength(128)]
+        [Comment("指令类型")]
+        public string OrderType { get; set; }
+
+        /// <summary>
+        /// 生产批次
+        /// </summary>
+        [StringLength(128)]
+        [Comment("生产批次")]
+        public string ProductionBatch { get; set; }
+
+        /// <summary>
+        /// 生产状态
+        /// </summary>
+        [StringLength(128)]
+        [Comment("生产状态")]
+        public string ProductionStatus { get; set; }
+
+        /// <summary>
+        /// 产品线    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("产品线")]
+        public string ProdLine { get; set; }
+
+        /// <summary>
+        /// 产品系列    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("产品系列")]
+        public string ProdRange { get; set; }
+
+        /// <summary>
+        /// 车间线体(产线)    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("车间线体(产线)")]
+        public string Line { get; set; }
+
+        /// <summary>
+        /// 物料编码   
+        /// </summary>
+        [StringLength(128)]
+        [Comment("物料编码")]
+        public string ItemNumber { get; set; }
+
+        /// <summary>
+        /// 规格型号    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("规格型号")]
+        public string Model { get; set; }
+
+        /// <summary>
+        /// 语种    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("语种")]
+        public string Languages { get; set; }
+
+        /// <summary>
+        /// 计划数量    
+        /// </summary>
+        [Precision(18,5)]
+        [Comment("计划数量")]
+        public decimal Qty { get; set; }
+
+        /// <summary>
+        /// 物料情况    
+        /// </summary>
+        [StringLength(128)]
+        [Comment("物料情况")]
+        public string ItemStatus { get; set; }
+
+        /// <summary>
+        /// 预计齐套时间    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("预计齐套时间")]
+        public DateTime PlanKittingDate { get; set; }
+
+        /// <summary>
+        /// 灭菌开始日期    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("灭菌开始日期")]
+        public DateTime SterilizationDate { get; set; }
+
+
+        /// <summary>
+        /// 成品入库日期    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("成品入库日期")]
+        public DateTime InStockDate { get; set; }
+
+        /// <summary>
+        /// 组装工时    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("组装工时")]
+        public decimal AssembleHours { get; set; }
+
+        /// <summary>
+        /// 热封工时    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("热封工时")]
+        public decimal HeatSealHours { get; set; }
+
+        /// <summary>
+        /// 包装工时    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("包装工时")]
+        public decimal PackageHours { get; set; }
+
+        /// <summary>
+        /// 总工时    
+        /// </summary>
+        [Precision(18, 5)]
+        [Comment("包装工时")]
+        public decimal TotalHours { get; set; }
+    }
+}

+ 2 - 2
MicroServices/Business/Business.EntityFrameworkCore/EntityFrameworkCore/BusinessDbContextModelCreatingExtensions.cs

@@ -283,9 +283,9 @@ namespace Business.EntityFrameworkCore
                 b.ConfigureByConvention();
             });
 
-            builder.Entity<ReplenishmentModel>(b =>
+            builder.Entity<ReplenishmentROP>(b =>
             {
-                b.ToTable("replenishmentmodel");
+                b.ToTable("ReplenishmentROP");
                 b.HasIndex(b => new { b.number, b.zero_based_seqno, b.long_period, b.short_period, b.tenant_id, b.company_id, b.factory_id });
                 b.ConfigureByConvention();
             });

+ 4 - 3
MicroServices/Business/Business.EntityFrameworkCore/EntityFrameworkCore/DOP/BusinessDbContext.cs

@@ -1,6 +1,7 @@
 using Business.Domain;
 using Business.StructuredDB.MES;
 using Business.StructuredDB.Production;
+using Business.StructuredDB.Replenishment;
 using Business.StructuredDB.SaleFcst;
 using Business.StructuredDB.WMS;
 using Microsoft.EntityFrameworkCore;
@@ -224,7 +225,7 @@ namespace Business.EntityFrameworkCore
         /// <summary>
         /// 年度生产大纲
         /// </summary>
-        public DbSet<AnnualProductionOutline> AnnualProductionOutline { get; set; }
+        public DbSet<ReplenishmentAnnualProduction> ReplenishmentAnnualProduction { get; set; }
 
         /// <summary>
         /// 主生产计划
@@ -258,7 +259,7 @@ namespace Business.EntityFrameworkCore
 
         public DbSet<WMS_PlatformSpecificationComparison> WMS_PlatformSpecificationComparison { get; set; }
 
-        public DbSet<ReplenishmentModel> ReplenishmentModel { get; set; }
+        public DbSet<ReplenishmentROP> ReplenishmentROP { get; set; }
 
         public DbSet<ASNBOLShipperDetail> ASNBOLShipperDetail { get; set; }
 
@@ -269,7 +270,7 @@ namespace Business.EntityFrameworkCore
         /// </summary>
         public DbSet<SAPInv> SAPInv { get; set; }
 
-        public DbSet<replenishmentabcfmr> replenishmentabcfmr { get; set; }
+        public DbSet<ReplenishmentServiceLevel> ReplenishmentServiceLevel { get; set; }
 
         #endregion
 

+ 0 - 47
MicroServices/Business/Business.HttpApi/Controllers/AnnualProductionOutlineController.cs

@@ -1,47 +0,0 @@
-using Business.Dto;
-using Business.SaleForecast;
-using Microsoft.AspNetCore.Mvc;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Volo.Abp;
-
-namespace Business.Controllers
-{
-    /// <summary>
-    /// 年度生产大纲
-    /// </summary>
-    [RemoteService]
-    [Area("Business")]
-    [Route("api/business/AnnualProductionOutline")]
-    public class AnnualProductionOutlineController
-    {
-        /// <summary>
-        /// 年度生产大纲
-        /// </summary>
-        private readonly IAnnualProductionOutlineAppService _IAnnualProductionOutlineAppService;
-
-        /// <summary>
-        /// 构造函数
-        /// </summary>
-        /// <param name="MonthlyCapacityLoadAppService"></param>
-        public AnnualProductionOutlineController(IAnnualProductionOutlineAppService MonthlyCapacityLoadAppService)
-        {
-            _IAnnualProductionOutlineAppService = MonthlyCapacityLoadAppService;
-        }
-        /// <summary>
-        /// 月度需求分析
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        [HttpPost]
-        [Route("SaveAnnualProductionOutline")]
-        public Task<string> SaveAnnualProductionOutline(InputDto input)
-        {
-            return _IAnnualProductionOutlineAppService.SaveAnnualProductionOutline(input);
-        }
-
-    }
-}

+ 0 - 73
MicroServices/Business/Business.HttpApi/Controllers/MonthlyCapacityLoadController.cs

@@ -1,73 +0,0 @@
-using Business.Dto;
-using Business.ResourceExamineManagement;
-using Business.SaleForecast;
-using Microsoft.AspNetCore.Mvc;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Volo.Abp;
-using Volo.Abp.AspNetCore.Mvc;
-
-namespace Business.Controllers
-{
-    /// <summary>
-    /// 月度产能分析接口
-    /// </summary>
-    [RemoteService]
-    [Area("Business")]
-    [Route("api/business/monthly_capacity_load")]
-    public class MonthlyCapacityLoadController:AbpController
-    {
-        /// <summary>
-        /// 产能分析接口
-        /// </summary>
-        private readonly IMonthlyCapacityLoadAppService _MonthlyCapacityLoadAppService;
-
-        /// <summary>
-        /// 构造函数
-        /// </summary>
-        /// <param name="MonthlyCapacityLoadAppService"></param>
-        public MonthlyCapacityLoadController(IMonthlyCapacityLoadAppService MonthlyCapacityLoadAppService)
-        {
-            _MonthlyCapacityLoadAppService = MonthlyCapacityLoadAppService;
-        }
-
-        ///// <summary>
-        ///// 产能分析
-        ///// </summary>
-        ///// <param name="input"></param>
-        ///// <returns></returns>
-        //[HttpPost]
-        //[Route("capacityanalysis")]
-        //public Task<string> CapacityAnalysis(InputDto input)
-        //{
-        //    return _MonthlyCapacityLoadAppService.CapacityAnalysis(input);
-        //}
-
-        /// <summary>
-        /// 月度需求分析
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        [HttpPost]
-        [Route("demandanalysis")]
-        public Task<string> DemandAnalysis(InputDto input)
-        {
-            return _MonthlyCapacityLoadAppService.DemandAnalysis(input);
-        }
-
-        /// <summary>
-        /// 生成整体需求计划
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        [HttpPost]
-        [Route("overalldemandplan")]
-        public Task<string> OverallDemandPlan(InputDto input)
-        {
-            return _MonthlyCapacityLoadAppService.OverallDemandPlan(input);
-        }
-    }
-}

+ 70 - 20
MicroServices/Business/Business.HttpApi/Controllers/ReplenishmentController.cs

@@ -33,17 +33,6 @@ namespace Business.Controllers
             _ReplenishmentAppService = ReplenishmentAppService;
         }
 
-        ///// <summary>
-        ///// 计划工单齐套检查
-        ///// </summary>
-        ///// <param name="workOrd"></param>
-        ///// <returns></returns>
-        //[HttpPost]
-        //[Route("PlanOrderResourceCheck")]
-        //public Task<string> PlanOrderResourceCheck(string companyid)
-        //{
-        //    return _ReplenishmentAppService.PlanOrderResourceCheck(companyid);
-        //}
 
         /// <summary>
         /// 调整ROP和最高库存水位
@@ -57,16 +46,77 @@ namespace Business.Controllers
             return _ReplenishmentAppService.CalcROP(input);
         }
 
-        ///// <summary>
-        ///// 更新周计划
-        ///// </summary>
-        ///// <param name="input"></param>
-        ///// <returns></returns>
-        //[HttpPost]
-        //[Route("weekplan")]
-        //public Task<string> WeekPlan(InputDto input)
+        /// <summary>
+        /// 生产周计划
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [Route("calcweekplan")]
+        public Task<string> CalcWeekPlan(InputDto input)
+        {
+            return _ReplenishmentAppService.CalcWeekPlan(input);
+        }
+
+
+        /// <summary>
+        /// 刷新年度销售预测
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [Route("demandanalysis")]
+        public Task<string> DemandAnalysis(InputDto input)
+        {
+            return _ReplenishmentAppService.DemandAnalysis(input);
+        }
+
+        /// <summary>
+        /// 定时任务长周期物料
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [HttpGet]
+        [Route("calclongperioditempr")]
+        public Task<string> CalcLongPeriodItemPR(InputDto input)
+        {
+            return _ReplenishmentAppService.CalcLongPeriodItemPR(input);
+        }
+
+        /// <summary>
+        /// 定时任务每天补货
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [HttpGet]
+        [Route("calcdayplan")]
+        public Task<string> CalcDayPlan(InputDto input)
+        {
+            return _ReplenishmentAppService.CalcDayPlan(input);
+        }
+
+        /// <summary>
+        /// 生成整体需求计划
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [Route("overalldemandplan")]
+        //public Task<string> OverallDemandPlan(InputDto input)
         //{
-        //    return _ReplenishmentAppService.WeekPlan(input);
+        //    return _ReplenishmentAppService.OverallDemandPlan(input);
         //}
+
+        /// <summary>
+        /// 年度生产大纲
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [Route("SaveAnnualProductionOutline")]
+        public Task<string> SaveAnnualProductionOutline(InputDto input)
+        {
+            return _ReplenishmentAppService.SaveAnnualProductionOutline(input);
+        }
     }
 }

File diff suppressed because it is too large
+ 60 - 0
MicroServices/Business/QuartzSettings/logs/logs.txt


+ 1 - 1
MicroServices/Business/QuartzSettings/task_job.json

@@ -1 +1 @@
-[{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","Interval":"0 32 15 * * ?","ApiUrl":"http://123.60.180.165:8028/api/business/systemquartzjob/syncwmsdatatomysql","Describe":"系统定时任务,勿删勿动","LastRunTime":null,"Status":6,"TaskType":2,"ApiRequestType":"GET","ApiAuthKey":null,"ApiAuthValue":null,"ApiParameter":null,"DllClassName":null,"DllActionName":null,"id":4,"timeflag":null,"changetime":null},{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","Interval":"0 01 01 * * ?","ApiUrl":"http://123.60.180.165:8028/api/business/systemquartzjob/loginstall","Describe":"系统定时任务,勿删勿动","LastRunTime":null,"Status":6,"TaskType":2,"ApiRequestType":"GET","ApiAuthKey":null,"ApiAuthValue":null,"ApiParameter":null,"DllClassName":null,"DllActionName":null,"id":5,"timeflag":null,"changetime":null},{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","Interval":"0 04 17 * * ?","ApiUrl":"http://localhost:51186/api/business/systemquartzjob/syncbasedatatomongodb","Describe":"系统定时任务,勿删勿动","LastRunTime":"2023-07-04T17:03:12","Status":6,"TaskType":2,"ApiRequestType":"GET","ApiAuthKey":null,"ApiAuthValue":null,"ApiParameter":null,"DllClassName":null,"DllActionName":null,"id":6,"timeflag":null,"changetime":null}]
+[{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","Interval":"0 32 15 * * ?","ApiUrl":"http://123.60.180.165:8028/api/business/systemquartzjob/syncwmsdatatomysql","Describe":"系统定时任务,勿删勿动","LastRunTime":null,"Status":6,"TaskType":2,"ApiRequestType":"GET","ApiAuthKey":null,"ApiAuthValue":null,"ApiParameter":null,"DllClassName":null,"DllActionName":null,"id":4,"timeflag":null,"changetime":null},{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","Interval":"0 01 01 * * ?","ApiUrl":"http://123.60.180.165:8028/api/business/systemquartzjob/loginstall","Describe":"系统定时任务,勿删勿动","LastRunTime":null,"Status":6,"TaskType":2,"ApiRequestType":"GET","ApiAuthKey":null,"ApiAuthValue":null,"ApiParameter":null,"DllClassName":null,"DllActionName":null,"id":5,"timeflag":null,"changetime":null},{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","Interval":"0 04 17 * * ?","ApiUrl":"http://localhost:51186/api/business/systemquartzjob/syncbasedatatomongodb","Describe":"系统定时任务,勿删勿动","LastRunTime":"2023-07-04T17:03:12","Status":6,"TaskType":2,"ApiRequestType":"GET","ApiAuthKey":null,"ApiAuthValue":null,"ApiParameter":null,"DllClassName":null,"DllActionName":null,"id":6,"timeflag":null,"changetime":null},{"TaskName":"长周期物料PR","GroupName":"systemquartzjob","Interval":"0 0 0 14 * ?","ApiUrl":"http://localhost:51186/api/business/replenishment/calclongperioditempr?year= 0&month= 0&tenant_id= 1000&company_id= 1000&factory_id= 1001&org_id= 1001","Describe":"系统定时任务,勿删勿动","LastRunTime":"2023-09-06T00:29:05","Status":6,"TaskType":2,"ApiRequestType":"GET","ApiAuthKey":null,"ApiAuthValue":null,"ApiParameter":null,"DllClassName":null,"DllActionName":null,"id":7,"timeflag":null,"changetime":null}]

+ 51 - 0
MicroServices/DopInterfacePlatform/ClientIpCheckActionFilter.cs

@@ -0,0 +1,51 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using System.Net;
+
+namespace WebApiTest
+{
+    public class ClientIpCheckActionFilter : ActionFilterAttribute
+    {
+        private readonly ILogger _logger;
+        private readonly string _safelist;
+
+        public ClientIpCheckActionFilter(string safelist, ILogger logger)
+        {
+            _safelist = safelist;
+            _logger = logger;
+        }
+
+        public override void OnActionExecuting(ActionExecutingContext context)
+        {
+            var remoteIp = context.HttpContext.Connection.RemoteIpAddress;
+            _logger.LogDebug("Remote IpAddress: {RemoteIp}", remoteIp);
+            var ip = _safelist.Split(';');
+            var badIp = true;
+
+            if (remoteIp.IsIPv4MappedToIPv6)
+            {
+                remoteIp = remoteIp.MapToIPv4();
+            }
+
+            foreach (var address in ip)
+            {
+                var testIp = IPAddress.Parse(address);
+
+                if (testIp.Equals(remoteIp))
+                {
+                    badIp = false;
+                    break;
+                }
+            }
+
+            if (badIp)
+            {
+                _logger.LogWarning("Forbidden Request from IP: {RemoteIp}", remoteIp);
+                context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
+                return;
+            }
+
+            base.OnActionExecuting(context);
+        }
+    }
+}

+ 40 - 0
MicroServices/DopInterfacePlatform/Controllers/TokenController.cs

@@ -0,0 +1,40 @@
+using DopInterfacePlatform.Interface;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using System.Security.Claims;
+
+namespace DopInterfacePlatform.Controllers
+{
+    [Route("api/[controller]")]
+    [ApiController]
+    public class TokenController : ControllerBase
+    {
+        public IJwtService _jwtService { set; get; }
+
+        private IConfiguration _configuration;
+        public TokenController(IJwtService jwtService, IConfiguration configuration)
+        {
+            _jwtService = jwtService;
+            _configuration = configuration;
+        }
+
+        [AllowAnonymous]
+        [HttpGet]
+        [Route("token")]
+        public string GetToken()
+        {
+            JwtOptions jwtOptions=new JwtOptions();
+            jwtOptions.ExpireSeconds = Convert.ToInt32(_configuration["JWT:ExpireSeconds"]);
+            jwtOptions.Issuer = _configuration["JWT:Issuer"];
+            jwtOptions.Audience = _configuration["JWT:Audience"];
+            jwtOptions.Key = _configuration["JWT:Key"];
+            List<Claim> claims = new List<Claim>();
+            claims.Add(new Claim(ClaimTypes.Name, "用户1"));
+            claims.Add(new Claim(ClaimTypes.Role, "超级管理员"));
+            return _jwtService.BuildToken(claims, jwtOptions);
+        }
+    }
+}

+ 73 - 0
MicroServices/DopInterfacePlatform/Controllers/WeatherForecastController.cs

@@ -0,0 +1,73 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using System.ServiceModel;
+using System.Xml;
+
+namespace DopInterfacePlatform.Controllers
+{
+    [ApiController]
+    [Route("[controller]/[action]")]
+    [Authorize]
+    public class WeatherForecastController : ControllerBase
+    {
+        private static readonly string[] Summaries = new[]
+        {
+        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
+    };
+
+        private readonly ILogger<WeatherForecastController> _logger;
+
+        public WeatherForecastController(ILogger<WeatherForecastController> logger)
+        {
+            _logger = logger;
+        }
+
+        [HttpGet(Name = "GetWeatherForecast")]
+        [Authorize]
+        public IEnumerable<WeatherForecast> Get()
+        {
+            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
+            {
+                Date = DateTime.Now.AddDays(index),
+                TemperatureC = Random.Shared.Next(-20, 55),
+                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
+            })
+            .ToArray();
+        }
+
+        [HttpGet(Name = "GetByCount")]
+        [Authorize]
+        public int GetByCount(int count)
+        {
+            return count+7;
+        }
+
+
+        [HttpGet(Name = "GetByCount1")]
+        [Authorize]
+        public int GetByCount1(int count,int count2)
+        {
+            return count + 7+count2;
+        }
+
+        [HttpGet(Name = "TestWebservice")]
+        [Authorize]
+        public string TestWebservice()
+        {
+            var parameters = new Dictionary<string, string> { { "byProvinceName", "湖北" } };
+            HttpContent httpContent = new FormUrlEncodedContent(parameters);
+
+            // contentType对应 webservice提示 如下图
+            httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
+            HttpClient httpClient = new HttpClient();
+            HttpResponseMessage response = httpClient.PostAsync("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getSupportCity", httpContent).Result;
+            var statusCode = response.StatusCode.ToString();
+            var result = response.Content.ReadAsStringAsync().Result;
+            var doc = new XmlDocument();
+            doc.LoadXml(result);
+            // xml返回值数据所在标签,替换成你的xml结果标签,如下图
+            var status = doc.InnerXml;
+            return status;
+        }
+    }
+}

+ 23 - 0
MicroServices/DopInterfacePlatform/DopInterfacePlatform.csproj

@@ -0,0 +1,23 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <Nullable>enable</Nullable>
+    <ImplicitUsings>enable</ImplicitUsings>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.21" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.21" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.21" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.21">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
+    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.32.2" />
+    <PackageReference Include="System.ServiceModel.Http" Version="6.0.0" />
+  </ItemGroup>
+
+</Project>

+ 8 - 0
MicroServices/DopInterfacePlatform/DopInterfacePlatform.csproj.user

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Controller_SelectedScaffolderID>ApiControllerEmptyScaffolder</Controller_SelectedScaffolderID>
+    <Controller_SelectedScaffolderCategoryPath>root/Common/Api</Controller_SelectedScaffolderCategoryPath>
+    <NameOfLastUsedPublishProfile>D:\DOPCore\MicroServices\DOPInterfacePlatform\Properties\PublishProfiles\FolderProfile.pubxml</NameOfLastUsedPublishProfile>
+  </PropertyGroup>
+</Project>

+ 25 - 0
MicroServices/DopInterfacePlatform/DopInterfacePlatform.sln

@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33205.214
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DopInterfacePlatform", "DopInterfacePlatform.csproj", "{58B598BA-29FC-492E-A976-D271F3A842C8}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{58B598BA-29FC-492E-A976-D271F3A842C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{58B598BA-29FC-492E-A976-D271F3A842C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{58B598BA-29FC-492E-A976-D271F3A842C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{58B598BA-29FC-492E-A976-D271F3A842C8}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {7F2B40AE-DFBA-4D9F-B6CB-01281BA69379}
+	EndGlobalSection
+EndGlobal

+ 14 - 0
MicroServices/DopInterfacePlatform/DopInterfacePlatformContext.cs

@@ -0,0 +1,14 @@
+using DopInterfacePlatform.Entity;
+using Microsoft.EntityFrameworkCore;
+
+namespace DopInterfacePlatform
+{
+    public class DopInterfacePlatformContext: DbContext
+    {
+        public DbSet<InterfacePlatformLog> InterfacePlatformLog { get; set; }
+        public DopInterfacePlatformContext(DbContextOptions<DopInterfacePlatformContext> options)
+           : base(options)
+        {
+        }
+    }
+}

+ 49 - 0
MicroServices/DopInterfacePlatform/Entity/InterfacePlatformLog.cs

@@ -0,0 +1,49 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Security.Principal;
+
+namespace DopInterfacePlatform.Entity
+{
+    [Table("InterfacePlatformLog")]
+    public class InterfacePlatformLog
+    {
+        [Key]
+        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
+        public Int64 operatorcol_id { get; set; }
+
+        /// <summary>
+        /// Desc:
+        /// Default:
+        /// Nullable:False
+        /// </summary>           
+        public string operatorcol_ip { get; set; }
+
+        /// <summary>
+        /// Desc:调用入参
+        /// Default:
+        /// Nullable:True
+        /// </summary>           
+        public string operatorcol_request { get; set; }
+
+        /// <summary>
+        /// Desc:调用出参
+        /// Default:
+        /// Nullable:True
+        /// </summary>           
+        public string operatorcol_respone { get; set; }
+
+        /// <summary>
+        /// Desc:
+        /// Default:
+        /// Nullable:False
+        /// </summary>           
+        public DateTime operatorcol_time { get; set; }
+
+        /// <summary>
+        /// Desc:调用接口耗时,单位为毫秒
+        /// Default:
+        /// Nullable:False
+        /// </summary>           
+        public int operatorcol_duration { get; set; }
+    }
+}

+ 9 - 0
MicroServices/DopInterfacePlatform/Interface/IJwtService.cs

@@ -0,0 +1,9 @@
+using System.Security.Claims;
+
+namespace DopInterfacePlatform.Interface
+{
+    public interface IJwtService
+    {
+        string BuildToken(IEnumerable<Claim> claims, JwtOptions options);
+    }
+}

+ 55 - 0
MicroServices/DopInterfacePlatform/IpWhiteListMiddleware.cs

@@ -0,0 +1,55 @@
+using System.Net;
+
+namespace DopInterfacePlatform
+{
+    public class IpWhiteListMiddleware
+    {
+        private readonly RequestDelegate _next;
+        private readonly ILogger<IpWhiteListMiddleware> _logger;
+        private readonly string _adminSafeList;
+
+        public IpWhiteListMiddleware(
+            RequestDelegate next,
+            ILogger<IpWhiteListMiddleware> logger,
+            string adminSafeList)
+        {
+            _adminSafeList = adminSafeList;
+            _next = next;
+            _logger = logger;
+        }
+
+        public async Task Invoke(HttpContext context)
+        {
+            if (context.Request.Method != "GET")
+            {
+                var remoteIp = context.Connection.RemoteIpAddress;
+                _logger.LogDebug($"Request from Remote IP address: {remoteIp}");
+
+                string[] ip = _adminSafeList.Split(';');
+
+                var bytes = remoteIp.GetAddressBytes();
+                var badIp = true;
+                foreach (var address in ip)
+                {
+                    var testIp = IPAddress.Parse(address);
+                    if (testIp.GetAddressBytes().SequenceEqual(bytes))
+                    {
+                        badIp = false;
+                        break;
+                    }
+                }
+
+                if (badIp)
+                {
+                    _logger.LogInformation(
+                        $"Forbidden Request from Remote IP address: {remoteIp}");
+                    context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
+                    return;
+                }
+            }
+
+            await _next.Invoke(context);
+
+        }
+    }
+}

+ 28 - 0
MicroServices/DopInterfacePlatform/JWTExtensions.cs

@@ -0,0 +1,28 @@
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.IdentityModel.Tokens;
+using System.Text;
+
+namespace DopInterfacePlatform
+{
+    public static class JWTExtensions
+    {
+        public static AuthenticationBuilder AddJWTAuthentication(this IServiceCollection services, JwtOptions jwtOptions)
+        {
+            return services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+                .AddJwtBearer(x =>
+                {
+                    x.TokenValidationParameters = new()
+                    {
+                        ValidateIssuer = true,//是否验证发行商
+                        ValidateAudience = true,//是否验证受众者
+                        ValidateLifetime = true,//是否验证失效时间
+                        ValidateIssuerSigningKey = true,//是否验证签名键
+                        ValidIssuer = jwtOptions.Issuer,
+                        ValidAudience = jwtOptions.Audience,
+                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.Key))
+                    };
+                });
+        }
+    }
+}

+ 25 - 0
MicroServices/DopInterfacePlatform/JwtOptions.cs

@@ -0,0 +1,25 @@
+namespace DopInterfacePlatform
+{
+    public class JwtOptions
+    {
+        /// <summary>
+        /// 签发者
+        /// </summary>
+        public string Issuer { get; set; }
+
+        /// <summary>
+        /// 接收者
+        /// </summary>
+        public string Audience { get; set; }
+
+        /// <summary>
+        /// 密钥
+        /// </summary>
+        public string Key { get; set; }
+
+        /// <summary>
+        /// 过期时间
+        /// </summary>
+        public int ExpireSeconds { get; set; }
+    }
+}

+ 108 - 0
MicroServices/DopInterfacePlatform/LogFilter.cs

@@ -0,0 +1,108 @@
+using DopInterfacePlatform.Entity;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+using System.Diagnostics;
+
+namespace DopInterfacePlatform
+{
+    /// <summary>
+    /// 记录日志
+    /// </summary>
+    public class LogFilter : ActionFilterAttribute
+    {
+        // private IBusApiOperatorRepository api_operator_repository;
+
+        private Stopwatch stopwach { get; set; }
+        private string actionArguments { get; set; }
+        private Dictionary<string, object> keyValuePairs { set; get; }
+
+        private readonly DopInterfacePlatformContext _context;
+
+        public LogFilter(DopInterfacePlatformContext context)
+        {
+            _context = context;
+        }
+
+        public override void OnActionExecuting(ActionExecutingContext context)
+        {
+            base.OnActionExecuting(context);
+
+            //is not controller return
+            if (!(context.ActionDescriptor is ControllerActionDescriptor action))
+                return;
+            var request = context.HttpContext.Request;
+            //启动倒带方式
+            request.EnableBuffering();
+            if (request.Method.ToLower().Equals("post"))
+            {
+                request.Body.Position = 0;
+                using var requestReader = new StreamReader(request.Body);
+                var requestContent = requestReader.ReadToEnd();
+                request.Body.Position = 0;
+            }
+
+            stopwach = new Stopwatch();
+            stopwach.Start();
+            if(context.ActionArguments.Count>0)
+            {
+                actionArguments = context.ActionArguments.ToJsonString();
+            }
+            stopwach = new Stopwatch();
+            stopwach.Start();
+        }
+
+        public override void OnActionExecuted(ActionExecutedContext context)
+        {
+            base.OnActionExecuted(context);
+
+            //is not controller return
+            if (!(context.ActionDescriptor is ControllerActionDescriptor action))
+                return;
+
+            stopwach.Stop();
+            var time = stopwach.Elapsed;
+
+            // string url = context.HttpContext.Request.Host + context.HttpContext.Request.Path + context.HttpContext.Request.QueryString;
+            string logMethod = context.HttpContext.Request.Method;
+            dynamic result = context.Result.GetType().Name == "EmptyResult"
+                ? new { Value = "无返回结果" }
+                : context.Result as dynamic;
+            string res = "在返回结果前发生了异常";
+            try
+            {
+                if (result != null)
+                {
+                    res = Newtonsoft.Json.JsonConvert.SerializeObject(result.Value);
+                }
+            }
+            catch (System.Exception ex)
+            {
+                res = "日志未获取到结果,返回的数据无法序列化!" + ex.Message;
+            }
+
+            //转换ActionDescriptor 
+            string logController = context.RouteData.Values["Controller"].ToString();
+            var logAction = context.RouteData.Values["Action"].ToString();
+            var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
+            var ipAddress = context.HttpContext.Connection.RemoteIpAddress.ToString();
+            if(logAction!="GetToken")
+            {
+                var model = new InterfacePlatformLog();
+                if (actionArguments == null)
+                {
+                    actionArguments = "";
+                }
+                model.operatorcol_time = DateTime.Now;
+                model.operatorcol_ip = ipAddress;
+                model.operatorcol_duration = (int)time.TotalSeconds * 1000;
+                model.operatorcol_request = $"{logController}-{logAction}-{logMethod}-{actionArguments}"; //调用入参
+                model.operatorcol_respone = res; //调用出参 
+
+                _context.InterfacePlatformLog.Add(model);
+                _context.SaveChanges();
+            }
+        }
+    }
+}

+ 65 - 0
MicroServices/DopInterfacePlatform/Program.cs

@@ -0,0 +1,65 @@
+using DopInterfacePlatform.Interface;
+using DopInterfacePlatform.Service;
+using Microsoft.EntityFrameworkCore;
+using Swashbuckle.AspNetCore.SwaggerGen;
+using WebApiTest;
+
+namespace DopInterfacePlatform
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            var builder = WebApplication.CreateBuilder(args);
+
+            // Add services to the container.
+
+            builder.Services.AddControllers();
+            builder.Services.AddScoped<ClientIpCheckActionFilter>(container =>
+            {
+                var loggerFactory = container.GetRequiredService<ILoggerFactory>();
+                var logger = loggerFactory.CreateLogger<ClientIpCheckActionFilter>();
+
+                return new ClientIpCheckActionFilter(builder.Configuration["IpWhiteList"], logger);
+            });
+            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
+            builder.Services.AddEndpointsApiExplorer();
+            builder.Services.AddSwaggerGen();
+            builder.Services.AddScoped<IJwtService, JwtService>();
+            JwtOptions jwtOpt = builder.Configuration.GetSection("JWT").Get<JwtOptions>();
+            builder.Services.AddJWTAuthentication(jwtOpt);
+            builder.Services.Configure<SwaggerGenOptions>(c =>
+            {
+                c.AddAuthenticationHeader();
+            });
+
+            builder.Services.AddDbContext<DopInterfacePlatformContext>(opt =>
+               opt.UseSqlServer(builder.Configuration["ConnectionStrings:todoContext"]));
+
+
+            builder.Services.AddMvcCore(options =>
+            {
+                options.Filters.Add<LogFilter>();
+            }).AddApiExplorer();
+
+            var app = builder.Build();
+
+            // Configure the HTTP request pipeline.
+
+            app.UseSwagger();
+            app.UseSwaggerUI();
+
+
+            app.UseHttpsRedirection();
+
+            app.UseAuthentication();//注意,一定得先启动这个
+            app.UseAuthorization();
+
+            app.UseMiddleware<IpWhiteListMiddleware>(builder.Configuration["IpWhiteList"]);
+
+            app.MapControllers();
+
+            app.Run();
+        }
+    }
+}

+ 21 - 0
MicroServices/DopInterfacePlatform/Properties/PublishProfiles/FolderProfile.pubxml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <DeleteExistingFiles>true</DeleteExistingFiles>
+    <ExcludeApp_Data>false</ExcludeApp_Data>
+    <LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
+    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
+    <LastUsedPlatform>Any CPU</LastUsedPlatform>
+    <PublishProvider>FileSystem</PublishProvider>
+    <PublishUrl>C:\Users\yuanhefei\Desktop\DOP文档\publish\DOPInterfacePlatform</PublishUrl>
+    <WebPublishMethod>FileSystem</WebPublishMethod>
+    <_TargetId>Folder</_TargetId>
+    <SiteUrlToLaunchAfterPublish />
+    <TargetFramework>net6.0</TargetFramework>
+    <ProjectGuid>58b598ba-29fc-492e-a976-d271f3a842c8</ProjectGuid>
+    <SelfContained>false</SelfContained>
+  </PropertyGroup>
+</Project>

+ 11 - 0
MicroServices/DopInterfacePlatform/Properties/PublishProfiles/FolderProfile.pubxml.user

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <_PublishTargetUrl>C:\Users\yuanhefei\Desktop\DOP文档\publish\DOPInterfacePlatform</_PublishTargetUrl>
+    <History>True|2023-09-06T08:32:23.0343111Z;True|2023-09-06T16:29:00.3120067+08:00;True|2023-09-06T16:20:50.3191564+08:00;True|2023-09-06T16:16:12.2283892+08:00;True|2023-09-06T16:16:02.3726602+08:00;True|2023-09-06T16:12:46.4394558+08:00;True|2023-09-06T15:50:40.9163484+08:00;True|2023-09-06T15:15:21.6056173+08:00;</History>
+    <LastFailureDetails />
+  </PropertyGroup>
+</Project>

+ 31 - 0
MicroServices/DopInterfacePlatform/Properties/launchSettings.json

@@ -0,0 +1,31 @@
+{
+  "$schema": "https://json.schemastore.org/launchsettings.json",
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:24100",
+      "sslPort": 44393
+    }
+  },
+  "profiles": {
+    "DopInterfacePlatform": {
+      "commandName": "Project",
+      "dotnetRunMessages": true,
+      "launchBrowser": true,
+      "launchUrl": "swagger",
+      "applicationUrl": "http://localhost:9800;https://localhost:9801",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "launchUrl": "swagger",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}

+ 21 - 0
MicroServices/DopInterfacePlatform/Service/JwtService.cs

@@ -0,0 +1,21 @@
+using DopInterfacePlatform.Interface;
+using Microsoft.IdentityModel.Tokens;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using System.Text;
+
+namespace DopInterfacePlatform.Service
+{
+    public class JwtService : IJwtService
+    {
+        public string BuildToken(IEnumerable<Claim> claims, JwtOptions options)
+        {
+            //过期时间
+            TimeSpan timeSpan = TimeSpan.FromSeconds(options.ExpireSeconds);//token过期时间
+            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(options.Key));//加密的token密钥
+            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);//签名证书,其值为securityKey和HmacSha256Signature算法
+            var tokenDescriptor = new JwtSecurityToken(options.Issuer, options.Audience, claims, expires: DateTime.Now.Add(timeSpan), signingCredentials: credentials);//表示jwt token的描述信息,其值包括Issuer签发方,Audience接收方,Claims载荷,过期时间和签名证书
+            return new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);//使用该方法转换为字符串形式的jwt token返回
+        }
+    }
+}

+ 610 - 0
MicroServices/DopInterfacePlatform/StringHelper.cs

@@ -0,0 +1,610 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System.Collections;
+using System.Text;
+using System.Xml;
+
+namespace DopInterfacePlatform
+{
+    public static class StringHelper
+    {
+        private static int[] numbers = new[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+        /// <summary>
+        /// 随机字符串数组集合
+        /// </summary>
+        private static readonly string[] NonceStrings = new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
+        /// <summary>
+        /// 四舍五入取整数部分
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static int StringToIntMathRound(this object @this)
+        {
+            string s_this = @this.ToString();
+            int i_result = 0;
+            if (s_this.Contains("."))
+            {
+                var tS =s_this.Split(".");
+                i_result = Convert.ToInt32(tS[0]);
+                if (Convert.ToInt32(tS[1].Substring(0, 1)) > 4)
+                {
+                    i_result += 1;
+                }
+            }
+            else
+            {
+                i_result = Convert.ToInt32(@this);
+            }
+
+            return i_result;
+        }
+        
+        /// <summary>
+        /// 生成指定长度的随机字符串
+        /// </summary>
+        /// <returns></returns>
+        public static string CreateNonceStr(this int stringLenght)
+        {
+            Random random = new Random();
+            var sb = new StringBuilder();
+            var length = NonceStrings.Length;
+            for (int i = 0; i < stringLenght; i++)
+            {
+                //通过random获得的随机索引到,NonceStrings数组中获取对应数组值
+                sb.Append(NonceStrings[random.Next(length - 1)]);
+            }
+            return sb.ToString();
+        }
+
+        
+        /// <summary>
+        /// 获取指定长度的随机数
+        /// </summary>
+        /// <returns></returns>
+        public static string GetRandom(this string @prexString, int lenght)
+        {
+            string result = prexString;
+            Random rd = new Random();
+            for (int i = 0; i < lenght - prexString.Length; i++)
+            {
+                int RandKey = rd.Next(100, 999);
+                var index = RandKey % 10;
+                result += numbers[index].ToString();
+            }
+            return result;
+        }
+
+
+        /// <summary>
+        /// decimal取指定位小数返回
+        /// </summary>
+        /// <param name="this"></param>
+        /// <param name="decimals"></param>
+        /// <returns></returns>
+        public static decimal DecimalsFormat(this decimal @this,int decimals=2)
+        {
+            return Math.Round(@this, decimals);
+        }
+
+        /// <summary>
+        /// 涉及到金额部分把最后的0 去掉
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static string CashFormat(this object @this)
+        {
+            string cashValue = @this.ToString();
+            if (cashValue != null && cashValue.Contains(".")) //
+            {
+                while (cashValue.EndsWith("0"))
+                {
+                    cashValue = cashValue.Substring(0, cashValue.Length - 1);
+                }
+
+                if (cashValue.EndsWith("."))
+                    cashValue = cashValue.Substring(0, cashValue.Length - 1);
+            }
+
+            return cashValue;
+        }
+
+        /// <summary>
+        /// 判断是否为空
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static bool IsNullOrWhiteSpace(this string @this)
+        {
+            if (@this == null) return true;
+            return string.IsNullOrWhiteSpace(@this.Trim()) || @this == "null";
+        }
+
+        /// <summary>
+        /// tostring的另一个版本,当是null字符串时返回空串
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static string ToSelfOrNullString(this string @this)
+        {
+            if (@this == null) return "";
+            return string.IsNullOrWhiteSpace(@this.Trim()) || @this == "null" ? "" : @this;
+        }
+
+        public static Hashtable GetProperties<T>(this T @userInfo)
+        {
+            Hashtable hashtable = new Hashtable();
+            foreach (System.Reflection.PropertyInfo p in userInfo.GetType().GetProperties())
+            {
+                hashtable.Add(p.Name, p.GetValue(userInfo));
+            }
+            return hashtable;
+        }
+        /// <summary>
+        /// 去掉Emoji表情
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static string RemoveEmoji(this string @this)
+        {
+            foreach (var strTmp in @this)
+            {
+                byte[] bts = Encoding.UTF32.GetBytes(strTmp.ToString());
+                
+                if (bts[0].ToString() == "253"&& bts[1].ToString() == "255")
+                {
+                    @this = @this.Replace(strTmp.ToString(), "");
+                }
+                    
+            }
+            return @this;
+        }
+
+
+        /// <summary>
+        /// 将Json字符串转换为对应的Json对象
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static T ToJsonObject<T>(this string @this)
+        {
+            return JsonConvert.DeserializeObject<T>(@this);
+        }
+        public static string DateTimeOfDayWeek(this string @this)
+        {
+            try
+            {
+
+                return ((int) Convert.ToDateTime(@this).DayOfWeek).ToString();
+            }
+            catch (Exception e)
+            {
+                return "";
+            }
+        }
+
+        public static string YuanToFen(this string money)
+        {
+            return Convert.ToInt64(Convert.ToDecimal(money) * 100).ToString();
+        } 
+        
+        public static string FenToYuan(this int money)
+        {
+            return (Convert.ToDecimal(money)/100).ToString();
+        }
+        /// <summary>
+        /// 将对象转换为string字符串
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static string ToJsonString(this object @this)
+        {
+            return JsonConvert.SerializeObject(@this);
+        }
+
+        /// <summary>
+        /// 排序字段
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static Dictionary<string, object> SortDictionary(this Dictionary<string, object> @this)
+        {
+            Dictionary<string, object> keyValues = new Dictionary<string, object>();
+            foreach (var item in @this)
+            {
+                if (item.Value == null || item.Value.ToString() == "")
+                {
+                    continue;
+                }
+                if(item.Key== "PatType")
+                {
+
+                }
+                if (item.Value.GetType().Name == "JObject")
+                {
+                    JObject j_object = item.Value as JObject;
+                    keyValues = keyValues.Concat(j_object.JObjectToDictionary()).ToDictionary(k => k.Key, v => v.Value);
+                }
+                else
+                {
+                    keyValues.Add(item.Key, item.Value);
+                }
+            }
+            return keyValues.OrderBy(p => p.Key).Where(d => d.Value != null).ToDictionary(p => p.Key, o => o.Value);
+        }
+
+        /// <summary>
+        /// JObject to Dictionary<string, object>
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        private static Dictionary<string, object> JObjectToDictionary(this JObject @this)
+        {
+            Dictionary<string, object> keyValues = new Dictionary<string, object>();
+            foreach (var item in @this)
+            {
+                keyValues.Add(item.Key, item.Value);
+
+                //不考虑有多层的情况
+                //if (item.Value.GetType().Name == "JObject")
+                //{
+                //    JObject j_object = item.Value as JObject;
+                //    //还有子项目
+                //    keyValues = keyValues.Concat(j_object.JObjectToDictionary()).ToDictionary(k => k.Key, v => v.Value);
+                //}
+                //else
+                //{
+                //    keyValues.Add(item.Key, item.Value);
+                //}
+            }
+            return keyValues;
+        }
+
+        /// <summary>
+        /// 转换成签名串
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static string ToSignString(this object @this)
+        {
+            var objName = @this.GetType().Name;
+            if (objName == "DateTime")
+            {
+                return Convert.ToDateTime(@this).ToString("yyyy-MM-dd HH:mm:ss");
+            }
+            else
+            {
+                return @this.ToString();
+            }
+        }
+
+        /// <summary>
+        /// BASE64编码
+        /// </summary>
+        /// <param name="un_code_string"></param>
+        /// <param name="code_type"></param>
+        /// <returns></returns>
+        public static string EncodeBase64(this string un_code_string,string code_type= "utf-8")
+        {
+            byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(un_code_string);
+            string encode;
+            try
+            {
+                encode = Convert.ToBase64String(bytes);
+            }
+            catch
+            {
+                encode = un_code_string;
+            }
+            return encode;
+        }
+        /// <summary>
+        /// BASE64解码
+        /// </summary>
+        /// <param name="code_string"></param>
+        /// <param name="code_type"></param>
+        /// <returns></returns>
+        public static string DecodeBase64(this string code_string,string code_type = "utf-8")
+        {
+            byte[] bytes = Convert.FromBase64String(code_string);
+            string decode;
+            try
+            {
+                decode = Encoding.GetEncoding(code_type).GetString(bytes);
+            }
+            catch
+            {
+                decode = code_string;
+            }
+            return decode;
+        }
+
+
+        /// <summary>
+        /// xml格式的字符串转换成对象
+        /// </summary>
+        /// <param name="xmlStr"></param>
+        /// <returns></returns>
+        public static T XmlToObject<T>(this string xmlStr) where T : new()
+        {
+            try
+            {
+                T obj = new T();
+                var repType = typeof(T);
+                XmlDocument document = new XmlDocument();
+                document.LoadXml(xmlStr);    //加载Xml文件  
+                XmlElement node = document.DocumentElement; //xml的根标签
+                var properties = repType.GetProperties();
+                foreach (var itemProp in properties)
+                {
+                    #region current type is List
+                    if (itemProp.PropertyType.FullName.Contains("System.Collections.Generic.List"))
+                    {
+                        object array = new object();
+                        var arryLength = 0;
+                        var notNullLength = 0;
+                        var arryType = itemProp.PropertyType.UnderlyingSystemType;
+
+                        var objList = itemProp.GetValue(obj, null) as System.Collections.IEnumerable;
+                        var enumt = objList.GetEnumerator();
+                        //enumt.
+                        var currentType = itemProp.PropertyType.GetGenericArguments()[0];
+
+                        foreach (XmlNode xmlitem in node.ChildNodes)
+                        {
+                            if (xmlitem.Name == itemProp.Name)
+                            {
+                                arryLength++;
+                            }
+                        }
+                        if (arryLength > 0)
+                        {
+                            var arrayModel = arryType.InvokeMember("Set", System.Reflection.BindingFlags.CreateInstance, null, array, new object[] { arryLength }) as System.Collections.IList;
+                            foreach (XmlNode item in node.ChildNodes)
+                            {
+                                //current type is array
+                                if (item.Name == itemProp.Name)
+                                {
+                                    var model = currentType.Assembly.CreateInstance(currentType.FullName); // arryType.GetElementType().Assembly.CreateInstance(currentType.FullName);
+                                    SetArray(item.ChildNodes, model, true);
+                                    arrayModel.Add(model);
+                                    //arrayModel[notNullLength] = model;
+                                    notNullLength++;
+                                }
+                            }
+                            itemProp.SetValue(obj, arrayModel, null);
+                        }
+
+                        continue;
+                    }
+                    #endregion
+                    var baseType = itemProp.PropertyType.BaseType.Name;
+                    if (baseType == "Array")
+                    {
+                        #region Current type is Array
+                        object array = new object();
+                        var arryLength = 0;
+                        var notNullLength = 0;
+                        var arryType = itemProp.PropertyType.UnderlyingSystemType;
+
+                        foreach (XmlNode xmlitem in node.ChildNodes)
+                        {
+                            if (xmlitem.Name == itemProp.Name && xmlitem.ChildNodes!=null && xmlitem.ChildNodes.Count>0)
+                            {
+                                arryLength++;
+                            }
+                        }
+                        if (arryLength > 0)
+                        {
+                            var arrayModel = arryType.InvokeMember("Set", System.Reflection.BindingFlags.CreateInstance, null, array, new object[] { arryLength }) as System.Collections.IList;
+                            foreach (XmlNode item in node.ChildNodes)
+                            {
+                                //current type is array
+                                if (item.Name == itemProp.Name && item.ChildNodes!=null && item.ChildNodes.Count>0)
+                                {
+                                    var model = arryType.GetElementType().Assembly.CreateInstance(arryType.GetElementType().FullName);
+                                    SetArray(item.ChildNodes, model);
+                                    arrayModel[notNullLength] = model;
+                                    notNullLength++;
+                                }
+                            }
+                            itemProp.SetValue(obj, arrayModel, null);
+                        }
+                        #endregion
+                    }
+                    else
+                    {
+                        #region Current type isn't Array
+                        foreach (XmlNode item in node.ChildNodes)
+                        {
+                            #region Current type is Number
+                            if (itemProp.Name == item.Name && (itemProp.PropertyType == typeof(long) || itemProp.PropertyType == typeof(int) || itemProp.PropertyType == typeof(string)))
+                            {
+                                if (itemProp.PropertyType == typeof(int) || itemProp.PropertyType == typeof(long))
+                                {
+                                    if (!string.IsNullOrEmpty(item.InnerText))
+                                    {
+                                        if (itemProp.PropertyType == typeof(int))
+                                        {
+                                            itemProp.SetValue(obj, Convert.ToInt32(item.InnerText), null);
+                                        }
+                                        else
+                                        {
+                                            itemProp.SetValue(obj, Convert.ToInt64(item.InnerText), null);
+                                        }
+
+                                    }
+                                    else
+                                    {
+                                        itemProp.SetValue(obj, 0, null);
+                                    }
+                                }
+                                else
+                                {
+                                    itemProp.SetValue(obj, item.InnerText, null);
+                                }
+                            }
+                            #endregion
+
+                            #region Current type is Model
+                            if (itemProp.PropertyType != typeof(long) && itemProp.PropertyType != typeof(string) && itemProp.PropertyType != typeof(int) && itemProp.PropertyType.Name == item.Name && item.HasChildNodes && item.FirstChild.NodeType == System.Xml.XmlNodeType.Element)
+                            {
+                                var modelType = itemProp.PropertyType.UnderlyingSystemType;
+                                var model = modelType.Assembly.CreateInstance(modelType.FullName);
+                                SetArray(item.ChildNodes, model);
+                                itemProp.SetValue(obj, model, null);
+                            }
+                            #endregion
+                        }
+                        #endregion
+
+                    }
+                }
+                repType = obj.GetType();
+                return obj;
+            }
+            catch (Exception ex)
+            {
+                throw ex;
+            }
+        }
+
+        #region Set array value
+        private static Object SetArray(XmlNodeList xmlNodeList, object obj, bool isList = false)
+        {
+            try
+            {
+                var type = obj.GetType();
+                var properties = type.GetProperties();
+                foreach (var itemProp in properties)
+                {
+                    //if (isList)
+                    if (itemProp.PropertyType.FullName.Contains("System.Collections.Generic.List"))
+                    {
+                        #region Current type is List
+                        object array = new object();
+                        var arryLength = 0;
+                        var notNullLength = 0;
+                        var arryType = itemProp.PropertyType.UnderlyingSystemType;
+                        var currentType = itemProp.PropertyType.GetGenericArguments()[0];
+                        foreach (XmlNode xmlitem in xmlNodeList)
+                        {
+                            if (xmlitem.Name == itemProp.Name)
+                            {
+                                arryLength++;
+                            }
+                        }
+
+                        if (arryLength > 0)
+                        {
+                            var arrayModel = arryType.InvokeMember("Set", System.Reflection.BindingFlags.CreateInstance, null, array, new object[] { arryLength }) as System.Collections.IList;
+                            foreach (XmlNode item in xmlNodeList)
+                            {
+                                //current type is array
+                                if (item.Name == itemProp.Name)
+                                {
+                                    var model = currentType.Assembly.CreateInstance(currentType.FullName); // var model = arryType.GetElementType().Assembly.CreateInstance(arryType.GetElementType().FullName);
+                                    SetArray(item.ChildNodes, model, true);
+                                    arrayModel.Add(model);
+                                    notNullLength++;
+
+                                }
+                            }
+                            itemProp.SetValue(obj, arrayModel, null);
+                        }
+                        #endregion
+                        return obj;
+                    }
+
+
+                    var baseType = itemProp.PropertyType.BaseType.Name;
+                    if (baseType == "Array")
+                    {
+                        #region Current type is Array
+                        object array = new object();
+                        var arryLength = 0;
+                        var notNullLength = 0;
+                        var arryType = itemProp.PropertyType.UnderlyingSystemType;
+                        foreach (XmlNode xmlitem in xmlNodeList)
+                        {
+                            if (xmlitem.Name == itemProp.Name)
+                            {
+                                arryLength++;
+                            }
+                        }
+
+                        if (arryLength > 0)
+                        {
+                            var arrayModel = arryType.InvokeMember("Set", System.Reflection.BindingFlags.CreateInstance, null, array, new object[] { arryLength }) as System.Collections.IList;
+                            foreach (XmlNode item in xmlNodeList)
+                            {
+                                //current type is array
+                                if (item.Name == itemProp.Name)
+                                {
+                                    var model = arryType.GetElementType().Assembly.CreateInstance(arryType.GetElementType().FullName);
+                                    SetArray(item.ChildNodes, model);
+                                    arrayModel[notNullLength] = model;
+                                    notNullLength++;
+
+                                }
+                            }
+                            itemProp.SetValue(obj, arrayModel, null);
+                        }
+                        #endregion
+                    }
+                    else
+                    {
+                        foreach (XmlNode item in xmlNodeList)
+                        {
+                            #region Current type is Number
+                            if (itemProp.Name == item.Name && (itemProp.PropertyType == typeof(long) || itemProp.PropertyType == typeof(int) || itemProp.PropertyType == typeof(string)))
+                            {
+                                if (itemProp.PropertyType == typeof(int) || itemProp.PropertyType == typeof(long))
+                                {
+                                    if (!string.IsNullOrEmpty(item.InnerText))
+                                    {
+                                        if (itemProp.PropertyType == typeof(int))
+                                        {
+                                            itemProp.SetValue(obj, Convert.ToInt32(item.InnerText), null);
+                                        }
+                                        else
+                                        {
+                                            itemProp.SetValue(obj, Convert.ToInt64(item.InnerText), null);
+                                        }
+                                    }
+                                    else
+                                    {
+                                        itemProp.SetValue(obj, 0, null);
+                                    }
+                                }
+                                else
+                                {
+                                    itemProp.SetValue(obj, item.InnerText, null);
+                                }
+                            }
+                            #endregion
+
+                            #region Current type is Model
+                            if (itemProp.PropertyType != typeof(long) && itemProp.PropertyType != typeof(int) && itemProp.PropertyType != typeof(string) && itemProp.PropertyType.Name == item.Name && item.HasChildNodes && item.FirstChild.NodeType == System.Xml.XmlNodeType.Element)
+                            {
+                                var modelType = itemProp.PropertyType.UnderlyingSystemType;
+                                var model = modelType.Assembly.CreateInstance(modelType.FullName);
+                                SetArray(item.ChildNodes, model);
+                                itemProp.SetValue(obj, model, null);
+                            }
+                            #endregion
+                        }
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message);
+            }
+            return obj;
+        }
+        #endregion
+    }
+}

+ 44 - 0
MicroServices/DopInterfacePlatform/SwaggerGenOptionsExtensions.cs

@@ -0,0 +1,44 @@
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+
+namespace DopInterfacePlatform
+{
+    public static class SwaggerGenOptionsExtensions
+    {
+        /// <summary>
+        /// 为swagger增加Authentication报文头
+        /// </summary>
+        /// <param name="option"></param>
+        public static void AddAuthenticationHeader(this SwaggerGenOptions option)
+        {
+            option.AddSecurityDefinition("Authorization",
+                new OpenApiSecurityScheme
+                {
+                    Description = "Authorization header. \r\nExample:Bearer 12345ABCDE",
+                    Name = "Authorization",
+                    In = ParameterLocation.Header,
+                    Type = SecuritySchemeType.ApiKey,
+                    Scheme = "Authorization"
+                }
+                ); ;
+
+            option.AddSecurityRequirement(new OpenApiSecurityRequirement()
+            {
+                {
+                    new OpenApiSecurityScheme
+                    {
+                        Reference=new OpenApiReference
+                        {
+                            Type=ReferenceType.SecurityScheme,
+                            Id="Authorization"
+                        },
+                        Scheme="oauth2",
+                        Name="Authorization",
+                        In=ParameterLocation.Header,
+                    },
+                    new List<string>()
+                }
+            });
+        }
+    }
+}

+ 13 - 0
MicroServices/DopInterfacePlatform/WeatherForecast.cs

@@ -0,0 +1,13 @@
+namespace DopInterfacePlatform
+{
+    public class WeatherForecast
+    {
+        public DateTime Date { get; set; }
+
+        public int TemperatureC { get; set; }
+
+        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
+
+        public string? Summary { get; set; }
+    }
+}

+ 8 - 0
MicroServices/DopInterfacePlatform/appsettings.Development.json

@@ -0,0 +1,8 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  }
+}

+ 19 - 0
MicroServices/DopInterfacePlatform/appsettings.json

@@ -0,0 +1,19 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  },
+  "AllowedHosts": "*",
+  "JWT": {
+    "Issuer": "zzy2025@qq.com",
+    "Audience": "zzy2025@qq.com",
+    "Key": "A86DA1301B954748B3B21B6AA9F2F743", //加密密钥
+    "ExpireSeconds": 600 //密钥过期时间
+  },
+  "IpWhiteList": "172.16.8.154;127.0.0.1;192.168.1.5;::1",
+  "ConnectionStrings": {
+    "todoContext": "Server=172.16.8.154;Database=DopInterfacePlatform;uid=sa;pwd=ac%qams)aCXI;Trusted_Connection=false;TrustServerCertificate=True"
+  }
+}

Some files were not shown because too many files changed in this diff