Murphy преди 2 години
родител
ревизия
0da6d80453
променени са 20 файла, в които са добавени 1254 реда и са изтрити 1557 реда
  1. 4 0
      MicroServices/Business/Business.Application.Contracts/Business.Application.Contracts.csproj
  2. 37 2
      MicroServices/Business/Business.Application.Contracts/ReplenishmentManagement/IReplenishmentAppService.cs
  3. 0 20
      MicroServices/Business/Business.Application.Contracts/SaleForecast/IAnnualProductionOutlineAppService.cs
  4. 0 38
      MicroServices/Business/Business.Application.Contracts/SaleForecast/IMonthlyCapacityLoadAppService.cs
  5. 730 20
      MicroServices/Business/Business.Application/ReplenishmentManagement/ReplenishmentAppService.cs
  6. 1 1
      MicroServices/Business/Business.Application/ResourceExamineManagement/ResourceExamineAppService.cs
  7. 0 308
      MicroServices/Business/Business.Application/SaleForecastManagement/AnnualProductionOutlineAppService.cs
  8. 0 1034
      MicroServices/Business/Business.Application/SaleForecastManagement/MonthlyCapacityLoadAppService.cs
  9. 2 2
      MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentAnnualProduction.cs
  10. 176 0
      MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentMonthPlan.cs
  11. 3 3
      MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentROP.cs
  12. 3 3
      MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentServiceLevel.cs
  13. 193 0
      MicroServices/Business/Business.Domain/StructuredDB/Replenishment/ReplenishmentWeekPlan.cs
  14. 2 2
      MicroServices/Business/Business.EntityFrameworkCore/EntityFrameworkCore/BusinessDbContextModelCreatingExtensions.cs
  15. 4 3
      MicroServices/Business/Business.EntityFrameworkCore/EntityFrameworkCore/DOP/BusinessDbContext.cs
  16. 0 47
      MicroServices/Business/Business.HttpApi/Controllers/AnnualProductionOutlineController.cs
  17. 0 73
      MicroServices/Business/Business.HttpApi/Controllers/MonthlyCapacityLoadController.cs
  18. 60 0
      MicroServices/Business/Business.HttpApi/Controllers/ReplenishmentController.cs
  19. 38 0
      MicroServices/Business/QuartzSettings/logs/logs.txt
  20. 1 1
      MicroServices/Business/QuartzSettings/task_job.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>

+ 37 - 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,52 @@ 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>
         /// 检查所有成品半成品原材料是否需要补货先判断SS再判断ROP
         /// </summary>
         /// <param name="input"></param>
         /// <returns></returns>
         Task<string> DayCheckAllByFinalGoods(InputDto input);
-
-        Task<string> LongPeriodItemPR(InputDto input, int month);
     }
 }

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

+ 730 - 20
MicroServices/Business/Business.Application/ReplenishmentManagement/ReplenishmentAppService.cs

@@ -7,7 +7,6 @@ using Business.PriorityManagement;
 using Business.ReplenishmentManagement;
 using Business.ResourceExamineManagement.Dto;
 using Business.ResourceExamineManagement;
-using Business.SaleForecast;
 using Business.StructuredDB.SaleFcst;
 using Business.StructuredDB.WMS;
 using System;
@@ -23,6 +22,10 @@ using Newtonsoft.Json;
 using EFCore.BulkExtensions;
 using Business.Core.Enum;
 using Org.BouncyCastle.Crypto;
