Murphy 2 anni fa
parent
commit
2f758d87ca

+ 595 - 17
MicroServices/Business/Business.Application/ReplenishmentManagement/ReplenishmentAppService.cs

@@ -537,8 +537,10 @@ namespace Business.Replenishment
             {
                 try
                 {
-                    await _replenishmentAnnualProduction.DeleteAsync(a => a.Year == input.year && a.tenant_id == input.tenant_id && a.factory_id == input.factory_id);
+                    await _replenishmentAnnualProduction.DeleteAsync(a => a.Year == input.year && a.factory_id == input.factory_id);
                     await _replenishmentAnnualProduction.InsertManyAsync(annualProductionOutlines);
+                    await CalcROP(input);
+                    await SaveProductionMasterPlan(input, annualProductionOutlines);
                     await unitOfWork.CompleteAsync();
                 }
                 catch (Exception e)
@@ -556,15 +558,14 @@ namespace Business.Replenishment
         /// </summary>
         /// <param name="input"></param>
         /// <returns></returns>
-        public async Task<string> SaveProductionMasterPlan(InputDto input)
+        public async Task<string> SaveProductionMasterPlan(InputDto input,List<ReplenishmentAnnualProduction> annual)
         {
             //计算当前年月的N0,N+1,N+2
             List<string> planMons = GetPlanMonth(4);
             List<ProductionMasterPlan> productionMasters= new List<ProductionMasterPlan>();
             List<ProductionMasterPlan> pre3MonthPlan = _productionMasterPlan.GetListAsync(a => GetPlanMonth(-3).Contains(a.PlanMonth) && a.factory_id == input.factory_id && a.tenant_id == input.tenant_id && a.company_id == input.company_id).Result;
             //N0,N+1,N+2月度发货计划
-            var annualProduction = _replenishmentAnnualProduction.GetListAsync(x => planMons.Contains(x.PlanMonth) && !x.IsDeleted && x.tenant_id == input.tenant_id && x.company_id == input.company_id && x.factory_id == input.factory_id).Result.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
-            
+            var annualProduction = _monthlyShipmentPlan.Select(x => planMons.Contains(x.PlanMonth) && !x.IsDeleted && x.tenant_id == input.tenant_id && x.company_id == input.company_id && x.factory_id == input.factory_id).OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
             var productionMasterPlan = _productionMasterPlan.GetListAsync(x => planMons.Contains(x.PlanMonth) && !x.IsDeleted && x.tenant_id == input.tenant_id && x.company_id == input.company_id && x.factory_id == input.factory_id).Result.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
             List<LocationDetail> locations = _locationDetail.Select(x => annualProduction.Select(m => m.SAPItemNumber).Contains(x.ItemNum) && x.Domain == input.factory_id.ToString() && x.IsActive).ToList();
             var InProdcutQty=GetInProdcutQty(annualProduction.Select(m => m.SAPItemNumber).ToList(),input);
@@ -575,7 +576,7 @@ namespace Business.Replenishment
                 plan.Area = item.Area;
                 plan.ProdLine = item.ProdLine;
                 plan.ProdRange = item.ProdRange;
-                plan.WorkshopLine = item.WorkshopLine;
+                plan.WorkshopLine = annual.Find(a=>a.PlanMonth==item.PlanMonth && a.SAPItemNumber==item.SAPItemNumber).WorkshopLine;
                 plan.ItemNumber = item.SAPItemNumber;
                 plan.Model = item.Model;
                 plan.Languages = item.Languages;
@@ -631,6 +632,8 @@ namespace Business.Replenishment
             {
                 try
                 {
+                    var planList = productionMasters.Select(a => a.PlanMonth).ToList();
+                    await _productionMasterPlan.DeleteAsync(a => planList.Contains(a.PlanMonth) && a.tenant_id == input.tenant_id && a.factory_id == input.factory_id);
                     await _productionMasterPlan.InsertManyAsync(productionMasters);
                     await unitOfWork.CompleteAsync();
                 }
@@ -704,12 +707,6 @@ namespace Business.Replenishment
             string productResult=await SaveAnnualProductionOutline(input);
             if(productResult!="OK")
                 return productResult;
-            string ropResult=await CalcROP(input);
-            if(ropResult!="OK")
-                return ropResult;
-            string masterPlanResult = await SaveProductionMasterPlan(input);
-            if (masterPlanResult != "OK")
-                return masterPlanResult;
             return "OK|刷新成功!";
         }
 
@@ -1063,6 +1060,7 @@ namespace Business.Replenishment
 
             if (workOrds.Any())
             {
+                workOrds=CalcPriority(workOrds, input.factory_id.ToString());
                 _workOrdMaster.Insert(workOrds);
             }
             var DBworkOrdList = _workOrdMaster.Select(a => a.Domain == workOrds[0].Domain && workOrds.Select(c => c.WorkOrd).Contains(a.WorkOrd));
@@ -1114,8 +1112,6 @@ namespace Business.Replenishment
             });
 
             await _replenishmentWeekPlan.InsertManyAsync(weekPlan);
