Explorar el Código

产销测试问题调整

Murphy hace 2 años
padre
commit
611a82f91a

+ 30 - 0
MicroServices/Business/Business.Application.Contracts/Dto/ReplenishmentSubItemDto.cs

@@ -0,0 +1,30 @@
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Business.Dto
+{
+    /// <summary>
+    /// 原材料补货模型
+    /// </summary>
+    public class ReplenishmentSubItemDto
+    {
+        /// <summary>
+        /// 物料编码
+        /// </summary>
+        public string ItemNumber { get; set; }
+
+        // <summary>
+        /// 数量
+        /// </summary>
+        public decimal Qty { get; set; }
+
+        /// <summary>
+        /// 年月   
+        /// </summary>
+        public string PlanMonth { get; set; }
+    }
+}

+ 228 - 244
MicroServices/Business/Business.Application/ReplenishmentManagement/ReplenishmentAppService.cs

@@ -432,7 +432,7 @@ namespace Business.Replenishment
 
             var planList = _mysql_ic_item.GetListAsync(a => sapItemList.Contains(a.number) && a.factory_id == input.factory_id && !a.IsDeleted).Result.ToList();
             var bomList = _mysql_ic_bom.GetListAsync(a => sapItemList.Contains(a.item_number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
-
+            
             var planItemList = planList.Select(a => a.number).Distinct().ToList();
             var expectedList = sapItemList.Except(planItemList).ToList();
             if (expectedList.Count > 0)
@@ -446,7 +446,7 @@ namespace Business.Replenishment
             {
                 throw new NotImplementedException("年度销售预测物料" + string.Join(",", expectedBOMList) + "在BOM没有维护!");
             }
-
+            var itemMasterList = _itemMaster.Select(i => sapItemList.Contains(i.ItemNum) && i.Domain == input.factory_id.ToString());
             List<RoutingOpDetail> routingOps = _routingOpDetail.Select(p => sapItemList.Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
             var routingOpList = routingOps.Where(x => x.Ufld1 == "组装" && x.MilestoneOp).ToList();
             //生产线明细表
@@ -495,24 +495,33 @@ namespace Business.Replenishment
             //年度生产大纲实体
             List<ReplenishmentAnnualProduction> annualProductionOutlines = new List<ReplenishmentAnnualProduction>();
             List<YearDemandManagement> frontYearDemand = new List<YearDemandManagement>();
-            foreach (var item in yearDemands)
+            for(int i=0;i< yearDemands.Count;i++)
             {
-                var routingOp = routingOps.Where(x => x.RoutingCode == item.SAPItemNumber).ToList();
+                if (yearDemands.Where(a=>a.SAPItemNumber==yearDemands[i].SAPItemNumber).Count()!=12)
+                {
+                    throw new NotImplementedException("年度销售预测物料" + yearDemands[i].SAPItemNumber + "年度的12个月数据不完整!");
+                }
+                //if (yearDemands.Where(a => a.SAPItemNumber == yearDemands[i].SAPItemNumber).Sum(s=>s.Qty)==0)
+                //{
+                //    throw new NotImplementedException("年度销售预测物料" + yearDemands[i].SAPItemNumber + "年度的12个月数据不能全为零!");
+                //}
+                frontYearDemand.Add(yearDemands[i]);
+                var routingOp = routingOps.Where(x => x.RoutingCode == yearDemands[i].SAPItemNumber).ToList();
                 //组装标准工时
                 var Assembly = routingOp.Where(x => x.Ufld1 == "组装" && x.MilestoneOp).FirstOrDefault();
                 //热封标准工时
                 var HeatSealing = routingOp.Where(x => x.Ufld1 == "热封" && x.MilestoneOp).FirstOrDefault();
                 //包装标准工时
                 var Packaging = routingOp.Where(x => x.Ufld1 == "包装" && x.MilestoneOp).FirstOrDefault();
-                var prodLine = prodLines.Where(x => x.Part == item.SAPItemNumber).OrderBy(x => x.Sequence).FirstOrDefault();
+                var prodLine = prodLines.Where(x => x.Part == yearDemands[i].SAPItemNumber).OrderBy(x => x.Sequence).FirstOrDefault();
                 //不同库位库存数量
                 //5008成品线边库,8001成品合格库,8000成品待检
-                var locationList = locations.Where(x => x.ItemNum == item.SAPItemNumber && (x.Location=="5008" || x.Location=="8000" || x.Location=="8001")).ToList();
+                var locationList = locations.Where(x => x.ItemNum == yearDemands[i].SAPItemNumber && (x.Location == "5008" || x.Location == "8000" || x.Location == "8001")).ToList();
                 //平台数据
                 decimal? hwStock = 0;
-                if (DMSItemList.Find(d => d.CfnERPCode == item.SAPItemNumber) != null)
+                if (DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber) != null)
                 {
-                    var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == item.SAPItemNumber).CfnCode && o.DealerCode == "RQ000002").ToList();
+                    var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber).CfnCode && o.DealerCode == "RQ000002").ToList();
                     if (itemDMS.Count > 0)
                     {
                         var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First();
@@ -520,9 +529,9 @@ namespace Business.Replenishment
                     }
                 }
                 decimal? gkStock = 0;