+using Business.StructuredDB.Replenishment;
+using System.ComponentModel.Design;
+using Newtonsoft.Json.Linq;
+using MathNet.Numerics.RootFinding;
 
 namespace Business.Replenishment
 {
@@ -36,7 +39,7 @@ namespace Business.Replenishment
         /// 雪花算法
         /// </summary>
         SnowFlake help = new SnowFlake();
-        private readonly IRepository<ReplenishmentModel, long> _replenishmentModel;
+        private readonly IRepository<ReplenishmentROP, long> _replenishmentROP;
         private readonly IRepository<DomesticTerminalFcst, long> _domesticTerminalFcst;
         private readonly ISqlRepository<ASNBOLShipperDetail> _ASNBOLShipperDetail;
         private readonly IRepository<StandardItemModelSet, long> _standardItemModelSet;
@@ -93,6 +96,64 @@ namespace Business.Replenishment
         private readonly IRepository<crm_seorderentry, long> _mysql_crm_seorderentry;
         private readonly IRepository<mo_mes_oorder, long> _mes_oorder;
         private readonly ISqlRepository<ScheduleResultOpMaster> _scheduleResultOpMaster;
+        private readonly IRepository<ProductionMasterPlan, long> _productionMasterPlan;
+
+
+
+        /// <summary>
+        /// 年度销售预测
+        /// </summary>
+        private IRepository<YearDemandManagement, long> _yearDemandManagement;
+
+        /// <summary>
+        /// 年度销售预测历史记录
+        /// </summary>
+        private IRepository<YearDemandManagementHistory, long> _yearDemandManagementHistory;
+
+        /// <summary>
+        /// 年度生产大纲
+        /// </summary>
+        private IRepository<ReplenishmentAnnualProduction, long> _replenishmentAnnualProduction;
+
+
+        /// <summary>
+        /// 平台库存表
+        /// </summary>
+        private readonly IRepository<WMS_PlatformInventory, long> _PlatformInventory;
+
+        /// <summary>
+        /// 工单工艺路线明细
+        /// </summary>
+        private ISqlRepository<WorkOrdRouting> _workOrdRouting;
+
+
+
+
+
+
+        /// <summary>
+        /// 月度产能共识表
+        /// </summary>
+        private IRepository<MonthlyProdCapacity, long> _monthlyProdCapacity;
+
+        /// <summary>
+        /// 月度产能共识明细表
+        /// </summary>
+        private IRepository<MonthlyProdCapacityDtl, long> _monthlyProdCapacityDtl;
+        /// <summary>
+        /// 计划订单表
+        /// </summary>
+        private IRepository<crm_planorder, long> _crm_planorder;
+
+
+        /// <summary>
+        /// 平台库存表
+        /// </summary>
+        private IRepository<WMS_PlatformInventory, long> _platformInventory;
+
+
+
+
         /// <summary>
         /// 在途检查
         /// </summary>
@@ -106,6 +167,12 @@ namespace Business.Replenishment
         /// 预处理
         /// </summary>
         private readonly PretreatmentAppService _pretreatmentAppService;
+
+        /// <summary>
+        /// 产能检查
+        /// </summary>
+        private readonly ProductExamineAppService _productExamineAppService;
+
         /// <summary>
         /// 资源检查入参
         /// </summary>
@@ -152,7 +219,7 @@ namespace Business.Replenishment
         /// 构造函数
         /// </summary>
         public ReplenishmentAppService(
-            IRepository<ReplenishmentModel, long> replenishmentModel,
+            IRepository<ReplenishmentROP, long> replenishmentROP,
             IRepository<DomesticTerminalFcst, long> domesticTerminalFcst,
             ISqlRepository<ASNBOLShipperDetail> ASNBOLShipperDetail,
             IRepository<StandardItemModelSet, long> standardItemModelSet,
@@ -209,6 +276,19 @@ namespace Business.Replenishment
             IRepository<crm_seorderentry, long> mysql_crm_seorderentry,
             IRepository<mo_mes_oorder, long> mes_oorder,
             ISqlRepository<ScheduleResultOpMaster> scheduleResultOpMaster,
+            IRepository<ProductionMasterPlan, long> productionMasterPlan,
+
+            IRepository<YearDemandManagement, long> yearDemandManagement,
+            IRepository<ReplenishmentAnnualProduction, long> replenishmentAnnualProduction,
+            IRepository<YearDemandManagementHistory, long> yearDemandManagementHistory,
+            IRepository<WMS_PlatformInventory, long> PlatformInventory,
+            ISqlRepository<WorkOrdRouting> workOrdRouting,
+            IRepository<MonthlyProdCapacity, long> monthlyProdCapacity,
+            IRepository<MonthlyProdCapacityDtl, long> monthlyProdCapacityDtl,
+            IRepository<crm_planorder, long> crm_planorder,
+            IRepository<WMS_PlatformInventory, long> platformInventory,
+
+
 
 
             PretreatmentAppService pretreatmentAppService,
@@ -220,7 +300,7 @@ namespace Business.Replenishment
             ICurrentTenant currentTenant,
             IUnitOfWorkManager unitOfWorkManager)
         {
-            _replenishmentModel = replenishmentModel;
+            _replenishmentROP = replenishmentROP;
             _domesticTerminalFcst = domesticTerminalFcst;
             _ASNBOLShipperDetail = ASNBOLShipperDetail;
             _standardItemModelSet = standardItemModelSet;
@@ -277,11 +357,25 @@ namespace Business.Replenishment
             _mysql_crm_seorderentry = mysql_crm_seorderentry;
             _mes_oorder = mes_oorder;
             _scheduleResultOpMaster = scheduleResultOpMaster;
+            _productionMasterPlan=productionMasterPlan;
 
 
+            _PlatformInventory = PlatformInventory;
+            _workOrdRouting = workOrdRouting;
+            _ASNBOLShipperDetail = ASNBOLShipperDetail;
+            _yearDemandManagement = yearDemandManagement;
+            _yearDemandManagementHistory = yearDemandManagementHistory;
+            _replenishmentAnnualProduction = replenishmentAnnualProduction;
+            _holidayMaster = holidayMaster;
+            _monthlyProdCapacity = monthlyProdCapacity;
+            _monthlyProdCapacityDtl = monthlyProdCapacityDtl;
+            _crm_planorder = crm_planorder;
+            _platformInventory = platformInventory;
+
             _pretreatmentAppService = pretreatmentAppService;
             _CalcBomViewAppService = CalcBomViewAppService;
             _purchaseOrderAppService = purchaseOrderAppService;
+            _productExamineAppService = productExamineAppService;
             _currentTenant =currentTenant;
             _businessBangDbContext= businessBangDbContext;
             _businessDbContext = businessDbContext;
@@ -289,6 +383,359 @@ namespace Business.Replenishment
         }
         #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 = _replenishmentROP.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();
+            Dictionary<string, decimal> dictInProduction = new Dictionary<string, decimal>();
+            //按照工单循环
+            //某工单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;
+                if (dictInProduction.ContainsKey(MaxOp.ItemNum))
+                {
+                    dictInProduction[MaxOp.ItemNum] += InProductionQty.Value;
+                }
+                else
+                {
+                    dictInProduction.Add(MaxOp.ItemNum, InProductionQty.Value);
+                }
+            }
+            #endregion
+            //年度生产大纲实体
+            List<ReplenishmentAnnualProduction> annualProductionOutlines = new List<ReplenishmentAnnualProduction>();
+            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();
+                decimal itemInProduct = 0;
+                if(dictInProduction.ContainsKey(item.SAPItemNumber))
+                {
+                    itemInProduct = dictInProduction[item.SAPItemNumber];
+                }
+                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)) + itemInProduct + 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;
+                }
+
+                //生成年度生产大纲
+                ReplenishmentAnnualProduction annualProductionOutline = new ReplenishmentAnnualProduction();
+                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 _replenishmentAnnualProduction.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";
+
+        }
+
+        /// <summary>
+        /// 更新年度生产大纲
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        /// <exception cref="NotImplementedException"></exception>
+        public async Task<string> DemandAnalysis(InputDto input)
+        {
+            string productResult=await SaveAnnualProductionOutline(input);
+            if(productResult!="OK")
+                return productResult;
+            string ropResult=await CalcROP(input);
+            if(ropResult!="OK")
+                return ropResult;
+            return "OK|刷新成功!";
+        }
+
+        /// <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|刷新成功!";
+        //}
+
         /// <summary>
         /// 调整ROP和最高库存水位
         /// </summary>