-            //TODO:优先级排序
-
             return "OK";
         }
 
@@ -1157,16 +1153,254 @@ namespace Business.Replenishment
             //DOP运行资源检查每个成品和半成品SKU的可用库存,当可用库存 <= 修正后ROP时,自动生成月度计划订单(MPlan order,MPO48年月日3位流水号)= EOP;可用库存为没有被其他SO和PO占用的(合格成品或半成品库存 + WIP);
             var ropModelList = _replenishmentROP.GetListAsync(a =>a.isparam && a.factory_id==input.factory_id && a.company_id==input.company_id && !a.IsDeleted).Result;
             var itemStock = CalcStock(ropModelList.Select(a => a.number).ToList(), input);
+            var bomList = _ic_bom.GetListAsync(a => ropModelList.Select(a => a.number).ToList().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>();
+
+            var itemNeedPRList = ropModelList.Where(a => a.erp_cls == 1).ToList();
+            int count = 0;
+            itemNeedPRList.ForEach(a => {
+                if (itemStock.First(c => c.ItemNumber == a.number).Qty < a.rop_revised)
+                {
+                    count++;
+                }
+            });
+            var list = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "MPO", count, "", 1);
+            var nbrlistDto = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", count, "", 1);
+            int j = 0;
+            DateTime currentTime = DateTime.Now;
+            int week = Convert.ToInt32(currentTime.DayOfWeek);
+            week = week == 0 ? 7 : week;
+            long bang_id = help.NextId();
             ropModelList.Where(a => a.erp_cls == 1)?.ToList().ForEach(b =>
             {
-
+                
+                if(itemStock.First(c=>c.ItemNumber==b.number).Qty<b.rop_revised)
+                {
+                    var bom = bomList.Find(c => c.item_number ==b.number);
+                    mes_morder mes_Morder = new mes_morder();
+                    mes_Morder.GenerateNewId(help.NextId());
+                    mes_Morder.morder_type = MorderEnum.JhMorder;
+                    //mes_Morder.morder_icitem_type
+                    mes_Morder.work_order_type = MorderEnum.FhMorder;
+                    mes_Morder.morder_state = MorderEnum.Initial_state;
+                    mes_Morder.morder_no = list[j].NbrResult;
+                    mes_Morder.fms_number =b.number;
+                    mes_Morder.bom_number = bom.bom_number;
+                    mes_Morder.fmodel = b.model;
+                    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 = b.number;
+                    mes_Morder.product_name = b.name;
+                    mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
+                    //成品半成品取周一开始 + 取供应提前期为结束时间
+                    mes_Morder.moentry_stime = currentTime.AddDays(1 - week + 7);
+                    mes_Morder.moentry_sys_etime = currentTime.AddDays(1 - week + 7 + Convert.ToDouble(b.supply_leadtime));
+                    //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 = "";
+                    mes_Morder.morder_production_number = b.eop;
+                    mes_Morder.need_number = b.eop;
+                    mes_Morder.remaining_number = 0;
+                    mes_Morder.create_time = DateTime.Now;
+                    mes_Morder.bang_id = bang_id;
+                    //生成工单子表数据
+                    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 = "";
+                    mes_Moentry.morder_production_number = b.eop;
+                    mes_Moentry.need_number = b.eop;
+                    mes_Moentry.remaining_number = 0;
+                    mes_Moentry.tenant_id = input.tenant_id;
+                    mes_Moentry.factory_id = input.factory_id;
+                    mes_Moentry.company_id = input.company_id;
+                    mes_Moentry.org_id = input.org_id;
+                    mes_Moentry.create_time = DateTime.Now;
+                    mes_Moentry.bang_id = bang_id;
+                    moList.Add(mes_Morder);
+                    moentryList.Add(mes_Moentry);
+                    j++;
+                }
             });