-                if (DMSItemList.Find(d => d.CfnERPCode == item.SAPItemNumber) != null)
+                if (DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber) != null)
                 {
-                    var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == item.SAPItemNumber).CfnCode && o.DealerCode == "RQ000005").ToList();
+                    var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber).CfnCode && o.DealerCode == "RQ000005").ToList();
                     if (itemDMS.Count > 0)
                     {
                         var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First();
@@ -530,64 +539,74 @@ namespace Business.Replenishment
                     }
                 }
                 //销售预测 对应 Excel中公式 AVERAGE 如果预测为0不参与计算排产批量
-                var QtySum = yearDemands.Where(x => x.SAPItemNumber == item.SAPItemNumber && x.Qty > 0).ToList();
+                var QtySum = yearDemands.Where(x => x.SAPItemNumber == yearDemands[i].SAPItemNumber && x.Qty > 0).ToList();
                 //排产批量:(AVG(1 - 12月销售预测)/ 100 )=(0.45 = 1 小数向上取整)  *100 = 100
                 decimal pcpl = 0;
-                if (QtySum!=null && QtySum.Count>0)
+                if (QtySum != null && QtySum.Count > 0)
                 {
                     pcpl = Math.Ceiling(QtySum.Average(p => p.Qty) / 100) * 100;
                 }
                 //库存合计 + 在制+已发货 + 灭菌中 
-                var ship = shipList.Where(x => x.ContainerItem == item.SAPItemNumber).ToList();
+                var ship = shipList.Where(x => x.ContainerItem == yearDemands[i].SAPItemNumber).ToList();
                 decimal itemInProduct = 0;
-                if(dictInProduction.ContainsKey(item.SAPItemNumber))
+                if (dictInProduction.ContainsKey(yearDemands[i].SAPItemNumber))
                 {
-                    itemInProduct = dictInProduction[item.SAPItemNumber];
+                    itemInProduct = dictInProduction[yearDemands[i].SAPItemNumber];
                 }
                 decimal? InSterilizationQty = 0.00m;
-                if (sapInvList.Count>0 && sapInvList.Any(a=>a.MATNR==item.SAPItemNumber))
+                if (sapInvList.Count > 0 && sapInvList.Any(a => a.MATNR == yearDemands[i].SAPItemNumber))
                 {
-                    InSterilizationQty = sapInvList.Where(a => a.MATNR == item.SAPItemNumber).Sum(x => Convert.ToDecimal(x.LABST) + Convert.ToDecimal(x.INSME) + Convert.ToDecimal(x.SPEME));
+                    InSterilizationQty = sapInvList.Where(a => a.MATNR == yearDemands[i].SAPItemNumber).Sum(x => Convert.ToDecimal(x.LABST) + Convert.ToDecimal(x.INSME) + Convert.ToDecimal(x.SPEME));
                 }
-                var locationSum = (locationList.Count == 0 ? 0 : locationList.Sum(x => x.AvailStatusQty.GetValueOrDefault() + x.Assay.GetValueOrDefault())) + gkStock+ hwStock + (ship.Count == 0 ? 0 : ship.Sum(x => x.RealQty)) + itemInProduct + InSterilizationQty;
+                var locationSum = (locationList.Count == 0 ? 0 : locationList.Sum(x => x.AvailStatusQty.GetValueOrDefault() + x.Assay.GetValueOrDefault())) + gkStock + hwStock + (ship.Count == 0 ? 0 : ship.Sum(x => x.QtyToShip)) + itemInProduct + InSterilizationQty;
                 //前面N个月的生产数量
-                var frontQtySum = annualProductionOutlines.Sum(x => x.Qty);
+                var frontQtySum = annualProductionOutlines.Where(a=>a.SAPItemNumber== yearDemands[i].SAPItemNumber).Sum(x => x.Qty);
                 //生产数量:3月为例子,if((库存合计和前2月生产数量)-(前2个月销售预测数据)-当月销售预测数据 / 2 < 0)
                 // { 排产批量 * ((-(库存合计+前12个月生产数量)) +  (前12个月销售预测) + 当月销售预测 / 2 ) / 排产批量 ) } else {0}
                 decimal ProduceQty = 0.00m;
-                //判断库存是否满足需要,满足则不用生产
-                var num = (locationSum.Value + frontQtySum) - frontYearDemand.Sum(m => m.Qty) + 0 - item.Qty / 2;
-                if (num > 0 && pcpl!=0)
+                decimal NextMonthQty = 0.00m;
+                if (yearDemands[i].PlanMonth.Substring(5)!="12")
+                {
+                    NextMonthQty = yearDemands[i + 1].Qty;
+                }else
                 {
-                    ProduceQty = pcpl * Math.Ceiling((-(locationSum.Value + frontQtySum) + (frontYearDemand.Sum(m => m.Qty) + 0) + item.Qty / 2)/ pcpl);
+                    NextMonthQty = pcpl;
                 }