@@ -319,7 +766,7 @@ namespace Business.Replenishment
             var srm_purchaseList = _srmPurchase.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
 
             //获取补货模型前H周期和未来F个周期的数据
-            var ropModelList = _replenishmentModel.GetListAsync(a => a.zero_based_seqno >= -1 * replenishmentDto.HistoryOutStockMonth && a.zero_based_seqno <= replenishmentDto.SaleFcstMonth).Result;
+            var ropModelList = _replenishmentROP.GetListAsync(a => a.zero_based_seqno >= -1 * replenishmentDto.HistoryOutStockMonth && a.zero_based_seqno <= replenishmentDto.SaleFcstMonth).Result;
             //发货计划物料列表
             List<string> planItemList = planList?.Select(a => a.SAPItemNumber).ToList();
             //获取成品库存、灭菌库存、在制库存(会从SAP同步的库存表更新到LocationDetail、ic_item表中)
@@ -346,8 +793,8 @@ namespace Business.Replenishment
                      QtyToShip = p.Sum(a => a.QtyToShip),
                      ContainerItem = p.Key
                  }).ToList();
-            List<ReplenishmentModel> addList = new List<ReplenishmentModel>();
-            List<ReplenishmentModel> updateList = new List<ReplenishmentModel>();//更新上一个月的实际出库数量
+            List<ReplenishmentROP> addList = new List<ReplenishmentROP>();
+            List<ReplenishmentROP> updateList = new List<ReplenishmentROP>();//更新上一个月的实际出库数量
             var mathtool = new MathNet.Numerics.Distributions.Normal();
             ropModelList?.Where(r => r.isparam && r.seqno == DateTime.Now.AddMonths(-1).Month && r.year == DateTime.Now.AddMonths(-1).Year).ToList()?.ForEach
                 (m =>
@@ -361,7 +808,7 @@ namespace Business.Replenishment
             //需要按照成品资源检查计算原材料
             planList?.Where(s => s.PlanMonth == planMonth).ToList()?.ForEach(a =>
             {
-                ReplenishmentModel rop = new ReplenishmentModel();
+                ReplenishmentROP rop = new ReplenishmentROP();
                 rop.number = a.SAPItemNumber;
                 var icItem = itemList.Find(s => s.number == a.SAPItemNumber);
                 if (icItem != null)
@@ -430,11 +877,160 @@ namespace Business.Replenishment
             });
             addList?.ForEach(item => { item.GenerateNewId(help.NextId()); });
 
-            await _replenishmentModel.InsertManyAsync(addList);
-            await _replenishmentModel.UpdateManyAsync(updateList);
-            var ropModeAllList = _replenishmentModel.GetListAsync(a => a.year != DateTime.Now.Year && a.seqno != DateTime.Now.Month && a.isparam).Result;
+            await _replenishmentROP.InsertManyAsync(addList);
+            await _replenishmentROP.UpdateManyAsync(updateList);
+            var ropModeAllList = _replenishmentROP.GetListAsync(a => a.year != DateTime.Now.Year && a.seqno != DateTime.Now.Month && a.isparam).Result;
             ropModeAllList?.ForEach(item => { item.seqno = item.seqno - 1; });
-            await _replenishmentModel.UpdateManyAsync(ropModeAllList);
+            await _replenishmentROP.UpdateManyAsync(ropModeAllList);
+            return "OK";
+        }
+
+        /// <summary>
+        /// 根据月计划生产周计划
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public async Task<string> CalcWeekPlan(InputDto input)
+        {
+            //1.获取补货模型全局参数
+            ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
+
+            //Step1:按照瑞奇、两大平台分别根据历史出库数据和预测出货数据计算ROP
+            //Step2:计算瑞奇的M-M+2共12周补货(每次补EOP/4),计算海王的M-M+2共12周补货(每次补EOP/4),计算国科的M-M+2共12周补货(每次补EOP/4)
+            //Step3:汇总Step2所有补货,为工厂的制造需求
+            //Step4:按照Step3制造需求做资源检查,按月统计各物料消耗预测
+            //Step5:按照各SKU的历史出库数据和Step4里计算的预测消耗数量计算参数
+            //Step6:计算各SKU的12周采购补货
+
+
+
+            //获取月度发货计划(一次导入三个月的销售预测),因为是固定格式yyyy-MM所以可以用字符串比较,避免写很多字符串判断相等
+            string planMonth = $"{DateTime.Now.Year}-{DateTime.Now.Month.ToString("00")}";
+            string planMonthMax = $"{DateTime.Now.AddMonths(replenishmentDto.SaleFcstMonth).Year}-{DateTime.Now.AddMonths(replenishmentDto.SaleFcstMonth).Month.ToString("00")}";
+            var planList = _monthlyShipmentPlan.Select(a => a.PlanMonth.CompareTo(planMonth) >= 0 && a.PlanMonth.CompareTo(planMonthMax) <= 0 && !a.IsDeleted).ToList();
+
+
+            var itemList = _ic_item.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
+            var mesItemList = _itemMaster.Select(a => planList.Select(p => p.SAPItemNumber).Contains(a.ItemNum) && a.Domain == input.factory_id.ToString() && a.IsActive);
+            var srm_purchaseList = _srmPurchase.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
+
+            //获取补货模型前H周期和未来F个周期的数据
+            var ropModelList = _replenishmentROP.GetListAsync(a => a.zero_based_seqno >= -1 * replenishmentDto.HistoryOutStockMonth && a.zero_based_seqno <= replenishmentDto.SaleFcstMonth).Result;
+            //发货计划物料列表
+            List<string> planItemList = planList?.Select(a => a.SAPItemNumber).ToList();
+            //获取成品库存、灭菌库存、在制库存(会从SAP同步的库存表更新到LocationDetail、ic_item表中)
+            //List<SAPInv> sAPInvs = _SAPInv.Select(p => p.WERKS == input.factory_id.ToString() && itemNums.Contains(p.MATNR));
+            var locations = _locationDetail.Select(p => p.Domain == input.factory_id.ToString() && planList.Select(a => a.SAPItemNumber).Contains(p.ItemNum) && p.IsActive);
+            var sapItemInv = _SAPInv.Select(a => planItemList.Contains(a.MATNR) && a.WERKS == input.factory_id.ToString());
+
+            //取上一个月发货出库记录
+            var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && planItemList.Contains(a.ContainerItem) && a.ShipDate >= getMonthStartTime(-1) && a.ShipDate <= getMonthEndTime(-1));
+
+            //取本月发货出库记录
+            var shipMList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && planItemList.Contains(a.ContainerItem) && a.ShipDate >= getMonthStartTime(0) && a.ShipDate <= DateTime.Now);
+            //按照物料分组统计出货金额
+            var itemGroup = shipList.GroupBy(p => p.ContainerItem)
+                 .Select(p => new ASNBOLShipperDetail
+                 {
+                     QtyToShip = p.Sum(a => a.QtyToShip),
+                     ContainerItem = p.Key
+                 }).ToList();
+            //按照物料分组统计出货金额
+            var itemMGroup = shipMList.GroupBy(p => p.ContainerItem)
+                 .Select(p => new ASNBOLShipperDetail
+                 {
+                     QtyToShip = p.Sum(a => a.QtyToShip),
+                     ContainerItem = p.Key
+                 }).ToList();
+            List<ReplenishmentROP> addList = new List<ReplenishmentROP>();
+            List<ReplenishmentROP> updateList = new List<ReplenishmentROP>();//更新上一个月的实际出库数量
+            var mathtool = new MathNet.Numerics.Distributions.Normal();
+            ropModelList?.Where(r => r.isparam && r.seqno == DateTime.Now.AddMonths(-1).Month && r.year == DateTime.Now.AddMonths(-1).Year).ToList()?.ForEach
+                (m =>
+                {
+                    if (itemGroup.Any(a => a.ContainerItem == m.number))
+                    {
+                        m.actual_out_qty = itemGroup.Find(a => a.ContainerItem == m.number)?.QtyToShip;
+                        updateList.Add(m);
+                    }
+                });
+            //需要按照成品资源检查计算原材料
+            planList?.Where(s => s.PlanMonth == planMonth).ToList()?.ForEach(a =>
+            {
+                ReplenishmentROP rop = new ReplenishmentROP();
+                rop.number = a.SAPItemNumber;
+                var icItem = itemList.Find(s => s.number == a.SAPItemNumber);
+                if (icItem != null)
+                {
+                    rop.name = icItem.name;
+                    rop.model = a.Model;
+                    rop.erp_cls = icItem.erp_cls; //物料属性: 0.配置类 1.自制 2.委外加工 3.外购 4.虚拟件
+                    rop.fversion = icItem.fversion;
+                    rop.min_pack_qty = icItem.minpackqty;
+                    rop.moq = icItem.moq;
+                }
+                rop.actual_period_start_instock = 0;
+                if (rop.distributionchannel == "海王" || rop.distributionchannel == "国科")
+                {
+                    rop.actual_period_start_instock = locations.Find(l => l.ItemNum == a.SAPItemNumber)?.QtyOnHand;
+                }
+                else
+                {
+                    rop.actual_period_start_instock = sapItemInv.Find(s => s.MATNR == a.SAPItemNumber)?.LABST.ToDecimal();
+                }
+                rop.distributionchannel = a.DistributionChannel;
+                rop.lifecycle = a.LifeCycle;
+                rop.area = a.Area;
+                rop.plan_out_qty = Math.Ceiling(a.Qty);
+                rop.actual_out_qty = 0;
+                if (itemMGroup.Any(m => m.ContainerItem == a.SAPItemNumber))
+                {
+                    rop.actual_out_qty = itemMGroup.Find(m => m.ContainerItem == a.SAPItemNumber)?.QtyToShip;
+                }
+                rop.year = DateTime.Now.Year;
+                rop.long_period = "Y";
+                rop.short_period = "M";
+                rop.seqno = DateTime.Now.Month;
+                rop.zero_based_seqno = 0;
+                rop.period_start_date = getMonthStartTime(0);
+                rop.period_end_date = getMonthEndTime(0);
+                rop.monthl_avg_demand = CalcAvgDemand(planList, a.SAPItemNumber);
+                rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(CalcVariance(planList, a.SAPItemNumber)));
+                rop.monthl_avg_outstock = CalcAvgOutStock(ropModelList, replenishmentDto, rop.actual_out_qty.Value, a.SAPItemNumber);
+                if (mesItemList.Find(s => s.ItemNum == a.SAPItemNumber) != null)
+                {
+                    rop.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber).StockTurnOver;
+                    rop.supply_leadtime = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber)?.PurLT;
+                    rop.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber)?.StockTurnOver;
+                }
+                else
+                {
+                    rop.stock_turnover = 4;
+                }
+                if (srm_purchaseList.Find(s => s.number == a.SAPItemNumber) != null)
+                {
+                    rop.supply_leadtime = srm_purchaseList.Find(s => s.number == a.SAPItemNumber).lead_time;
+                }
+                CalcFMRAndABC(rop, replenishmentDto, input);
+                rop.security_stock = Math.Ceiling((decimal)(mathtool.InverseCumulativeDistribution((double)rop.service_level_pct.Value) * (double)rop.monthl_avg_demand_variance));
+                rop.eop = Math.Ceiling(rop.monthl_avg_demand.Value * rop.supply_leadtime.Value / DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month));
+                rop.rop_computed = rop.security_stock + rop.eop;
+                rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover);
+                rop.rop_revised = Math.Min(rop.rop_computed.Value, rop.max_stock_level.Value);
+                rop.isparam = true;
+                rop.tenant_id = input.tenant_id;
+                rop.factory_id = input.factory_id;
+                rop.create_time = DateTime.Now;
+                rop.org_id = input.org_id;
+                addList.Add(rop);
+            });
+            addList?.ForEach(item => { item.GenerateNewId(help.NextId()); });
+
+            await _replenishmentROP.InsertManyAsync(addList);
+            await _replenishmentROP.UpdateManyAsync(updateList);
+            var ropModeAllList = _replenishmentROP.GetListAsync(a => a.year != DateTime.Now.Year && a.seqno != DateTime.Now.Month && a.isparam).Result;
+            ropModeAllList?.ForEach(item => { item.seqno = item.seqno - 1; });
+            await _replenishmentROP.UpdateManyAsync(ropModeAllList);
             return "OK";
         }
 