+            await PlanOrderResourceCheck(moList, moentryList, bang_id, input);
+
+            List<RoutingOpDetail> routingOps = _routingOpDetail.Select(p => ropModelList.Where(a=>a.erp_cls==1).Select(a => a.number).ToList().Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
+            var examine_resultList = _mysql_examine_result.GetListAsync(a => a.bangid == bang_id).Result;
+
+            //批量保存 后期考虑子工单
+            List<WorkOrdMaster> workOrds = new List<WorkOrdMaster>();
+            List<WorkOrdRouting> workOrdRoutings = new List<WorkOrdRouting>();
+            List<WorkOrdDetail> workOrdDetails = new List<WorkOrdDetail>();
+            if (moList.Any())
+            {
+                moList.ForEach(s => { s.create_time = DateTime.Now; });
+                List<b_bom_child_examine> childExamineList = _mysql_bom_child_examine.GetListAsync(c => examine_resultList.Select(x => x.Id).Contains(c.examine_id.GetValueOrDefault())).Result;
+                //同步工单
+                CreateWorkOrdDates(moList, routingOps, workOrds, workOrdRoutings, workOrdDetails, examine_resultList, childExamineList);
+            }
+
+            if (workOrds.Any())
+            {
+                workOrds = CalcPriority(workOrds, input.factory_id.ToString());
+                _workOrdMaster.Insert(workOrds);
+            }
+            var DBworkOrdList = _workOrdMaster.Select(a => a.Domain == workOrds[0].Domain && workOrds.Select(c => c.WorkOrd).Contains(a.WorkOrd));
+            if (workOrdRoutings.Any())
+            {
+                workOrdRoutings.ForEach(c =>
+                {
+                    c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
+                });
+                _workOrdRouting.Insert(workOrdRoutings);
+            }
+            if (workOrdDetails.Any())
+            {
+                workOrdDetails.ForEach(c =>
+                {
+                    c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
+                });
+                _workOrdDetail.Insert(workOrdDetails);
+            }
             //成品半成品取下周一开始+取供应提前期为结束时间
             //原材料取第二天开始+取供应提前期为结束时间
 
 
             //DOP运行资源检查每个原材料SKU的可用库存,当可用库存<=修正后ROP时,自动生成月度采购申请(Purchase request,PR46年月日4位流水号)=EOP;可用库存为没有被其他SO和PO占用的(合格原材料库存+在途库存);
-
+            var planList = _ic_item.GetListAsync().Result;
+            List< srm_pr_main> prList = new List<srm_pr_main>();
+            var numbers = ropModelList.Where(a => a.erp_cls == 3).Select(b => b.number).ToList();
+            var icItemList = _mysql_ic_item.GetListAsync(c => numbers.Contains(c.number)).Result;
+            var srm_pr_mains = _srm_pr_main.GetListAsync(x => icItemList.Select(p => p.Id).ToList().Contains(x.icitem_id.Value) && x.state != 0 && !x.IsDeleted && x.state!=4).Result;
+            var quarter_srm_pr_mains=srm_pr_mains.Where(s => s.pr_psend_date >= _CalcBomViewAppService.quarter_starttime && s.pr_psend_date < _CalcBomViewAppService.quarter_endtime).ToList();
+            ropModelList.Where(a => a.erp_cls ==3)?.ToList().ForEach(b =>
+            {
+                if (itemStock.First(c => c.ItemNumber == b.number).Qty < b.rop_revised)
+                {
+                    mo_srm_purchase supplier = null;
+                    var plan = planList.Find(x => x.number == b.number);
+                    var item = icItemList.Find(d => d.number == b.number);
+                    var supplist = supplierList.Where(s => s.number == b.number).ToList();
+                    decimal day = 0;
+                    var plan_date = DateTime.Now.AddDays(1 + Convert.ToDouble(b.supply_leadtime));
+                    //判断当前时间与交期还剩余多少天
+                    var timesp = plan_date - DateTime.Now.Date;
+                        //交期-生产时长-物料前处理周期
+                        day = timesp.Days;
+                        if (day > 0)
+                        {
+                            supplist = supplist.Where(s => s.lead_time.GetValueOrDefault() < day).ToList();
+                            if (supplist.Any())
+                            {
+                                //TODO:走配额管理
+                                List<mo_srm_pr_main> itemPrlist = quarter_srm_pr_mains.Where(s => s.icitem_id == item.Id).ToList();
+                                if (itemPrlist.Any())
+                                {
+                                    decimal qtyCount = itemPrlist.Sum(x => x.pr_aqty).GetValueOrDefault();
+                                    //按配额比例,计算使用哪个供应商。
+                                    List<PrPurchaseDto> PrPurchaseDtoList = new List<PrPurchaseDto>();
+                                    supplist.ForEach(s => {
+                                        PrPurchaseDto purDto = new PrPurchaseDto();
+                                        purDto.pr_purchaseid = s.supplier_id;
+                                        purDto.num = itemPrlist.Where(x => x.pr_purchaseid == s.supplier_id).Sum(c => c.pr_aqty.GetValueOrDefault());
+                                        purDto.ratio = Math.Round(purDto.num / qtyCount, 2, MidpointRounding.AwayFromZero);
+                                        purDto.quota_priority = s.quota_priority;
+                                        purDto.quota_rate = s.quota_rate.GetValueOrDefault();
+                                        PrPurchaseDtoList.Add(purDto);
+                                    });
+
+                                    //首先取出占比还小于配额比的数据
+                                    var priorityPurlist = PrPurchaseDtoList.Where(s => s.quota_rate - s.ratio > 2).ToList();
+                                    if (!priorityPurlist.Any())
+                                    {
+                                        //没有则取出当前集合中的供应商的数据,计算差额
+                                        priorityPurlist = PrPurchaseDtoList;
+                                    }
+                                    //还没有达到配额比的供应商,优先分配
+                                    decimal difference = 0;
+                                    PrPurchaseDto dto1 = priorityPurlist[0];
+                                    priorityPurlist.ForEach(s => {
+                                        decimal diff = s.quota_rate - s.ratio;
+                                        if (diff > difference)
+                                        {
+                                            difference = diff;
+                                            dto1 = s;
+                                        }
+                                    });
+                                    supplier = supplist.Find(s => s.supplier_id == dto1.pr_purchaseid);
+                                }
+                                else
+                                {
+                                    supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
+                                }
+                            }
+                            else
+                            {
+                                supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
+                            }
+                        }
+                        else
+                        {
+                            supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
+                        }
+                    srm_pr_main srm_Pr = new srm_pr_main();
+                    srm_Pr.GenerateNewId(help.NextId());
+                    srm_Pr.IsRequireGoods = supplier.IsRequireGoods;
+                    srm_Pr.pr_purchaseid = supplier.supplier_id;//供应商id  
+                    srm_Pr.pr_purchasenumber = supplier.supplier_number;//供应商编码
+                    srm_Pr.pr_purchasename = supplier.supplier_name;//供应商名称
+                    srm_Pr.pr_purchaser = supplier.order_rector_name;//采购员
+                    srm_Pr.pr_purchaser_num = supplier.order_rector_num;//采购员工号(采购信息表)
+                                                                        //数量圆整 按最小包装量向上圆整
+                    decimal qty =b.eop.Value;
+                    //判断最小起订量
+                    qty = qty > supplier.qty_min ? qty : supplier.qty_min.GetValueOrDefault();
+                    srm_Pr.pr_rqty = qty;//需求数量
+                    srm_Pr.pr_aqty = qty;//申请数量
+                    srm_Pr.pr_sqty = qty;//建议数量
+                    srm_Pr.icitem_id = item.Id;//物料id
+                    srm_Pr.icitem_name = b.name;//物料名称
+                    srm_Pr.pr_order_type = 1;//单据类型
+                    srm_Pr.pr_ssend_date = DateTime.Now.Date.AddDays(1);//系统建议下单日期
+                    srm_Pr.pr_sarrive_date = DateTime.Now.AddDays((double)supplier.lead_time.GetValueOrDefault());//系统建议到达日期(建议到货日期)
+                    
+                    srm_Pr.pr_sysprice = supplier.order_price;//系统价格(含税)
+                    srm_Pr.pr_orderprice = qty * supplier.order_price;//订单价格(含税)
+                    srm_Pr.pr_price = supplier.netpurchase_price;//采购净价(不含税)
+                    srm_Pr.pr_rate = supplier.taxrate;//税率
+                    srm_Pr.pr_unit = item.unit;//单位
+                    srm_Pr.state = 1;//状态
+                    srm_Pr.old_apply_aqty = 0;//已申请数量
+                    srm_Pr.pr_type = b.erp_cls;//申请类型
+                    srm_Pr.currencytype = supplier.currency_type == null ? 1 : supplier.currency_type.Value;//币种
+                    srm_Pr.secInv_ratio = plan.secinv_ratio;//安全库存触发采购比例
+                    srm_Pr.tenant_id =input.tenant_id;
+                    srm_Pr.company_id = input.company_id;
+                    srm_Pr.factory_id = input.factory_id;
+                    srm_Pr.create_time = DateTime.Now;
+                    srm_Pr.create_by_name = "admin";
+                    srm_Pr.update_time = DateTime.Now;
+                    srm_Pr.update_by_name = "admin";
+                    prList.Add(srm_Pr);
+                }
+            });
+            prList.ForEach(a =>
+            {
+                a.GenerateNewId(help.NextId());
+            });
+            await _mysql_srm_pr_main.InsertManyAsync(prList);
+            await CalcDayPlanSafeStock(input);
             //每天DOP检查每个SKU的可用库存<=SS时,第二次触发PO或PR,每次补货数量=圆整后EOP;SKU可用库存=实际库存+WIP或在途库存-销售订单占用-计划订单占用;当M+1\M+2实际有销售订单产生时,相同SKU的销售订单和计划订单先进行冲销;
 
 
@@ -1185,6 +1419,266 @@ namespace Business.Replenishment
             return "OK";
         }
 