-                else
+                //判断库存是否满足需要,满足则不用生产
+                //安全库存
+                decimal? safeQty=itemMasterList.Find(a => a.ItemNum == yearDemands[i].SAPItemNumber)?.SafetyStk;
+                //前N个月的需求数量
+                decimal frontYearDemandQty = frontYearDemand.Where(f => f.SAPItemNumber == yearDemands[i].SAPItemNumber).Sum(m => m.Qty);
+                if(locationSum.GetValueOrDefault()+frontQtySum-safeQty-frontYearDemandQty-NextMonthQty/2<0)
                 {
-                    ProduceQty = 0;
+                    if (pcpl == 0)
+                    {
+                        ProduceQty = 0;
+                    }
+                    else
+                    {
+                        ProduceQty = Math.Ceiling((-locationSum.GetValueOrDefault() - frontQtySum + safeQty.GetValueOrDefault() + frontYearDemandQty + NextMonthQty / 2) / pcpl) * pcpl;
+                    }
                 }
-                if (ProduceQty < 0)
-                    ProduceQty = 0;
-
                 //生成年度生产大纲
                 ReplenishmentAnnualProduction annualProductionOutline = new ReplenishmentAnnualProduction();
-                annualProductionOutline.Year = item.Year;
-                annualProductionOutline.Area = item.Area;
-                annualProductionOutline.ProdLine = item.ProdLine;
-                annualProductionOutline.ProdRange = item.ProdRange;
-                if(prodLine == null|| lineMasters.Find(b => b.Line == prodLine.Line)==null)
+                annualProductionOutline.Year = yearDemands[i].Year;
+                annualProductionOutline.Area = yearDemands[i].Area;
+                annualProductionOutline.ProdLine = yearDemands[i].ProdLine;
+                annualProductionOutline.ProdRange = yearDemands[i].ProdRange;
+                if (prodLine == null || lineMasters.Find(b => b.Line == prodLine.Line) == null)
                 {
-                    annualProductionOutline.WorkshopLine ="";
+                    annualProductionOutline.WorkshopLine = "";
                 }
                 else
                 {
-
                     annualProductionOutline.WorkshopLine = lineMasters.Find(b => b.Line == prodLine.Line).Describe;
                 }
-                
-                annualProductionOutline.SAPItemNumber = item.SAPItemNumber;
-                annualProductionOutline.Model = item.Model;
-                annualProductionOutline.Languages = item.Languages;
-                annualProductionOutline.PlanMonth = item.PlanMonth;
+
+                annualProductionOutline.SAPItemNumber = yearDemands[i].SAPItemNumber;
+                annualProductionOutline.Model = yearDemands[i].Model;
+                annualProductionOutline.Languages = yearDemands[i].Languages;
+                annualProductionOutline.PlanMonth = yearDemands[i].PlanMonth;
                 annualProductionOutline.Qty = ProduceQty;
                 annualProductionOutline.StandardHours = (Assembly == null ? 0 : Assembly.RunTime) + (HeatSealing == null ? 0 : HeatSealing.RunTime) + (Packaging == null ? 0 : Packaging.RunTime);
                 //组装热封包装工时乘以数量 =单月工时
@@ -595,22 +614,22 @@ namespace Business.Replenishment
                 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;
-                annualProductionOutline.create_time= DateTime.Now;
+                annualProductionOutline.OrderNum = yearDemands[i].OrderNum;
+                annualProductionOutline.create_time = DateTime.Now;
                 annualProductionOutline.tenant_id = input.tenant_id;
-                annualProductionOutline.company_id= input.company_id;
-                annualProductionOutline.factory_id= input.factory_id;
-                annualProductionOutline.org_id= input.org_id;
+                annualProductionOutline.company_id = input.company_id;
+                annualProductionOutline.factory_id = input.factory_id;
+                annualProductionOutline.org_id = input.org_id;
                 annualProductionOutlines.Add(annualProductionOutline);