@@ -1425,17 +2021,132 @@ namespace Business.Replenishment
         }
 
         /// <summary>
-        /// 生产长周期物料要货令
+        /// 生产长周期物料PR
         /// </summary>
         /// <param name="input">需要传入工厂编码</param>
-        /// <param name="month">要生成多少个月的长周期要货令,导入年度销售预测为12,编辑滚动更新为6个月</param>
         /// <returns></returns>
-        public async Task<string> LongPeriodItemPR(InputDto input, int month)
+        public async Task<string> CalcLongPeriodItemPR(InputDto input)
         {
-
+            //取年份最大的数据
+            int yearMax=DateTime.Now.Year;
+            yearMax=_businessDbContext.ReplenishmentAnnualProduction.Where(m => m.factory_id ==input.factory_id && !m.IsDeleted).Max(m => (int?)m.Year).GetValueOrDefault();
+            var productList = _replenishmentAnnualProduction.GetListAsync(a => a.Year == yearMax && !a.IsDeleted && a.factory_id == input.factory_id).Result.OrderBy(s=>s.OrderNum).ToList();
+            var itemList= productList.Select(a=>a.SAPItemNumber).ToList();
+            var planList=_mysql_ic_item.GetListAsync(a=>itemList.Contains(a.number) && a.factory_id==input.factory_id && !a.IsDeleted).Result.ToList();
+            var mesItem=_itemMaster.Select(a => itemList.Contains(a.ItemNum) &&a.IsActive && a.Domain==input.factory_id.ToString());
+            var bomList = _mysql_ic_bom.GetListAsync(a => itemList.Contains(a.item_number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
+            List<mes_morder> moList=new List<mes_morder>();
+            List<mes_moentry> moentryList = new List<mes_moentry>();
+            for (int i = 0;i< productList.Count();i++)
+            {
+                var ic_item = planList.Find(x => x.number == productList[i].SAPItemNumber);
+                var bom = bomList.Find(a => a.item_number == productList[i].SAPItemNumber);
+                mes_morder mes_Morder = new mes_morder();
+                mes_Morder.GenerateNewId(help.NextId());
+                mes_Morder.morder_type = MorderEnum.XsMorder;
+                //mes_Morder.morder_icitem_type
+                mes_Morder.work_order_type = MorderEnum.CgMorder;
+                mes_Morder.morder_state = MorderEnum.Initial_state;
+                mes_Morder.morder_no = GetMaxSerialNumber(457253186445381);
+                mes_Morder.fms_number = ic_item.fms_number;
+                mes_Morder.bom_number = bom.bom_number;
+                mes_Morder.fmodel = ic_item.model;
+                mes_Morder.urgent = 1;
+                mes_Morder.moentry_startup_status = 0;
+                mes_Morder.tenant_id = param.company_id.GetValueOrDefault();
+                mes_Morder.factory_id = param.factoryId;
+                mes_Morder.company_id = param.company_id;
+                mes_Morder.org_id = param.org_id;
+                mes_Morder.product_code = ic_item.number;
+                mes_Morder.product_name = ic_item.name;
+                mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
+                mes_Morder.moentry_sys_etime = Convert.ToDateTime(productList[i].PlanMonth + "-01");
+                //mes_Morder.morder_fstate = "计划";
+                //TODO:目前没有取值位置
+                mes_Morder.moentry_prd = null;
+                mes_Morder.moentry_prdname = null;
+                mes_Morder.moentry_wrkc = null;
+                mes_Morder.moentry_wrkcname = null;
+                mes_Morder.picking_qty = 0;
+                //TODO:可删除主表字段
+                mes_Morder.unit = ic_item.unit;
+                mes_Morder.morder_production_number = productList[i].Qty;
+                mes_Morder.need_number = productList[i].Qty;
+                mes_Morder.remaining_number = 0;
+                mes_Morder.create_time = DateTime.Now;
+                //生成工单子表数据
+                mes_moentry mes_Moentry = new mes_moentry();
+                mes_Moentry.GenerateNewId(help.NextId());
+                mes_Moentry.moentry_moid = mes_Morder.Id;
+                mes_Moentry.moentry_mono = mes_Morder.morder_no;
+                mes_Moentry.unit = ic_item.unit;
+                mes_Moentry.morder_production_number = productList[i].Qty;
+                mes_Moentry.need_number = productList[i].Qty;
+                mes_Moentry.remaining_number = 0;
+                mes_Moentry.factory_id = param.factoryId;
+                mes_Moentry.company_id = param.company_id;
+                mes_Moentry.org_id = param.org_id;
+                mes_Moentry.create_time = DateTime.Now;
+
+                moList.Add(mes_Morder);
+                moentryList.Add(mes_Moentry);
+            }
+            await _mysql_mes_morder.InsertManyAsync(moList);
+            await _mysql_mes_moentry.InsertManyAsync(moentryList);
+            await PlanOrderResourceCheck(input.factory_id.ToString());
             return "OK";
         }
 
+        /// <summary>
+        /// 得到一个流水号的最大流水号
+        /// </summary>
+        /// <param name="id">流水号id</param>
+        /// <param name="formData">json数据,可以用json中的某个字段值作为通配符字替换流水号格式。</param>
+        /// <returns></returns>
+        public string GetMaxSerialNumber(long id, JObject? formData = null)
+        {
+            var modelList = _rf_serialnumber.Select(s => s.Id == id);
+            if (modelList == null || modelList.Count < 1)
+            {
+                return string.Empty;
+            }
+            var model = modelList[0];
+            int max = model.CurrentNumber + 1;
+            var date = DateTime.Now;
+            var lastDate = model.LastTime;
+            switch (model.NumberType)
+            {
+                case 1: //年流水
+                    if (date.Year > lastDate.Year)
+                    {
+                        max = 1;
+                    }
+                    break;
+                case 2: //月流水
+                    if (date.Year > lastDate.Year || date.Month > lastDate.Month)
+                    {
+                        max = 1;
+                    }
+                    break;
+                case 3: //日流水
+                    if (date.Year > lastDate.Year || date.Month > lastDate.Month || date.Day > lastDate.Day)
+                    {
+                        max = 1;
+                    }
+                    break;
+            }
+            string number = max.ToString().PadLeft(model.NumberSize, '0');
+            string serialNumber = string.IsNullOrWhiteSpace(model.Format) ? number
+                : model.Format.ContainsIgnoreCase("{number}")
+                ? model.Format.ReplaceIgnoreCase("{number}", number)
+                : model.Format + number;
+            //更新当前编号和最后时间
+            model.LastTime = date;
+            model.CurrentNumber = max;
+            _rf_serialnumber.Update(model);
+            return Wildcard.Replace(serialNumber, formData);
+        }
+
         public ReplenishmentDto GetROPParam(string domain)
         {
             //select [Domain],Val,Ufld1,UDeci1 from GeneralizedCodeMaster where [Domain] = '1001' AND FldName ='SystemConfig' 
@@ -1541,7 +2252,7 @@ namespace Business.Replenishment
         /// <param name="replenishmentDto"></param>
         /// <param name="input"></param>
         /// <param name="type">1为全部一起算,2为成品算成品原材料算原材料</param>
-        public void CalcFMRAndABC(List<ReplenishmentModel> replenishmentModels, ReplenishmentDto replenishmentDto, InputDto input, int type)
+        public void CalcFMRAndABC(List<ReplenishmentROP> replenishmentModels, ReplenishmentDto replenishmentDto, InputDto input, int type)
         {
             var itemNumList = replenishmentModels?.Select(a => a.number).ToList();
             //发货出库记录
@@ -1620,7 +2331,7 @@ namespace Business.Replenishment
         /// 计算ABC分类和FMR分类
         /// </summary>
         /// <param name="replenishmentModels"></param>
-        public void CalcFMRAndABC(ReplenishmentModel replenishmentModel, ReplenishmentDto replenishmentDto, InputDto input)
+        public void CalcFMRAndABC(ReplenishmentROP replenishmentModel, ReplenishmentDto replenishmentDto, InputDto input)
         {
             //发货出库记录
             var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.ShipDate >= DateTime.Now.AddMonths(-6) && a.RealQty > 0 && replenishmentModel.number == a.ContainerItem);
@@ -1711,7 +2422,7 @@ namespace Business.Replenishment
         /// <param name="replenishmentDto">全局参数</param>
         /// <param name="itemNum">物料编码</param>
         /// <returns></returns>
-        public decimal CalcAvgOutStock(List<ReplenishmentModel> list, ReplenishmentDto replenishmentDto, decimal MQty, string itemNum)
+        public decimal CalcAvgOutStock(List<ReplenishmentROP> list, ReplenishmentDto replenishmentDto, decimal MQty, string itemNum)
         {
             return (list.Where(i => i.number == itemNum && i.zero_based_seqno > 1 - replenishmentDto.HistoryOutStockMonth && i.zero_based_seqno <= 0).Select(a => a.actual_out_qty.Value).Sum() + MQty) / (replenishmentDto.HistoryOutStockMonth + 1);
         }
@@ -1732,7 +2443,6 @@ namespace Business.Replenishment
         /// <reutrn>返回第几周</reutrn>
         public static int GetWeekOfYear(DateTime dt)
         {
-
             System.Globalization.GregorianCalendar gc = new System.Globalization.GregorianCalendar();
             int weekOfYear = gc.GetWeekOfYear(dt, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday);
             return weekOfYear;

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

@@ -458,7 +458,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,

+ 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|刷新成功!";
-        }
-    }
-}

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

+ 60 - 0
MicroServices/Business/Business.HttpApi/Controllers/ReplenishmentController.cs

@@ -57,6 +57,18 @@ namespace Business.Controllers
             return _ReplenishmentAppService.CalcROP(input);
         }
 
+        /// <summary>
+        /// 根据月计划生产周计划
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [Route("calcweekplan")]
+        public Task<string> CalcCalcWeekPlanROP(InputDto input)
+        {
+            return _ReplenishmentAppService.CalcWeekPlan(input);
+        }
+
         ///// <summary>
         ///// 更新周计划
         ///// </summary>
@@ -68,5 +80,53 @@ namespace Business.Controllers
         //{
         //    return _ReplenishmentAppService.WeekPlan(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>
+        [HttpPost]
+        [Route("calclongperioditempr")]
+        public Task<string> CalcLongPeriodItemPR(InputDto input)
+        {
+            return _ReplenishmentAppService.CalcLongPeriodItemPR(input);
+        }
+
+        /// <summary>
+        /// 生成整体需求计划
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [Route("overalldemandplan")]
+        //public Task<string> OverallDemandPlan(InputDto 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);
+        }
     }
 }