+        /// <summary>
+        /// 每天补货
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public async Task<string> CalcDayPlanSafeStock(InputDto input)
+        {
+            ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
+            var ropModelList = _replenishmentROP.GetListAsync(a => a.isparam && a.factory_id == input.factory_id && a.company_id == input.company_id && !a.IsDeleted).Result;
+            var itemStock = CalcStock(ropModelList.Select(a => a.number).ToList(), input);
+            var bomList = _ic_bom.GetListAsync(a => ropModelList.Select(a => a.number).ToList().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>();
+
+            var itemNeedPRList = ropModelList.Where(a => a.erp_cls == 1).ToList();
+            int count = 0;
+            itemNeedPRList.ForEach(a => {
+                if (itemStock.First(c => c.ItemNumber == a.number).Qty < a.security_stock)
+                {
+                    count++;
+                }
+            });
+            var list = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "MPO", count, "", 1);
+            var nbrlistDto = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", count, "", 1);
+            int j = 0;
+            DateTime currentTime = DateTime.Now;
+            int week = Convert.ToInt32(currentTime.DayOfWeek);
+            week = week == 0 ? 7 : week;
+            long bang_id = help.NextId();
+            ropModelList.Where(a => a.erp_cls == 1)?.ToList().ForEach(b =>
+            {
+
+                if (itemStock.First(c => c.ItemNumber == b.number).Qty < b.rop_revised)
+                {
+                    var bom = bomList.Find(c => c.item_number == b.number);
+                    mes_morder mes_Morder = new mes_morder();
+                    mes_Morder.GenerateNewId(help.NextId());
+                    mes_Morder.morder_type = MorderEnum.JhMorder;
+                    //mes_Morder.morder_icitem_type
+                    mes_Morder.work_order_type = MorderEnum.FhMorder;
+                    mes_Morder.morder_state = MorderEnum.Initial_state;
+                    mes_Morder.morder_no = list[j].NbrResult;
+                    mes_Morder.fms_number = b.number;
+                    mes_Morder.bom_number = bom.bom_number;
+                    mes_Morder.fmodel = b.model;
+                    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 = b.number;
+                    mes_Morder.product_name = b.name;
+                    mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
+                    //成品半成品取周一开始 + 取供应提前期为结束时间
+                    mes_Morder.moentry_stime = currentTime.AddDays(1 - week + 7);
+                    mes_Morder.moentry_sys_etime = currentTime.AddDays(1 - week + 7 + Convert.ToDouble(b.supply_leadtime));
+                    //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 = "";
+                    mes_Morder.morder_production_number = b.eop;
+                    mes_Morder.need_number = b.eop;
+                    mes_Morder.remaining_number = 0;
+                    mes_Morder.create_time = DateTime.Now;
+                    mes_Morder.bang_id = bang_id;
+                    //生成工单子表数据
+                    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 = "";
+                    mes_Moentry.morder_production_number = b.eop;
+                    mes_Moentry.need_number = b.eop;
+                    mes_Moentry.remaining_number = 0;
+                    mes_Moentry.tenant_id = input.tenant_id;
+                    mes_Moentry.factory_id = input.factory_id;
+                    mes_Moentry.company_id = input.company_id;
+                    mes_Moentry.org_id = input.org_id;
+                    mes_Moentry.create_time = DateTime.Now;
+                    mes_Moentry.bang_id = bang_id;
+                    moList.Add(mes_Morder);
+                    moentryList.Add(mes_Moentry);
+                    j++;
+                }
+            });
+            await PlanOrderResourceCheck(moList, moentryList, bang_id, input);
+
+            List<RoutingOpDetail> routingOps = _routingOpDetail.Select(p => ropModelList.Where(a => a.erp_cls == 1).Select(a => a.number).ToList().Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
+            var examine_resultList = _mysql_examine_result.GetListAsync(a => a.bangid == bang_id).Result;
+
+            //批量保存 后期考虑子工单
+            List<WorkOrdMaster> workOrds = new List<WorkOrdMaster>();
+            List<WorkOrdRouting> workOrdRoutings = new List<WorkOrdRouting>();
+            List<WorkOrdDetail> workOrdDetails = new List<WorkOrdDetail>();
+            if (moList.Any())
+            {
+                moList.ForEach(s => { s.create_time = DateTime.Now; });
+                List<b_bom_child_examine> childExamineList = _mysql_bom_child_examine.GetListAsync(c => examine_resultList.Select(x => x.Id).Contains(c.examine_id.GetValueOrDefault())).Result;
+                //同步工单
+                CreateWorkOrdDates(moList, routingOps, workOrds, workOrdRoutings, workOrdDetails, examine_resultList, childExamineList);
+            }
+
+            if (workOrds.Any())
+            {
+                workOrds = CalcPriority(workOrds, input.factory_id.ToString());
+                _workOrdMaster.Insert(workOrds);
+            }
+            var DBworkOrdList = _workOrdMaster.Select(a => a.Domain == workOrds[0].Domain && workOrds.Select(c => c.WorkOrd).Contains(a.WorkOrd));
+            if (workOrdRoutings.Any())
+            {
+                workOrdRoutings.ForEach(c =>
+                {
+                    c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
+                });
+                _workOrdRouting.Insert(workOrdRoutings);
+            }
+            if (workOrdDetails.Any())
+            {
+                workOrdDetails.ForEach(c =>
+                {
+                    c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
+                });
+                _workOrdDetail.Insert(workOrdDetails);
+            }
+            //成品半成品取下周一开始+取供应提前期为结束时间
+            //原材料取第二天开始+取供应提前期为结束时间
+
+
+            //DOP运行资源检查每个原材料SKU的可用库存,当可用库存<=修正后ROP时,自动生成月度采购申请(Purchase request,PR46年月日4位流水号)=EOP;可用库存为没有被其他SO和PO占用的(合格原材料库存+在途库存);
+            var planList = _ic_item.GetListAsync().Result;
+            List<srm_pr_main> prList = new List<srm_pr_main>();
+            var numbers = ropModelList.Where(a => a.erp_cls == 3).Select(b => b.number).ToList();
+            var icItemList = _mysql_ic_item.GetListAsync(c => numbers.Contains(c.number)).Result;
+            var srm_pr_mains = _srm_pr_main.GetListAsync(x => icItemList.Select(p => p.Id).ToList().Contains(x.icitem_id.Value) && x.state != 0 && !x.IsDeleted && x.state != 4).Result;
+            var quarter_srm_pr_mains = srm_pr_mains.Where(s => s.pr_psend_date >= _CalcBomViewAppService.quarter_starttime && s.pr_psend_date < _CalcBomViewAppService.quarter_endtime).ToList();
+            ropModelList.Where(a => a.erp_cls == 3)?.ToList().ForEach(b =>
+            {
+                if (itemStock.First(c => c.ItemNumber == b.number).Qty < b.security_stock)
+                {
+                    mo_srm_purchase supplier = null;
+                    var plan = planList.Find(x => x.number == b.number);
+                    var item = icItemList.Find(d => d.number == b.number);
+                    var supplist = supplierList.Where(s => s.number == b.number).ToList();
+                    decimal day = 0;
+                    var plan_date = DateTime.Now.AddDays(1 + Convert.ToDouble(b.supply_leadtime));
+                    //判断当前时间与交期还剩余多少天
+                    var timesp = plan_date - DateTime.Now.Date;
+                    //交期-生产时长-物料前处理周期
+                    day = timesp.Days;
+                    if (day > 0)
+                    {
+                        supplist = supplist.Where(s => s.lead_time.GetValueOrDefault() < day).ToList();
+                        if (supplist.Any())
+                        {
+                            //TODO:走配额管理
+                            List<mo_srm_pr_main> itemPrlist = quarter_srm_pr_mains.Where(s => s.icitem_id == item.Id).ToList();
+                            if (itemPrlist.Any())
+                            {
+                                decimal qtyCount = itemPrlist.Sum(x => x.pr_aqty).GetValueOrDefault();
+                                //按配额比例,计算使用哪个供应商。
+                                List<PrPurchaseDto> PrPurchaseDtoList = new List<PrPurchaseDto>();
+                                supplist.ForEach(s => {
+                                    PrPurchaseDto purDto = new PrPurchaseDto();
+                                    purDto.pr_purchaseid = s.supplier_id;
+                                    purDto.num = itemPrlist.Where(x => x.pr_purchaseid == s.supplier_id).Sum(c => c.pr_aqty.GetValueOrDefault());
+                                    purDto.ratio = Math.Round(purDto.num / qtyCount, 2, MidpointRounding.AwayFromZero);
+                                    purDto.quota_priority = s.quota_priority;
+                                    purDto.quota_rate = s.quota_rate.GetValueOrDefault();
+                                    PrPurchaseDtoList.Add(purDto);
+                                });
+
+                                //首先取出占比还小于配额比的数据
+                                var priorityPurlist = PrPurchaseDtoList.Where(s => s.quota_rate - s.ratio > 2).ToList();
+                                if (!priorityPurlist.Any())
+                                {
+                                    //没有则取出当前集合中的供应商的数据,计算差额
+                                    priorityPurlist = PrPurchaseDtoList;
+                                }
+                                //还没有达到配额比的供应商,优先分配
+                                decimal difference = 0;
+                                PrPurchaseDto dto1 = priorityPurlist[0];
+                                priorityPurlist.ForEach(s => {
+                                    decimal diff = s.quota_rate - s.ratio;
+                                    if (diff > difference)
+                                    {
+                                        difference = diff;
+                                        dto1 = s;
+                                    }
+                                });
+                                supplier = supplist.Find(s => s.supplier_id == dto1.pr_purchaseid);
+                            }
+                            else
+                            {
+                                supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
+                            }
+                        }
+                        else
+                        {
+                            supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
+                        }
+                    }
+                    else
+                    {
+                        supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
+                    }
+                    srm_pr_main srm_Pr = new srm_pr_main();
+                    srm_Pr.GenerateNewId(help.NextId());
+                    srm_Pr.IsRequireGoods = supplier.IsRequireGoods;
+                    srm_Pr.pr_purchaseid = supplier.supplier_id;//供应商id  
+                    srm_Pr.pr_purchasenumber = supplier.supplier_number;//供应商编码
+                    srm_Pr.pr_purchasename = supplier.supplier_name;//供应商名称
+                    srm_Pr.pr_purchaser = supplier.order_rector_name;//采购员
+                    srm_Pr.pr_purchaser_num = supplier.order_rector_num;//采购员工号(采购信息表)
+                                                                        //数量圆整 按最小包装量向上圆整
+                    decimal qty = b.eop.Value;
+                    //判断最小起订量
+                    qty = qty > supplier.qty_min ? qty : supplier.qty_min.GetValueOrDefault();
+                    srm_Pr.pr_rqty = qty;//需求数量
+                    srm_Pr.pr_aqty = qty;//申请数量
+                    srm_Pr.pr_sqty = qty;//建议数量
+                    srm_Pr.icitem_id = item.Id;//物料id
+                    srm_Pr.icitem_name = b.name;//物料名称
+                    srm_Pr.pr_order_type = 1;//单据类型
+                    srm_Pr.pr_ssend_date = DateTime.Now.Date.AddDays(1);//系统建议下单日期
+                    srm_Pr.pr_sarrive_date = DateTime.Now.AddDays((double)supplier.lead_time.GetValueOrDefault());//系统建议到达日期(建议到货日期)
+
+                    srm_Pr.pr_sysprice = supplier.order_price;//系统价格(含税)
+                    srm_Pr.pr_orderprice = qty * supplier.order_price;//订单价格(含税)
+                    srm_Pr.pr_price = supplier.netpurchase_price;//采购净价(不含税)
+                    srm_Pr.pr_rate = supplier.taxrate;//税率
+                    srm_Pr.pr_unit = item.unit;//单位
+                    srm_Pr.state = 1;//状态
+                    srm_Pr.old_apply_aqty = 0;//已申请数量
+                    srm_Pr.pr_type = b.erp_cls;//申请类型
+                    srm_Pr.currencytype = supplier.currency_type == null ? 1 : supplier.currency_type.Value;//币种
+                    srm_Pr.secInv_ratio = plan.secinv_ratio;//安全库存触发采购比例
+                    srm_Pr.tenant_id = input.tenant_id;
+                    srm_Pr.company_id = input.company_id;
+                    srm_Pr.factory_id = input.factory_id;
+                    srm_Pr.create_time = DateTime.Now;
+                    srm_Pr.create_by_name = "admin";
+                    srm_Pr.update_time = DateTime.Now;
+                    srm_Pr.update_by_name = "admin";
+                    prList.Add(srm_Pr);
+                }
+            });
+            prList.ForEach(a =>
+            {
+                a.GenerateNewId(help.NextId());
+            });
+           await _mysql_srm_pr_main.InsertManyAsync(prList);
+            return "OK";
+        }
+
         /// <summary>
         /// 同步工单等相关数据
         /// </summary>
@@ -1382,6 +1876,89 @@ namespace Business.Replenishment
             return orderedList;
         }
 