-                frontYearDemand.Add(item);
             }
             //保存数据
             using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
             {
                 try
                 {
-                    await _replenishmentAnnualProduction.HardDeleteAsync(a => a.Year == input.year && a.factory_id == input.factory_id);
-                    await _replenishmentAnnualProduction.InsertManyAsync(annualProductionOutlines);
+                    var toDelete = _businessDbContext.ReplenishmentAnnualProduction.Where(a => a.Year == input.year && a.factory_id == input.factory_id).ToList();
+                    await _businessDbContext.BulkDeleteAsync(toDelete);
+                    await _businessDbContext.BulkInsertAsync(annualProductionOutlines);
                     await CalcLongPeriodItemPR(input);
                     await CalcROP(input);
                     await SaveProductionMasterPlan(input, annualProductionOutlines);
@@ -913,8 +932,6 @@ namespace Business.Replenishment
             ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
             List<ReplenishmentROPWeekPlan> addList = new List<ReplenishmentROPWeekPlan>();
             List<ReplenishmentROPWeekPlan> updateList = new List<ReplenishmentROPWeekPlan>();//更新上一个月的实际出库数量
-            List<ReplenishmentServiceLevel> addServiceLevelList = new List<ReplenishmentServiceLevel>();
-            List<ReplenishmentServiceLevel> updateServiceLevelList = new List<ReplenishmentServiceLevel>();
             //获取存货周转率设置
             var turnOverlist = _ReplenishmentTurnOverSet.GetListAsync(a => a.factory_id == input.factory_id).Result;
             //获取补货模型前H周期和未来F个周期的数据
@@ -1149,7 +1166,7 @@ namespace Business.Replenishment
 
             //更新瑞奇原材料上个月出库次数(按照BOM展开合计汇总)
             string planPreMonth = $"{DateTime.Now.AddMonths(-1).Year}-{DateTime.Now.AddMonths(-1).Month.ToString("00")}";
-            Dictionary<string, decimal?> subItem = new Dictionary<string, decimal?>();
+            List<ReplenishmentSubItemDto> subItem = new List<ReplenishmentSubItemDto>();
             planList.Where(a => a.DistributionChannel == "瑞奇" && a.PlanMonth == planPreMonth).ToList().ForEach(a =>
             {
                 var planBOM = boms.Find(b => b.item_number == a.SAPItemNumber);
@@ -1173,13 +1190,13 @@ namespace Business.Replenishment
                     CaclMaterialShortage(returnlist);
                     foreach (var item in returnlist)
                     {
-                        if (subItem.ContainsKey(item.item_number))
+                        if (subItem.Any(s=>s.ItemNumber==item.item_number&&s.PlanMonth== planPreMonth))
                         {
-                            subItem[item.item_number] += item.needCount;
+                            subItem.Find(s => s.ItemNumber == item.item_number && s.PlanMonth == planPreMonth).Qty += item.needCount;
                         }
                         else
                         {
-                            subItem.Add(item.item_number, item.needCount);
+                            subItem.Add(new ReplenishmentSubItemDto { ItemNumber = item.item_number,Qty=item.needCount,PlanMonth= planPreMonth }); 
                         }
                     }
                 }
@@ -1189,15 +1206,15 @@ namespace Business.Replenishment
                 (m =>
                 {
                     //只更新原材料
-                    if (!planList.Any(a => a.SAPItemNumber == m.number) && subItem.ContainsKey(m.number))
+                    if (!planList.Any(a => a.SAPItemNumber == m.number) && subItem.Any(s=>s.ItemNumber==m.number && s.PlanMonth==planPreMonth))
                     {
-                        m.plan_out_qty = subItem[m.number];
+                        m.plan_out_qty = subItem.Find(s => s.ItemNumber == m.number && s.PlanMonth == planPreMonth).Qty;
                         updateList.Add(m);
                     }
                 });
 
-            var serviceList = _replenishmentServiceLevel.GetListAsync(a => a.factory_id == input.factory_id).Result;
-
+            var RQShipPlanList = planList.FindAll(s =>s.DistributionChannel == "瑞奇");
+            List<ReplenishmentSubItemDto> subItemRQList=CalcMonthPlanSubItem(RQShipPlanList, boms,pretreatments);
             for (int j = 0; j < replenishmentDto.SaleFcstMonth; j++)
             {
                 string itemMonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
@@ -1393,214 +1410,181 @@ namespace Business.Replenishment
                     }
                 });
                 //计算原材料
-                planList?.Where(s => s.PlanMonth == itemMonth && s.DistributionChannel=="瑞奇").ToList()?.ForEach(a =>
+                List<ReplenishmentSubItemDto> subItemRQ = subItemRQList.FindAll(a=>a.PlanMonth== itemMonth);
+                foreach(var d in subItemRQ)
                 {
-                    foreach (var d in subItem)
+                    var icItem = itemProductList.Find(s => s.number == d.ItemNumber);
+                    if (icItem != null && !planList.Select(r => r.SAPItemNumber).ToList().Contains(d.ItemNumber))
                     {
-                        var icItem = itemProductList.Find(s => s.number == d.Key);
-                        if (icItem != null && !planList.Select(r => r.SAPItemNumber).ToList().Contains(d.Key))
+                        bool isExist = ropModelList.Find(r => r.planmonth == itemMonth && r.number == d.ItemNumber && r.distributionchannel == "瑞奇") == null ? false : true;
+                        var rop = new ReplenishmentROPWeekPlan();
+                        if (isExist)
                         {
-                            bool isExist = ropModelList.Find(r => r.planmonth == itemMonth && r.number == d.Key && r.distributionchannel=="瑞奇") == null ? false : true;
-                            var rop = new ReplenishmentROPWeekPlan();
-                            if (isExist)
-                            {
-                                rop = ropModelList.Find(r => r.planmonth == itemMonth && r.number == d.Key && r.distributionchannel == "瑞奇");
-                            }
-                            rop.number = d.Key;
-                            rop.name = icItem.name;
-                            rop.model = icItem.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.distributionchannel = a.DistributionChannel;
-                            rop.lifecycle = a.LifeCycle;
-                            rop.area = a.Area;
-                            rop.plan_out_qty = Math.Ceiling(d.Value.GetValueOrDefault());
-                            //月均需求用几个月的发货计划按照bom展开合计计算
-                            var subQty = CalcSubItemAvaQty(planList.Where(p=> p.PlanMonth == itemMonth && p.DistributionChannel=="瑞奇").ToList(), a.SAPItemNumber, boms, pretreatments);
-                            if (subQty.ContainsKey(rop.number))
+                            rop = ropModelList.Find(r => r.planmonth == itemMonth && r.number == d.ItemNumber && r.distributionchannel == "瑞奇");
+                        }
+                        rop.number = d.ItemNumber;
+                        rop.name = icItem.name;
+                        rop.model = icItem.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.distributionchannel ="";
+                        rop.lifecycle = "";
+                        rop.area ="";
+                        rop.plan_out_qty = Math.Ceiling(d.Qty);
+                        //月均需求用几个月的发货计划按照bom展开合计计算
+                        CalcSubItem(subItemRQList,rop,replenishmentDto, d.ItemNumber);
+                        //计算原材料月均出库
+                        rop.monthl_avg_outstock = Math.Ceiling(pickbilllist.Where(z => z.ItemNum == rop.number).Sum(q => q.QtyChange.GetValueOrDefault() * -1) / 6);
+                        rop.year = DateTime.Now.AddMonths(j).Year;
+                        rop.month = DateTime.Now.AddMonths(j).Month;
+                        rop.planmonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
+                        //供应提前期,成品取物料主数据维护的,原材料从货源清单取取不到取物料维护的
+                        if (icItem.erp_cls == 1)
+                        {
+                            rop.supply_leadtime = icItem.PurLT;//默认
+                        }
+                        else
+                        {
+                            if (srm_purchaseList.Find(s => s.number == rop.number) != null)
                             {
-                                rop.monthl_avg_demand = subQty[rop.number];
-                                rop.monthl_avg_demand_variance = CalcSubStdEV(planList.Where(p => p.PlanMonth == itemMonth && p.DistributionChannel == "瑞奇").ToList(), a.SAPItemNumber, rop.number, rop.monthl_avg_demand.GetValueOrDefault(), boms, pretreatments);
+                                rop.supply_leadtime = srm_purchaseList.Find(s => s.number == rop.number).lead_time;
                             }
                             else
                             {
-                                rop.monthl_avg_demand = 0;
-                                rop.monthl_avg_demand_variance = 0;
-                            }
-                            //计算原材料月均出库
-                            rop.monthl_avg_outstock = Math.Ceiling(pickbilllist.Where(z=>z.ItemNum==rop.number).Sum(q=>q.QtyChange.GetValueOrDefault()*-1)/6);
-                            rop.year = DateTime.Now.AddMonths(j).Year;
-                            rop.month = DateTime.Now.AddMonths(j).Month;
-                            rop.planmonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
-                            //供应提前期,成品取物料主数据维护的,原材料从货源清单取取不到取物料维护的
-                            if (icItem.erp_cls == 1)
-                            {
                                 rop.supply_leadtime = icItem.PurLT;//默认
                             }
-                            else
-                            {
-                                if (srm_purchaseList.Find(s => s.number == rop.number) != null)
-                                {
-                                    rop.supply_leadtime = srm_purchaseList.Find(s => s.number == rop.number).lead_time;
-                                }
-                                else
-                                {
-                                    rop.supply_leadtime = icItem.PurLT;//默认
-                                }
-                            }
-                            if(rop.supply_leadtime==0)
-                                rop.supply_leadtime = 22;//默认
-                            //原材料周转率取物料
-                            if (mesItemList.Find(s => s.ItemNum ==rop.number) != null)
-                            {
-                                rop.stock_turnover = mesItemList.Find(s => s.ItemNum == rop.number).StockTurnOver;
-                                if(rop.stock_turnover==0)
-                                {
-                                    rop.stock_turnover = 4;
-                                }
-                            }
-                            else
-                            {
-                                rop.stock_turnover = 4;
-                            }
+                        }
+                        if (rop.supply_leadtime == 0)
+                            rop.supply_leadtime = 22;//默认
+                        //原材料周转率取物料
+                        if (mesItemList.Find(s => s.ItemNum == rop.number) != null)
+                        {
+                            rop.stock_turnover = mesItemList.Find(s => s.ItemNum == rop.number).StockTurnOver;
                             if (rop.stock_turnover == 0)
-                                rop.stock_turnover = 4;
-                            CalcFMRAndABC(rop, replenishmentDto, shipList, pickbilllist, 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.AddMonths(j).Year, DateTime.Now.AddMonths(j).Month));
-                            rop.rop_computed = rop.security_stock + rop.eop;
-                            rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover);
-                            //瑞奇是ROP和最高库存值两者之间取较小的值,平台是取较大的值。
-                            //瑞奇是ROP和最高库存值两者之间取较小的值,平台是取较大的值。
-                            if (a.DistributionChannel != "瑞奇")
                             {
-                                rop.rop_revised = Math.Max(rop.rop_computed.Value, rop.max_stock_level.Value);
-                            }
-                            else
-                            {
-                                rop.rop_revised = Math.Min(rop.rop_computed.Value, rop.max_stock_level.Value);
+                                rop.stock_turnover = 4;
                             }
-                     
+                        }
+                        else
+                        {
+                            rop.stock_turnover = 4;
+                        }
+                        if (rop.stock_turnover == 0)
+                            rop.stock_turnover = 4;
+                        CalcFMRAndABC(rop, replenishmentDto, shipList, pickbilllist, input);
+                        rop.security_stock = Math.Ceiling((decimal)(mathtool.InverseCumulativeDistribution((double)rop.service_level_pct.Value) * (double)rop.monthl_avg_demand_variance));
 
-                            //存在上一个月补货
-                            if (updateList.Find(r => r.number == a.SAPItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
-                            {
-                                var avaItem = updateList.Find(r => r.number == a.SAPItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
-                                rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - a.Qty);
-                            }
-                            else if (addList.Find(r => r.number == a.SAPItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
-                            {
-                                var avaItem = addList.Find(r => r.number == a.SAPItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
-                                rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - a.Qty);
-                            }
-                            else
-                            {
-                                //取实际库存
-                                //1开始的库位为原料仓
-                                rop.avaStockQty = locations.Where(a=>a.ItemNum==rop.number && a.Location.StartsWith("1")).Sum(a=> a.AvailStatusQty.GetValueOrDefault() + a.Assay.GetValueOrDefault());
-                            }
-                            rop.montheop1 = rop.rop_computed > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
-                            rop.montheop2 = rop.security_stock > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
-                            rop.ProdLine = a.ProdLine;
-                            rop.ProdRange = a.ProdRange;
-                            rop.Languages = a.Languages;
-                            rop.tenant_id = input.tenant_id;
-                            rop.company_id = input.company_id;
-                            rop.factory_id = input.factory_id;
-                            rop.create_time = DateTime.Now;
-                            rop.org_id = input.org_id;
-                            if (isExist)
-                            {
-                                updateList.Add(rop);
-                            }
-                            else
-                            {
-                                addList.Add(rop);
-                            }
+                        rop.eop = Math.Ceiling(rop.monthl_avg_demand.Value * rop.supply_leadtime.Value / DateTime.DaysInMonth(DateTime.Now.AddMonths(j).Year, DateTime.Now.AddMonths(j).Month));
+                        rop.rop_computed = rop.security_stock + rop.eop;
+                        rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover);
+                        //瑞奇是ROP和最高库存值两者之间取较小的值,平台是取较大的值。
+                        //瑞奇是ROP和最高库存值两者之间取较小的值,平台是取较大的值。
+                        rop.rop_revised = Math.Min(rop.rop_computed.Value, rop.max_stock_level.Value);
+                        //存在上一个月补货
+                        if (updateList.Find(r => r.number ==d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
+                        {
+                            var avaItem = updateList.Find(r => r.number == d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
+                            rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - d.Qty);
+                        }
+                        else if (addList.Find(r => r.number ==d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
+                        {
+                            var avaItem = addList.Find(r => r.number == d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
+                            rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - d.Qty);
+                        }
+                        else
+                        {
+                            //取实际库存
+                            //1开始的库位为原料仓
+                            rop.avaStockQty = locations.Where(a => a.ItemNum == rop.number && a.Location.StartsWith("1")).Sum(a => a.AvailStatusQty.GetValueOrDefault() + a.Assay.GetValueOrDefault());
+                        }
+                        rop.montheop1 = rop.rop_computed > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
+                        rop.montheop2 = rop.security_stock > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
+                        rop.ProdLine = "";
+                        rop.ProdRange = "";
+                        rop.Languages = "";
+                        rop.tenant_id = input.tenant_id;
+                        rop.company_id = input.company_id;
+                        rop.factory_id = input.factory_id;
+                        rop.create_time = DateTime.Now;
+                        rop.org_id = input.org_id;
+                        if (isExist)
+                        {
+                            updateList.Add(rop);
+                        }
+                        else
+                        {
+                            addList.Add(rop);
                         }
                     }
-                });
+                }
             }
             addList?.ForEach(item => { item.GenerateNewId(help.NextId()); });
-            await _replenishmentROPWeekPlan.InsertManyAsync(addList);
-            await _replenishmentROPWeekPlan.UpdateManyAsync(updateList);
+            await _businessDbContext.BulkInsertAsync(addList);
+            await _businessDbContext.BulkUpdateAsync(updateList);
             await CalcWeekPlan(input);
             return "OK";
         }
-        //计算原材料月均出库
-        public Dictionary<string,decimal> CalcSubItemAvaQty(List<MonthlyShipmentPlan> planList,string ItemNum,List<mo_ic_bom> boms, List<b_bom_pretreatment> pretreatments)
+        private List<ReplenishmentSubItemDto> CalcMonthPlanSubItem(List<MonthlyShipmentPlan> planList,List<mo_ic_bom> boms, List<b_bom_pretreatment> pretreatments)
         {
-            Dictionary<string, decimal> subItem = new Dictionary<string, decimal>();
-            var sumQty = planList.Where(c=>c.SAPItemNumber== ItemNum).Sum(a => a.Qty);
-            var planBOM = boms.Find(b => b.item_number == ItemNum);
-            var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
-            var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
-            returnlist = returnlist.OrderBy(s => s.num_order).ToList();
-            var level1Dto = returnlist[0];
-            level1Dto.needCount = sumQty;
-            CaclMaterialShortage(returnlist);
-            foreach (var item in returnlist)
+            List<ReplenishmentSubItemDto> subItemRQ = new List<ReplenishmentSubItemDto>();
+            planList?.ForEach(r =>
             {
-                if (subItem.ContainsKey(item.item_number))
+                var planBOM = boms.Find(b => b.item_number == r.SAPItemNumber);
+                if (planBOM == null)
                 {
-                    subItem[item.item_number] += item.needCount;
+                    new NLogHelper("CalcROP").WriteLog("CalcROP", "CalcROP数据错误:" + r.SAPItemNumber + "不在BOM里", _currentTenant.Id.ToString());
                 }
                 else
                 {
-                    if(item.item_number!=ItemNum)
-                    {
-                        subItem.Add(item.item_number, item.needCount);
-                    }
-                }
-            }
-            return subItem;
-        }
-
-        //计算原材料方差
-        public decimal CalcSubStdEV(List<MonthlyShipmentPlan> planList, string ItemNum,string subItemNum,decimal avaRequire, List<mo_ic_bom> boms, List<b_bom_pretreatment> pretreatments)
-        {
-            List<decimal> MonthItem = new List<decimal>();
-            var planMonthList = planList.Where(a => a.SAPItemNumber == ItemNum).ToList().Select(a => a.PlanMonth).Distinct().ToList();
-            
-            for(int j=0;j<planMonthList.Count();j++)
-            {
-                Dictionary<string, decimal> subItem = new Dictionary<string, decimal>();
-                var sumQty = planList.Find(c => c.SAPItemNumber == ItemNum && c.PlanMonth == planMonthList[j]).Qty;
-                var planBOM = boms.Find(b => b.item_number == ItemNum);
-                var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
-                var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
-                returnlist = returnlist.OrderBy(s => s.num_order).ToList();
-                var level1Dto = returnlist[0];
-                level1Dto.needCount = sumQty;
-                CaclMaterialShortage(returnlist);
-                foreach (var item in returnlist)
-                {
-                    if (subItem.ContainsKey(item.item_number))
-                    {
-                        subItem[item.item_number] += item.needCount;
-                    }
-                    else
+                    var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
+                    var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
+                    returnlist = returnlist.OrderBy(s => s.num_order).ToList();
+                    var level1Dto = returnlist[0];
+                    level1Dto.needCount = r.Qty;
+                    CaclMaterialShortage(returnlist);
+                    foreach (var item in returnlist)
                     {
-                        if(item.item_number!=ItemNum)
+                        var isExist = subItemRQ.Find(s => s.ItemNumber == item.item_number && s.PlanMonth == r.PlanMonth);
+                        if (isExist != null)
+                        {
+                            isExist.Qty += item.needCount;
+                        }
+                        else
                         {
-                            subItem.Add(item.item_number, item.needCount);
+                            subItemRQ.Add(new ReplenishmentSubItemDto { ItemNumber = item.item_number, Qty = item.needCount, PlanMonth = r.PlanMonth });
                         }
                     }
                 }
-                if(subItem.ContainsKey(subItemNum))
+            });
+            return subItemRQ;
+        }
+        //计算原材料月均需求和方差
+        public void CalcSubItem(List<ReplenishmentSubItemDto> subItemRQ, ReplenishmentROPWeekPlan rop, ReplenishmentDto replenishmentDto,string ItemNum)
+        {
+            int MonthCount = 0;
+            decimal SumOutQty = 0;
+            for (int k = -1 * replenishmentDto.HistoryOutStockMonth; k < replenishmentDto.SaleFcstMonth; k++)
+            {
+                string itemMonth = $"{DateTime.Now.AddMonths(k).Year}-{DateTime.Now.AddMonths(k).Month.ToString("00")}";
+                if (subItemRQ.Find(z => z.PlanMonth == itemMonth && z.ItemNumber == ItemNum) != null)
                 {
-                    MonthItem.Add(subItem[subItemNum]);
+                    SumOutQty += subItemRQ.Find(z => z.PlanMonth == itemMonth && z.ItemNumber == ItemNum).Qty;
+                    MonthCount++;
                 }
             }
-            if(MonthItem.Count<=1)
+            decimal avaRequire = 0;
+            rop.monthl_avg_demand = 0;
+            rop.monthl_avg_demand_variance = 0;
+            if (MonthCount>0)
             {
-                return 0;
-            }else
+                avaRequire= Math.Ceiling(SumOutQty / MonthCount);
+                rop.monthl_avg_demand = avaRequire;
+            }
+            if (MonthCount> 1)
             {
-                return Math.Ceiling(Convert.ToDecimal(Math.Sqrt(MonthItem.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(avaRequire), 2)) / (MonthItem.Count() - 1))));
+                rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(Math.Sqrt(subItemRQ.Where(w=>w.ItemNumber==ItemNum).Sum(x => Math.Pow(Convert.ToDouble(x.Qty) - Convert.ToDouble(avaRequire), 2)) / (MonthCount - 1))));
             }
         }
         /// <summary>