+ 38 - 0
MicroServices/Business/QuartzSettings/logs/logs.txt

@@ -140,3 +140,41 @@
 {"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-07-13T18:19:21.7756453+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
 {"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-07-13T18:19:21.8208718+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
 {"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-07-13T18:19:21.8258524+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T15:59:10.1297969+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T15:59:10.1759407+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T15:59:10.1790412+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T16:05:54.3652233+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T16:05:54.4299183+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T16:05:54.4370152+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T16:10:17.4636192+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T16:10:17.5277031+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T16:10:17.5315807+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T16:36:47.3913199+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T16:36:47.4663284+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T16:36:47.4719019+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:21:14.7877905+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:21:14.8555678+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:21:14.8617842+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:34:12.0083757+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:34:12.0743511+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:34:12.0825213+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:37:36.552967+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:37:36.6380508+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:37:36.6447156+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:44:49.0965277+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:44:49.1440142+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:44:49.1472428+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:53:10.3279742+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:53:10.3963259+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T17:53:10.4018425+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T18:06:48.1067708+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T18:06:48.1722047+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T18:06:48.1793846+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T18:59:22.7221735+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T18:59:22.7815616+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T18:59:22.7859593+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-04T19:03:11.8533785+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-04T19:03:11.9048915+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-04T19:03:11.9093768+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"长周期物料PR","GroupName":"systemquartjob","BeginDate":null,"EndDate":null,"Msg":"任务新建,未启动,状态为:0","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"长周期物料PR","GroupName":"systemquartzjob","BeginDate":"2023-09-04T19:18:01.0768087+08:00","EndDate":"2023-09-04T19:18:01.5646014+08:00","Msg":"","id":0,"timeflag":null,"changetime":null}

+ 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","Describe":"系统定时任务,勿删勿动","LastRunTime":null,"Status":6,"TaskType":2,"ApiRequestType":"POST","ApiAuthKey":null,"ApiAuthValue":null,"ApiParameter":"{   \"year\": 0,   \"month\": 0,   \"tenant_id\": 1000,   \"company_id\": 1000,   \"factory_id\": 1001,   \"org_id\": 1001,   \"create_by\": 0,   \"create_by_name\": \"string\" }","DllClassName":null,"DllActionName":null,"id":7,"timeflag":null,"changetime":null}]