+        /// <summary>
+        /// 根据工单排优先级(用于先排优先级再写入的场景)
+        /// </summary>
+        /// <param name="workOrdMasters">工单编号列表</param>
+        /// <param name="domain">工厂编码</param>
+        /// <returns></returns>
+        //计算工单优先级
+        public List<WorkOrdMaster> CalcPriority(List<WorkOrdMaster> works, string domain)
+        {
+            var saleWordOrd = works.Where(a => !string.IsNullOrEmpty(a.SalesJob));
+            Dictionary<string, int> dict = new Dictionary<string, int>();
+            var soList = _mysql_crm_seorder.GetListAsync(a => saleWordOrd.Select(b => b.SalesJob).Contains(a.bill_no)).Result;
+
+            var custList = _custMaster.Select(a => soList.Select(b => b.custom_no).Contains(a.Cust) && a.Domain == domain);
+            //T1海外客户
+            var T1CustList = custList.FindAll(a => a.Terms == "T1" || a.Terms == "海外").Select(a => a.Cust);
+            //国科海王客户
+            var T2CustList = custList.FindAll(a => a.Terms == "国科" || a.Terms == "海王").Select(a => a.Cust);
+            //T1海外订单
+            var T1SOList = soList.Where(a => T1CustList.Contains(a.custom_no)).Select(a => a.bill_no);
+            //国科海王订单
+            var T2SOList = soList.Where(a => T2CustList.Contains(a.custom_no)).Select(a => a.bill_no);
+            //T1海外工单
+            var T1WOList = saleWordOrd.Where(a => T1SOList.Contains(a.SalesJob)).ToList();
+            //国科海王工单
+            var T2WOList = saleWordOrd.Where(a => T2SOList.Contains(a.SalesJob)).ToList();
+            //在制工单
+            var inProductList = _mes_mooccupy.GetListAsync(a => works.Select(a => a.WorkOrd).Contains(a.moo_mo)).Result;
+
+            //优先1:T1、海外销售订单新产生的生产指令;
+            var T1WOListNew = T1WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ToList();
+            //优先2:T1、海外销售订单关联的在制生产指令;
+            var T1WOListInProduct = T1WOList.Where(a => inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ToList();
+            //优先3:平台(国科、海王)销售订单新产生的生产指令;
+            var T2WOListNew = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ToList();
+            //优先4:平台(国科、海王)销售订单关联的在制生产指令;
+            var T2WOListInProduct = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ToList();
+            //优先5:除销售订单以外,计划补货订单关联的生产指令;
+            var PlanWOList = works.Except(T1WOListNew).ToList();
+            PlanWOList = works.Except(T1WOListInProduct).ToList();
+            PlanWOList = works.Except(T2WOListNew).ToList();
+            PlanWOList = works.Except(T2WOListInProduct).ToList();
+            PlanWOList = PlanWOList.OrderBy(a => a.DueDate).ToList();
+            //先按生产指令的类型,再按生产指令的完工日期顺序排产;
+            List<WorkOrdMaster> orderedList = new List<WorkOrdMaster>();
+            decimal Priority = 1.0m;
+            for (int i = 0; i < T1WOListNew.Count; i++)
+            {
+                T1WOListNew[i].Priority = Priority;
+                orderedList.Add(T1WOListNew[i]);
+                Priority = Priority + 1.0m;
+            }
+
+            for (int i = 0; i < T1WOListInProduct.Count; i++)
+            {
+                T1WOListInProduct[i].Priority = Priority;
+                orderedList.Add(T1WOListInProduct[i]);
+                Priority = Priority + 1.0m;
+            }
+
+            for (int i = 0; i < T2WOListNew.Count; i++)
+            {
+                T2WOListNew[i].Priority = Priority;
+                orderedList.Add(T2WOListNew[i]);
+                Priority = Priority + 1.0m;
+            }
+
+            for (int i = 0; i < T2WOListInProduct.Count; i++)
+            {
+                T2WOListInProduct[i].Priority = Priority;
+                orderedList.Add(T2WOListInProduct[i]);
+                Priority = Priority + 1.0m;
+            }
+
+            for (int i = 0; i < PlanWOList.Count; i++)
+            {
+                PlanWOList[i].Priority = Priority;
+                orderedList.Add(PlanWOList[i]);
+                Priority = Priority + 1.0m;
+            }
+            return orderedList;
+        }
+
         /// <summary>
         /// 手动调整优先级
         /// </summary>
@@ -2524,8 +3101,9 @@ namespace Business.Replenishment
                 moList.Add(mes_Morder);
                 moentryList.Add(mes_Moentry);
             }