@@ -1840,8 +1824,8 @@ namespace Business.Replenishment
             //    }
             //}
             #endregion
-            await _replenishmentWeekPlan.InsertManyAsync(addRopList);
-            await _replenishmentWeekPlan.UpdateManyAsync(updateRopList);
+            await _businessDbContext.BulkInsertAsync(addRopList);
+            await _businessDbContext.BulkInsertAsync(updateRopList);
 
             //更新周生产计划
             //生产线明细表
@@ -2566,8 +2550,8 @@ namespace Business.Replenishment
             await PlanOrderResourceCheck(moList, moentryList, bang_id, input);
 
             var examine_resultList = _mysql_examine_result.GetListAsync(a => a.bangid == bang_id).Result;
-            await _mysql_mes_morder.InsertManyAsync(moList);
-            await _mysql_mes_moentry.InsertManyAsync(moentryList);
+            await _businessDbContext.BulkInsertAsync(moList);
+            await _businessDbContext.BulkInsertAsync(moentryList);
 
             //批量保存 后期考虑子工单
             List<WorkOrdMaster> workOrdSave = new List<WorkOrdMaster>();
@@ -2641,7 +2625,7 @@ namespace Business.Replenishment
                     }
                 }
             });
-            await _replenishmentWeekPlan.InsertManyAsync(weekPlan);
+            await _businessDbContext.BulkInsertAsync(weekPlan);
             return "OK";
         }
 
@@ -4621,10 +4605,10 @@ namespace Business.Replenishment
             long bangid = help.NextId();
             for (int i = 0;i< productList.Count();i++)
             {
-                var ic_item = planList.Find(x => x.number == productList[i].SAPItemNumber);
+                var ic_item = mesItem.Find(x => x.ItemNum == productList[i].SAPItemNumber);
                 var bom = bomList.Find(a => a.item_number == productList[i].SAPItemNumber);
-                if (ic_item.PurLT < ropParam.LongPeriodDay)
-                    continue;
+                ////if (ic_item.PurLT < ropParam.LongPeriodDay)
+                ////    continue;
                 mes_morder mes_Morder = new mes_morder();
                 mes_Morder.GenerateNewId(help.NextId());
                 mes_Morder.morder_type = MorderEnum.JhMorder;
@@ -4632,17 +4616,17 @@ namespace Business.Replenishment
                 mes_Morder.work_order_type = MorderEnum.CgMorder;
                 mes_Morder.morder_state ="";
                 mes_Morder.morder_no = list[i].NbrResult.ToString();
-                mes_Morder.fms_number = ic_item.fms_number;
+                mes_Morder.fms_number = "";
                 mes_Morder.bom_number = bom.bom_number;
-                mes_Morder.fmodel = ic_item.model;
+                mes_Morder.fmodel = ic_item.Descr1;
                 mes_Morder.urgent = 1;
                 mes_Morder.moentry_startup_status = 0;
                 mes_Morder.tenant_id = input.tenant_id;
                 mes_Morder.factory_id = input.factory_id;
                 mes_Morder.company_id = input.company_id;
                 mes_Morder.org_id = input.org_id;
-                mes_Morder.product_code = ic_item.number;
-                mes_Morder.product_name = ic_item.name;
+                mes_Morder.product_code = ic_item.ItemNum;
+                mes_Morder.product_name = ic_item.Descr;
                 mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
                 mes_Morder.moentry_sys_stime= Convert.ToDateTime(productList[i].PlanMonth + "-01");
                 //mes_Morder.morder_fstate = "计划";
@@ -4653,7 +4637,7 @@ namespace Business.Replenishment
                 mes_Morder.moentry_wrkcname = null;
                 mes_Morder.picking_qty = 0;
                 //TODO:可删除主表字段
-                mes_Morder.unit = ic_item.unit;
+                mes_Morder.unit = ic_item.UM;
                 mes_Morder.morder_production_number = productList[i].Qty;
                 mes_Morder.need_number = productList[i].Qty;
                 mes_Morder.remaining_number = 0;
@@ -4663,7 +4647,7 @@ namespace Business.Replenishment
                 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.unit = ic_item.UM;
                 mes_Moentry.morder_production_number = productList[i].Qty;
                 mes_Moentry.need_number = productList[i].Qty;
                 mes_Moentry.remaining_number = 0;

+ 2 - 1
MicroServices/Business/Business.Application/SystemJobManagement/SystemJobAppService.cs

@@ -726,7 +726,8 @@ namespace Business.SystemJobManagement
                             bat_change_economy = 1,
                             total_tqq = 1,
                             order_point = 1,
-                            secinv = 1,
+                            secinv = custList[i].SafetyStk,
+                            item_type= custList[i].ItemType,
                             secinv_ratio = 1,
                             self_inspection_date = custList[i].InsLT,
                             Warehousing_date = 1,

+ 0 - 1
MicroServices/Business/Business.Core/Business.Core.csproj

@@ -15,7 +15,6 @@
     <PackageReference Include="NLog.Extensions.Logging" Version="5.2.2" />
     <PackageReference Include="NLog.Web.AspNetCore" Version="5.2.2" />
     <PackageReference Include="RSAExtensions" Version="1.1.1" />
-    <PackageReference Include="ThoughtWorks.QRCode" Version="1.1.0" />
     <PackageReference Include="Volo.Abp.Ddd.Domain" Version="6.0.3" />
   </ItemGroup>