-            await _mysql_mes_morder.InsertManyAsync(moList);
-            await _mysql_mes_moentry.InsertManyAsync(moentryList);
+            //长周期物料只产生PR不生成实际工单
+            //await _mysql_mes_morder.InsertManyAsync(moList);
+            //await _mysql_mes_moentry.InsertManyAsync(moentryList);
             await PlanOrderResourceCheck(moList,moentryList, bangid,input);
             return "OK";
         }

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

@@ -463,3 +463,15 @@
 {"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-17T13:53:48.5425855+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
 {"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-17T13:53:48.5478919+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
 {"TaskName":"长周期物料PR","GroupName":"systemquartzjob","BeginDate":"2023-09-17T13:53:48.5510056+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-18T01:37:41.5379799+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-18T01:37:41.6025067+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-18T01:37:41.6081817+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"长周期物料PR","GroupName":"systemquartzjob","BeginDate":"2023-09-18T01:37:41.6101546+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-18T01:52:00.52446+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-18T01:52:00.5945725+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-18T01:52:00.5995141+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"长周期物料PR","GroupName":"systemquartzjob","BeginDate":"2023-09-18T01:52:00.6019508+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步WMS物料订单等基础数据到MySQL","GroupName":"systemquartzjob","BeginDate":"2023-09-18T02:07:55.28627+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时创建NLog日志按月分表","GroupName":"systemquartzjob","BeginDate":"2023-09-18T02:07:55.3518218+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"定时同步MySQL基础数据到MongoDB","GroupName":"systemquartzjob","BeginDate":"2023-09-18T02:07:55.3563462+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}
+{"TaskName":"长周期物料PR","GroupName":"systemquartzjob","BeginDate":"2023-09-18T02:07:55.3591345+08:00","EndDate":null,"Msg":"任务初始化启动成功:6","id":0,"timeflag":null,"changetime":null}