using Amazon.Runtime.Internal.Util; using Business.Core.Enum; using Business.Core.Utilities; using Business.Domain; using Business.Dto; using Business.EntityFrameworkCore; using Business.EntityFrameworkCore.SqlRepositories; using Business.ReplenishmentManagement; using Business.ResourceExamineManagement; using Business.ResourceExamineManagement.Dto; using Business.StructuredDB.MES; using Business.StructuredDB.MES.IC; using Business.StructuredDB.Production; using Business.StructuredDB.Replenishment; using Business.StructuredDB.SaleFcst; using Business.StructuredDB.WMS; using Business.SystemJob; using Business.SystemJobManagement; using EFCore.BulkExtensions; using Microsoft.EntityFrameworkCore; using MongoDB.Driver; using MongoDB.Driver.Linq; using Newtonsoft.Json; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel.Design; 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.ObjectMapping; using Volo.Abp.Uow; using static Azure.Core.HttpHeader; namespace Business.Replenishment { /// /// 产能分析 /// public class ReplenishmentAppService : ApplicationService, IReplenishmentAppService, ITransientDependency { #region 服务 /// /// 雪花算法 /// SnowFlake help = new SnowFlake(); private readonly IRepository _replenishmentROPWeekPlan; private readonly ISqlRepository _ASNBOLShipperDetail; private readonly ISqlRepository _ASNBOLShipperMaster; private readonly ISqlRepository _invTransHist; private readonly ISqlRepository _invMaster; private readonly ISqlRepository _SAPInv; private readonly IRepository _srmPurchase; /// /// 交货计划 /// private readonly IRepository _icdemandschedule; /// /// 交货单 /// private readonly ISqlRepository _srmpolistds; /// /// 采购明细表 /// private readonly ISqlRepository _PurOrdDetail; /// /// 采购单表 /// private readonly ISqlRepository _PurOrdMaster; private ISqlRepository _nbrMaster; private ISqlRepository _nbrDetail; /// /// 送货单子表 /// private readonly ISqlRepository _scm_shdzb; /// /// 交货单异常记录表 /// private readonly ISqlRepository _DeliveryExceptionMaster; private readonly ISqlRepository _monthlyShipmentPlan; private readonly ISqlRepository _monthlyShipmentPlanHistory; private readonly ISqlRepository _generalizedCodeMaster; private readonly IRepository _ic_item; private readonly IRepository _mysql_ic_item; private readonly ISqlRepository _itemMaster; private readonly IRepository _srm_pr_main; private readonly IRepository _mysql_srm_pr_main; private readonly IRepository _srm_po_occupy; private readonly IRepository _mysql_srm_po_occupy; private readonly IRepository _mysql_srm_pr_main_occupy; private readonly IRepository _mes_morder; private readonly IRepository _mes_moentry; private readonly IRepository _mes_mooccupy; private readonly IRepository _mysql_mes_mooccupy; private readonly IRepository _mysql_b_bom_pretreatment; private readonly ISqlRepository _workOrdMaster; private readonly ISqlRepository _prodLineDetail; private readonly ISqlRepository _lineMaster; private readonly IRepository _ic_bom; private readonly IRepository _mysql_ic_bom; private readonly IRepository _ic_bom_child; private readonly IRepository _mysql_ic_bom_child; private readonly ISqlRepository _holidayMaster; private readonly IRepository _ic_item_stockoccupy; private readonly IRepository _mysql_ic_item_stockoccupy; private readonly IRepository _ic_item_stock; private readonly IRepository _mysql_ic_item_stock; private readonly IRepository _ic_substitute; private readonly IRepository _ic_substitute_group; private readonly IRepository _ic_substitute_group_detail; private readonly IRepository _mysql_ic_substitute; private readonly IRepository _mysql_ic_substitute_group; private readonly IRepository _mysql_ic_substitute_group_detail; private readonly IRepository _mysql_mes_moentry; private readonly ISqlRepository _workOrdDetail; private readonly IRepository _srm_po_list; private readonly IRepository _mysql_srm_po_list; private readonly ISqlRepository _routingOpDetail; private readonly ISqlRepository _productStructureMaster; private readonly ISqlRepository _shopCalendarWorkCtr; private readonly ISqlRepository _qualityLineWorkDetail; private readonly ISqlRepository _custMaster; private readonly IRepository _srm_po_main; private readonly IRepository _mysql_srm_po_main; private readonly IRepository _srm_purchase; private readonly IRepository _mysql_srm_purchase; private readonly IRepository _mysql_mes_morder; private readonly IRepository _mysql_crm_seorder; private readonly IRepository _mysql_crm_seorderentry; private readonly IRepository _productionMasterPlan; private readonly IRepository _replenishmentWeekPlan; private readonly IRepository _mysql_examine_result; private readonly IRepository _mysql_bom_child_examine; private readonly IRepository _replenishmentServiceLevel; private readonly IExtSqlRepository _DMS_IN_ITEMMAPPING; private readonly IExtSqlRepository _DMS_IN_LOCDETAIL; private readonly IExtSqlRepository _DMS_IN_SHIPPINGDETAIL; private readonly IRepository _ReplenishmentTurnOverSet; /// /// 成品虚拟件工序关系表 /// private readonly ISqlRepository _productStructureOp; /// /// 年度销售预测 /// private IRepository _yearDemandManagement; /// /// 年度销售预测历史记录 /// private IRepository _yearDemandManagementHistory; /// /// 年度生产大纲 /// private IRepository _replenishmentAnnualProduction; /// /// 平台库存表 /// private readonly IRepository _PlatformInventory; /// /// 工单工艺路线明细 /// private ISqlRepository _workOrdRouting; /// /// 排产结果明细 /// private ISqlRepository _scheduleResultOpMaster; /// /// 排产记录表 /// private readonly ISqlRepository _periodSequenceDet; /// /// 计划订单表 /// private IRepository _crm_planorder; /// /// 平台库存表 /// private IRepository _platformInventory; /// /// 在途检查 /// private readonly PurchaseOrderAppService _purchaseOrderAppService; /// /// 计算BOM平铺物料情况 /// private readonly CalcBomViewAppService _CalcBomViewAppService; /// /// 预处理 /// private readonly PretreatmentAppService _pretreatmentAppService; private readonly SerialNumberAppService _serialNumberAppService; /// /// 产能检查 /// private readonly ProductExamineAppService _productExamineAppService; /// /// 账号时效性验证 /// private readonly AccountValidityAppService _AccountValidityAppService; /// /// 资源检查入参 /// private readonly SeorderentryDto param = new SeorderentryDto(); /// /// 生产线明细表 /// public List prodLines = new List(); /// /// 标准工艺路径表 /// public List routingOps = new List(); /// /// 排产记录表 /// public List periodSequences = new List(); /// /// 工作日历 /// public List calendarWorks = new List(); /// /// 休息时间段 /// public List qualityLineWorks = new List(); private readonly ISqlRepository _configurationItem; /// /// 节假日 /// public List holidays = new List(); private List leadTimeList; private List supplierList; private readonly BusinessBangDbContext _businessBangDbContext; private readonly BusinessDbContext _businessDbContext; private readonly ICurrentTenant _currentTenant; private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly SystemJobAppService _systemJobAppService; #endregion #region 构造函数 /// /// 构造函数 /// public ReplenishmentAppService( IRepository replenishmentROPWeekPlan, ISqlRepository ASNBOLShipperDetail, ISqlRepository ASNBOLShipperMaster, ISqlRepository invTransHist, IRepository srmPurchase, ISqlRepository monthlyShipmentPlan, ISqlRepository monthlyShipmentPlanHistory, ISqlRepository generalizedCodeMaster, ISqlRepository invMaster, ISqlRepository SAPInv, IRepository ic_item, IRepository mysql_ic_item, ISqlRepository itemMaster, IRepository srm_pr_main, IRepository mysql_srm_pr_main, IRepository srm_po_occupy, IRepository mysql_srm_po_occupy, IRepository mysql_srm_pr_main_occupy, IRepository mes_morder, IRepository mes_moentry, IRepository mes_mooccupy, IRepository mysql_mes_mooccupy, IRepository mysql_b_bom_pretreatment, ISqlRepository workOrdMaster, ISqlRepository prodLineDetail, ISqlRepository lineMaster, IRepository ic_bom, IRepository mysql_ic_bom, IRepository ic_bom_child, IRepository mysql_ic_bom_child, ISqlRepository holidayMaster, IRepository ic_item_stockoccupy, IRepository mysql_ic_item_stockoccupy, IRepository ic_item_stock, IRepository mysql_ic_item_stock, IRepository ic_substitute, IRepository ic_substitute_group, IRepository ic_substitute_group_detail, IRepository mysql_ic_substitute, IRepository mysql_ic_substitute_group, IRepository mysql_ic_substitute_group_detail, IRepository mysql_mes_moentry, ISqlRepository workOrdDetail, IRepository srm_po_list, IRepository mysql_srm_po_list, ISqlRepository routingOpDetail, ISqlRepository productStructureMaster, ISqlRepository shopCalendarWorkCtr, ISqlRepository periodSequenceDet, ISqlRepository qualityLineWorkDetail, ISqlRepository scheduleResultOpMaster, IRepository srm_po_main, IRepository mysql_srm_po_main, IRepository srm_purchase, IRepository mysql_srm_purchase, IRepository mysql_mes_morder, IRepository mysql_crm_seorder, IRepository mysql_crm_seorderentry, IRepository mes_oorder, IRepository productionMasterPlan, ISqlRepository productStructureOp, IRepository yearDemandManagement, IRepository replenishmentAnnualProduction, IRepository yearDemandManagementHistory, IRepository PlatformInventory, ISqlRepository workOrdRouting, ISqlRepository custMaster, IRepository crm_planorder, IRepository platformInventory, IRepository replenishmentWeekPlan, IRepository mysql_examine_result, IRepository mysql_bom_child_examine, IRepository replenishmentServiceLevel, ISqlRepository nbrMaster, ISqlRepository nbrDetail, IExtSqlRepository DMS_IN_ITEMMAPPING, IExtSqlRepository DMS_IN_LOCDETAIL, IExtSqlRepository DMS_IN_SHIPPINGDETAIL, IRepository ReplenishmentTurnOverSet, ISqlRepository configurationItem, SerialNumberAppService serialNumberAppService, PretreatmentAppService pretreatmentAppService, PurchaseOrderAppService purchaseOrderAppService, CalcBomViewAppService CalcBomViewAppService, AccountValidityAppService AccountValidityAppService, ProductExamineAppService productExamineAppService, BusinessBangDbContext businessBangDbContext, BusinessDbContext businessDbContext, ICurrentTenant currentTenant, IRepository icdemandschedule, ISqlRepository srmpolistds, ISqlRepository PurOrdDetail, ISqlRepository PurOrdMaster, ISqlRepository DeliveryExceptionMaster, ISqlRepository scm_shdzb, IUnitOfWorkManager unitOfWorkManager, SystemJobAppService systemJobAppService) { _replenishmentROPWeekPlan = replenishmentROPWeekPlan; _ASNBOLShipperDetail = ASNBOLShipperDetail; _ASNBOLShipperMaster = ASNBOLShipperMaster; _invTransHist = invTransHist; _srmPurchase = srmPurchase; _monthlyShipmentPlan = monthlyShipmentPlan; _monthlyShipmentPlanHistory = monthlyShipmentPlanHistory; _generalizedCodeMaster = generalizedCodeMaster; _invMaster = invMaster; _SAPInv = SAPInv; _nbrMaster = nbrMaster; _nbrDetail = nbrDetail; _ic_item = ic_item; _mysql_ic_item = mysql_ic_item; _itemMaster = itemMaster; _srm_pr_main = srm_pr_main; _mysql_srm_pr_main = mysql_srm_pr_main; _srm_po_occupy = srm_po_occupy; _mysql_srm_po_occupy = mysql_srm_po_occupy; _mysql_srm_pr_main_occupy = mysql_srm_pr_main_occupy; _mes_morder = mes_morder; _mes_moentry = mes_moentry; _mes_mooccupy = mes_mooccupy; _mysql_mes_mooccupy = mysql_mes_mooccupy; _mysql_b_bom_pretreatment = mysql_b_bom_pretreatment; _workOrdMaster = workOrdMaster; _scheduleResultOpMaster = scheduleResultOpMaster; _periodSequenceDet = periodSequenceDet; _custMaster = custMaster; _prodLineDetail = prodLineDetail; _lineMaster = lineMaster; _ic_bom = ic_bom; _mysql_ic_bom = mysql_ic_bom; _ic_bom_child = ic_bom_child; _mysql_ic_bom_child = mysql_ic_bom_child; _holidayMaster = holidayMaster; _ic_item_stockoccupy = ic_item_stockoccupy; _mysql_ic_item_stockoccupy = mysql_ic_item_stockoccupy; _ic_item_stock = ic_item_stock; _mysql_ic_item_stock = mysql_ic_item_stock; _ic_substitute = ic_substitute; _ic_substitute_group = ic_substitute_group; _ic_substitute_group_detail = ic_substitute_group_detail; _mysql_ic_substitute = mysql_ic_substitute; _mysql_ic_substitute_group = mysql_ic_substitute_group; _mysql_ic_substitute_group_detail = mysql_ic_substitute_group_detail; _mysql_mes_moentry = mysql_mes_moentry; _workOrdDetail = workOrdDetail; _srm_po_list = srm_po_list; _mysql_srm_po_list = mysql_srm_po_list; _routingOpDetail = routingOpDetail; _productStructureMaster = productStructureMaster; _shopCalendarWorkCtr = shopCalendarWorkCtr; _qualityLineWorkDetail = qualityLineWorkDetail; _srm_po_main = srm_po_main; _mysql_srm_po_main = mysql_srm_po_main; _srm_purchase = srm_purchase; _mysql_srm_purchase = mysql_srm_purchase; _mysql_mes_morder = mysql_mes_morder; _mysql_crm_seorder = mysql_crm_seorder; _mysql_crm_seorderentry = mysql_crm_seorderentry; _productionMasterPlan = productionMasterPlan; _replenishmentWeekPlan = replenishmentWeekPlan; _mysql_examine_result = mysql_examine_result; _mysql_bom_child_examine = mysql_bom_child_examine; _replenishmentServiceLevel = replenishmentServiceLevel; _productStructureOp = productStructureOp; _PlatformInventory = PlatformInventory; _workOrdRouting = workOrdRouting; _ASNBOLShipperDetail = ASNBOLShipperDetail; _yearDemandManagement = yearDemandManagement; _yearDemandManagementHistory = yearDemandManagementHistory; _replenishmentAnnualProduction = replenishmentAnnualProduction; _holidayMaster = holidayMaster; _crm_planorder = crm_planorder; _platformInventory = platformInventory; _DMS_IN_ITEMMAPPING = DMS_IN_ITEMMAPPING; _DMS_IN_LOCDETAIL = DMS_IN_LOCDETAIL; _DMS_IN_SHIPPINGDETAIL = DMS_IN_SHIPPINGDETAIL; _ReplenishmentTurnOverSet = ReplenishmentTurnOverSet; _configurationItem = configurationItem; _serialNumberAppService = serialNumberAppService; _pretreatmentAppService = pretreatmentAppService; _CalcBomViewAppService = CalcBomViewAppService; _AccountValidityAppService = AccountValidityAppService; _purchaseOrderAppService = purchaseOrderAppService; _productExamineAppService = productExamineAppService; _currentTenant = currentTenant; _businessBangDbContext = businessBangDbContext; _businessDbContext = businessDbContext; _unitOfWorkManager = unitOfWorkManager; _icdemandschedule = icdemandschedule; _srmpolistds = srmpolistds; _PurOrdDetail = PurOrdDetail; _PurOrdMaster = PurOrdMaster; _DeliveryExceptionMaster = DeliveryExceptionMaster; _scm_shdzb = scm_shdzb; _systemJobAppService = systemJobAppService; } #endregion /// /// 生成年度生产大纲 /// /// /// /// public async Task SaveAnnualProductionOutline(InputDto input) { //来自定时任务的请求 if (input.year == 0 && input.month == 0) { input.year = DateTime.Now.Year; input.month = DateTime.Now.Month; } //每年10月份做下一年的销售预测 if (DateTime.Now.Month >= 10) { input.year = DateTime.Now.AddYears(1).Year; input.month = DateTime.Now.Month; } //获取当前导入或修改数据 List yearDemands = _yearDemandManagement.GetListAsync(p => p.Year == input.year && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ThenBy(o => o.PlanMonth).ToList(); if (yearDemands == null || yearDemands.Count == 0) { input.year = DateTime.Now.Year; input.month = DateTime.Now.Month; yearDemands = _yearDemandManagement.GetListAsync(p => p.Year == input.year && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ThenBy(o => o.PlanMonth).ToList(); } //标准工艺路径表 var sapItemList = yearDemands.Select(m => m.SAPItemNumber).Distinct().ToList(); 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) { return "年度销售预测物料" + string.Join(",", expectedList) + "在DOP物料表找不到!"; } var bomItemList = bomList.Select(a => a.item_number).Distinct().ToList(); var expectedBOMList = sapItemList.Except(bomItemList).ToList(); if (expectedBOMList.Count > 0) { return "年度销售预测物料" + string.Join(",", expectedBOMList) + "在BOM没有维护!"; } var itemMasterList = _itemMaster.Select(i => sapItemList.Contains(i.ItemNum) && i.Domain == input.factory_id.ToString()); List 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(); //生产线明细表 List prodLines = _prodLineDetail.Select(p => sapItemList.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 lineMasters = _lineMaster.Select(p => prodLines.Select(a => a.Line).Distinct().ToList().Contains(p.Line) && p.Domain == input.factory_id.ToString() && p.IsActive).ToList(); List locations = _invMaster.Select(x => sapItemList.Contains(x.ItemNum) && x.Domain == input.factory_id.ToString() && x.IsActive).ToList(); //平台库存 var DMSItemList = _DMS_IN_ITEMMAPPING.Select(a => sapItemList.Contains(a.CfnERPCode)); var gkhwStock = _DMS_IN_LOCDETAIL.Select(a => (a.DealerCode == "RQ000005" || a.DealerCode == "RQ000002")); var sapInvList = _SAPInv.Select(a => a.WERKS == input.factory_id.ToString() && sapItemList.Contains(a.MATNR) && (a.SOBKZ.ToUpper() == "O")); // 获取某年某月的起始日期和结束日期 DateTime start = new DateTime(DateTime.Now.Year, DateTime.Now.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(DateTime.Now.AddYears(-1).Year, 4, 1); DateTime endYear = new DateTime(DateTime.Now.Year, 12, 31); List 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 dictInProduction = new Dictionary(); //按照工单循环 //某工单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 annualProductionOutlines = new List(); List frontYearDemand = new List(); for (int i = 0; i < yearDemands.Count; i++) { if (yearDemands.Where(a => a.SAPItemNumber == yearDemands[i].SAPItemNumber).Count() != 12) { return "年度销售预测物料" + 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 == yearDemands[i].SAPItemNumber).OrderBy(x => x.Sequence).FirstOrDefault(); //不同库位库存数量 //5008成品线边库,8001成品合格库,8000成品待检 var locationList = locations.Where(x => x.ItemNum == yearDemands[i].SAPItemNumber && (x.Location == "5008" || x.Location == "5009" || x.Location == "5010" || x.Location == "8000" || x.Location == "8001" || x.Location == "8002" || x.Location == "8002" || x.Location == "8003" || x.Location == "8004" || x.Location == "8005")).ToList(); //平台数据 decimal? hwStock = 0; if (DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber) != null) { 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(); hwStock = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty); } } decimal? gkStock = 0; if (DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber) != null) { 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(); gkStock = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty); } } //销售预测 对应 Excel中公式 AVERAGE 如果预测为0不参与计算排产批量 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) { pcpl = Math.Ceiling(QtySum.Average(p => p.Qty) / 100) * 100; } //库存合计 + 在制+已发货 + 灭菌中 var ship = shipList.Where(x => x.ContainerItem == yearDemands[i].SAPItemNumber).ToList(); decimal itemInProduct = 0; if (dictInProduction.ContainsKey(yearDemands[i].SAPItemNumber)) { itemInProduct = dictInProduction[yearDemands[i].SAPItemNumber]; } decimal? InSterilizationQty = 0.00m; if (sapInvList.Count > 0 && sapInvList.Any(a => a.MATNR == yearDemands[i].SAPItemNumber)) { InSterilizationQty = sapInvList.Where(a => a.MATNR == yearDemands[i].SAPItemNumber && a.SOBKZ.ToUpper() == "O").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.QtyToShip)) + itemInProduct + InSterilizationQty; //前面N个月的生产数量 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; decimal NextMonthQty = 0.00m; if (yearDemands[i].PlanMonth.Substring(5) != "12") { NextMonthQty = yearDemands[i + 1].Qty; } else { NextMonthQty = pcpl; } //判断库存是否满足需要,满足则不用生产 //安全库存 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) { if (pcpl == 0) { ProduceQty = 0; } else { ProduceQty = Math.Ceiling((-locationSum.GetValueOrDefault() - frontQtySum + safeQty.GetValueOrDefault() + frontYearDemandQty + NextMonthQty / 2) / pcpl) * pcpl; } } //生成年度生产大纲 ReplenishmentAnnualProduction annualProductionOutline = new ReplenishmentAnnualProduction(); 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 = ""; } else { annualProductionOutline.WorkshopLine = lineMasters.Find(b => b.Line == prodLine.Line).Describe; } 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); //组装热封包装工时乘以数量 =单月工时 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 = 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; annualProductionOutlines.Add(annualProductionOutline); } //保存数据 using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { 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); //await CalcWeekPlan(input); 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"; } /// /// 生成主计划 /// /// /// public async Task SaveProductionMasterPlan(InputDto input, List annual) { //来自定时任务的请求 if (input.year == 0 && input.month == 0) { input.year = DateTime.Now.Year; input.month = DateTime.Now.Month; } //计算当前年月的N0,N+1,N+2 List planMons = GetPlanMonth(4); List productionMasters = new List(); List pre3MonthPlan = _productionMasterPlan.GetListAsync(a => GetPlanMonth(-3).Contains(a.PlanMonth) && a.factory_id == input.factory_id).Result; //N0,N+1,N+2月度发货计划 var annualProduction = new List(); foreach (var itemMonth in planMons) { var annualProductionMonth = _monthlyShipmentPlan.Select(x => itemMonth == x.PlanMonth && !x.IsDeleted && x.factory_id == input.factory_id).OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList(); if (annualProductionMonth != null && annualProductionMonth.Count > 0) { annualProduction.AddRange(annualProductionMonth); } else { var MaxVersion = _monthlyShipmentPlanHistory.Select(a => a.factory_id == input.factory_id && !a.IsDeleted).Max(b => b.VERSION); if (!string.IsNullOrEmpty(MaxVersion)) { var annualProductionMonthHistory = _monthlyShipmentPlanHistory.Select(x => itemMonth == x.PlanMonth && x.VERSION == MaxVersion && !x.IsDeleted && x.factory_id == input.factory_id).OrderByDescending(v => v.VERSION).ThenBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList(); if (annualProductionMonthHistory != null && annualProductionMonthHistory.Count > 0) { var returnlist = ObjectMapper.Map, List>(annualProductionMonthHistory); annualProduction.AddRange(returnlist); } } } } annualProduction = annualProduction.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList(); var productionMasterPlan = _productionMasterPlan.GetListAsync(x => planMons.Contains(x.PlanMonth) && !x.IsDeleted && x.factory_id == input.factory_id).Result.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList(); List locations = _invMaster.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); var itemStock = CalcStock(annualProduction.Select(m => m.SAPItemNumber).Distinct().ToList(), input); //主生产计划渠道合并,只考虑瑞奇库存不考虑国科海王库存 List shipList = new List(); foreach (var item in annualProduction) { if (shipList.Any(a => a.SAPItemNumber == item.SAPItemNumber && a.PlanMonth == item.PlanMonth)) { shipList.Find(b => b.SAPItemNumber == item.SAPItemNumber && b.PlanMonth == item.PlanMonth).Qty += item.Qty; } else { shipList.Add(item); } } shipList.OrderBy(a => a.PlanMonth); var shipItemList = shipList.Select(a => a.SAPItemNumber).Distinct().ToList(); var ropPlan = _replenishmentROPWeekPlan.GetListAsync(x => shipItemList.Contains(x.number) && planMons.Contains(x.planmonth) && !x.IsDeleted && x.factory_id == input.factory_id).Result; var sapInvList = _SAPInv.Select(a => a.WERKS == input.factory_id.ToString() && shipItemList.Contains(a.MATNR) && (a.SOBKZ.ToUpper() == "O")); foreach (var item in shipList) { var ropItem = ropPlan.Find(x => x.number == item.SAPItemNumber); if (ropItem != null) { ProductionMasterPlan plan = new ProductionMasterPlan(); plan.Area = item.Area; plan.ProdLine = item.ProdLine; plan.ProdRange = item.ProdRange; plan.WorkshopLine = annual.Find(a => a.PlanMonth == item.PlanMonth && a.SAPItemNumber == item.SAPItemNumber)?.WorkshopLine; if (plan.WorkshopLine == null) { plan.WorkshopLine = ""; } plan.ItemNumber = item.SAPItemNumber; plan.Model = item.Model; plan.Languages = item.Languages; plan.PlanMonth = item.PlanMonth; plan.PlanShipQty = item.Qty; var preMonth = Convert.ToDateTime($"{plan.PlanMonth}-01").AddMonths(-1); var preMonthStr = $"{preMonth.Year}-{preMonth.Month}"; var preMaster = productionMasters.Find(t => t.ItemNumber == plan.ItemNumber && t.PlanMonth == preMonthStr && t.factory_id == input.factory_id); var preStock = pre3MonthPlan.Find(t => t.ItemNumber == plan.ItemNumber && t.PlanMonth == preMonthStr && t.factory_id == input.factory_id); if (preMaster != null) { plan.PlanProductQty = Math.Ceiling(item.Qty - ( preMaster.PlanStockQty - ropItem.security_stock.GetValueOrDefault() ));//发货计划-(上个月期末库存作为本月期初库存-安全库存) if (plan.PlanProductQty < 0) { plan.PlanProductQty = 0; } plan.PlanStockQty = Math.Ceiling(preMaster.PlanStockQty + plan.PlanProductQty - item.Qty); } else if (preStock != null) { plan.PlanProductQty = Math.Ceiling(item.Qty - ( preStock.PlanStockQty - ropItem.security_stock.GetValueOrDefault() ));//发货计划-(上个月期末库存作为本月期初库存-安全库存) if (plan.PlanProductQty < 0) { plan.PlanProductQty = 0; } plan.PlanStockQty = Math.Ceiling(preStock.PlanStockQty + plan.PlanProductQty - item.Qty); } else { decimal itemStockQty = 0; if (itemStock.Any(a => a.ItemNumber == item.SAPItemNumber)) { itemStockQty = itemStock.Find(a => a.ItemNumber == item.SAPItemNumber).Qty; } decimal itemInProdcutQty = 0; if (InProdcutQty.Any(a => a.ItemNumber == item.SAPItemNumber)) { itemInProdcutQty = InProdcutQty.Find(a => a.ItemNumber == item.SAPItemNumber).Qty; } plan.PlanProductQty = item.Qty - (itemStockQty + itemInProdcutQty - ropItem.security_stock.GetValueOrDefault() );//发货计划-(库存+在制-安全库存) if (plan.PlanProductQty < 0) plan.PlanProductQty = 0; plan.PlanStockQty = Math.Ceiling( itemStock.Find(a => a.ItemNumber == item.SAPItemNumber).Qty + InProdcutQty.Find(a => a.ItemNumber == item.SAPItemNumber).Qty + plan.PlanProductQty - item.Qty); } if (locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "8001") != null) { plan.Inventory = locations.Where(a => a.ItemNum == item.SAPItemNumber && a.Location == "8001").Sum(c => c.AvailStatusQty.GetValueOrDefault() + c.Assay.GetValueOrDefault()); } else { plan.Inventory = 0; } if (locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "8000") != null) { plan.Inventory1 = locations.Where(a => a.ItemNum == item.SAPItemNumber && a.Location == "8000").Sum(c => c.AvailStatusQty.GetValueOrDefault() + c.Assay.GetValueOrDefault()); } else { plan.Inventory1 = 0; } if (locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "5008") != null) { plan.Inventory2 = locations.Where(a => a.ItemNum == item.SAPItemNumber && a.Location == "5008").Sum(c => c.AvailStatusQty.GetValueOrDefault() + c.Assay.GetValueOrDefault()); } else { plan.Inventory2 = 0; } decimal InSterilizationQty = 0.00m; if (sapInvList.Count > 0 && sapInvList.Any(a => a.MATNR == item.SAPItemNumber && a.SOBKZ.ToUpper() == "O")) { InSterilizationQty = sapInvList.Where(a => a.MATNR == item.SAPItemNumber && a.SOBKZ.ToUpper() == "O").Sum(x => Convert.ToDecimal(x.LABST) + Convert.ToDecimal(x.INSME) + Convert.ToDecimal(x.SPEME)); } plan.DuringSterilization = InSterilizationQty; plan.InProduction = InProdcutQty.Find(a => a.ItemNumber == item.SAPItemNumber).Qty; if (pre3MonthPlan.Where(a => a.ItemNumber == item.SAPItemNumber).Count() > 0) { plan.EconomicLotSize = pre3MonthPlan.Where(a => a.ItemNumber == item.SAPItemNumber).Average(a => a.PlanProductQty); } else { plan.EconomicLotSize = plan.PlanProductQty; } plan.tenant_id = input.tenant_id; plan.factory_id = input.factory_id; plan.company_id = input.company_id; plan.org_id = input.org_id; plan.create_time = DateTime.Now; plan.OrderNum = item.OrderNum; productionMasters.Add(plan); } else { new NLogHelper("AnnualProductionOutlineAppService").WriteLog("SaveProductionMasterPlan", "【" + input.year + "年" + "】主计划找不到发货计划物料:" + item.SAPItemNumber, _currentTenant.Id.ToString()); } } //保存数据 using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { var planList = productionMasters.Select(a => a.PlanMonth).ToList(); await _productionMasterPlan.DeleteAsync(a => planList.Contains(a.PlanMonth) && a.factory_id == input.factory_id); await _businessDbContext.BulkInsertAsync(productionMasters); 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"; } /// /// 获取物料在制数量 /// /// /// /// public List GetInProdcutQty(List itemNumbers, InputDto input) { List itemQty = new List(); DateTime startYear = new DateTime(DateTime.Now.AddYears(-1).Year, 1, 1); DateTime endYear = new DateTime(DateTime.Now.Year, 12, 31); List 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 dictInProduction = new Dictionary(); //按照工单循环 //某工单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); } } itemNumbers.ForEach(a => { EOPDto eOP = new EOPDto(); eOP.ItemNumber = a; eOP.Qty = 0; if (dictInProduction.ContainsKey(a)) eOP.Qty = dictInProduction[a]; itemQty.Add(eOP); }); return itemQty; } /// /// 更新年度生产大纲 /// /// /// /// public async Task DemandAnalysis(InputDto input) { string productResult = await SaveAnnualProductionOutline(input); if (productResult != "OK") return productResult; return "OK|刷新成功!"; } /// /// 调整成品ROP和最高库存水位 /// /// /// public async Task CalcROP(InputDto input) { //var IsActived = _AccountValidityAppService.IsActived(); //if (!IsActived) //{ // return "此账号已限制访问"; //} //来自定时任务的请求 if (input.year == 0 && input.month == 0) { input.year = DateTime.Now.Year; input.month = DateTime.Now.Month; } //1.获取补货模型全局参数 ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString()); List addList = new List(); List updateList = new List();//更新上一个月的实际出库数量 //获取存货周转率设置 var turnOverlist = _ReplenishmentTurnOverSet.GetListAsync(a => a.factory_id == input.factory_id).Result; //获取补货模型前H周期和未来F个周期的数据 List planMonthList = new List(); for (int j = -replenishmentDto.HistoryOutStockMonth; j < replenishmentDto.SaleFcstMonth; j++) { string itemMonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}"; planMonthList.Add(itemMonth); } var planList = new List(); foreach (var itemMonth in planMonthList) { var annualProductionMonth = _monthlyShipmentPlan.Select(x => itemMonth == x.PlanMonth && !x.IsDeleted && x.factory_id == input.factory_id).OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList(); if (annualProductionMonth != null && annualProductionMonth.Count > 0) { planList.AddRange(annualProductionMonth); } else { var MaxVersion = _monthlyShipmentPlanHistory.Select(a => a.factory_id == input.factory_id && !a.IsDeleted).Max(b => b.VERSION); if (!string.IsNullOrEmpty(MaxVersion)) { var annualProductionMonthHistory = _monthlyShipmentPlanHistory.Select(x => itemMonth == x.PlanMonth && x.VERSION == MaxVersion && !x.IsDeleted && x.factory_id == input.factory_id).OrderByDescending(v => v.VERSION).ThenBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList(); if (annualProductionMonthHistory != null && annualProductionMonthHistory.Count > 0) { var returnlist = ObjectMapper.Map, List>(annualProductionMonthHistory); planList.AddRange(returnlist); } } } } planList = planList.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList(); //获取BOM用于分解到原材料 var boms = _ic_bom.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Distinct().ToList().Contains(a.item_number) && a.factory_id == input.factory_id).Result; var planItemList = planList.Select(a => a.SAPItemNumber).Distinct().ToList(); var bomItemList = boms.Select(a => a.item_number).Distinct().ToList(); var expectedList = planItemList.Except(bomItemList).ToList(); if (expectedList.Count > 0) { throw new NotImplementedException("月度发货计划物料" + string.Join(",", expectedList) + "没有维护BOM!"); } var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; List autoCreates = new List(); boms.ForEach(p => { if (!pretreatments.Where(s => s.sourceid == p.mysql_id).Any()) { autoCreates.Add(p); } }); if (autoCreates.Any()) { AutoCreateBomBill(input.company_id.ToString(), autoCreates); pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; } var mesItemList = _itemMaster.Select(a => pretreatments.Select(p => p.item_number).Contains(a.ItemNum) && a.Domain == input.factory_id.ToString() && a.IsActive); var itemProductList = _mysql_ic_item.GetListAsync(a => pretreatments.Select(p => p.item_number).Contains(a.number) && !a.IsDeleted && a.factory_id == input.factory_id).Result; var itemList = itemProductList.Select(a => a.number).ToList(); var srm_purchaseList = _srmPurchase.GetListAsync(a => pretreatments.Select(p => p.item_number).Contains(a.number) && !a.IsDeleted).Result; var ropModelList = _replenishmentROPWeekPlan.GetListAsync(a => itemList.Contains(a.number) && planMonthList.Contains(a.planmonth) && a.factory_id == input.factory_id).Result; //获取成品库存、灭菌库存、在制库存(会从SAP同步的库存表更新到LocationDetail、ic_item表中) var locations = _invMaster.Select(p => p.Domain == input.factory_id.ToString() && itemList.Contains(p.ItemNum) && p.IsActive); //国科海王只有成品 var DMSItemList = _DMS_IN_ITEMMAPPING.Select(a => planList.Select(p => p.SAPItemNumber).ToList().Contains(a.CfnERPCode)); var gkhwStock = _DMS_IN_LOCDETAIL.Select(a => (a.DealerCode == "RQ000005" || a.DealerCode == "RQ000002")); decimal? InProductionQty = 0.00m; //获取在制数量 获取工单数取每年4月到12月底的工单 DateTime startYear = new DateTime(DateTime.Now.Year, 1, 1); DateTime endYear = new DateTime(DateTime.Now.Year, 12, 31); List workOrdRoutings = _workOrdRouting.Select(x => x.IsActive && x.QtyComplete > 0 && x.Domain == input.factory_id.ToString()).Where(p => p.DueDate >= startYear && p.DueDate <= endYear).ToList(); var workOrds = workOrdRoutings.GroupBy(x => x.WorkOrd).ToList(); Dictionary dictItemStock = new Dictionary(); //按照工单循环 //某工单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 (dictItemStock.ContainsKey(MaxOp.ItemNum)) { dictItemStock[MaxOp.ItemNum] += InProductionQty.Value; } else { dictItemStock.Add(MaxOp.ItemNum, InProductionQty.Value); } } foreach (var item in locations) { //库存合计 + 在制 + 灭菌中 (InvMaster没有过滤灭菌中状态可能已经算在可用库存中了) //5008成品线边库,8001成品合格库,8000成品待检 if (item.Location == "5008" || item.Location == "5009" || item.Location == "5010" || item.Location == "8000" || item.Location == "8001" || item.Location == "8002" || item.Location == "8003" || item.Location == "8004" || item.Location == "8005") { if (dictItemStock.ContainsKey(item.ItemNum)) { dictItemStock[item.ItemNum] += (item.AvailStatusQty.GetValueOrDefault() + item.Assay.GetValueOrDefault()); } else { dictItemStock.Add(item.ItemNum, (item.AvailStatusQty.GetValueOrDefault() + item.Assay.GetValueOrDefault())); } } } foreach (var item in itemList) { if (!dictItemStock.ContainsKey(item)) { dictItemStock.Add(item, 0); } } //取过去6个月成品发货出库记录 var dateBegin = DateTime.Now.AddMonths(-6); var datePreBegin = DateTime.Now.AddMonths(-1); var dateEnd = DateTime.Now; //获取瑞奇发往国科海王的记录 var gkhwList = _ASNBOLShipperMaster.Select(a => a.Domain == input.factory_id.ToString() && (a.SoldTo == "10002080" || a.SoldTo == "10001981")); var recidList = gkhwList.Select(a => Convert.ToInt64(a.RecID)).ToList(); //获取瑞奇发货记录 var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && itemList.Contains(a.ContainerItem) && a.ShipDate >= dateBegin && a.ShipDate <= dateEnd && !recidList.Contains(a.ASNBOLShipperRecID));//瑞奇只算瑞奇排除国科海王 //获取瑞奇上月发货记录 var shipMList = shipList.Where(a => a.ShipDate >= datePreBegin && a.ShipDate <= dateEnd).ToList();//瑞奇只算瑞奇排除国科海王 //获取国科海王发货记录 var gkItemList = planList.Where(p => p.DistributionChannel == "国科").Select(p => p.SAPItemNumber).ToList(); var DMSItemListGK = _DMS_IN_ITEMMAPPING.Select(a => gkItemList.Contains(a.CfnERPCode)); var shipListGK = _DMS_IN_SHIPPINGDETAIL.Select(a => DMSItemListGK.Select(g => g.CfnCode).Contains(a.UPN) && a.ParentDealerCode == "RQ000005" && a.ShipmentDate >= DateOnly.FromDateTime(dateBegin) && a.ShipmentDate <= DateOnly.FromDateTime(dateEnd));//国科 var hwItemList = planList.Where(p => p.DistributionChannel == "海王").Select(p => p.SAPItemNumber).ToList(); var DMSItemListHW = _DMS_IN_ITEMMAPPING.Select(a => hwItemList.Contains(a.CfnERPCode)); var shipListHW = _DMS_IN_SHIPPINGDETAIL.Select(a => DMSItemListHW.Select(g => g.CfnCode).Contains(a.UPN) && a.ParentDealerCode == "RQ000002" && a.ShipmentDate >= DateOnly.FromDateTime(dateBegin) && a.ShipmentDate <= DateOnly.FromDateTime(dateEnd));//海王 //领料出库记录 var pickbilllist = _invTransHist.Select(a => a.Domain == input.factory_id.ToString() && a.TransType == "iss-wo" && a.IsActive && a.CreateTime >= dateBegin && itemList.Contains(a.ItemNum)); //出库记录 var invTransHists = _invTransHist.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.CreateTime >= dateBegin && itemList.Contains(a.ItemNum) && a.QtyChange<0); //对账单,取对账日期最新的数据 string sqldzd = @"SELECT ItemNum,NETPR FROM (SELECT MATNR AS ItemNum,NETPR,ROW_NUMBER() OVER (PARTITION BY MATNR ORDER BY BUDAT DESC) AS rn FROM SupplierStatement ) as SupplierStatement WHERE rn = 1"; var supplierStatementDtos = _businessDbContext.SupplierStatementDto.FromSqlRaw(sqldzd).ToList(); List replenishmentROPWeekPlanDtos = GetRopAmount(itemList.Distinct().ToList(), supplierStatementDtos, invTransHists,input); var gkCNCCodeList = DMSItemListGK.Select(g => g.CfnCode).ToList(); var dateOnlyCurrent = DateOnly.FromDateTime(datePreBegin); var dateOnlyNow = DateOnly.FromDateTime(dateEnd); var shipMListGK = _DMS_IN_SHIPPINGDETAIL.Select(a => gkCNCCodeList.Contains(a.UPN) && a.ParentDealerCode == "RQ000005" && a.ShipmentDate >= dateOnlyCurrent && a.ShipmentDate <= dateOnlyNow);//国科 var hwCNCCodeList = DMSItemListHW.Select(g => g.CfnCode).ToList(); var shipMListHW = _DMS_IN_SHIPPINGDETAIL.Select(a => hwCNCCodeList.Contains(a.UPN) && a.ParentDealerCode == "RQ000002" && a.ShipmentDate >= dateOnlyCurrent && a.ShipmentDate <= dateOnlyNow);//海王 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(); var itemGroupGK = shipListGK.GroupBy(p => p.UPN) .Select(p => new ASNBOLShipperDetail { QtyToShip = p.Sum(a => a.Qty), ContainerItem = p.Key }).ToList(); var itemMGroupGK = shipMListGK.GroupBy(p => p.UPN) .Select(p => new ASNBOLShipperDetail { QtyToShip = p.Sum(a => a.Qty), ContainerItem = p.Key }).ToList(); var itemGroupHW = shipListHW.GroupBy(p => p.UPN) .Select(p => new ASNBOLShipperDetail { QtyToShip = p.Sum(a => a.Qty), ContainerItem = p.Key }).ToList(); var itemMGroupHW = shipMListHW.GroupBy(p => p.UPN) .Select(p => new ASNBOLShipperDetail { QtyToShip = p.Sum(a => a.Qty), ContainerItem = p.Key }).ToList(); var mathtool = new MathNet.Numerics.Distributions.Normal(); //更新上个月计划发货数据为实际出库数据(先算成品,原材料后面单独计算) Dictionary preMonthRQQty = new Dictionary(); ropModelList?.Where(r => r.year == DateTime.Now.AddMonths(-1).Year && r.month == DateTime.Now.AddMonths(-1).Month).ToList()?.ForEach (m => { //只更新成品 if (planList.Any(a => a.SAPItemNumber == m.number)) { if (m.distributionchannel == "瑞奇") { if (!preMonthRQQty.ContainsKey(m.number)) { preMonthRQQty.Add(m.number, m.plan_out_qty); } //成品算销售出库数量 if (itemGroup.Any(a => a.ContainerItem == m.number)) { m.plan_out_qty = itemGroup.Find(a => a.ContainerItem == m.number)?.QtyToShip; updateList.Add(m); preMonthRQQty[m.number] = m.plan_out_qty; } } else if (m.distributionchannel == "国科") { if (itemGroupGK.Any(a => a.ContainerItem == m.number)) { m.plan_out_qty = itemGroupGK.Find(a => a.ContainerItem == m.number)?.QtyToShip; updateList.Add(m); } } else if (m.distributionchannel == "海王") { if (itemGroupHW.Any(a => a.ContainerItem == m.number)) { m.plan_out_qty = itemGroupHW.Find(a => a.ContainerItem == m.number)?.QtyToShip; updateList.Add(m); } } } }); //更新瑞奇原材料上个月出库次数(按照BOM展开合计汇总) string planPreMonth = $"{DateTime.Now.AddMonths(-1).Year}-{DateTime.Now.AddMonths(-1).Month.ToString("00")}"; List subItem = new List(); planList.Where(a => a.DistributionChannel == "瑞奇" && a.PlanMonth == planPreMonth).ToList().ForEach(a => { var planBOM = boms.Find(b => b.item_number == a.SAPItemNumber); if (planBOM == null) { new NLogHelper("CalcROP").WriteLog("CalcROP", "CalcROP数据错误:" + a.SAPItemNumber + "不在BOM里", _currentTenant.Id.ToString()); } else { var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); var returnlist = ObjectMapper.Map, List>(pretreament); returnlist = returnlist.OrderBy(s => s.num_order).ToList(); var level1Dto = returnlist[0]; if (preMonthRQQty.ContainsKey(a.SAPItemNumber)) { level1Dto.needCount = preMonthRQQty[a.SAPItemNumber].GetValueOrDefault(); } else { level1Dto.needCount = a.Qty; } CaclMaterialShortage(returnlist); foreach (var item in returnlist) { if (item.item_number != a.SAPItemNumber) { if (subItem.Any(s => s.ItemNumber == item.item_number && s.PlanMonth == planPreMonth)) { subItem.Find(s => s.ItemNumber == item.item_number && s.PlanMonth == planPreMonth).Qty += item.needCount; } else { subItem.Add(new ReplenishmentSubItemDto { ItemNumber = item.item_number, Qty = item.needCount, PlanMonth = planPreMonth }); } } } } }); ropModelList?.Where(r => r.year == DateTime.Now.AddMonths(-1).Year && r.month == DateTime.Now.AddMonths(-1).Month && r.distributionchannel == "瑞奇").ToList()?.ForEach (m => { //只更新原材料 if (!planList.Any(a => a.SAPItemNumber == m.number) && subItem.Any(s => s.ItemNumber == m.number && s.PlanMonth == planPreMonth)) { m.plan_out_qty = subItem.Find(s => s.ItemNumber == m.number && s.PlanMonth == planPreMonth).Qty; updateList.Add(m); } }); var RQShipPlanList = planList.FindAll(s => s.DistributionChannel == "瑞奇"); List 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")}"; //先计算成品 planList?.Where(s => s.PlanMonth == itemMonth).ToList()?.ForEach(a => { var icItem = itemProductList.Find(p => p.number == a.SAPItemNumber); if (icItem != null) { bool isExist = ropModelList.Find(r => r.planmonth == itemMonth && r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel) == null ? false : true; var rop = new ReplenishmentROPWeekPlan(); if (isExist) { rop = ropModelList.Find(r => r.planmonth == itemMonth && r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel); } rop.number = a.SAPItemNumber; 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.distributionchannel = a.DistributionChannel; rop.lifecycle = a.LifeCycle; rop.area = a.Area; rop.plan_out_qty = Math.Ceiling(a.Qty); if (planList.Where(i => i.SAPItemNumber == a.SAPItemNumber && i.DistributionChannel == a.DistributionChannel).Count() > 0) { rop.monthl_avg_demand = planList.Where(i => i.SAPItemNumber == a.SAPItemNumber && i.DistributionChannel == a.DistributionChannel).Average(a => a.Qty); var nums = planList.Where(i => i.SAPItemNumber == a.SAPItemNumber && i.DistributionChannel == a.DistributionChannel).Select(a => a.Qty); if (nums.Count() <= 1) { rop.monthl_avg_demand_variance = 0; } else { rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(Math.Sqrt(nums.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(rop.monthl_avg_demand), 2)) / (nums.Count() - 1)))); } } else { rop.monthl_avg_demand = 0; rop.monthl_avg_demand_variance = 0; } //计算月均出库 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 (k < 0) { if (ropModelList.Find(z => z.planmonth == itemMonth && z.number == a.SAPItemNumber && z.distributionchannel == a.DistributionChannel) != null) { SumOutQty += ropModelList.Find(z => z.planmonth == itemMonth && z.number == a.SAPItemNumber && z.distributionchannel == a.DistributionChannel).plan_out_qty.GetValueOrDefault(); MonthCount++; } } else { if (planList.Find(z => z.PlanMonth == itemMonth && z.SAPItemNumber == a.SAPItemNumber && z.DistributionChannel == a.DistributionChannel) != null) { SumOutQty += planList.Find(z => z.PlanMonth == itemMonth && z.SAPItemNumber == a.SAPItemNumber && z.DistributionChannel == a.DistributionChannel).Qty; MonthCount++; } } } if (MonthCount == 0) { rop.monthl_avg_outstock = 0; } else { rop.monthl_avg_outstock = Math.Ceiling(SumOutQty / MonthCount); } 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 (turnOverlist.Find(t => t.Model == rop.model) != null) { rop.stock_turnover = turnOverlist.Find(t => t.Model == rop.model).RQTurnOver; } else if (turnOverlist.Find(t => t.ProdRange == a.ProdRange) != null) { rop.stock_turnover = turnOverlist.Find(t => t.ProdRange == a.ProdRange).RQTurnOver; } else if (turnOverlist.Find(t => t.ProdLine == a.ProdLine) != null) { rop.stock_turnover = turnOverlist.Find(t => t.ProdLine == a.ProdLine).RQTurnOver; } else if (mesItemList.Find(s => s.ItemNum == a.SAPItemNumber) != null) { rop.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber).StockTurnOver; } else { rop.stock_turnover = 4; } CalcFMRAndABC(rop, replenishmentDto, shipList, pickbilllist,replenishmentROPWeekPlanDtos, 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(months: j).Month)); rop.rop_computed = rop.security_stock + rop.eop; rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover); //瑞奇是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); } //存在上一个月补货 if (updateList.Find(r => r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel && 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.distributionchannel == a.DistributionChannel && 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.distributionchannel == a.DistributionChannel && 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.distributionchannel == a.DistributionChannel && 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 (a.DistributionChannel == "海王") { if (DMSItemList.Find(d => d.CfnERPCode == rop.number) != null) { var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == rop.number).CfnCode && o.DealerCode == "RQ000002").ToList(); if (itemDMS.Count > 0) { var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First(); rop.avaStockQty = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty); } } } else if (a.DistributionChannel == "国科") { if (DMSItemList.Find(d => d.CfnERPCode == rop.number) != null) { var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == rop.number).CfnCode && o.DealerCode == "RQ000005").ToList(); if (itemDMS.Count > 0) { var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First(); rop.avaStockQty = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty); } } } else { rop.avaStockQty = dictItemStock[a.SAPItemNumber]; } } 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); } } }); //计算原材料 List subItemRQ = subItemRQList.FindAll(a => a.PlanMonth == itemMonth); foreach (var d in subItemRQ) { var icItem = itemProductList.Find(s => s.number == d.ItemNumber); if (icItem != null && !planList.Select(r => r.SAPItemNumber).ToList().Contains(d.ItemNumber)) { bool isExist = ropModelList.Find(r => r.planmonth == itemMonth && r.number == d.ItemNumber && r.distributionchannel == "瑞奇") == null ? false : true; var rop = new ReplenishmentROPWeekPlan(); if (isExist) { 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.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.stock_turnover == 0) rop.stock_turnover = 4; CalcFMRAndABC(rop, replenishmentDto, shipList, pickbilllist,replenishmentROPWeekPlanDtos, 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和最高库存值两者之间取较小的值,平台是取较大的值。 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 _businessDbContext.BulkInsertAsync(addList); await _businessDbContext.BulkUpdateAsync(updateList); return "OK"; } private List CalcMonthPlanSubItem(List planList, List boms, List pretreatments) { List subItemRQ = new List(); planList?.ForEach(r => { var planBOM = boms.Find(b => b.item_number == r.SAPItemNumber); if (planBOM == null) { new NLogHelper("CalcROP").WriteLog("CalcROP", "CalcROP数据错误:" + r.SAPItemNumber + "不在BOM里", _currentTenant.Id.ToString()); } else { var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); var returnlist = ObjectMapper.Map, List>(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 != r.SAPItemNumber) { var isExist = subItemRQ.Find(s => s.ItemNumber == item.item_number && s.PlanMonth == r.PlanMonth); if (isExist != null) { isExist.Qty += item.needCount; } else { subItemRQ.Add(new ReplenishmentSubItemDto { ItemNumber = item.item_number, Qty = item.needCount, PlanMonth = r.PlanMonth }); } } } } }); return subItemRQ; } //计算原材料月均需求和方差 public void CalcSubItem(List 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) { SumOutQty += subItemRQ.Find(z => z.PlanMonth == itemMonth && z.ItemNumber == ItemNum).Qty; MonthCount++; } } decimal avaRequire = 0; rop.monthl_avg_demand = 0; rop.monthl_avg_demand_variance = 0; if (MonthCount > 0) { avaRequire = Math.Ceiling(SumOutQty / MonthCount); rop.monthl_avg_demand = avaRequire; } if (MonthCount > 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)))); } } /// /// 平铺计算物料情况 /// /// /// /// public void CaclMaterialShortage(List returnlist) { foreach (var item in returnlist) { if (item.level == 1) { continue; } //循环平铺整个资源检查的物料库存情况、缺料情况,子集缺料需要用父级缺料*子集使用数量- var parent = returnlist.Find(s => s.fid == item.parent_id); //当前物料总共需要数量 item.needCount = Math.Ceiling(parent.needCount * item.qty * (1 + (item.scrap.GetValueOrDefault() / 100)) + item.wastage.GetValueOrDefault()); item.needCountNoloss = parent.needCount * item.qty; } } /// /// 根据月度计划生成周计划 /// /// /// public async Task CalcWeekPlan(InputDto input) { //var IsActived = _AccountValidityAppService.IsActived(); //if (!IsActived) //{ // return "此账号已限制访问"; //} //1.获取补货模型全局参数 ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString()); //发货计划列表,用于判断成品物料编码 //获取补货模型前H周期和未来F个周期的数据 List planMonthList = new List(); for (int j = -replenishmentDto.HistoryOutStockMonth; j < replenishmentDto.SaleFcstMonth + 1; j++) { string itemMonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}"; planMonthList.Add(itemMonth); } var shipPlanList = new List(); foreach (var itemMonth in planMonthList) { var annualProductionMonth = _monthlyShipmentPlan.Select(x => itemMonth == x.PlanMonth && !x.IsDeleted && x.factory_id == input.factory_id).OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList(); if (annualProductionMonth != null && annualProductionMonth.Count > 0) { shipPlanList.AddRange(annualProductionMonth); } else { var MaxVersion = _monthlyShipmentPlanHistory.Select(a => a.factory_id == input.factory_id && !a.IsDeleted).Max(b => b.VERSION); if (!string.IsNullOrEmpty(MaxVersion)) { var annualProductionMonthHistory = _monthlyShipmentPlanHistory.Select(x => itemMonth == x.PlanMonth && x.VERSION == MaxVersion && !x.IsDeleted && x.factory_id == input.factory_id).OrderByDescending(v => v.VERSION).ThenBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList(); if (annualProductionMonthHistory != null && annualProductionMonthHistory.Count > 0) { var returnlist = ObjectMapper.Map, List>(annualProductionMonthHistory); shipPlanList.AddRange(returnlist); } } } } shipPlanList = shipPlanList.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList(); //滚动三个月12周的周计划,已经发布的周计划不改(TODO:删除未来未发布的周计划和工单(是否影响资源检查)) //最小经济批量 var weekPlanDelete = _replenishmentWeekPlan.GetListAsync(a => planMonthList.Contains(a.PlanMonth) && a.ProductionStatus != "已发布" && a.IsReplenishmentModel == "N" && a.factory_id == input.factory_id).Result; var workOrderDelete = weekPlanDelete.Select(b => b.ProductionOrder).ToList(); _workOrdMaster.Delete(a => workOrderDelete.Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString()); _workOrdRouting.Delete(a => workOrderDelete.Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString()); _workOrdDetail.Delete(a => workOrderDelete.Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString()); var deletedOrderList = _mysql_mes_morder.GetListAsync(a => workOrderDelete.Contains(a.morder_no) && a.factory_id == input.factory_id).Result; var deletedIds = deletedOrderList.Select(a => a.Id).ToList(); await _mysql_mes_morder.HardDeleteAsync(deletedOrderList); var deletedEntryList = _mysql_mes_moentry.GetListAsync(a => workOrderDelete.Contains(a.moentry_mono) && a.factory_id == input.factory_id).Result; await _mysql_mes_moentry.HardDeleteAsync(deletedEntryList); var examine_result = _mysql_examine_result.GetListAsync(a => workOrderDelete.Contains(a.morder_no) && a.factory_id == input.factory_id).Result; List occupy = await _mysql_srm_po_occupy.GetListAsync(s => workOrderDelete.Contains(s.morder_mo)); _businessDbContext.BulkDelete(occupy); //清理工单占用 List mooccupy = await _mysql_mes_mooccupy.GetListAsync(s => deletedIds.Contains(s.moo_id.GetValueOrDefault())); if (mooccupy.Any()) { _businessDbContext.BulkDelete(mooccupy); } //清理掉库存占用 var itemstockoccupy = _mysql_ic_item_stockoccupy.GetListAsync(s => workOrderDelete.Contains(s.morder_mo)).Result; if (itemstockoccupy.Any()) { _businessDbContext.BulkDelete(itemstockoccupy); } await _mysql_bom_child_examine.HardDeleteAsync(a => examine_result.Select(b => b.Id).ToList().Contains(a.examine_id.Value) && a.factory_id == input.factory_id); await _mysql_examine_result.HardDeleteAsync(examine_result); await _replenishmentWeekPlan.HardDeleteAsync(weekPlanDelete); //月度补货模型 var planList = _replenishmentROPWeekPlan.GetListAsync(a => planMonthList.Contains(a.planmonth) && !a.IsDeleted && a.factory_id == input.factory_id).Result; //周补货计划 var weekPlanList = _replenishmentWeekPlan.GetListAsync(a => planMonthList.Contains(a.PlanMonth) && !a.IsDeleted && a.factory_id == input.factory_id && a.IsReplenishmentModel == "Y").Result; //周生产计划 var weekProductPlanList = _replenishmentWeekPlan.GetListAsync(a => planMonthList.Contains(a.PlanMonth) && !a.IsDeleted && a.factory_id == input.factory_id && a.IsReplenishmentModel == "N").Result; //发货计划物料列表 List planItemList = shipPlanList?.Select(a => a.SAPItemNumber).Distinct().ToList(); var itemList = _mysql_ic_item.GetListAsync(a => planItemList.Contains(a.number) && !a.IsDeleted).Result; var bomList = _mysql_ic_bom.GetListAsync(a => planItemList.Contains(a.item_number) && !a.IsDeleted && a.factory_id == input.factory_id).Result; var monthPlan = _productionMasterPlan.GetListAsync(a => planItemList.Contains(a.ItemNumber) && !a.IsDeleted && a.factory_id == input.factory_id).Result; long bang_id = help.NextId(); //获取BOM用于分解到原材料 var boms = _ic_bom.GetListAsync(a => planItemList.Contains(a.item_number) && a.factory_id == input.factory_id).Result; var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; List autoCreates = new List(); boms.ForEach(p => { if (!pretreatments.Where(s => s.sourceid == p.mysql_id).Any()) { autoCreates.Add(p); } }); if (autoCreates.Any()) { AutoCreateBomBill(input.company_id.ToString(), autoCreates); pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; } routingOps = _routingOpDetail.Select(p => p.Domain == input.factory_id.ToString()).ToList(); //更新周补货计划 List updateRopList = new List(); List addRopList = new List(); //生成12周补货计划 for (int k = 0; k < 12; k++) { var weekPlanTime = GetNextMonday(); weekPlanTime = weekPlanTime.AddDays(7 * k); string kMonth = $"{weekPlanTime.Year}-{weekPlanTime.Month.ToString("00")}"; //如果该10月有发布的2周生产计划,则周补货量=10月补货量-已发布的2周生产计划数量/剩余周次(2) //周补货计划只计算成品,不需要到原材料 var monthWeekPlan = planList.Where(a => a.planmonth == kMonth && planItemList.Contains(a.number)).ToList(); foreach (var item in monthWeekPlan) { int publishedWeekCount = weekProductPlanList.Where(a => a.PlanMonth == kMonth && a.ItemNumber == item.number && a.ProductionStatus == "已发布" && a.DistributionChannel == item.distributionchannel).Count(); decimal publishedWeekQtySum = weekProductPlanList.Where(a => a.PlanMonth == kMonth && a.ItemNumber == item.number && a.ProductionStatus == "已发布" && a.DistributionChannel == item.distributionchannel).Sum(a => a.Qty); var weekItemPlan = weekPlanList.Find(a => a.PlanMonth == kMonth && a.ItemNumber == item.number && a.WeekSeq == WeekOfMonth(weekPlanTime, 1) && a.DistributionChannel == item.distributionchannel); if (publishedWeekCount < 4) { if (weekItemPlan != null) { weekItemPlan.Qty = Math.Ceiling((item.montheop1.GetValueOrDefault() + item.montheop2.GetValueOrDefault() - publishedWeekQtySum) / (4 - publishedWeekCount)); updateRopList.Add(weekItemPlan); } else { ReplenishmentWeekPlan weekItemPlanAdd = new ReplenishmentWeekPlan(); weekItemPlanAdd.Area = item.area; weekItemPlanAdd.Week = $"WK{GetWeekOfYear(weekPlanTime).ToString("00")}"; weekItemPlanAdd.DistributionChannel = item.distributionchannel; weekItemPlanAdd.ProdLine = item.ProdLine; weekItemPlanAdd.ProdRange = item.ProdRange; weekItemPlanAdd.Model = item.model; weekItemPlanAdd.ItemNumber = item.number; weekItemPlanAdd.Languages = item.Languages; weekItemPlanAdd.Qty = Math.Ceiling((item.montheop1.GetValueOrDefault() + item.montheop2.GetValueOrDefault() - publishedWeekQtySum) / (4 - publishedWeekCount)); weekItemPlanAdd.Year = weekPlanTime.Year; weekItemPlanAdd.Month = weekPlanTime.Month; weekItemPlanAdd.PlanMonth = $"{weekPlanTime.Year}-{weekPlanTime.Month.ToString("00")}"; ; weekItemPlanAdd.WeekSeq = WeekOfMonth(weekPlanTime, 1); weekItemPlanAdd.tenant_id = input.tenant_id; weekItemPlanAdd.company_id = input.company_id; weekItemPlanAdd.factory_id = input.factory_id; weekItemPlanAdd.create_time = DateTime.Now; weekItemPlanAdd.org_id = input.org_id; weekItemPlanAdd.ItemStatus = ""; weekItemPlanAdd.IsReplenishmentModel = "Y"; addRopList.Add(weekItemPlanAdd); } } } } await _businessDbContext.BulkInsertAsync(addRopList); await _businessDbContext.BulkUpdateAsync(updateRopList); //更新周生产计划 //生产线明细表 List prodLines = new List(); List lineMasters = new List(); var routingOpList = _routingOpDetail.Select(x => x.Ufld1 == "组装" && x.MilestoneOp).ToList(); //生成12周计划工单 //中间件汇总,比如A成品10、11、12月都需要中间件C,B成品11、12月都需要中间件C,那么中间件C需要每个月汇总平均分到4周 Dictionary subProductItem = new Dictionary(); Dictionary subProductItemModel = new Dictionary(); var ropList = planList.Where(t => shipPlanList.Select(s => s.SAPItemNumber).Distinct().ToList().Contains(t.number)).Select(t => t.number).Distinct().ToList(); var itemMasterList = _itemMaster.Select(t => ropList.Contains(t.ItemNum) && t.Domain == input.factory_id.ToString()); Dictionary minordsalesQty = new Dictionary(); List moList = new List(); List moentryList = new List(); List weekPlan = new List(); for (int k = 0; k < 12; k++) { var weekTime = GetNextMonday().AddDays(28);//增加四周 weekTime = weekTime.AddDays(7 * k); string kMonth = $"{weekTime.Year}-{weekTime.Month.ToString("00")}"; var monthWeekPlan = planList.Where(a => a.planmonth == kMonth).ToList(); foreach (var itemSeq in ropList) { var monthPlanItem = monthPlan.Find(x => x.ItemNumber == itemSeq); //瑞奇国科海王 var monthPlanTotal = monthWeekPlan.Where(x => x.number == itemSeq).ToList(); if (monthPlanTotal != null && monthPlanTotal.Count > 0) { var item = monthPlanTotal[0]; //瑞奇补货计划!Y5 + 瑞奇补货计划!Z5 + 国科补货计划!Y5 + 国科补货计划!Z5 + 海王补货计划!Y4 + 海王补货计划!Z4 var itemQty = monthPlanTotal.Sum(a => a.montheop1) + monthPlanTotal.Sum(a => a.montheop2); int days = 15; if (item.area != "国内" && item.area != "中国") { days = 8; } if (itemQty <= 0) itemQty = 0; //四周数量合并,完工日期取第三周的时间 if (k <= 3) { var MonthMo = moList.Find(a => a.product_code == itemSeq && ( a.moentry_sys_etime == GetNextMonday().AddDays(28).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 7).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 14).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 21).AddDays(-days))); if (MonthMo != null) { MonthMo.morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); MonthMo.need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); MonthMo.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-ProductTime(routingOps, MonthMo.product_code, input.factory_id.ToString(), MonthMo.need_number.GetValueOrDefault()) - days); MonthMo.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-days); moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanStartDate = MonthMo.moentry_sys_stime; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Week = $"WK{GetWeekOfYear(MonthMo.moentry_sys_stime.Value).ToString("00")}"; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Qty = MonthMo.morder_production_number.Value; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Year = GetNextMonday().AddDays(28).AddDays(14).Year; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Month = GetNextMonday().AddDays(28).AddDays(14).Month; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(14), 1); weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(14).Year}-{GetNextMonday().AddDays(28).AddDays(14).Month.ToString("00")}"; if (item.area == "国内" || item.area == "中国") { weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days); } else { weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days); } } else { var bom = bomList.Find(b => b.item_number == itemSeq); var ic_item = itemList.Find(b => b.number == itemSeq); mes_morder mes_Morder = new mes_morder(); mes_Morder.GenerateNewId(help.NextId()); mes_Morder.morder_type = MorderEnum.JhMorder; mes_Morder.work_order_type = MorderEnum.CgMorder; mes_Morder.morder_state = ""; mes_Morder.morder_no = Guid.NewGuid().ToString(); mes_Morder.fms_number = ic_item.fms_number; mes_Morder.bom_number = bom.bom_number; mes_Morder.fmodel = ic_item.model; 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.morder_date = DateTime.Now.Date.AddDays(1); 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; mes_Morder.unit = ic_item.unit; mes_Morder.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); mes_Morder.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); //成品半成品取周一为入库时间开始往前推 mes_Morder.moentry_sys_stime = weekTime.AddDays(-ProductTime(routingOps, ic_item.number, input.factory_id.ToString(), mes_Morder.need_number.GetValueOrDefault()) - days); mes_Morder.moentry_sys_etime = weekTime.AddDays(-days); 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 = ic_item.unit; mes_Moentry.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); mes_Moentry.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); 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; ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan(); weekItem.Priority = 1; weekItem.Area = item.area; weekItem.PlanStartDate = mes_Morder.moentry_sys_stime.GetValueOrDefault(); weekItem.Week = $"WK{GetWeekOfYear(mes_Morder.moentry_sys_stime.Value).ToString("00")}"; weekItem.OrderNO = Guid.NewGuid().ToString(); weekItem.ProductionOrder = mes_Morder.morder_no; weekItem.SAPOrderNO = ""; weekItem.OrderType = "量产"; weekItem.ProductionBatch = ""; weekItem.ProductionStatus = ""; weekItem.ProdLine = item.ProdLine; weekItem.ProdRange = item.ProdRange; weekItem.Line = monthPlanItem?.WorkshopLine; weekItem.ItemNumber = item.number; weekItem.Model = item.model; weekItem.Languages = item.Languages; weekItem.Qty = mes_Morder.morder_production_number.Value; weekItem.ItemStatus = ""; weekItem.PlanKittingDate = DateTime.Now; weekItem.Year = weekTime.Year; weekItem.Month = weekTime.Month; weekItem.WeekSeq = WeekOfMonth(weekTime, 1); weekItem.PlanMonth = kMonth; weekItem.tenant_id = input.tenant_id; weekItem.factory_id = input.factory_id; weekItem.company_id = input.company_id; weekItem.org_id = input.org_id; weekItem.create_time = DateTime.Now; weekItem.DistributionChannel = item.distributionchannel; weekItem.IsReplenishmentModel = "N"; if (item.area == "国内" || item.area == "中国") { weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value; weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days); } else { weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value; weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days); } weekItem.AssembleHours = 0; weekItem.HeatSealHours = 0; weekItem.PackageHours = 0; weekItem.TotalHours = 0; //Q2023/11/15的需求同一周有相同物料的工单不继续生成,不考虑数量的偏差 if (!weekProductPlanList.Any(a => a.ItemNumber == item.number && a.Week == weekItem.Week)) { weekPlan.Add(weekItem); moList.Add(mes_Morder); moentryList.Add(mes_Moentry); } } if (k == 3) { var MonthMoTotal = moList.Find(a => a.product_code == itemSeq && ( a.moentry_sys_etime == GetNextMonday().AddDays(28).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 7).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 14).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 21).AddDays(-days))); if (MonthMoTotal != null) { if (MonthMoTotal.need_number > 0) { var itemMaster = itemMasterList.Find(i => i.ItemNum == itemSeq); if (itemMaster != null && itemMaster.MinOrd > 0) { //考虑生产批量的计算逻辑 decimal productQty; bool exist = minordsalesQty.TryGetValue(itemSeq, out productQty); if (exist) { //不需要生产 if (MonthMoTotal.need_number <= productQty) { minordsalesQty[itemSeq] -= MonthMoTotal.need_number.GetValueOrDefault(); moList.Remove(MonthMoTotal); moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no); weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no); } else { //需要生产但是小于生产批量按生产批量生产,大于生产批量不需要改动 if (MonthMoTotal.need_number - productQty < itemMaster.MinOrd) { decimal needProductQty = MonthMoTotal.need_number.GetValueOrDefault() - productQty; minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - needProductQty; MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days); MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-days); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}"; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(14).Year; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(14).Month; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(14), 1); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(14).Year}-{GetNextMonday().AddDays(28).AddDays(14).Month.ToString("00")}"; if (item.area == "国内" || item.area == "中国") { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } else { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } } } } else { if (MonthMoTotal.need_number < Math.Ceiling(itemMaster.MinOrd)) { minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - MonthMoTotal.need_number.Value; MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days); MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-days); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}"; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(14).Year; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(14).Month; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(14), 1); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(14).Year}-{GetNextMonday().AddDays(28).AddDays(14).Month.ToString("00")}"; if (item.area == "国内" || item.area == "中国") { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } else { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } } } var planBOM = boms.Find(b => b.item_number == itemSeq); var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); var returnlist = ObjectMapper.Map, List>(pretreament); returnlist = returnlist.OrderBy(s => s.num_order).ToList(); var level1Dto = returnlist[0]; level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault(); CaclMaterialShortage(returnlist); foreach (var r in returnlist) { if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number)) { if (subProductItem.ContainsKey(r.item_number)) { subProductItem[r.item_number] += r.needCount; } else { subProductItem.Add(r.item_number, r.needCount); subProductItemModel.Add(r.item_number, r); } } } } else { var planBOM = boms.Find(b => b.item_number == itemSeq); var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); var returnlist = ObjectMapper.Map, List>(pretreament); returnlist = returnlist.OrderBy(s => s.num_order).ToList(); var level1Dto = returnlist[0]; level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault(); CaclMaterialShortage(returnlist); foreach (var r in returnlist) { if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number)) { if (subProductItem.ContainsKey(r.item_number)) { subProductItem[r.item_number] += r.needCount; } else { subProductItem.Add(r.item_number, r.needCount); subProductItemModel.Add(r.item_number, r); } } } } } else { moList.Remove(MonthMoTotal); moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no); weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no); } } } } else if (k <= 7) { var MonthMo = moList.Find(a => a.product_code == itemSeq && ( a.moentry_sys_etime == GetNextMonday().AddDays(28 + 28).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 35).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 42).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 49).AddDays(-days))); if (MonthMo != null) { MonthMo.morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); MonthMo.need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); MonthMo.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-ProductTime(routingOps, MonthMo.product_code, input.factory_id.ToString(), MonthMo.need_number.GetValueOrDefault()) - days); MonthMo.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-days); moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanStartDate = MonthMo.moentry_sys_stime; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Week = $"WK{GetWeekOfYear(MonthMo.moentry_sys_stime.Value).ToString("00")}"; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Qty = MonthMo.morder_production_number.Value; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Year = GetNextMonday().AddDays(28).AddDays(42).Year; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Month = GetNextMonday().AddDays(28).AddDays(42).Month; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(42), 1); weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(42).Year}-{GetNextMonday().AddDays(28).AddDays(42).Month.ToString("00")}"; if (item.area == "国内" || item.area == "中国") { weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days); } else { weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days); } var planBOM = boms.Find(b => b.item_number == itemSeq); var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); var returnlist = ObjectMapper.Map, List>(pretreament); returnlist = returnlist.OrderBy(s => s.num_order).ToList(); var level1Dto = returnlist[0]; level1Dto.needCount = Math.Ceiling(itemQty.GetValueOrDefault() / 4); CaclMaterialShortage(returnlist); foreach (var r in returnlist) { if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number)) { if (subProductItem.ContainsKey(r.item_number)) { subProductItem[r.item_number] += r.needCount; } else { subProductItem.Add(r.item_number, r.needCount); subProductItemModel.Add(r.item_number, r); } } } } else { var bom = bomList.Find(b => b.item_number == itemSeq); var ic_item = itemList.Find(b => b.number == itemSeq); mes_morder mes_Morder = new mes_morder(); mes_Morder.GenerateNewId(help.NextId()); mes_Morder.morder_type = MorderEnum.JhMorder; mes_Morder.work_order_type = MorderEnum.CgMorder; mes_Morder.morder_state = ""; mes_Morder.morder_no = Guid.NewGuid().ToString(); mes_Morder.fms_number = ic_item.fms_number; mes_Morder.bom_number = bom.bom_number; mes_Morder.fmodel = ic_item.model; 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.morder_date = DateTime.Now.Date.AddDays(1); 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; mes_Morder.unit = ic_item.unit; mes_Morder.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); mes_Morder.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); //成品半成品取周一为入库时间开始往前推 mes_Morder.moentry_sys_stime = weekTime.AddDays(-ProductTime(routingOps, ic_item.number, input.factory_id.ToString(), mes_Morder.need_number.GetValueOrDefault()) - days); mes_Morder.moentry_sys_etime = weekTime.AddDays(-days); 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 = ic_item.unit; mes_Moentry.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ; mes_Moentry.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ; 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; ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan(); weekItem.Priority = 1; weekItem.Area = item.area; weekItem.PlanStartDate = mes_Morder.moentry_sys_stime.GetValueOrDefault(); weekItem.Week = $"WK{GetWeekOfYear(mes_Morder.moentry_sys_stime.Value).ToString("00")}"; weekItem.OrderNO = Guid.NewGuid().ToString(); weekItem.ProductionOrder = mes_Morder.morder_no; weekItem.SAPOrderNO = ""; weekItem.OrderType = "量产"; weekItem.ProductionBatch = ""; weekItem.ProductionStatus = ""; weekItem.ProdLine = item.ProdLine; weekItem.ProdRange = item.ProdRange; weekItem.Line = monthPlanItem?.WorkshopLine; weekItem.ItemNumber = item.number; weekItem.Model = item.model; weekItem.Languages = item.Languages; weekItem.Qty = mes_Morder.morder_production_number.Value; weekItem.ItemStatus = ""; weekItem.PlanKittingDate = DateTime.Now; weekItem.Year = weekTime.Year; weekItem.Month = weekTime.Month; weekItem.WeekSeq = WeekOfMonth(weekTime, 1); weekItem.PlanMonth = kMonth; weekItem.tenant_id = input.tenant_id; weekItem.factory_id = input.factory_id; weekItem.company_id = input.company_id; weekItem.org_id = input.org_id; weekItem.create_time = DateTime.Now; weekItem.DistributionChannel = item.distributionchannel; weekItem.IsReplenishmentModel = "N"; if (item.area == "国内" || item.area == "中国") { weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value; weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days); } else { weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value; weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days); } weekItem.AssembleHours = 0; weekItem.HeatSealHours = 0; weekItem.PackageHours = 0; weekItem.TotalHours = 0; //Q2023/11/15的需求同一周有相同物料的工单不继续生成,不考虑数量的偏差 if (!weekProductPlanList.Any(a => a.ItemNumber == item.number && a.Week == weekItem.Week)) { weekPlan.Add(weekItem); moList.Add(mes_Morder); moentryList.Add(mes_Moentry); } } if (k == 7) { var MonthMoTotal = moList.Find(a => a.product_code == itemSeq && ( a.moentry_sys_etime == GetNextMonday().AddDays(28 + 28).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 35).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 42).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 49).AddDays(-days))); if (MonthMoTotal != null) { if (MonthMoTotal.need_number > 0) { var itemMaster = itemMasterList.Find(i => i.ItemNum == itemSeq); if (itemMaster != null && itemMaster.MinOrd > 0) { //考虑生产批量的计算逻辑 decimal productQty; bool exist = minordsalesQty.TryGetValue(itemSeq, out productQty); if (exist) { //不需要生产 if (MonthMoTotal.need_number <= productQty) { minordsalesQty[itemSeq] -= MonthMoTotal.need_number.GetValueOrDefault(); moList.Remove(MonthMoTotal); moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no); weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no); } else { //需要生产但是小于生产批量按生产批量生产,大于生产批量不需要改动 if (MonthMoTotal.need_number - productQty < itemMaster.MinOrd) { decimal needProductQty = MonthMoTotal.need_number.GetValueOrDefault() - productQty; minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - needProductQty; MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days); MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-days); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}"; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(42).Year; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(42).Month; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(42), 1); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(42).Year}-{GetNextMonday().AddDays(28).AddDays(42).Month.ToString("00")}"; if (item.area == "国内" || item.area == "中国") { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } else { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } } } } else { if (MonthMoTotal.need_number < Math.Ceiling(itemMaster.MinOrd)) { minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - MonthMoTotal.need_number.Value; MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days); MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-days); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}"; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(42).Year; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(42).Month; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(42), 1); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(42).Year}-{GetNextMonday().AddDays(28).AddDays(42).Month.ToString("00")}"; if (item.area == "国内" || item.area == "中国") { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } else { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } } } var planBOM = boms.Find(b => b.item_number == itemSeq); var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); var returnlist = ObjectMapper.Map, List>(pretreament); returnlist = returnlist.OrderBy(s => s.num_order).ToList(); var level1Dto = returnlist[0]; level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault(); CaclMaterialShortage(returnlist); foreach (var r in returnlist) { if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number)) { if (subProductItem.ContainsKey(r.item_number)) { subProductItem[r.item_number] += r.needCount; } else { subProductItem.Add(r.item_number, r.needCount); subProductItemModel.Add(r.item_number, r); } } } } else { var planBOM = boms.Find(b => b.item_number == itemSeq); var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); var returnlist = ObjectMapper.Map, List>(pretreament); returnlist = returnlist.OrderBy(s => s.num_order).ToList(); var level1Dto = returnlist[0]; level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault(); CaclMaterialShortage(returnlist); foreach (var r in returnlist) { if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number)) { if (subProductItem.ContainsKey(r.item_number)) { subProductItem[r.item_number] += r.needCount; } else { subProductItem.Add(r.item_number, r.needCount); subProductItemModel.Add(r.item_number, r); } } } } } else { moList.Remove(MonthMoTotal); moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no); weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no); } } } } else { var MonthMo = moList.Find(a => a.product_code == itemSeq && ( a.moentry_sys_etime == GetNextMonday().AddDays(28 + 56).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 63).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 70).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 77).AddDays(-days))); if (MonthMo != null) { MonthMo.morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); MonthMo.need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); MonthMo.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-ProductTime(routingOps, MonthMo.product_code, input.factory_id.ToString(), MonthMo.need_number.GetValueOrDefault()) - days); MonthMo.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-days); moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4); weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanStartDate = MonthMo.moentry_sys_stime; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Week = $"WK{GetWeekOfYear(MonthMo.moentry_sys_stime.Value).ToString("00")}"; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Qty = MonthMo.morder_production_number.Value; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Year = GetNextMonday().AddDays(28).AddDays(70).Year; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Month = GetNextMonday().AddDays(28).AddDays(70).Month; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(70), 1); weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(70).Year}-{GetNextMonday().AddDays(28).AddDays(70).Month.ToString("00")}"; if (item.area == "国内" || item.area == "中国") { weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days); } else { weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days); } } else { var bom = bomList.Find(b => b.item_number == itemSeq); var ic_item = itemList.Find(b => b.number == itemSeq); mes_morder mes_Morder = new mes_morder(); mes_Morder.GenerateNewId(help.NextId()); mes_Morder.morder_type = MorderEnum.JhMorder; mes_Morder.work_order_type = MorderEnum.CgMorder; mes_Morder.morder_state = ""; mes_Morder.morder_no = Guid.NewGuid().ToString(); mes_Morder.fms_number = ic_item.fms_number; mes_Morder.bom_number = bom.bom_number; mes_Morder.fmodel = ic_item.model; 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.morder_date = DateTime.Now.Date.AddDays(1); 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; mes_Morder.unit = ic_item.unit; mes_Morder.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); mes_Morder.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); //成品半成品取周一为入库时间开始往前推 mes_Morder.moentry_sys_stime = weekTime.AddDays(-ProductTime(routingOps, ic_item.number, input.factory_id.ToString(), mes_Morder.need_number.GetValueOrDefault()) - days); mes_Morder.moentry_sys_etime = weekTime.AddDays(-days); 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 = ic_item.unit; mes_Moentry.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ; mes_Moentry.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ; 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; ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan(); weekItem.Priority = 1; weekItem.Area = item.area; weekItem.PlanStartDate = mes_Morder.moentry_sys_stime.GetValueOrDefault(); weekItem.Week = $"WK{GetWeekOfYear(mes_Morder.moentry_sys_stime.Value).ToString("00")}"; weekItem.OrderNO = Guid.NewGuid().ToString(); weekItem.ProductionOrder = mes_Morder.morder_no; weekItem.SAPOrderNO = ""; weekItem.OrderType = "量产"; weekItem.ProductionBatch = ""; weekItem.ProductionStatus = ""; weekItem.ProdLine = item.ProdLine; weekItem.ProdRange = item.ProdRange; weekItem.Line = monthPlanItem?.WorkshopLine; weekItem.ItemNumber = item.number; weekItem.Model = item.model; weekItem.Languages = item.Languages; weekItem.Qty = mes_Morder.morder_production_number.Value; weekItem.ItemStatus = ""; weekItem.PlanKittingDate = DateTime.Now; weekItem.Year = weekTime.Year; weekItem.Month = weekTime.Month; weekItem.WeekSeq = WeekOfMonth(weekTime, 1); weekItem.PlanMonth = kMonth; weekItem.tenant_id = input.tenant_id; weekItem.factory_id = input.factory_id; weekItem.company_id = input.company_id; weekItem.org_id = input.org_id; weekItem.create_time = DateTime.Now; weekItem.DistributionChannel = item.distributionchannel; weekItem.IsReplenishmentModel = "N"; if (item.area == "国内" || item.area == "中国") { weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value; weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days); } else { weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value; weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days); } weekItem.AssembleHours = 0; weekItem.HeatSealHours = 0; weekItem.PackageHours = 0; weekItem.TotalHours = 0; //Q2023/11/15的需求同一周有相同物料的工单不继续生成,不考虑数量的偏差 if (!weekProductPlanList.Any(a => a.ItemNumber == item.number && a.Week == weekItem.Week)) { weekPlan.Add(weekItem); moList.Add(mes_Morder); moentryList.Add(mes_Moentry); } } if (k == 11) { var MonthMoTotal = moList.Find(a => a.product_code == itemSeq && ( a.moentry_sys_etime == GetNextMonday().AddDays(28 + 56).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 63).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 70).AddDays(-days) || a.moentry_sys_etime == GetNextMonday().AddDays(28 + 77).AddDays(-days))); if (MonthMoTotal != null) { if (MonthMoTotal.need_number > 0) { var itemMaster = itemMasterList.Find(i => i.ItemNum == itemSeq); if (itemMaster != null && itemMaster.MinOrd > 0) { //考虑生产批量的计算逻辑 decimal productQty; bool exist = minordsalesQty.TryGetValue(itemSeq, out productQty); if (exist) { //不需要生产 if (MonthMoTotal.need_number <= productQty) { minordsalesQty[itemSeq] -= MonthMoTotal.need_number.GetValueOrDefault(); moList.Remove(MonthMoTotal); moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no); weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no); } else { //需要生产但是小于生产批量按生产批量生产,大于生产批量不需要改动 if (MonthMoTotal.need_number - productQty < itemMaster.MinOrd) { decimal needProductQty = MonthMoTotal.need_number.GetValueOrDefault() - productQty; minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - needProductQty; MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days); MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-days); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}"; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(70).Year; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(70).Month; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(70), 1); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(70).Year}-{GetNextMonday().AddDays(28).AddDays(70).Month.ToString("00")}"; if (item.area == "国内" || item.area == "中国") { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } else { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } } } } else { if (MonthMoTotal.need_number < Math.Ceiling(itemMaster.MinOrd)) { minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - MonthMoTotal.need_number.Value; MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd); MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days); MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-days); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd); moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}"; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(70).Year; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(70).Month; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(70), 1); weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(70).Year}-{GetNextMonday().AddDays(28).AddDays(70).Month.ToString("00")}"; if (item.area == "国内" || item.area == "中国") { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } else { weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value; weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days); } } } var planBOM = boms.Find(b => b.item_number == itemSeq); var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); var returnlist = ObjectMapper.Map, List>(pretreament); returnlist = returnlist.OrderBy(s => s.num_order).ToList(); var level1Dto = returnlist[0]; level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault(); CaclMaterialShortage(returnlist); foreach (var r in returnlist) { if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number)) { if (subProductItem.ContainsKey(r.item_number)) { subProductItem[r.item_number] += r.needCount; } else { subProductItem.Add(r.item_number, r.needCount); subProductItemModel.Add(r.item_number, r); } } } } else { var planBOM = boms.Find(b => b.item_number == itemSeq); var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); var returnlist = ObjectMapper.Map, List>(pretreament); returnlist = returnlist.OrderBy(s => s.num_order).ToList(); var level1Dto = returnlist[0]; level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault(); CaclMaterialShortage(returnlist); foreach (var r in returnlist) { if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number)) { if (subProductItem.ContainsKey(r.item_number)) { subProductItem[r.item_number] += r.needCount; } else { subProductItem.Add(r.item_number, r.needCount); subProductItemModel.Add(r.item_number, r); } } } } } else { moList.Remove(MonthMoTotal); moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no); weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no); } } } } } } } #region //滚动12周逻辑保留 //for (int k = 0; k < 12; k++) //{ // var weekTime = GetNextMonday().AddDays(28);//增加四周 // weekTime = weekTime.AddDays(7 * k); // string kMonth = $"{weekTime.Year}-{weekTime.Month.ToString("00")}"; // var monthWeekPlan = planList.Where(a => a.planmonth == kMonth).ToList(); // var ropList = planList.Where(t=>shipPlanList.Select(s => s.SAPItemNumber).ToList().Contains(t.number)).Select(t => t.number).Distinct().ToList(); // foreach (var itemSeq in ropList) // { // var monthPlanItem = monthPlan.Find(x => x.ItemNumber == itemSeq); // //瑞奇国科海王 // var monthPlanTotal = monthWeekPlan.Where(x => x.number == itemSeq).ToList(); // if (monthPlanTotal != null && monthPlanTotal.Count > 0) // { // var item = monthPlanTotal[0]; // //瑞奇补货计划!Y5 + 瑞奇补货计划!Z5 + 国科补货计划!Y5 + 国科补货计划!Z5 + 海王补货计划!Y4 + 海王补货计划!Z4 // var itemQty = monthPlanTotal.Sum(a => a.montheop1) + monthPlanTotal.Sum(a => a.montheop2); // //每次都是发布12周,每个月4周,不用判断存不存在(退市的可能没有) // int days = 15; // if (item.area != "国内" && item.area != "中国") // { // days = 8; // } // if (itemQty > 0) // { // var bom = bomList.Find(b => b.item_number == itemSeq); // var ic_item = itemList.Find(b => b.number == itemSeq); // mes_morder mes_Morder = new mes_morder(); // mes_Morder.GenerateNewId(help.NextId()); // mes_Morder.morder_type = MorderEnum.JhMorder; // mes_Morder.work_order_type = MorderEnum.CgMorder; // mes_Morder.morder_state = ""; // mes_Morder.morder_no = Guid.NewGuid().ToString(); // mes_Morder.fms_number = ic_item.fms_number; // mes_Morder.bom_number = bom.bom_number; // mes_Morder.fmodel = ic_item.model; // 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.morder_date = DateTime.Now.Date.AddDays(1); // 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; // mes_Morder.unit = ic_item.unit; // mes_Morder.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); // mes_Morder.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); // //成品半成品取周一为入库时间开始往前推 // mes_Morder.moentry_sys_stime = weekTime.AddDays(-ProductTime(routingOps, ic_item.number, input.factory_id.ToString(), mes_Morder.need_number.GetValueOrDefault()) - days); // mes_Morder.moentry_sys_etime = weekTime.AddDays(-days); // 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 = ic_item.unit; // mes_Moentry.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ; // mes_Moentry.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ; // 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; // ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan(); // weekItem.Priority = 1; // weekItem.Area = item.area; // weekItem.PlanStartDate = mes_Morder.moentry_sys_stime.GetValueOrDefault(); // weekItem.Week = $"WK{GetWeekOfYear(mes_Morder.moentry_sys_stime.Value).ToString("00")}"; // weekItem.OrderNO = Guid.NewGuid().ToString(); // weekItem.ProductionOrder = mes_Morder.morder_no; // weekItem.SAPOrderNO = ""; // weekItem.OrderType = "量产"; // weekItem.ProductionBatch = ""; // weekItem.ProductionStatus = ""; // weekItem.ProdLine = item.ProdLine; // weekItem.ProdRange = item.ProdRange; // weekItem.Line = monthPlanItem?.WorkshopLine; // weekItem.ItemNumber = item.number; // weekItem.Model = item.model; // weekItem.Languages = item.Languages; // weekItem.Qty = mes_Morder.morder_production_number.Value; // weekItem.ItemStatus = ""; // weekItem.PlanKittingDate = DateTime.Now; // weekItem.Year = weekTime.Year; // weekItem.Month = weekTime.Month; // weekItem.WeekSeq = WeekOfMonth(weekTime, 1); // weekItem.PlanMonth = kMonth; // weekItem.tenant_id = input.tenant_id; // weekItem.factory_id = input.factory_id; // weekItem.company_id = input.company_id; // weekItem.org_id = input.org_id; // weekItem.create_time = DateTime.Now; // weekItem.DistributionChannel = item.distributionchannel; // weekItem.IsReplenishmentModel = "N"; // if (item.area == "国内" || item.area == "中国") // { // weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value; // weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days); // } // else // { // weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value; // weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days); // } // weekItem.AssembleHours = 0; // weekItem.HeatSealHours = 0; // weekItem.PackageHours = 0; // weekItem.TotalHours = 0; // //Q2023/11/15的需求同一周有相同物料的工单不继续生成,不考虑数量的偏差 // if (!weekProductPlanList.Any(a => a.ItemNumber == item.number && a.Week == weekItem.Week)) // { // weekPlan.Add(weekItem); // moList.Add(mes_Morder); // moentryList.Add(mes_Moentry); // var planBOM = boms.Find(b => b.item_number == itemSeq); // var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); // var returnlist = ObjectMapper.Map, List>(pretreament); // returnlist = returnlist.OrderBy(s => s.num_order).ToList(); // var level1Dto = returnlist[0]; // level1Dto.needCount = itemQty.GetValueOrDefault(); // CaclMaterialShortage(returnlist); // foreach (var r in returnlist) // { // if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number)) // { // if (subProductItem.ContainsKey(r.item_number)) // { // subProductItem[r.item_number] += r.needCount; // } // else // { // subProductItem.Add(r.item_number, r.needCount); // subProductItemModel.Add(r.item_number, r); // } // } // } // } // } // } // } //} #endregion List subItems = new List(); for (int j = 0; j < 3; j++) { var jweekTime = GetNextMonday().AddDays(28); jweekTime = jweekTime.AddDays(28 * j); string jMonth = $"{jweekTime.Year}-{jweekTime.Month.ToString("00")}"; subItems.Add(jMonth); } var weeksubPlanList = _replenishmentWeekPlan.GetListAsync(a => subItems.Contains(a.PlanMonth) && !a.IsDeleted && a.factory_id == input.factory_id && a.IsReplenishmentModel == "N").Result; //中间件钉匣泡壳四周开一张工单 for (int i = 0; i < 3; i++) { var weekTime = GetNextMonday().AddDays(28); weekTime = weekTime.AddDays(28 * i); var weekofMonth = WeekOfMonth(weekTime, 1); string kMonth = $"{weekTime.Year}-{weekTime.Month.ToString("00")}"; if (prodLines.Count == 0) { prodLines = _prodLineDetail.Select(p => subProductItem.Keys.Contains(p.Part) && p.Domain == input.factory_id.ToString() && p.IsActive && routingOpList.Select(m => m.Op).Contains(p.Op)).OrderBy(x => x.Sequence).ToList(); } if (lineMasters.Count == 0) { lineMasters = _lineMaster.Select(p => prodLines.Select(a => a.Line).Contains(p.Line) && p.Domain == input.factory_id.ToString() && p.IsActive).ToList(); } var middleItemList = _itemMaster.Select(a => subProductItem.Keys.Contains(a.ItemNum) && a.Domain == input.factory_id.ToString()); foreach (var key in subProductItem.Keys) { var itemQty = subProductItem[key] / 3; var middle = middleItemList.Find(m => m.ItemNum == key); var middleItem = middle.MinOrd; if (middleItem > 0) { if (itemQty < middleItem) itemQty = middleItem; if (middle.ItemType == "RS30" && middle.PurMfg == "L" && middle.OrdMult > 0) { itemQty = Math.Ceiling(Math.Ceiling(itemQty.GetValueOrDefault() / middle.OrdMult) * middle.OrdMult); } else { itemQty = Math.Ceiling(itemQty.GetValueOrDefault()); } } else { itemQty = Math.Ceiling(itemQty.GetValueOrDefault()); } if (!weeksubPlanList.Any(a => a.ItemNumber == subProductItemModel[key].item_number && a.PlanMonth == kMonth) && itemQty > 0) { mes_morder mes_Morder = new mes_morder(); mes_Morder.GenerateNewId(help.NextId()); mes_Morder.morder_type = MorderEnum.JhMorder; mes_Morder.work_order_type = MorderEnum.CgMorder; mes_Morder.morder_state = ""; mes_Morder.morder_no = Guid.NewGuid().ToString(); mes_Morder.fms_number = ""; mes_Morder.bom_number = subProductItemModel[key].bom_number; mes_Morder.fmodel = subProductItemModel[key].model; 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 = subProductItemModel[key].item_number; mes_Morder.product_name = subProductItemModel[key].item_name; mes_Morder.morder_date = DateTime.Now.Date.AddDays(1); 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; mes_Morder.unit = subProductItemModel[key].unit; mes_Morder.morder_production_number = itemQty; mes_Morder.need_number = itemQty; //成品半成品取周一为入库时间开始往前推 mes_Morder.moentry_sys_stime = weekTime.AddDays(-ProductTime(routingOps, subProductItemModel[key].item_number, input.factory_id.ToString(), mes_Morder.need_number.GetValueOrDefault())); mes_Morder.moentry_sys_etime = weekTime; 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 = subProductItemModel[key].unit; mes_Moentry.morder_production_number = itemQty; mes_Moentry.need_number = itemQty; 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; var prodLine = prodLines.Where(x => x.Part == key).OrderBy(x => x.Sequence).FirstOrDefault(); ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan(); weekItem.Priority = 1; weekItem.Area = ""; weekItem.PlanStartDate = mes_Morder.moentry_sys_stime.GetValueOrDefault(); weekItem.Week = $"WK{GetWeekOfYear(mes_Morder.moentry_sys_stime.Value).ToString("00")}"; weekItem.OrderNO = Guid.NewGuid().ToString(); weekItem.ProductionOrder = mes_Morder.morder_no; weekItem.SAPOrderNO = ""; weekItem.OrderType = "量产"; weekItem.ProductionBatch = ""; weekItem.ProductionStatus = ""; weekItem.ProdLine = ""; weekItem.ProdRange = ""; if (prodLine != null && lineMasters.Find(b => b.Line == prodLine.Line) != null) { weekItem.Line = lineMasters.Find(b => b.Line == prodLine.Line).Describe; } else { weekItem.Line = ""; } weekItem.ItemNumber = key; weekItem.Model = subProductItemModel[key].model; weekItem.Languages = ""; weekItem.Qty = mes_Morder.morder_production_number.Value; weekItem.ItemStatus = ""; weekItem.PlanKittingDate = DateTime.Now; weekItem.Year = mes_Morder.moentry_sys_stime.Value.Year; weekItem.Month = mes_Morder.moentry_sys_stime.Value.Month; weekItem.PlanMonth = kMonth; weekItem.WeekSeq = weekofMonth; weekItem.tenant_id = input.tenant_id; weekItem.factory_id = input.factory_id; weekItem.company_id = input.company_id; weekItem.org_id = input.org_id; weekItem.create_time = DateTime.Now; weekItem.DistributionChannel = "瑞奇"; weekItem.IsReplenishmentModel = "N"; weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value; weekItem.AssembleHours = 0; weekItem.HeatSealHours = 0; weekItem.PackageHours = 0; weekItem.TotalHours = 0; weekPlan.Add(weekItem); moList.Add(mes_Morder); moentryList.Add(mes_Moentry); } } } var morder_noList = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", moList.Count, "", 1); var OrderNOList = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "MPO", moList.Count, "", 1); for (int i = 0; i < moList.Count; i++) { moList[i].morder_no = morder_noList[i].NbrResult; moentryList[i].moentry_mono = morder_noList[i].NbrResult; weekPlan[i].ProductionOrder = morder_noList[i].NbrResult; weekPlan[i].OrderNO = OrderNOList[i].NbrResult; } await _businessDbContext.BulkInsertAsync(moList); await _businessDbContext.BulkInsertAsync(moentryList); //批量保存 后期考虑子工单 List workOrdSave = new List(); List workOrdRoutingSave = new List(); List workOrdDetails = new List(); if (moList.Any()) { //同步工单 CreateWorkOrdDates(moList, routingOps, workOrdSave, workOrdRoutingSave, workOrdDetails, new List(), new List()); } if (workOrdSave.Any()) { _businessDbContext.BulkInsert(workOrdSave); CalcPriority(input.factory_id.ToString()); } var DBworkOrdList = _workOrdMaster.Select(a => workOrdSave.Count > 0 && a.Domain == workOrdSave[0].Domain && workOrdSave.Select(c => c.WorkOrd).Contains(a.WorkOrd)); if (workOrdRoutingSave.Any()) { workOrdRoutingSave.ForEach(c => { c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID; }); _businessDbContext.BulkInsert(workOrdRoutingSave); } if (workOrdDetails.Any()) { workOrdDetails.ForEach(c => { c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID; }); _businessDbContext.BulkInsert(workOrdDetails); } await PlanOrderResourceCheck(moList.OrderBy(a => a.moentry_sys_stime).ToList(), moentryList, bang_id, "", false, false); var examine_resultList = _mysql_examine_result.GetListAsync(a => a.bangid == bang_id).Result; weekPlan.ForEach(a => { if (a.IsReplenishmentModel == "N") { var moItem = examine_resultList.Find(b => b.morder_no == a.ProductionOrder); List routingOp = routingOps.Where(x => x.RoutingCode == a.ItemNumber).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.Descr == "包装" && x.MilestoneOp).FirstOrDefault(); if (moItem != null && moItem.kitting_times < a.PlanStartDate) { a.ItemStatus = "齐套"; a.PlanKittingDate = moItem.kitting_times; a.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * a.Qty; a.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * a.Qty; a.PackageHours = Packaging == null ? 0 : Packaging.RunTime * a.Qty; a.TotalHours = a.AssembleHours + a.HeatSealHours + a.PackageHours; } else { a.ItemStatus = "欠料"; a.PlanKittingDate = moItem.kitting_times; a.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * a.Qty; a.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * a.Qty; a.PackageHours = Packaging == null ? 0 : Packaging.RunTime * a.Qty; a.TotalHours = a.AssembleHours + a.HeatSealHours + a.PackageHours; } } }); await _businessDbContext.BulkInsertAsync(weekPlan); return "OK"; } /// /// 根据周计划生成周工单 /// /// /// public async Task CalcTempWeekPlan(InputDto input) { //var IsActived = _AccountValidityAppService.IsActived(); //if (!IsActived) //{ // return "此账号已限制访问"; //} await ClearDO(input.factory_id.ToString()); routingOps = _routingOpDetail.Select(p => p.Domain == input.factory_id.ToString()).ToList(); long bang_id = help.NextId(); var weekplans = _replenishmentWeekPlan.GetListAsync(a => a.IsReplenishmentModel == "N" && string.IsNullOrEmpty(a.ProductionStatus) && string.IsNullOrEmpty(a.ProductionOrder) && a.factory_id == input.factory_id).Result; if (weekplans.Any()) { input.company_id = weekplans[0].company_id.GetValueOrDefault(); input.tenant_id = weekplans[0].tenant_id.GetValueOrDefault(); input.org_id = weekplans[0].org_id.GetValueOrDefault(); } var itemIds = weekplans.Select(a => a.ItemNumber).Distinct().ToList(); var items = _itemMaster.Select(a => itemIds.Contains(a.ItemNum)); List moList = new List(); List moentryList = new List(); var morder_noList = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", weekplans.Count, "", 1); foreach (var item in weekplans) { mes_morder mes_Morder = new mes_morder(); mes_Morder.GenerateNewId(help.NextId()); mes_Morder.morder_type = MorderEnum.JhMorder; mes_Morder.work_order_type = MorderEnum.CgMorder; mes_Morder.morder_state = ""; mes_Morder.morder_no = Guid.NewGuid().ToString(); mes_Morder.fms_number = ""; mes_Morder.bom_number = item.ItemNumber; mes_Morder.fmodel = item.Model; 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 = item.ItemNumber; mes_Morder.product_name = items.Find(a => a.ItemNum == item.ItemNumber).Descr; mes_Morder.morder_date = DateTime.Now.Date.AddDays(1); 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; mes_Morder.unit = items.Find(a => a.ItemNum == item.ItemNumber).UM; mes_Morder.morder_production_number = item.Qty; mes_Morder.need_number = item.Qty; //成品半成品取周一为入库时间开始往前推 mes_Morder.moentry_sys_stime = item.PlanStartDate; mes_Morder.moentry_sys_etime = item.InStockDate; 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 = items.Find(a => a.ItemNum == item.ItemNumber).UM; mes_Moentry.morder_production_number = item.Qty; mes_Moentry.need_number = item.Qty; 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); } for (int i = 0; i < moList.Count; i++) { moList[i].morder_no = morder_noList[i].NbrResult; moentryList[i].moentry_mono = morder_noList[i].NbrResult; weekplans[i].ProductionOrder = morder_noList[i].NbrResult; } await _businessDbContext.BulkInsertAsync(moList); await _businessDbContext.BulkInsertAsync(moentryList); await _businessDbContext.BulkUpdateAsync(weekplans); //批量保存 后期考虑子工单 List workOrdSave = new List(); List workOrdRoutingSave = new List(); List workOrdDetails = new List(); if (moList.Any()) { //同步工单 CreateWorkOrdDates(moList, routingOps, workOrdSave, workOrdRoutingSave, workOrdDetails, new List(), new List()); } if (workOrdSave.Any()) { _businessDbContext.BulkInsert(workOrdSave); CalcPriority(input.factory_id.ToString()); } var DBworkOrdList = _workOrdMaster.Select(a => workOrdSave.Count > 0 && a.Domain == workOrdSave[0].Domain && workOrdSave.Select(c => c.WorkOrd).Contains(a.WorkOrd)); if (workOrdRoutingSave.Any()) { workOrdRoutingSave.ForEach(c => { c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID; }); _businessDbContext.BulkInsert(workOrdRoutingSave); } if (workOrdDetails.Any()) { workOrdDetails.ForEach(c => { c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID; }); _businessDbContext.BulkInsert(workOrdDetails); } //2024/01/10:卫亮工单需求对齐采购需求,取所有未下达的工单做资源检查(排除年度中间件工单) var moListCheck = _mysql_mes_morder.GetListAsync(a => (a.morder_state == MorderEnum.Initial_state || string.IsNullOrEmpty(a.morder_state)) && a.factory_id == input.factory_id && string.IsNullOrEmpty(a.analogcalcversion)).Result; var moEntryListCheck = _mysql_mes_moentry.GetListAsync(a => moListCheck.Select(b => b.morder_no).ToList().Contains(a.moentry_mono) && a.factory_id == input.factory_id).Result; await PlanOrderResourceCheck(moListCheck.OrderBy(a => a.moentry_sys_stime).ToList(), moEntryListCheck, bang_id, "", false, true); var examine_resultList = _mysql_examine_result.GetListAsync(a => a.bangid == bang_id).Result; var weekplanList = _replenishmentWeekPlan.GetListAsync(a => moListCheck.Select(b => b.morder_no).ToList().Contains(a.ProductionOrder) && a.IsReplenishmentModel == "N" && a.factory_id == input.factory_id).Result; weekplanList.ForEach(a => { var moItem = examine_resultList.Find(b => b.morder_no == a.ProductionOrder); List routingOp = routingOps.Where(x => x.RoutingCode == a.ItemNumber).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(); if (moItem != null) { if (moItem.kitting_times < a.PlanStartDate) { a.ItemStatus = "齐套"; a.PlanKittingDate = moItem.kitting_times; a.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * a.Qty; a.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * a.Qty; a.PackageHours = Packaging == null ? 0 : Packaging.RunTime * a.Qty; a.TotalHours = a.AssembleHours + a.HeatSealHours + a.PackageHours; } else { a.ItemStatus = "欠料"; a.PlanKittingDate = moItem.kitting_times; a.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * a.Qty; a.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * a.Qty; a.PackageHours = Packaging == null ? 0 : Packaging.RunTime * a.Qty; a.TotalHours = a.AssembleHours + a.HeatSealHours + a.PackageHours; } } }); await _businessDbContext.BulkUpdateAsync(weekplanList); return "OK"; } private DateTime GetNextMonday() { var preSunday = DateTime.Now.AddDays(0 - (int)DateTime.Now.DayOfWeek);//上周日 return Convert.ToDateTime(preSunday.AddDays(8).ToString("yyyy-MM-dd 00:00:00.000"));////上周日加八天即为下周一 } public static int WeekOfMonth(DateTime day, int WeekStart) { //WeekStart //1表示 周一至周日 为一周 //2表示 周日至周六 为一周 DateTime FirstofMonth; FirstofMonth = Convert.ToDateTime(day.Date.Year + "-" + day.Date.Month + "-" + 1); int i = (int)FirstofMonth.Date.DayOfWeek; if (i == 0) { i = 7; } if (WeekStart == 1) { return (day.Date.Day + i - 2) / 7 + 1; } if (WeekStart == 2) { return (day.Date.Day + i - 1) / 7; } return 0; //错误返回值0 } private async Task ClearDO(string domain) { var purordlist = _PurOrdMaster.Select(x => x.Status.ToUpper() != "C" && x.ReqBy == "DO" && x.Domain == domain && x.USAGE != "ECR" && x.USAGE != "研发").ToList(); var purdtllist = _PurOrdDetail.Select(x => purordlist.Select(c => c.RecID).Contains(x.PurOrdRecID) && x.Domain == domain).ToList(); var shdzblist = _scm_shdzb.Select(x => purordlist.Select(c => c.PurOrd).Contains(x.po_bill)).ToList(); var podslist = _srmpolistds.Select(x => purordlist.Select(c => c.PurOrd).Contains(x.ponumber) && x.isactive == 1).ToList(); List delMstlist = new List(); List delDtllist = new List(); List mstdtl = new List(); int rctqtyCount; int shdzbCount; int dsCount; bool isDel; foreach (var mst in purordlist) { rctqtyCount = 0; shdzbCount = 0; dsCount = 0; mstdtl = purdtllist.Where(x => x.PurOrdRecID == mst.RecID).ToList(); if (mstdtl.Any()) { foreach (var dtl in mstdtl) { isDel = true; if (dtl.RctQty > 0)//有收货数量 { rctqtyCount++; isDel = false; } if (shdzblist.Exists(x => x.po_bill == mst.PurOrd && x.sh_material_code == dtl.ItemNum && x.po_billline == dtl.Line.ToString()))//有发货 { shdzbCount++; isDel = false; } if (podslist.Exists(x => x.ponumber == mst.PurOrd && x.itemnum == dtl.ItemNum && x.poline == dtl.Line && ((x.status.ToUpper() != "C" && x.schedqty > 0) || (x.status.ToUpper() == "C" && x.sentqty > 0))))//非关闭但是有需求数量或已关闭但是有已交数量 则有交货单 { dsCount++; isDel = false; } if (isDel) { delDtllist.Add(dtl); } } //没有关联记录,则删除 if (rctqtyCount == 0 && shdzbCount == 0 && dsCount == 0) { delMstlist.Add(mst); } } else { delMstlist.Add(mst); } } //通过要删除的要货令明细,删除采购申请,然后根据删除的采购申请,删除srm_po_list var delpolist = _mysql_srm_po_main.GetListAsync(x => delMstlist.Select(c => c.PurOrd).Contains(x.po_billno) && x.factory_id.ToString() == domain).Result; var podtllist = _mysql_srm_po_list.GetListAsync(x => delDtllist.Select(c => c.PurOrd).Contains(x.po_billno) && x.factory_id.ToString() == domain).Result; List delpllist = new List(); foreach (var pl in podtllist) { if (delDtllist.Exists(x => x.PurOrd == pl.po_billno && x.ItemNum == pl.ItemNum && x.Line == pl.polist_row.GetValueOrDefault())) { delpllist.Add(pl); } } var delocclist = _mysql_srm_po_occupy.GetListAsync(x => delpllist.Select(c => c.Id).Contains(x.polist_id.GetValueOrDefault())).Result; var delprlist = _mysql_srm_pr_main.GetListAsync(x => delpllist.Select(c => c.pr_id).Contains(x.Id)).Result; using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { _businessDbContext.BulkDelete(delMstlist); _businessDbContext.BulkDelete(delDtllist); _businessDbContext.BulkDelete(delpolist); _businessDbContext.BulkDelete(delpllist); _businessDbContext.BulkDelete(delocclist); _businessDbContext.BulkDelete(delprlist); await unitOfWork.CompleteAsync(); } catch (Exception e) { unitOfWork.Dispose(); new NLogHelper("ClearDO").WriteLog("ClearDO", "清除要货令失败:" + e.Message, _currentTenant.Id.ToString()); } } } /// /// 根据标准工艺获取生产时长(天) /// /// /// public int ProductTime(List routingOps, string ItemNum,string Domain,decimal QtyOrd) { var allOps = routingOps.Where(s => s.RoutingCode ==ItemNum && s.Domain ==Domain).ToList(); if (allOps.Any()) { decimal maxRt = allOps.Max(s => s.RunTime); decimal sumRt = allOps.Sum(s => s.RunTime); decimal totalTime = (QtyOrd - 1) * maxRt + sumRt;//总计生产小时 return (int)(Math.Ceiling(totalTime / 8)); } return 1; } /// /// 发布周计划 /// /// /// public async Task PublishWeekPlan(InputDto input) { //默认发布未来四周工单 //主工单发布,子工单需要一起发布 var weekPlan = _replenishmentWeekPlan.GetListAsync(a => a.PlanStartDate > DateTime.Now.AddDays(-1) && a.PlanStartDate < DateTime.Now.AddDays(29) && a.IsReplenishmentModel == "N" && string.IsNullOrEmpty(a.ProductionStatus)).Result.OrderBy(a => a.Priority).ToList(); List mes_Morders = _mysql_mes_morder.GetListAsync(a => weekPlan.Select(p => p.ProductionOrder).ToList().Contains(a.morder_no) && a.factory_id == input.factory_id).Result; if(mes_Morders!=null&& mes_Morders.Count>0) { List mes_Morders_sub=_mysql_mes_morder.GetListAsync(a => mes_Morders.Select(p => p.Id).ToList().Contains(a.parent_id.GetValueOrDefault()) && a.factory_id == input.factory_id).Result; if (mes_Morders_sub != null && mes_Morders_sub.Count > 0) { mes_Morders.AddRange(mes_Morders_sub); } } List workMasters = _workOrdMaster.Select(a => mes_Morders.Select(m=>m.morder_no).ToList().Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString()); for(int i=0;i { if (b.ItemNum == weekPlan[i].ItemNumber && b.WorkOrd == weekPlan[i].ProductionOrder) { b.Status = "p"; } }); mes_Morders.ForEach(c => { c.morder_state = MorderEnum.Initial_state; }); } _workOrdMaster.Update(workMasters); await _businessDbContext.BulkUpdateAsync(mes_Morders); await _businessDbContext.BulkUpdateAsync(weekPlan); return "OK"; } /// /// 勾选发布周计划 /// /// /// public async Task SelectPublishWeekPlan(string ids, string factoryid) { List idList = AnalysisIdList(ids); //主工单发布,子工单需要一起发布 var weekPlan = _replenishmentWeekPlan.GetListAsync(a => idList.Contains(a.Id) && a.IsReplenishmentModel == "N" && string.IsNullOrEmpty(a.ProductionStatus) && a.factory_id.ToString()== factoryid).Result.OrderBy(a => a.Priority).ToList(); List mes_Morders = _mysql_mes_morder.GetListAsync(a => weekPlan.Select(p => p.ProductionOrder).ToList().Contains(a.morder_no) && a.factory_id.ToString() == factoryid).Result; if (mes_Morders != null && mes_Morders.Count > 0) { List mes_Morders_sub = _mysql_mes_morder.GetListAsync(a => mes_Morders.Select(p => p.Id).ToList().Contains(a.parent_id.GetValueOrDefault()) && a.factory_id.ToString() == factoryid).Result; if (mes_Morders_sub != null && mes_Morders_sub.Count > 0) { mes_Morders.AddRange(mes_Morders_sub); } } List workMasters = _workOrdMaster.Select(a => mes_Morders.Select(m => m.morder_no).ToList().Contains(a.WorkOrd) && a.Domain == factoryid); for (int i = 0; i < weekPlan.Count; i++) { weekPlan[i].ProductionStatus = "已发布"; workMasters.ForEach(b => { if (b.ItemNum == weekPlan[i].ItemNumber && b.WorkOrd == weekPlan[i].ProductionOrder) { b.Status = "p"; } }); mes_Morders.ForEach(c => { c.morder_state = MorderEnum.Initial_state; }); } //发布计划订单产生的工单 List planMo = _mysql_mes_morder.GetListAsync(a => idList.Contains(a.Id) && string.IsNullOrEmpty(a.morder_state) && a.factory_id.ToString() == factoryid).Result; if (planMo != null) { List mes_Morders_child = _mysql_mes_morder.GetListAsync(a => planMo.Select(p => p.Id).ToList().Contains(a.parent_id.GetValueOrDefault()) && a.factory_id.ToString() == factoryid).Result; if (mes_Morders_child != null && mes_Morders_child.Count > 0) { planMo.AddRange(mes_Morders_child); } List planwork = _workOrdMaster.Select(a => planMo.Select(m => m.morder_no).ToList().Contains(a.WorkOrd) && a.Domain == factoryid); planMo.ForEach(c => { c.morder_state = MorderEnum.Initial_state; }); planwork.ForEach(b => { b.Status = "p"; }); workMasters.AddRange(planwork); mes_Morders.AddRange(planMo); } _workOrdMaster.Update(workMasters); await _businessDbContext.BulkUpdateAsync(mes_Morders); await _businessDbContext.BulkUpdateAsync(weekPlan); return "OK"; } private List AnalysisIdList(string ids) { if (string.IsNullOrEmpty(ids)) { throw new NotImplementedException("传入参数不正确,请选择"); } Array alist = ids.Split(','); List idList = new List(); foreach (string longid in alist) { idList.Add(long.Parse(longid)); } return idList; } /// /// 每天补货 /// /// /// public async Task CalcDayPlan(InputDto input) { input.year = DateTime.Now.Year; input.month = DateTime.Now.Month; ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString()); //DOP运行资源检查每个成品和半成品SKU的可用库存,当可用库存 <= 修正后ROP时,自动生成月度计划订单(MPlan order,MPO48年月日3位流水号)= EOP;可用库存为没有被其他SO和PO占用的(合格成品或半成品库存 + WIP); string planMonthQuery = $"{DateTime.Now.Year}-{DateTime.Now.Month.ToString("00")}"; var ropModelList = _replenishmentROPWeekPlan.GetListAsync(a => a.planmonth== planMonthQuery && a.erp_cls==1 && a.distributionchannel=="瑞奇" && a.factory_id==input.factory_id && !a.IsDeleted).Result; List planItemList = ropModelList?.Select(a => a.number).Distinct().ToList(); var itemList = _mysql_ic_item.GetListAsync(a => planItemList.Contains(a.number) && !a.IsDeleted).Result; //获取BOM用于分解到原材料 var boms = _ic_bom.GetListAsync(a => ropModelList.Select(p => p.number).ToList().Contains(a.item_number) && a.factory_id == input.factory_id).Result; var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; List autoCreates = new List(); boms.ForEach(p => { if (!pretreatments.Where(s => s.sourceid == p.mysql_id).Any()) { autoCreates.Add(p); } }); if (autoCreates.Any()) { AutoCreateBomBill(input.company_id.ToString(), autoCreates); pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; } var itemStock = CalcStock(ropModelList.Select(a => a.number).Distinct().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 moList = new List(); List moentryList = new List(); List planMonthList = new List(); for (int j = 0; j < replenishmentDto.SaleFcstMonth+3; j++) { string itemMonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}"; planMonthList.Add(itemMonth); } planMonthList.Sort(); //获取周生产计划 var WeekPlanList=_replenishmentWeekPlan.GetListAsync(a => ropModelList.Select(b => b.number).ToList().Contains(a.ItemNumber) && a.IsReplenishmentModel == "N" && planMonthList.Contains(a.PlanMonth)).Result; var workOrdMasterList=_workOrdMaster.Select(s => WeekPlanList.Select(a => a.ProductionOrder).ToList().Contains(s.WorkOrd) && s.Domain == input.factory_id.ToString()); var workOrdDetailList = _workOrdDetail.Select(s => WeekPlanList.Select(a => a.ProductionOrder).ToList().Contains(s.WorkOrd) && s.Domain == input.factory_id.ToString()); var workOrdRoutingList = _workOrdRouting.Select(s => WeekPlanList.Select(a => a.ProductionOrder).ToList().Contains(s.WorkOrd) && s.Domain == input.factory_id.ToString()); var mesmorderList = _mysql_mes_morder.GetListAsync(s=>WeekPlanList.Select(a => a.ProductionOrder).ToList().Contains(s.morder_no) && s.factory_id == input.factory_id).Result; var mesmorderEntryList = _mysql_mes_moentry.GetListAsync(s => WeekPlanList.Select(a => a.ProductionOrder).ToList().Contains(s.moentry_mono) && s.factory_id == input.factory_id).Result; //扣减需要删除周生产计划 List deleteList=new List(); //扣减需要更新周生产计划 List updateList = new List(); //减货 ropModelList.ForEach(a => { //超出最高库存,优先扣减日期最近未发布的周生计划数量和对应的计划工单的数量 if(itemStock.First(c => c.ItemNumber == a.number).Qty>a.max_stock_level) { decimal? Qty = itemStock.First(c => c.ItemNumber == a.number).Qty - a.max_stock_level; var itemWeekPlan=WeekPlanList.FindAll(b => b.ItemNumber == a.number); //如果没找到周生成计划,那没法扣减,理论上不会出现这种数据场景 if(itemWeekPlan!=null&& itemWeekPlan.Count>0) { itemWeekPlan.OrderBy(a => a.Year).ThenBy(b => b.Month).ThenBy(c => c.Week).ThenBy(d => d.WeekSeq); for (int i = 0; i < itemWeekPlan.Count; i++) { if (itemWeekPlan[i].ProductionStatus!="已发布") { if(itemWeekPlan[i].Qty<=Qty) { deleteList.Add(itemWeekPlan[i]); Qty =Qty-itemWeekPlan[i].Qty; }else { itemWeekPlan[i].Qty = itemWeekPlan[i].Qty - Qty.GetValueOrDefault(); updateList.Add(itemWeekPlan[i]); break; } } } } } }); if(deleteList.Count>0) { await _businessDbContext.BulkDeleteAsync(deleteList); _workOrdMaster.Delete(workOrdMasterList.Where(a => deleteList.Select(b => b.ProductionOrder).ToList().Contains(a.WorkOrd)).ToList()); _workOrdDetail.Delete(workOrdDetailList.Where(a => deleteList.Select(b => b.ProductionOrder).ToList().Contains(a.WorkOrd)).ToList()); _workOrdRouting.Delete(workOrdRoutingList.Where(a => deleteList.Select(b => b.ProductionOrder).ToList().Contains(a.WorkOrd)).ToList()); await _businessDbContext.BulkDeleteAsync(mesmorderList.Where(a => deleteList.Select(b => b.ProductionOrder).ToList().Contains(a.morder_no)).ToList()); await _businessDbContext.BulkDeleteAsync(mesmorderEntryList.Where(a => deleteList.Select(b => b.ProductionOrder).ToList().Contains(a.moentry_mono)).ToList()); } if (updateList.Count > 0) { await _businessDbContext.BulkUpdateAsync(updateList); List itemUpdate = new List(); List itemDetailUpdate = new List(); List itemRoutingUpdate = new List(); List itemMesmorderList = new List(); List itemMesmorderEntryList = new List(); foreach (var item in updateList) { var workItem = workOrdMasterList.Find(a => a.ItemNum == item.ItemNumber && a.WorkOrd == item.ProductionOrder); workItem.QtyOrded = item.Qty; var workDetailItem = workOrdDetailList.Find(a => a.ItemNum == item.ItemNumber && a.WorkOrd == item.ProductionOrder); workDetailItem.QtyRequired= item.Qty; var workOrderItem = mesmorderList.Find(a => a.product_code == item.ItemNumber && a.morder_no == item.ProductionOrder); workOrderItem.need_number = item.Qty; workOrderItem.morder_production_number = item.Qty; var workOrdEntryItem = mesmorderEntryList.Find(a => a.moentry_mono == item.ProductionOrder); workOrdEntryItem.need_number = item.Qty; workOrdEntryItem.morder_production_number = item.Qty; itemUpdate.Add(workItem); itemDetailUpdate.Add(workDetailItem); itemMesmorderList.Add(workOrderItem); itemMesmorderEntryList.Add(workOrdEntryItem); var planBOM = boms.Find(b => b.item_number == item.ItemNumber); var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); var returnlist = ObjectMapper.Map, List>(pretreament); returnlist = returnlist.OrderBy(s => s.num_order).ToList(); var level1Dto = returnlist[0]; level1Dto.qty = item.Qty; CaclMaterialShortage(returnlist); foreach (var child in returnlist) { var itemWorkOrdRoutingList = workOrdRoutingList.FindAll(w => w.WorkOrd == item.ProductionOrder); if (itemWorkOrdRoutingList != null && itemWorkOrdRoutingList.Count > 0) { foreach (var r in itemWorkOrdRoutingList) { if (r.ItemNum == child.item_number) { r.QtyOrded = child.needCount; itemRoutingUpdate.Add(r); } } } } } _workOrdMaster.Update(itemUpdate); _workOrdDetail.Update(itemDetailUpdate); _workOrdRouting.Update(itemRoutingUpdate); await _businessDbContext.BulkUpdateAsync(itemMesmorderList); await _businessDbContext.BulkUpdateAsync(itemMesmorderEntryList); } //补货 List weekPlanAdd = new List(); List routingOps = _routingOpDetail.Select(p => planItemList.Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive); long bang_id = help.NextId(); ropModelList.ForEach(a => { //低于安全库存,优先调整日期最近未发布的周生计划数量和对应的计划工单的数量 if (itemStock.First(c => c.ItemNumber == a.number).Qty < a.security_stock) { decimal? Qty =a.max_stock_level- itemStock.First(c => c.ItemNumber == a.number).Qty; var itemWeekPlan = WeekPlanList.FindAll(b => b.ItemNumber == a.number); //如果没找到周生成计划,那没法扣减,理论上不会出现这种数据场景 if (itemWeekPlan != null && itemWeekPlan.Count > 0) { itemWeekPlan.OrderBy(a => a.Year).ThenBy(b => b.Month).ThenBy(c => c.Week).ThenBy(d => d.WeekSeq); for (int i = 0; i < itemWeekPlan.Count; i++) { if (itemWeekPlan[i].ProductionStatus != "已发布") { itemWeekPlan[i].Qty = itemWeekPlan[i].Qty + Qty.GetValueOrDefault(); weekPlanAdd.Add(itemWeekPlan[i]); } } } } }); if (weekPlanAdd.Count > 0) { await _businessDbContext.BulkInsertAsync(weekPlanAdd); List itemUpdate = new List(); List itemDetailUpdate = new List(); List itemRoutingUpdate = new List(); List itemMesmorderList = new List(); List itemMesmorderEntryList = new List(); foreach (var item in weekPlanAdd) { var workItem = workOrdMasterList.Find(a => a.ItemNum == item.ItemNumber && a.WorkOrd == item.ProductionOrder); workItem.QtyOrded = item.Qty; var workDetailItem = workOrdDetailList.Find(a => a.ItemNum == item.ItemNumber && a.WorkOrd == item.ProductionOrder); workDetailItem.QtyRequired = item.Qty; var workOrderItem = mesmorderList.Find(a => a.product_code == item.ItemNumber && a.morder_no == item.ProductionOrder); workOrderItem.need_number = item.Qty; workOrderItem.morder_production_number = item.Qty; var workOrdEntryItem = mesmorderEntryList.Find(a => a.moentry_mono == item.ProductionOrder); workOrdEntryItem.need_number = item.Qty; workOrdEntryItem.morder_production_number = item.Qty; itemUpdate.Add(workItem); itemDetailUpdate.Add(workDetailItem); itemMesmorderList.Add(workOrderItem); itemMesmorderEntryList.Add(workOrdEntryItem); var planBOM = boms.Find(b => b.item_number == item.ItemNumber); var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList(); var returnlist = ObjectMapper.Map, List>(pretreament); returnlist = returnlist.OrderBy(s => s.num_order).ToList(); var level1Dto = returnlist[0]; level1Dto.qty = item.Qty; CaclMaterialShortage(returnlist); foreach (var child in returnlist) { var itemWorkOrdRoutingList = workOrdRoutingList.FindAll(w => w.WorkOrd == item.ProductionOrder); if (itemWorkOrdRoutingList != null && itemWorkOrdRoutingList.Count > 0) { foreach (var r in itemWorkOrdRoutingList) { if (r.ItemNum == child.item_number) { r.QtyOrded = child.needCount; itemRoutingUpdate.Add(r); } } } } } _workOrdMaster.Update(itemUpdate); _workOrdDetail.Update(itemDetailUpdate); _workOrdRouting.Update(itemRoutingUpdate); await _businessDbContext.BulkUpdateAsync(itemMesmorderList); await _businessDbContext.BulkUpdateAsync(itemMesmorderEntryList); } //DOP运行资源检查每个原材料SKU的可用库存,当可用库存<=修正后ROP时,自动生成月度采购申请(Purchase request,PR46年月日4位流水号)=EOP;可用库存为没有被其他SO和PO占用的(合格原材料库存+在途库存); var ropMaterialModelList = _replenishmentROPWeekPlan.GetListAsync(a => a.planmonth == planMonthQuery && a.erp_cls == 3 && a.distributionchannel == "瑞奇" && a.factory_id == input.factory_id && !a.IsDeleted).Result; List prList = new List(); var numbers = ropMaterialModelList.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).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(); var materialItemStock = _invMaster.Select(a => numbers.Contains(a.ItemNum) && a.Domain == input.factory_id.ToString()); //更新未确认未合并的PR //占用的PR不能扣减 var prCanUpdateList = _mysql_srm_pr_main.GetListAsync(a => icItemList.Select(c => c.Id).ToList().Contains(a.icitem_id.GetValueOrDefault()) && a.pr_ssend_date >= DateTime.Now.Date.AddDays(1) && a.state==1).Result; var prIds = prCanUpdateList.Select(a => a.Id).ToList(); var prOccupy=_mysql_srm_po_occupy.GetListAsync(a => prIds.Contains(a.polist_id.GetValueOrDefault()) && a.factory_id==input.factory_id).Result; var prOccupyIds = prOccupy.Select(a => a.polist_id).ToList(); prCanUpdateList = prCanUpdateList.Where(a => !prOccupyIds.Contains(a.Id)).ToList(); List prUpdateList = new List(); List prDeleteList = new List(); ropMaterialModelList.ForEach(b => { var materialQty=materialItemStock?.Where(c => c.ItemNum == b.number && c.Location.StartsWith('1')); decimal QtyStock = materialQty != null ? materialQty.Sum(c => c.AvailStatusQty.GetValueOrDefault() + c.Assay.GetValueOrDefault()) : 0; if (QtyStock < b.security_stock) { mo_srm_purchase supplier = null; 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 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 PrPurchaseDtoList = new List(); 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 = Math.Max(b.eop.Value,b.security_stock.GetValueOrDefault()- QtyStock); //判断最小起订量 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 = item.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); } else if(QtyStock>b.max_stock_level) { //扣减PR var item = icItemList.Find(d => d.number == b.number); var ItemPRList= prCanUpdateList.FindAll(a => a.icitem_id == item.Id); if( ItemPRList.Any() ) { ItemPRList=ItemPRList.OrderBy(a => a.pr_ssend_date).ToList(); var supplist = supplierList.Where(s => s.number == b.number).ToList(); decimal? QtySub = b.max_stock_level - QtyStock; for (int i=0;i0) { var supplier = supplist.Find(s => s.mysql_id == ItemPRList[i].pr_purchaseid); //扣减的时候要不要考虑经济批量? if (ItemPRList[i].pr_rqty < QtySub) { prDeleteList.Add(ItemPRList[i]); QtySub = QtySub - ItemPRList[i].pr_rqty; } else { if (ItemPRList[i].pr_rqty > supplier.qty_min) { if (ItemPRList[i].pr_rqty - supplier.qty_min > QtySub) { ItemPRList[i].pr_rqty = ItemPRList[i].pr_rqty - QtySub; prUpdateList.Add(ItemPRList[i]); break; } else { QtySub = QtySub - (ItemPRList[i].pr_rqty - supplier.qty_min); ItemPRList[i].pr_rqty = supplier.qty_min; prUpdateList.Add(ItemPRList[i]); } } } } } } } }); await _businessDbContext.BulkUpdateAsync(prUpdateList); prList.ForEach(a => { a.GenerateNewId(help.NextId()); }); await _businessDbContext.BulkInsertAsync(prList); return "OK"; } /// /// 同步工单等相关数据 /// /// /// 工艺路线数据 public void CreateWorkOrdDates(List morders, List allRoutings, List workOrds, List workOrdRoutings, List workOrdDetails, List exmResult, List childExamineList) { //var IsActived = _AccountValidityAppService.IsActived(); //if (!IsActived) //{ // return; //} //工单主表 WorkOrdMaster workOrd; //工单工艺路线表 WorkOrdRouting woRouting; //处理全局变量 param.factoryId = morders[0].factory_id.GetValueOrDefault(); List orderCode = morders.Select(c => c.product_code).ToList(); //成品虚拟件对应关系 var productOpList = _productStructureOp.Select(x => orderCode.Contains(x.ProductItem) && x.Domain == param.factoryId.ToString()); //获取物料主数据 List itemMasters = _itemMaster.Select(p => orderCode.Contains(p.ItemNum) && p.Domain == param.factoryId.ToString()).ToList(); foreach (var item in morders) { var moItem = exmResult.Find(b => b.morder_no ==item.morder_no); //添加工单数据 workOrd = new WorkOrdMaster(); workOrd.Domain = item.factory_id.ToString(); workOrd.OrdDate = item.moentry_sys_stime.GetValueOrDefault().Date; workOrd.ReleaseDate = Convert.ToDateTime(item.moentry_sys_stime.GetValueOrDefault().ToString("u")); workOrd.DueDate = item.moentry_sys_etime; workOrd.WorkOrd = item.morder_no; workOrd.ItemNum = item.product_code;//物料编码 workOrd.QtyOrded = item.need_number.GetValueOrDefault(); workOrd.Period = 1; workOrd.Priority = item.urgent; workOrd.Status =""; workOrd.IsActive = true; workOrd.IsConfirm = true; var curItem = itemMasters.FirstOrDefault(p => p.ItemNum == item.product_code); workOrd.CreateGLforLaborVar = curItem == null ? false : curItem.Install; workOrd.CreateTime = DateTime.Now; workOrd.Typed = ""; workOrd.IssueSite = "VMI"; //workOrd.SalesJob = item.morder_no; workOrds.Add(workOrd); //添加工单工艺路线数据 var curRoutings = allRoutings.Where(p => p.RoutingCode == item.product_code).ToList(); foreach (var dtl in curRoutings) { woRouting = new WorkOrdRouting(); woRouting.Domain = item.factory_id.ToString(); woRouting.Descr = dtl.Descr; woRouting.MilestoneOp = dtl.MilestoneOp; woRouting.WorkOrd = item.morder_no; woRouting.OP = dtl.Op; woRouting.ParentOp = dtl.ParentOp; woRouting.RunTime = dtl.RunTime; woRouting.ItemNum = item.product_code; woRouting.QtyOrded = item.need_number.GetValueOrDefault(); woRouting.OverlapUnits = dtl.OverlapUnits; woRouting.Status = ""; woRouting.IsActive = true; woRouting.CommentIndex = dtl.CommentIndex; woRouting.CreateTime = DateTime.Now; woRouting.StdOp = dtl.StdOp; woRouting.PackingQty = dtl.PackingQty.GetValueOrDefault(); workOrdRoutings.Add(woRouting); } long fid = GetParentMo(morders, item); var exm = exmResult.Find(s => s.morder_id == fid); if (exm != null) { var childs = childExamineList.Where(s => s.examine_id == exm.Id && s.is_use == true).ToList(); var child = childs.Find(s => s.item_number == item.product_code); if (child == null) { continue; } List returnList = new List(); var productOps = productOpList.Where(x => x.ProductItem == item.product_code).ToList(); GetWorkDetalis(childs.Where(s => s.parent_id == child.fid).ToList(), returnList, childs, productOps); if (returnList.Any()) { WorkOrdDetail woDetail = null; var calereturnList = returnList.OrderBy(c => c.item_number).Select(x => x.item_number).Distinct().ToList(); short num = 1; foreach (var caleNumber in calereturnList) { var caleList = returnList.Where(x => x.item_number == caleNumber).ToList(); var itemMst = itemMasters.Find(x => x.ItemNum == caleNumber); //添加工单的物料信息 woDetail = new WorkOrdDetail(); woDetail.Domain = item.factory_id.ToString(); woDetail.WorkOrd = item.morder_no; var oplist = caleList.Where(x => x.Op > 0).ToList(); woDetail.Op = 0; if (oplist.Any()) { woDetail.Op = oplist.Min(f => f.Op); } woDetail.ItemNum = caleNumber; woDetail.QtyPosted = 0m; woDetail.QtyReturned = 0m; woDetail.Status = ""; woDetail.IsActive = true; woDetail.CreateTime = DateTime.Now; woDetail.Line = num; woDetail.QtyRequired = caleList.Sum(c => c.needCount.GetValueOrDefault()); woDetail.Location = itemMst == null ? "" : itemMst.Location; if (workOrd.QtyOrded != 0) { woDetail.FrozenBOMQty = Math.Round(woDetail.QtyRequired / workOrd.QtyOrded, 10); } workOrdDetails.Add(woDetail); num++; } } } } } public long GetParentMo(List morders, mes_morder item) { if (item.parent_id != null) { var parentMo = morders.Find(s => s.Id == item.parent_id); if (parentMo != null) { return GetParentMo(morders, parentMo); } else { return item.Id; } } else { return item.Id; } } /// /// 获取虚拟件明细 /// /// /// /// public void GetWorkDetalis(List dtl, List returnList, List childs, List productOps) { returnList.AddRange(dtl.Where(x => x.erp_cls != 4).ToList()); var rst = childs.Where(s => dtl.Where(x => x.erp_cls == 4).Select(c => c.fid).Contains(s.parent_id.GetValueOrDefault())).ToList(); if (rst.Any()) { if (productOps.Any()) { //rst 虚拟件的子物料 foreach (var item in rst) { var parent = childs.Find(x => x.fid == item.parent_id); if (parent != null) { var proOp = productOps.Find(x => x.ParentItem == parent.item_number && x.ComponentItem == item.item_number); if (proOp != null) { item.Op = proOp.Op; } } } } GetWorkDetalis(rst, returnList, childs, productOps); } return; } /// /// 获取虚拟件明细 /// /// /// /// public void GetWorkDetalis(List dtl, List returnList, List childs, List productOps) { returnList.AddRange(dtl.Where(x => x.erp_cls != 4).ToList()); var rst = childs.Where(s => dtl.Where(x => x.erp_cls == 4).Select(c => c.fid).Contains(s.parent_id.GetValueOrDefault())).ToList(); if (rst.Any()) { if (productOps.Any()) { //rst 虚拟件的子物料 foreach (var item in rst) { var parent = childs.Find(x => x.fid == item.parent_id); if (parent != null) { var proOp = productOps.Find(x => x.ParentItem == parent.item_number && x.ComponentItem == item.item_number); if (proOp != null) { item.Op = proOp.Op; } } } } GetWorkDetalis(rst, returnList, childs, productOps); } return; } /// /// 根据工单编号排优先级 /// /// 工单编号列表 /// 工厂编码 /// //计算工单优先级 //public List CalcPriority(List workOrdMasters,string domain) //{ // var works= _workOrdMaster.Select(a => workOrdMasters.Contains(a.WorkOrd) && a.Domain == domain && a.IsActive); // var saleWordOrd = works.Where(a => !string.IsNullOrEmpty(a.SalesJob)); // 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).ThenBy(a => a.OrdDate).ToList(); // //优先2:T1、海外销售订单关联的在制生产指令; // var T1WOListInProduct = T1WOList.Where(a => inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).ToList(); // //优先3:平台(国科、海王)销售订单新产生的生产指令; // var T2WOListNew = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).ToList(); // //优先4:平台(国科、海王)销售订单关联的在制生产指令; // var T2WOListInProduct = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).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).ThenBy(a => a.OrdDate).ToList(); // //先按生产指令的类型,再按生产指令的完工日期顺序排产; // List orderedList = new List(); // 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; //} public List CalcPriority(List workOrdMasters, string domain) { var works = _workOrdMaster.Select(a => workOrdMasters.Contains(a.WorkOrd) && a.Domain == domain && a.IsActive); works = works.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).ToList(); List orderedList = new List(); decimal Priority = 1.0m; for (int i = 0; i < works.Count; i++) { works[i].Priority = Priority; orderedList.Add(works[i]); Priority = Priority + 1.0m; } return orderedList; } /// /// 根据工单排优先级(用于先排优先级再写入的场景) /// /// 工单编号列表 /// 工厂编码 /// //计算工单优先级 //public List CalcPriority(List works, string domain) //{ // var saleWordOrd = works.Where(a => !string.IsNullOrEmpty(a.SalesJob)); // 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).ThenBy(a=>a.OrdDate).ToList(); // //优先2:T1、海外销售订单关联的在制生产指令; // var T1WOListInProduct = T1WOList.Where(a => inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a=>a.OrdDate).ToList(); // //优先3:平台(国科、海王)销售订单新产生的生产指令; // var T2WOListNew = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a=>a.OrdDate).ToList(); // //优先4:平台(国科、海王)销售订单关联的在制生产指令; // var T2WOListInProduct = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a=>a.OrdDate).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).ThenBy(a=>a.OrdDate).ToList(); // //先按生产指令的类型,再按生产指令的完工日期顺序排产; // List orderedList = new List(); // 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; //} public List CalcPriority(List works, string domain) { works = works.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).ToList(); //先按生产指令的类型,再按生产指令的完工日期顺序排产; List orderedList = new List(); decimal Priority = 1.0m; for (int i = 0; i < works.Count; i++) { works[i].Priority = Priority; orderedList.Add(works[i]); Priority = Priority + 1.0m; } return orderedList; } //所有未下达的工单按照日期排序计算优先级 public void CalcPriority(string domain) { var works = _workOrdMaster.Select(a =>(string.IsNullOrEmpty(a.Status) || a.Status.ToUpper()=="P") && a.Typed.ToUpper() != "PW" && a.Domain == domain && a.IsActive); works = works.OrderBy(a => a.OrdDate).ToList(); var workOrdsList = works.Select(a => a.WorkOrd).ToList(); var weekPlan = _replenishmentWeekPlan.GetListAsync(a=>a.IsReplenishmentModel=="N" && workOrdsList.Contains(a.ProductionOrder)).Result; decimal Priority = 1.0m; for (int i = 0; i < works.Count; i++) { works[i].Priority = Priority; if (weekPlan.Any(a => a.ProductionOrder == works[i].WorkOrd)) { weekPlan.First(a=>a.ProductionOrder == works[i].WorkOrd).Priority = Priority; } Priority = Priority + 1.0m; } _businessDbContext.BulkUpdate(works); _businessDbContext.BulkUpdate(weekPlan); } /// /// 手动调整优先级 /// /// 工单编号列表 /// 工厂编码 /// //计算工单优先级 public async Task ChangePriority(string weekplanid, string tenant_id, string factory_id, string company_id, string itemNumber, string qty, string instockdate, string priority) { try { if (string.IsNullOrEmpty(qty)) return "数量不正确,请检查"; if (string.IsNullOrEmpty(instockdate)) return "成品入库日期不正确,请检查"; if (string.IsNullOrEmpty(priority)) return "优先级不正确,请检查"; decimal newpriority=Convert.ToDecimal(priority); DateTime newinstockdate=Convert.ToDateTime(instockdate); decimal newqty=Convert.ToDecimal(qty); long id= Convert.ToInt64(weekplanid); long tenantid=Convert.ToInt64(tenant_id); long factoryid=Convert.ToInt64(factory_id); long companyid=Convert.ToInt64(company_id); var weekPlan=_replenishmentWeekPlan.FindAsync(a => a.Id == id && a.tenant_id == tenantid && a.factory_id == factoryid && a.company_id == companyid).Result; //周计划没有生成周工单的不校验优先级重复 if(weekPlan!=null && !string.IsNullOrEmpty(weekPlan.ProductionOrder)) { var isExistSamePriority = _workOrdMaster.Select(a => a.WorkOrd !=weekPlan.ProductionOrder && (string.IsNullOrEmpty(a.Status) || a.Status.ToUpper()=="P") && (string.IsNullOrEmpty(a.Typed) || (!string.IsNullOrEmpty(a.Typed) && a.Typed.ToUpper() != "PW" && a.BusinessID > 0)) && a.Priority == newpriority); if (isExistSamePriority.Any()) return "优先级重复,请重新调整。"; } weekPlan.Priority= newpriority; weekPlan.Qty= newqty; //newinstockdate其实传的的工单开工日期 weekPlan.PlanStartDate= newinstockdate; if(!string.IsNullOrEmpty(weekPlan.ProductionOrder)) { long bang_id = help.NextId(); var moList = _mysql_mes_morder.GetListAsync(a => a.morder_no == weekPlan.ProductionOrder && a.factory_id == factoryid).Result; var moentryList = _mysql_mes_moentry.GetListAsync(a => a.moentry_mono == weekPlan.ProductionOrder && a.factory_id == factoryid).Result; var workmasterList = _workOrdMaster.Select(a => a.WorkOrd == weekPlan.ProductionOrder && a.Domain == factory_id); var workRoutings = _workOrdRouting.Select(a => a.WorkOrd == weekPlan.ProductionOrder && a.Domain == factory_id); //判断 if (moList.Count > 0 && (moList[0].morder_state == MorderEnum.Initial_state || string.IsNullOrEmpty(moList[0].morder_state)) && workmasterList.Count > 0 && (string.IsNullOrEmpty(workmasterList[0].Status) || workmasterList[0].Status == "p")) { moList[0].moentry_sys_stime = newinstockdate; moList[0].need_number = newqty; moList[0].morder_production_number = newqty; moentryList[0].need_number = newqty; moentryList[0].morder_production_number = newqty; workmasterList[0].OrdDate = newinstockdate; workmasterList[0].Priority = newpriority; workmasterList[0].QtyOrded = newqty; workRoutings?.ForEach(a => { a.QtyOrded = newqty; }); await PlanOrderResourceCheck(moList.OrderBy(a => a.moentry_sys_stime).ToList(), moentryList, bang_id, "", true,false); var examine_resultList = _mysql_examine_result.GetListAsync(a => a.bangid == bang_id).Result; if (weekPlan.IsReplenishmentModel == "N") { var moItem = examine_resultList.Find(b => b.morder_no == weekPlan.ProductionOrder); List routingOp = routingOps.Where(x => x.RoutingCode == weekPlan.ItemNumber).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.Descr == "包装" && x.MilestoneOp).FirstOrDefault(); if (moItem != null && moItem.kitting_times < weekPlan.PlanStartDate) { weekPlan.ItemStatus = "齐套"; weekPlan.PlanKittingDate = moItem.kitting_times; weekPlan.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * weekPlan.Qty; weekPlan.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * weekPlan.Qty; weekPlan.PackageHours = Packaging == null ? 0 : Packaging.RunTime * weekPlan.Qty; weekPlan.TotalHours = weekPlan.AssembleHours + weekPlan.HeatSealHours + weekPlan.PackageHours; } else { weekPlan.ItemStatus = "欠料"; weekPlan.PlanKittingDate = moItem.kitting_times; weekPlan.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * weekPlan.Qty; weekPlan.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * weekPlan.Qty; weekPlan.PackageHours = Packaging == null ? 0 : Packaging.RunTime * weekPlan.Qty; weekPlan.TotalHours = weekPlan.AssembleHours + weekPlan.HeatSealHours + weekPlan.PackageHours; } } string sql = "UPDATE mes_morder SET moentry_sys_stime='"+ newinstockdate + "',need_number="+ newqty + ",morder_production_number="+ newqty + " WHERE morder_no='" + weekPlan.ProductionOrder + "';" + "UPDATE mes_moentry SET need_number="+ newqty + ",morder_production_number="+ newqty + " WHERE moentry_mono='" + weekPlan.ProductionOrder + "';" + "UPDATE WorkOrdMaster SET OrdDate='"+ newinstockdate + "',Priority="+ newpriority + ",QtyOrded="+ newqty + " WHERE WorkOrd='" + weekPlan.ProductionOrder + "';" + "UPDATE WorkOrdRouting SET QtyOrded="+ newqty + " WHERE WorkOrd='" + weekPlan.ProductionOrder + "'; "+ "UPDATE WorkOrdDetail SET QtyRequired=CEILING(" + newqty + "*FrozenBOMQty) WHERE WorkOrd='" + weekPlan.ProductionOrder + "'; "; _businessDbContext.Database.ExecuteSqlRaw(sql); await _replenishmentWeekPlan.UpdateAsync(weekPlan); /*await _mysql_mes_morder.UpdateManyAsync(moList); await _mysql_mes_moentry.UpdateManyAsync(moentryList); _workOrdMaster.Update(workmasterList); _workOrdRouting.Update(workRoutings);*/ } else { return "工单不是初始状态,不允许调整。"; } } else { await _replenishmentWeekPlan.UpdateAsync(weekPlan); return "ok"; } } catch(Exception e) { return "调整失败,请联系管理员。"; } return "ok"; } /// /// 根据物料编码获取可用库存 /// 成品半成品可用库存为没有被其他SO和PO占用的(合格成品或半成品库存+WIP) /// 原材料可用库存为没有被其他SO和PO占用的(合格原材料库存+在途库存); /// /// 物料编码列表 /// public List CalcStock(List itemNumbers,InputDto input) { List itemQty = new List(); var locations = _invMaster.Select(p => p.Domain == input.factory_id.ToString() && itemNumbers.Contains(p.ItemNum) && p.IsActive); var sapInvList = _SAPInv.Select(a => a.WERKS == input.factory_id.ToString() && itemNumbers.Contains(a.MATNR) && (a.SOBKZ.ToUpper() == "O")); var stockOccupyList = _mysql_ic_item_stockoccupy.GetListAsync(a=> itemNumbers.Contains(a.icitem_number) && a.factory_id == input.factory_id && !a.IsDeleted).Result; itemNumbers.ForEach(a => { EOPDto eOPDto=new EOPDto(); eOPDto.ItemNumber = a; decimal stockqty = 0; if (locations.Any(s => s.ItemNum == a)) { stockqty = locations.Where(s => s.ItemNum == a).Sum(x => x.AvailStatusQty.GetValueOrDefault()); } decimal InSterilizationQty = 0; if (sapInvList.Count > 0 && sapInvList.Any(s => s.MATNR ==a)) { InSterilizationQty = sapInvList.Where(s => s.MATNR == a && s.SOBKZ.ToUpper() == "O").Sum(x => Convert.ToDecimal(x.LABST) + Convert.ToDecimal(x.INSME) + Convert.ToDecimal(x.SPEME)); } stockqty += InSterilizationQty; var occupyQty=stockOccupyList.Where(s => s.icitem_number == a).Sum(s => s.quantity); stockqty -= occupyQty; eOPDto.Qty = stockqty; itemQty.Add(eOPDto); }); return itemQty; } /// /// 计划工单齐套检查 /// /// /// public async Task PlanOrderResourceCheck(List Mes_Morders, List moentryList,long bangid,string analogCalcVersion,bool isChangePriority,bool IsWeekPlan) { if (Mes_Morders.Any()) { //Mes_Morders.ForEach(s => { s.moentry_sys_stime = DateTime.Now.Date.AddDays((double)lookDay + 1); }); List monolist = Mes_Morders.Select(c => c.morder_no).ToList(); if (string.IsNullOrEmpty(analogCalcVersion)) { var workOrds = _workOrdMaster.Select(a => monolist.Contains(a.WorkOrd) && a.Domain == param.factoryId.ToString() && a.IsActive).OrderBy(c => c.Priority).ToList(); List PriorityList = new List(); foreach (var item in workOrds) { var mesItem = Mes_Morders.Find(a => a.morder_no == item.WorkOrd); if (mesItem != null) { PriorityList.Add(mesItem); } } if(PriorityList.Any()) { Mes_Morders = PriorityList; } } //清理PR的占用。 //如果PR没有转PO,则PR没有合并,就删除,有合并,就减少合并后的PR的数量。 //var prlist = _mysql_srm_pr_main.GetListAsync(s => monolist.Contains(s.pr_mono)).Result; //List alllist = new List(); //List updatelist = new List(); //List dellist = new List(); //RecursionGetDbPr2(prlist, alllist); //foreach (var pr in prlist) //{ // //找到没有关闭的PR,如果关联上的PR都是已关闭,则说明已经转了PO。 // //TODO:解决Database operation expected to affect 1 row(s) but actually affected 0 row(s). 如果业务逻辑有问题自行修改 // var getPr = RerunPr(pr, alllist); // if (getPr != null) // { // if (getPr.pr_aqty - pr.pr_aqty <= 0) // { // //删除这个pr,没有小于0则是更新 // dellist.Add(getPr); // } // else // { // getPr.pr_aqty = getPr.pr_aqty - pr.pr_aqty; // updatelist.Add(getPr); // } // } //} List occupy = await _mysql_srm_po_occupy.GetListAsync(s => monolist.Contains(s.morder_mo)); _businessDbContext.BulkDelete(occupy); //if (updatelist.Any()) //{ // _businessDbContext.BulkUpdate(updatelist); //} //if (dellist.Any()) //{ // _businessDbContext.BulkDelete(dellist); //} //清理工单占用 List mooccupy = await _mysql_mes_mooccupy.GetListAsync(s => Mes_Morders.Select(c => c.Id).Contains(s.moo_id.GetValueOrDefault())); if (mooccupy.Any()) { _businessDbContext.BulkDelete(mooccupy); } //清理掉库存占用 var itemstockoccupy = _mysql_ic_item_stockoccupy.GetListAsync(s => monolist.Contains(s.morder_mo)).Result; if (itemstockoccupy.Any()) { _businessDbContext.BulkDelete(itemstockoccupy); } //清理锁定期外的排程数据. //var periodList = _periodSequenceDet.Select(s => monolist.Contains(s.WorkOrds)); //if (periodList.Any()) //{ // _periodSequenceDet.Delete(s => monolist.Contains(s.WorkOrds)); //} //var schedulList = _scheduleResultOpMaster.Select(s => monolist.Contains(s.WorkOrd)); //if (schedulList.Any()) //{ // _scheduleResultOpMaster.Delete(s => monolist.Contains(s.WorkOrd)); //} //只走计划工单 var rtn = await OrderKittingCheck(Mes_Morders, moentryList, bangid,analogCalcVersion,isChangePriority, true, IsWeekPlan); } else { return "未查找到对应的计划工单,请联系管理员。"; } return "ok"; } //找到没有关闭的PR,做数量的减少 public srm_pr_main RerunPr(srm_pr_main pr, List referlist) { //如果当前PR已经关闭,则检查合并数据 if (pr.state == 0) { //已关闭,并且没有关联数据,则代表转PO了。 var refPr = referlist.Find(s => s.pr_billno == pr.refer_pr_billno); //如果有关联,继续往下查 if (refPr != null) { return RerunPr(refPr, referlist); } else { return null; } } else { return pr; } } /// /// 递归寻找PR,找到合并后的PR /// public void RecursionGetDbPr2(List list, List referlist) { List prlist = _mysql_srm_pr_main.GetListAsync(s => list.Select(c => c.refer_pr_billno).Contains(s.pr_billno)).Result; if (prlist.Any()) { referlist.AddRange(prlist); RecursionGetDbPr2(prlist, referlist); } } /// /// 工单检查物料齐套 /// /// public async Task OrderKittingCheck(List mo_Mes_Morders, List moentryList,long bangid,string analogCalcVersion, bool isChangePriority, bool planCheck = false,bool IsWeekPlan=false) { //资源检查结果 PschedDto rtn = new PschedDto(); //资源检查明细list List examines = new List(); OrderCheckDto input = new OrderCheckDto(); if (mo_Mes_Morders.Any()) { input.company_id = mo_Mes_Morders[0].company_id; input.factoryId = mo_Mes_Morders[0].factory_id.GetValueOrDefault(); } //资源检查入参全局变量赋值 param.company_id = input.company_id; param.factoryId = input.factoryId; param.checkflag = false; param.checkPlan = planCheck; if(!string.IsNullOrEmpty(analogCalcVersion)) { _CalcBomViewAppService.LongPeriod = true; } /*List mo_Mes_Morders = _mes_morder.GetManyByCondition(x => x.start_time > DateTime .Now.Date.AddDays(1) && x.start_time < DateTime .Now.Date.AddDays(input.Day) && x.morder_state == MorderEnum.Initial_state && !x.IsDeleted && x.tenant_id == param.tenantId && x.bang_id == bangid).Result; List mo_Mes_Moentries = _mes_moentry.GetManyByCondition(x=> mo_Mes_Morders.Select(s => s.id).Contains(x.moentry_moid.Value)).Result;*/ var morderIdList = mo_Mes_Morders.Select(s => s.Id).ToList(); //List mo_Mes_Moentries = _mysql_mes_moentry.GetListAsync(x => morderIdList.Contains(x.moentry_moid.Value)).Result; List mo_Mes_Moentries = moentryList; //获取订单行数据 List sentrys = _mysql_crm_seorderentry.GetListAsync(p => p.factory_id == input.factoryId && !p.IsDeleted && mo_Mes_Moentries.Select(x => x.soentry_id).Contains(p.Id)).Result; //删除同步Mysql后旧数据 await DeleteMySqlOldData(sentrys); List boms = _ic_bom.GetListAsync(p => mo_Mes_Morders.Select(m => m.bom_number).Distinct().ToList().Contains(p.bom_number) && p.factory_id == input.factoryId && !p.IsDeleted).Result.ToList(); //物料bom List bomlist = new List(); //物料bom明细 List bomchildlist = new List(); //物料信息 List icitemlist = new List(); //替代关系 List sublist = new List(); List suballlist = new List(); List subdtllist = new List(); //物料库存表 List stocklist = new List(); //物料占用记录 List sklist = new List(); //sorder=null 是因为齐套检查不需要生成工单、采购、委外等信息,所以不需要关联的工单信息传递进去。 var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).Distinct().ToList().Contains(s.sourceid)).Result; List autoCreates = new List(); boms.ForEach(p => { if (!pretreatments.Where(s => s.sourceid == p.mysql_id).Any()) { autoCreates.Add(p); } }); if (autoCreates.Any()) { AutoCreateBomBill(param.company_id.ToString(), autoCreates); pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; } //增加特殊工单的预处理结果,因为特殊工单是自定义物料清单 List tsWork = new List { "试制工单", "返工工单" }; var specialWork = mo_Mes_Morders.Where(x => tsWork.Contains(x.morder_type)).ToList(); pretreatments.AddRange(_mysql_b_bom_pretreatment.GetListAsync(s => specialWork.Select(c => c.Id).ToList().Contains(s.sourceid)).Result); List itemNums = new List(); //计算需求 List AlignmentCalcList = new List(); if (IsWeekPlan) { var locationRange = _configurationItem.Select(x => x.FldName == "MRPLocationRange" && x.Domain == param.factoryId.ToString()).FirstOrDefault(); List locationList = new List { "1000", "1001", "5008", "8000", "8001" }; if (locationRange != null && locationRange.Val != null) { locationList = locationRange.Val.SplitToArray(",").ToList(); } List nbrType = new List { "SM", "OA", "IA"}; var nbrList = _nbrMaster.Select(x => x.Domain == param.factoryId.ToString() && nbrType.Contains(x.Type) && x.Status.ToUpper() != "C").ToList(); if (nbrList.Any()) { var nbrDtlList = _nbrDetail.Select(x => nbrList.Select(c => c.RecID).Contains(x.NbrRecID) && locationList.Contains(x.LocationFrom) && x.Status.ToUpper() != "C" && x.IsActive).ToList(); if (nbrDtlList.Any()) { nbrDtlList.ForEach(x => { if (x.QtyOrd - x.QtyRec > 0) { var dto = AlignmentCalcList.Find(s => s.ItemNum == x.ItemNum); if (dto == null) { dto = new AlignmentCalcDto(); dto.ItemNum = x.ItemNum; AlignmentCalcList.Add(dto); } dto.NeedQty += x.QtyOrd - x.QtyRec; } }); } } //退料单逻辑相反 var wodNbrList = _nbrMaster.Select(x => x.Domain == param.factoryId.ToString() && x.Type == "WOD" && x.Status.ToUpper() != "C").ToList(); if (wodNbrList.Any()) { //WOD是退料 var wodNbrDtlList = _nbrDetail.Select(x => wodNbrList.Select(c => c.RecID).Contains(x.NbrRecID) && locationList.Contains(x.LocationTo) && x.Status.ToUpper() != "C" && x.IsActive).ToList(); if (wodNbrDtlList.Any()) { wodNbrDtlList.ForEach(x => { if (x.QtyOrd - x.QtyRec > 0) { var dto = AlignmentCalcList.Find(s => s.ItemNum == x.ItemNum); if (dto == null) { dto = new AlignmentCalcDto(); dto.ItemNum = x.ItemNum; AlignmentCalcList.Add(dto); } dto.NeedQty -= x.QtyOrd - x.QtyRec; } }); } } itemNums.AddRange(AlignmentCalcList.Select(x => x.ItemNum)); } var pretreatList = pretreatments.Select(x => x.item_number).Distinct().ToList(); itemNums.AddRange(pretreatList); await AsyncItemStockFromWMS(itemNums, analogCalcVersion); //数据库快照-同步mysql库数据到mongoDB中 await DbSnapShot(input.company_id, input.factoryId, bangid, pretreatments, analogCalcVersion); DataInitialization(boms, bangid, icitemlist, stocklist, pretreatments, sklist); _CalcBomViewAppService.param = param; List GenerateMoList = new List(); var moNbrlistDto = _serialNumberAppService.GetBillNo(input.factoryId.ToString(), "M5", mo_Mes_Morders.Count, "", 1); if (moNbrlistDto.Any()) { foreach (var nbr in moNbrlistDto) { GenerateMoList.Add(nbr.NbrResult); } } _CalcBomViewAppService.GenerateMoList = GenerateMoList; _CalcBomViewAppService.newStockOccList = new List(); foreach (var item in mo_Mes_Morders) { var moentry = mo_Mes_Moentries.Find(s => s.moentry_moid == item.Id); if (moentry == null) { continue; } var sentry = sentrys.Find(s => s.Id == moentry.soentry_id); //工单资源检查信息 ExamineResult dtl = new ExamineResult(); dtl.morder_id = item.Id; dtl.morder_no = item.morder_no; dtl.bangid = bangid; dtl.order_statr_time = item.start_time; dtl.bom_number = item.bom_number; dtl.need_qty = item.need_number.GetValueOrDefault(); //获取当前物料bom数据 //var childBom = boms.Where(p => p.bom_number == item.bom_number).FirstOrDefault(); //获取当前物料bom数据 List itemPrelist = new List(); //通过工单ID读取,考虑特殊工单的预处理 itemPrelist = pretreatments.Where(s => s.sourceid == item.Id).ToList(); if (!itemPrelist.Any()) { var childBom = boms.Where(p => p.bom_number == item.bom_number).FirstOrDefault(); if (childBom != null) { itemPrelist = pretreatments.Where(s => s.sourceid == childBom.mysql_id).ToList(); } else { continue; } } if (!itemPrelist.Any()) { continue; } var getBomList = ObjectMapper.Map, List>(itemPrelist); if (sentry != null) { dtl.sentry_id = sentry.Id; getBomList.ForEach(s => s.sentry_id = item.Id); } _CalcBomViewAppService.mes_morder = item; _CalcBomViewAppService.morder_type = item.morder_type; //库存初始化 _CalcBomViewAppService.BomStock(getBomList, stocklist, bangid); //计算 _CalcBomViewAppService.CalcView(getBomList, bangid, item.need_number.GetValueOrDefault(), item.moentry_sys_stime, sklist, sentry, icitemlist); //TODO:最晚开始时间 //var curFacDtl = leadTimeList.FirstOrDefault(p => p.item_id == childBom.icitem_id); //物料齐套时间 dtl.kitting_times = getBomList.Where(p => p.is_use && p.kitting_time != null).OrderByDescending(m => m.kitting_time).First().kitting_time.GetValueOrDefault(); //替代关系展开list dtl.BomChildExamineList = getBomList; //添加订单行开工信息 examines.Add(dtl); } rtn.examines = examines; if (planCheck) { //如果有计划工单,则需要生成pr po oo List prmainlist = new List(); List pr_mainlist = new List(); if (_CalcBomViewAppService.SRMPRDtoList.Any()) { List> prlist = _CalcBomViewAppService.SRMPRDtoList.Where(f => f.srm_Pr_Main != null).Select(s => s.srm_Pr_Main).ToList(); List list = new List(); foreach (var pr in prlist) { foreach (var item in pr) { list.Add(item); prmainlist.Add(item); } } if (list.Any()) rtn.srm_pr_list = _CalcBomViewAppService.SRMPRDtoList; } if (prmainlist.Any()) { var nbrlistDto = _serialNumberAppService.GetBillNo(prmainlist[0].factory_id.ToString(), "PR", prmainlist.Count, "admin", 1); int index = 0; foreach (var p in prmainlist) { if (nbrlistDto[index] != null) { p.pr_billno = nbrlistDto[index].NbrResult.ToString(); } index++; if (p.pr_purchaseid.GetValueOrDefault() == 0) { //数据丢失 var list = _mysql_srm_purchase.GetListAsync(s => s.icitem_id == p.icitem_id).Result; if (list.Any()) { var purchase = list.OrderBy(s => s.quota_priority).FirstOrDefault(); p.pr_purchaseid = purchase.supplier_id; p.pr_purchasename = purchase.supplier_name; p.pr_purchasenumber = purchase.supplier_number; } } } pr_mainlist = ObjectMapper.Map, List>(prmainlist); pr_mainlist.ForEach(a => { a.analogcalcversion = analogCalcVersion; }); } //暂时屏蔽重新生成工单物料明细 List mainWorkOrdDetails = new List(); List delWorkOrddetails = new List(); //获取物料主数据 List itemMasters = _itemMaster.Select(p => p.Domain == param.factoryId.ToString()).ToList(); //成品虚拟件对应关系 var productOpList = _productStructureOp.Select(x => mo_Mes_Morders.Select(c => c.product_code).Contains(x.ProductItem) && x.Domain == param.factoryId.ToString()); var workOrds = _workOrdMaster.Select(a => mo_Mes_Morders.Select(p => p.morder_no).ToList().Contains(a.WorkOrd) && a.Domain == param.factoryId.ToString() && a.IsActive); delWorkOrddetails = _workOrdDetail.Select(x => workOrds.Select(c => c.RecID).Contains((int)x.WorkOrdMasterRecID) && x.Domain == param.factoryId.ToString()); foreach (var workord in mo_Mes_Morders) { long fid = GetParentMo(mo_Mes_Morders, workord); var exm = examines.Find(s => s.morder_id == fid); //var exm = examines.Find(s => s.morder_no == workord.morder_no); if (exm != null) { var childs = exm.BomChildExamineList.Where(s => s.is_use == true).ToList(); var child = childs.Find(s => s.item_number == workord.product_code); if (workord.morder_type == "返工工单") { child = childs.Find(s => s.item_number == workord.product_code && s.level == 1); } if (child == null) { continue; } List returnList = new List(); var productOps = productOpList.Where(x => x.ProductItem == workord.product_code).ToList(); GetWorkDetalis(childs.Where(s => s.parent_id == child.fid).ToList(), returnList, childs, productOps); if (returnList.Any()) { WorkOrdDetail woDetail = null; var calereturnList = returnList.OrderBy(c => c.item_number).Select(x => x.item_number).Distinct().ToList(); var work = workOrds.Find(x => x.WorkOrd == workord.morder_no); if (work == null) { continue; } short num = 1; foreach (var caleNumber in calereturnList) { var caleList = returnList.Where(x => x.item_number == caleNumber).ToList(); var itmeMst = itemMasters.Find(x => x.ItemNum == caleNumber); //添加工单的物料信息 woDetail = new WorkOrdDetail(); woDetail.Domain = workord.factory_id.ToString(); woDetail.WorkOrd = workord.morder_no; var oplist = caleList.Where(x => x.Op > 0).ToList(); woDetail.Op = 0; if (oplist.Any()) { woDetail.Op = oplist.Min(f => f.Op); } woDetail.ItemNum = caleNumber; woDetail.QtyPosted = 0m; woDetail.QtyReturned = 0m; woDetail.Status = ""; woDetail.IsActive = true; woDetail.CreateTime = DateTime.Now; woDetail.Line = num; woDetail.QtyRequired = caleList.Sum(c => c.needCount); woDetail.WorkOrdMasterRecID = work.RecID; woDetail.Location = itmeMst == null ? "" : itmeMst.Location; if (workord.need_number != 0) { woDetail.FrozenBOMQty = Math.Round(woDetail.QtyRequired / workord.need_number.GetValueOrDefault(), 10); } mainWorkOrdDetails.Add(woDetail); num++; } } } } List updatPrList = new List(); List deletePrList = new List(); List addPrList = new List(); if (IsWeekPlan) { foreach (var exami in examines) { exami.BomChildExamineList.ForEach(x => { if ((x.erp_cls == 2 || x.erp_cls == 3) && x.is_use) { var dto = AlignmentCalcList.Find(s => s.ItemNum == x.item_number); if (dto == null) { dto = new AlignmentCalcDto(); dto.ItemNum = x.item_number; AlignmentCalcList.Add(dto); } dto.NeedQty += x.needCount; } }); } var ic_items = _mysql_ic_item.GetListAsync(x => AlignmentCalcList.Select(c => c.ItemNum).Contains(x.number)).Result; //库存 var dbitemstockList = _mysql_ic_item_stock.GetListAsync(a => AlignmentCalcList.Select(x => x.ItemNum).Contains(a.icitem_number) && a.factory_id == param.factoryId).Result; //获取PR和PO var DBprmainList = _mysql_srm_pr_main.GetListAsync(x => x.factory_id == param.factoryId && x.state != 0 && x.state != 4 && string.IsNullOrEmpty(x.analogcalcversion) == true && ic_items.Select(a => a.Id).Contains(x.icitem_id.GetValueOrDefault())).Result; //PO、DO var purordmstList = _PurOrdMaster.Select(x => string.IsNullOrEmpty(x.Status) && x.Status.ToUpper() != "C").ToList(); var purorddtlList = new List(); if (purordmstList.Any()) { purorddtlList = _PurOrdDetail.Select(x => purordmstList.Select(a => a.PurOrd).Contains(x.PurOrd) && x.QtyOrded - x.RctQty > 0 && string.IsNullOrEmpty(x.Status) && x.Status.ToUpper() != "C").ToList(); } AlignmentCalcList.ForEach(x => { var stock = dbitemstockList.Find(c => c.icitem_number == x.ItemNum); if (stock != null) { x.InventoryQty += stock.sqty.GetValueOrDefault(); } if (DBprmainList.Any() || prmainlist.Any()) { var icitem = ic_items.Find(a => a.number == x.ItemNum); if (icitem != null) { x.ProcureQty += DBprmainList.Where(a => a.icitem_id == icitem.Id).Sum(c => c.pr_aqty.GetValueOrDefault()); x.ProcureQty += prmainlist.Where(a => a.icitem_id == icitem.Id).Sum(c => c.pr_aqty.GetValueOrDefault()); } } if (purorddtlList.Any()) { x.ProcureQty += purorddtlList.Where(a => a.ItemNum == x.ItemNum).Sum(c => c.QtyOrded - c.RctQty); } //差异数量=工单需求总数-库存数量-PR、PO采购在途数量 x.DifferenceQty = x.NeedQty - x.InventoryQty - x.ProcureQty; }); //需要增加PR的集合 var prAddList = AlignmentCalcList.Where(x => x.DifferenceQty > 0).ToList(); //需要减少PR的集合 var prDelList = AlignmentCalcList.Where(x => x.DifferenceQty < 0).ToList(); var dbPurchaseList = _mysql_srm_purchase.GetListAsync(x => x.factory_id == param.factoryId && x.quota_rate.GetValueOrDefault() > 0 && AlignmentCalcList.Select(c => c.ItemNum).Contains(x.number)).Result; //获取需要新增的PR var sysSet = _generalizedCodeMaster.Select(s => s.FldName == "SystemConfig" && s.Val == "ScheduleAgreement" && s.Domain == param.factoryId.ToString()).ToList(); int ScheduleAgreement = 0;//计划协议 0不启用,1启用 if (sysSet.Any()) { if (!string.IsNullOrEmpty(sysSet[0].Ufld1)) { int.TryParse(sysSet[0].Ufld1, out ScheduleAgreement); } } //需要新增的PR集合 addPrList = CalcPrAdd(prAddList, dbPurchaseList, ic_items, ScheduleAgreement); if (addPrList.Any()) { var addPrlistDto = _serialNumberAppService.GetBillNo(param.factoryId.ToString(), "PR", addPrList.Count, "admin", 1); int index = 0; foreach (var p in addPrList) { if (addPrlistDto[index] != null) { p.pr_billno = addPrlistDto[index].NbrResult.ToString(); } index++; } } //数据库需要减少的PR集合 CalcPrDel(prDelList, dbPurchaseList, ic_items, DBprmainList.Where(x=>x.state==1).ToList(), updatPrList, deletePrList, pr_mainlist);//只取新增状态的PR,可以做删除或者修改 new NLogHelper("AlignmentCalcList").WriteLog("AlignmentCalcList", JsonConvert.SerializeObject(AlignmentCalcList), _currentTenant.Id.ToString()); } using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { _businessDbContext.BulkUpdate(mo_Mes_Morders); //长周期都是成品检查,生成的都是中间件工单,不需要写入;周计划包含中间件工单,需要写入 //长周期也需要写入,加字段版本区分 if (_CalcBomViewAppService.mordersInsertList.Any()) { var molist = ObjectMapper.Map, List>(_CalcBomViewAppService.mordersInsertList); molist.ForEach(a => { a.analogcalcversion = analogCalcVersion; }); _businessDbContext.BulkInsert(molist); List workOrdSave = new List(); List workOrdRoutingSave = new List(); List workOrdDetails = new List(); if (molist.Any()) { molist.ForEach(s => { s.create_time = DateTime.Now;s.factory_id = input.factoryId;s.company_id = input.company_id; }); //同步工单 CreateWorkOrdDates(molist, routingOps, workOrdSave, workOrdRoutingSave, workOrdDetails, new List(), new List()); if (workOrdSave.Any()) { workOrdSave.ForEach(a => { a.AnalogCalcVersion = analogCalcVersion; }); _businessDbContext.BulkInsert(workOrdSave); CalcPriority(input.factoryId.ToString()); } var DBworkOrdList = _workOrdMaster.Select(a => workOrdSave.Count > 0 && a.Domain == workOrdSave[0].Domain && workOrdSave.Select(c => c.WorkOrd).Contains(a.WorkOrd)); if (workOrdRoutingSave.Any()) { workOrdRoutingSave.ForEach(c => { c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID; }); _businessDbContext.BulkInsert(workOrdRoutingSave); } if (workOrdDetails.Any()) { workOrdDetails.ForEach(c => { c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID; }); _businessDbContext.BulkInsert(workOrdDetails); } } } if (_CalcBomViewAppService.moentriesInsertList.Any() && string.IsNullOrEmpty(analogCalcVersion)) { var moentrylist = ObjectMapper.Map, List>(_CalcBomViewAppService.moentriesInsertList); _businessDbContext.BulkInsert(moentrylist); } if (pr_mainlist.Any()) { _businessDbContext.BulkInsert(pr_mainlist); } if (_CalcBomViewAppService.newStockOccList.Any()) { var stockoccupylist = ObjectMapper.Map, List>(_CalcBomViewAppService.newStockOccList); stockoccupylist.ForEach(s => { s.GenerateNewId(help.NextId()); s.create_time = DateTime.Now; s.tenant_id = param.company_id.GetValueOrDefault(); s.company_id = param.company_id; s.factory_id = param.factoryId; }); _businessDbContext.BulkInsert(stockoccupylist); } if (_CalcBomViewAppService.srm_Po_OccupiesInsert.Any()) { _CalcBomViewAppService.srm_Po_OccupiesInsert.ForEach(s => { s.company_id = param.company_id; s.factory_id = param.factoryId; }); var srmpooccupyInsert = ObjectMapper.Map, List>(_CalcBomViewAppService.srm_Po_OccupiesInsert); srmpooccupyInsert.ForEach(x => { x.GenerateNewId(help.NextId()); }); _businessDbContext.BulkInsert(srmpooccupyInsert); } if (delWorkOrddetails.Any()) { _businessDbContext.BulkDelete(delWorkOrddetails); } if (mainWorkOrdDetails.Any()) { _businessDbContext.BulkInsert(mainWorkOrdDetails); } if (IsWeekPlan) { if (addPrList.Any()) { _businessDbContext.BulkInsert(addPrList); } if (updatPrList.Any()) { _businessDbContext.BulkUpdate(updatPrList); } if (deletePrList.Any()) { await _mysql_srm_pr_main.HardDeleteAsync(deletePrList); } } await unitOfWork.CompleteAsync(); } catch (Exception e) { unitOfWork.Dispose(); new NLogHelper("ResourceExamineAppService").WriteLog("OrderKittingCheck", "工单检查数据更新失败:" + e.Message, _currentTenant.Id.ToString()); } } } //检查结果写入数据库 await ExamineResultInsertDBAsync(examines); //清空快照数据 await ClearSnapShot(bangid); return rtn; } public void CalcPrDel(List prDelList,List purchase,List ic_items, List dbPrlist, List updatPrList, List deletePrList,List prmainlist) { prDelList.ForEach(dto => { var itemPurList = purchase.Where(x => x.number == dto.ItemNum).ToList(); var icitem = ic_items.Find(x => x.number == dto.ItemNum); if (itemPurList.Any() && icitem!=null) { itemPurList.ForEach(c => { //当前供应商需减少数量 decimal qty = Math.Floor(Math.Abs(dto.DifferenceQty) * c.quota_rate.GetValueOrDefault() / 100); var MoItemSupplierList = prmainlist.Where(x => x.icitem_id == icitem.Id && x.pr_purchaseid == c.supplier_id).OrderByDescending(f => f.pr_sarrive_date).ToList(); if (MoItemSupplierList.Any()) { foreach (var moPr in MoItemSupplierList) { if (moPr.pr_aqty > qty)//一个PR够减 { moPr.pr_aqty = moPr.pr_aqty - qty; moPr.pr_rqty = moPr.pr_aqty; moPr.pr_sqty = moPr.pr_aqty; dto.updateQty += qty; qty = 0; dto.updatePrlist.Add(moPr); continue; } else if (moPr.pr_aqty == qty)//一个PR够减 { dto.deleteQty += qty; prmainlist.Remove(moPr); qty = 0; dto.deletePrlist.Add(moPr); continue; } else { dto.deleteQty += moPr.pr_aqty.GetValueOrDefault(); qty -= moPr.pr_aqty.GetValueOrDefault(); prmainlist.Remove(moPr); dto.deletePrlist.Add(moPr); } } } if (qty > 0) { //当前物料当前供应商的在途采购申请 var itemSupplierList = dbPrlist.Where(x => x.icitem_id == icitem.Id && x.pr_purchaseid == c.supplier_id).OrderByDescending(f => f.pr_sarrive_date).ToList(); if (itemSupplierList.Any()) { foreach (var itemPr in itemSupplierList) { if (itemPr.pr_aqty > qty)//一个PR够减 { itemPr.pr_aqty = itemPr.pr_aqty - qty; itemPr.pr_rqty = itemPr.pr_aqty; itemPr.pr_sqty = itemPr.pr_aqty; updatPrList.Add(itemPr); dto.updatePrlist.Add(itemPr); dto.updateQty = qty; qty = 0; continue; } else if (itemPr.pr_aqty == qty)//一个PR够减 { dto.deleteQty += qty; deletePrList.Add(itemPr); dto.deletePrlist.Add(itemPr); qty = 0; continue; } else { dto.deleteQty += itemPr.pr_aqty.GetValueOrDefault(); qty -= itemPr.pr_aqty.GetValueOrDefault(); deletePrList.Add(itemPr); dto.deletePrlist.Add(itemPr); } if (qty == 0) { continue; } } } } }); } }); } public List CalcPrAdd(List prAddList, List purchase, List ic_items,int ScheduleAgreement) { List prList = new List(); prAddList.ForEach(dto => { var itemPurList = purchase.Where(x => x.number == dto.ItemNum).ToList(); var icitem = ic_items.Find(x => x.number == dto.ItemNum); foreach (var supplier in itemPurList) { srm_pr_main srm_Pr = new srm_pr_main(); srm_Pr.GenerateNewId(help.NextId()); srm_Pr.pr_order_type = icitem.erp_cls == 2 ? "L" : "";//单据类型 srm_Pr.supplier_type = supplier.supplier_type; srm_Pr.IsRequireGoods = supplier.IsRequireGoods; if (supplier.supplier_type == "VMI") { srm_Pr.IsRequireGoods = 1; srm_Pr.pr_order_type = "K"; } 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;//采购员工号(采购信息表) srm_Pr.pr_rqty = Math.Ceiling(dto.DifferenceQty * supplier.quota_rate.GetValueOrDefault() / 100);//需求数量 srm_Pr.pr_aqty = srm_Pr.pr_rqty;//申请数量 srm_Pr.pr_sqty = srm_Pr.pr_rqty;//建议数量 srm_Pr.icitem_id = icitem.Id;//物料id srm_Pr.icitem_name = icitem.name;//物料名称 //srm_Pr.num = returnlist.num; if (ScheduleAgreement==1) { supplier.lead_time = 7;//启用计划协议时,默认为7天。 srm_Pr.pr_ssend_date = DateTime.Now.Date.AddDays(1);//系统建议下单日期 srm_Pr.pr_sarrive_date = DateTime.Now.AddDays((double)supplier.lead_time.GetValueOrDefault());//系统建议到达日期(建议到货日期) }else { srm_Pr.pr_ssend_date = DateTime.Now.Date.AddDays(1);//系统建议下单日期 srm_Pr.pr_sarrive_date = DateTime.Now.Date.AddDays(1).AddDays((int)(Math.Ceiling(icitem.clean_leadtime.GetValueOrDefault() + icitem.self_inspection_date.GetValueOrDefault()))); } srm_Pr.pr_sysprice = supplier.order_price;//系统价格(含税) srm_Pr.pr_orderprice = srm_Pr.pr_rqty * supplier.order_price;//订单价格(含税) srm_Pr.pr_price = supplier.netpurchase_price;//采购净价(不含税) srm_Pr.pr_rate = supplier.taxrate;//税率 srm_Pr.pr_unit = icitem.unit;//单位 srm_Pr.state = 1;//状态 srm_Pr.old_apply_aqty = 0;//已申请数量 srm_Pr.pr_type = icitem.erp_cls == 2 ?2 :3;//申请类型 srm_Pr.currencytype = supplier.currency_type == null ? 1 : supplier.currency_type.Value;//币种 srm_Pr.secInv_ratio = icitem.secinv_ratio;//安全库存触发采购比例 srm_Pr.tenant_id = param.company_id; srm_Pr.company_id = param.company_id; srm_Pr.factory_id = param.factoryId; 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); dto.addPrlist.Add(srm_Pr); } }); return prList; } public async Task ExamineResultInsertDBAsync(List examines) { //检查结果写入数据库 List examineList = new List(); List bomExamineList = new List(); List mooccupyList = new List(); List moorderList = new List(); List ooderList = new List(); List purchaseList = new List(); List purchaseoccupyList = new List(); foreach (var ex in examines) { var b_ex = ObjectMapper.Map(ex); b_ex.GenerateNewId(help.NextId());// = help.NextId(); if (_CalcBomViewAppService.mordersInsertList.Any()) { var sentryMo = _CalcBomViewAppService.mordersInsertList.Where(s => s.mysql_id == b_ex.morder_id).FirstOrDefault(); if (sentryMo != null) { b_ex.morder_id = sentryMo.mysql_id; b_ex.morder_no = sentryMo.morder_no; } } b_ex.create_time = DateTime.Now; b_ex.company_id = param.company_id; b_ex.tenant_id = param.company_id; b_ex.factory_id = param.factoryId; examineList.Add(b_ex); ex.BomChildExamineList.ForEach(s => { var bc_ex = ObjectMapper.Map(s); bc_ex.GenerateNewId(help.NextId()); bc_ex.examine_id = b_ex.Id; bc_ex.company_id = param.company_id; bc_ex.tenant_id = param.company_id; bc_ex.factory_id = param.factoryId; bc_ex.create_time = DateTime.Now; bomExamineList.Add(bc_ex); if (s.mo_occupy_list != null) { var olist = ObjectMapper.Map, List>(s.mo_occupy_list); olist.ForEach(o => { o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id; o.factory_id = param.factoryId; }); mooccupyList.AddRange(olist); } if (s.make_list != null) { var mlist = ObjectMapper.Map, List>(s.make_list); mlist.ForEach(o => { o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id; o.factory_id = param.factoryId; }); moorderList.AddRange(mlist); } if (s.subcontracting_list != null) { var slist = ObjectMapper.Map, List>(s.subcontracting_list); slist.ForEach(o => { o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id; o.factory_id = param.factoryId; }); ooderList.AddRange(slist); } if (s.purchase_list != null) { var plist = ObjectMapper.Map, List>(s.purchase_list); plist.ForEach(o => { o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id; o.factory_id = param.factoryId; }); purchaseList.AddRange(plist); } if (s.purchase_occupy_list != null) { var purlist = ObjectMapper.Map, List>(s.purchase_occupy_list); purlist.ForEach(o => { o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id; o.factory_id = param.factoryId; }); purchaseoccupyList.AddRange(purlist); } }); } using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { if (examineList.Any()) { _businessBangDbContext.BulkInsert(examineList); } if (bomExamineList.Any()) { _businessBangDbContext.BulkInsert(bomExamineList.OrderBy(s => s.num_order).ToList()); } if (mooccupyList.Any()) { _businessBangDbContext.BulkInsert(mooccupyList); } if (moorderList.Any()) { _businessBangDbContext.BulkInsert(moorderList); } if (ooderList.Any()) { _businessBangDbContext.BulkInsert(ooderList); } if (purchaseList.Any()) { _businessBangDbContext.BulkInsert(purchaseList); } if (purchaseoccupyList.Any()) { _businessBangDbContext.BulkInsert(purchaseoccupyList); } await unitOfWork.CompleteAsync(); } catch (Exception e) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "资源检查计算结果相关数据更新失败:" + e.Message, _currentTenant.Id.ToString()); unitOfWork.Dispose(); } } } /// /// 删除旧订单行数据 /// /// /// /// /// public async Task DeleteMySqlOldData(List soentry_id) { List sentryids = soentry_id.Select(p => p.Id).ToList(); //删除工单相关表数据 /*var mes_moentry = _mysql_mes_moentry.GetListAsync(x => sentryids.Contains(x.soentry_id.Value)).Result; var mes_morder = _mysql_mes_morder.GetListAsync(x => mes_moentry.Select(p => p.moentry_moid).ToList().Contains(x.Id)).Result; if (mes_moentry.Count > 0) { await _mysql_mes_moentry.DeleteManyAsync(mes_moentry); } if (mes_morder.Count > 0) { await _mysql_mes_morder.DeleteManyAsync(mes_morder); }*/ var mysql_mes_mooccupy = _mysql_mes_mooccupy.GetListAsync(x => soentry_id.Select(p => p.Id).Contains(x.moo_id_billid.Value)).Result; if (mysql_mes_mooccupy.Count > 0) { await _businessDbContext.BulkDeleteAsync(mysql_mes_mooccupy); } /*var srm_pr_main = _mysql_srm_pr_main.GetListAsync(x => soentry_id.Select(p => p.Id).Contains(x.sentry_id.GetValueOrDefault())).Result; if (srm_pr_main.Count > 0) { await _mysql_srm_pr_main.DeleteManyAsync(srm_pr_main); }*/ /*var mes_oorders = _mysql_mes_oorder.GetListAsync(x => soentry_id.Select(p => p.Id).Contains(x.sentry_id.GetValueOrDefault())).Result; if (mes_oorders.Count > 0) { await _mysql_mes_oorder.DeleteManyAsync(mes_oorders); }*/ } /// /// 数据库快照 /// /// public async Task DbSnapShot(long? companyId, long factoryId, long bangid, List pretreatments, string analogCalcVersion) { //TODO:申老师明确后续需要调整 根据需要使用的字段,来同步表数据。 //同步物料库存数据 根据预处理,来只找出部分数据同步。 List itemIds = pretreatments.Select(s => s.item_id.GetValueOrDefault()).Distinct().ToList(); //var icitemStokc = _mysql_ic_item_stock.GetListAsync(p => p.tenant_id == tenantId && p.factory_id == factoryId).Result; var icitemStokc = _mysql_ic_item_stock.GetListAsync(p => itemIds.Contains(p.icitem_id) && p.company_id == companyId).Result; if (icitemStokc.Count > 0) { List numbers = pretreatments.Select(s => s.item_number).Distinct().ToList(); var locationRange = _configurationItem.Select(x => x.FldName == "MRPLocationRange" && x.Domain == factoryId.ToString()).FirstOrDefault(); List locationList = new List { "1000", "1001", "5008", "8000", "8001" }; if (locationRange != null && locationRange.Val != null) { locationList = locationRange.Val.SplitToArray(",").ToList(); } var locStock = _invMaster.Select(a => numbers.Contains(a.ItemNum) && a.IsActive && a.Domain == factoryId.ToString() && locationList.Contains(a.Location)); var sapInvList = _SAPInv.Select(a => numbers.Contains(a.MATNR) && a.WERKS == factoryId.ToString() && (a.SOBKZ.ToUpper() == "O" || locationList.Contains(a.LGORT))); //设置当前计算bangid icitemStokc.ForEach(item => { item.bang_id = bangid; item.sqty = 0; foreach (var lct in locationList) { var lctQty = locStock.Where(s => s.ItemNum == item.icitem_number && s.Location == lct).Sum(p => p.AvailStatusQty.GetValueOrDefault() + p.Assay.GetValueOrDefault()); if (lctQty == 0) { lctQty = sapInvList.Where(x => x.MATNR == item.icitem_number && x.LGORT == lct).Sum(p => p.LABST + p.INSME); } item.sqty += lctQty; } if(!string.IsNullOrEmpty(analogCalcVersion)) { item.sqty += sapInvList.Where(x => x.MATNR == item.icitem_number && x.SOBKZ.ToUpper() == "O").Sum(p => p.LABST + p.INSME); } }); var moIcitemStokc = ObjectMapper.Map, List>(icitemStokc); moIcitemStokc.ForEach(item => { item.GenerateNewId(help.NextId());item.create_time = DateTime.Now;}); //插入数据 await MongoHelper.InsertManyAsync(moIcitemStokc); } var workordmsters = new List(); if (string.IsNullOrEmpty(analogCalcVersion)) { //周计划屏蔽年度产生的工单 workordmsters = _workOrdMaster.Select(s => s.Domain == factoryId.ToString() && string.IsNullOrEmpty(s.Status) != true && s.Status.ToLower() != "c" && string.IsNullOrEmpty(s.AnalogCalcVersion)); } else { workordmsters = _workOrdMaster.Select(s => s.Domain == factoryId.ToString() && string.IsNullOrEmpty(s.Status) != true && s.Status.ToLower() != "c"); } if (workordmsters.Any()) { //根据工单表找到工单明细,然后根据DOP工单占用记录,对比工单明细发货数量,来做冲销。 //var workdetails = _workOrdDetail.Select(s => workordmsters.Select(c => c.WorkOrd).Contains(s.WorkOrd)); List item_occupy = new List(); /*if (!param.checkPlan) { //在库检,只计算下达工单的占用。 var pwork = workordmsters.Where(x => x.Status.ToLower() == "r").ToList(); item_occupy = _mysql_ic_item_stockoccupy.GetListAsync(p => p.company_id == companyId && itemIds.Contains(p.icitem_id) && pwork.Select(c => c.WorkOrd).Contains(p.morder_mo)).Result; } else { //物料库存占用记录表 item_occupy = _mysql_ic_item_stockoccupy.GetListAsync(p => p.company_id == companyId && itemIds.Contains(p.icitem_id) && workordmsters.Select(c => c.WorkOrd).Contains(p.morder_mo)).Result; }*/ //不论计划还是在库检,都是按全量跑工单,所以每次计算已占用库存,只算下达工单的占用。 var pwork = workordmsters.Where(x => x.Status.ToLower() == "r").ToList(); item_occupy = _mysql_ic_item_stockoccupy.GetListAsync(p => p.company_id == companyId && itemIds.Contains(p.icitem_id) && pwork.Select(c => c.WorkOrd).Contains(p.morder_mo)).Result; var nbrList = _nbrMaster.Select(x => pwork.Select(c => c.WorkOrd).Contains(x.WorkOrd) && x.Status.ToUpper() != "C").ToList(); if (nbrList.Any()) { var nbrDtlList = _nbrDetail.Select(x => nbrList.Select(c => c.RecID).Contains(x.NbrRecID) && x.Status.ToUpper() != "C").ToList(); if (nbrDtlList.Any()) { if (item_occupy.Any()) { item_occupy.ForEach(s => { //TODO:对发布数量和占用数量进行对冲,因为目前没有处理不同层级下使用相同物料的占用的问题。dop占用有项次号,而wms的发布数量明细没有项次号 var wdtl = nbrDtlList.Find(x => x.WorkOrd == s.morder_mo && x.ItemNum == s.icitem_number); if (wdtl != null) { s.quantity = wdtl.QtyOrd - wdtl.QtyRec; s.quantity = s.quantity < 0 ? 0 : s.quantity; } }); item_occupy = item_occupy.Where(s => s.quantity > 0).ToList(); if (item_occupy.Count > 0) { var mo_item_occupy = ObjectMapper.Map, List>(item_occupy); mo_item_occupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; }); await MongoHelper.InsertManyAsync(mo_item_occupy); } } } } //工单主表 var mes_morder = _mysql_mes_morder.GetListAsync(x => string.IsNullOrEmpty(x.morder_state) == false && x.morder_state != "完成" && x.company_id == companyId && string.IsNullOrEmpty(x.analogcalcversion) && x.factory_id == factoryId && workordmsters.Select(c => c.WorkOrd).Contains(x.morder_no)).Result; if (mes_morder.Count > 0) { mes_morder.ForEach(item => { item.bang_id = bangid; }); var moMes_morder = ObjectMapper.Map, List>(mes_morder); moMes_morder.ForEach(item => { item.GenerateNewId(help.NextId()); }); await MongoHelper.InsertManyAsync(moMes_morder); } //工单子表 var mes_moentry = _mysql_mes_moentry.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId).Result; if (mes_moentry.Count > 0) { mes_moentry.ForEach(item => { item.bang_id = bangid; }); var moMes_moentry = ObjectMapper.Map, List>(mes_moentry); moMes_moentry.ForEach(item => { item.GenerateNewId(help.NextId()); }); await MongoHelper.InsertManyAsync(moMes_moentry); } //在制工单占用记录表 var mes_mooccupy = _mysql_mes_mooccupy.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && mes_morder.Select(c => c.morder_no).Contains(x.moo_mo)).Result; if (mes_mooccupy.Count > 0) { var moMes_mooccupy = ObjectMapper.Map, List>(mes_mooccupy); moMes_mooccupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; }); await MongoHelper.InsertManyAsync(moMes_mooccupy); } } //根据物料信息,只同步在途未关闭的采购订单和采购申请 //采购订单明细 var srm_po_list = _mysql_srm_po_list.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && itemIds.Contains(x.icitem_id.GetValueOrDefault())).Result; if (srm_po_list.Count > 0) { //采购订单--取出状态为在途的PO var srm_po_main = _mysql_srm_po_main.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && srm_po_list.Select(c => c.po_id).Contains(x.Id) && x.state != 3).Result; if (srm_po_main.Count > 0) { var moSrm_po_main = ObjectMapper.Map, List>(srm_po_main); moSrm_po_main.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; }); await MongoHelper.InsertManyAsync(moSrm_po_main); //订单明细--根据在途PO过滤出有效的Po_list srm_po_list = srm_po_list.Where(s => srm_po_main.Select(x => x.Id).Contains(s.po_id.GetValueOrDefault())).ToList(); var moSrm_po_list = ObjectMapper.Map, List>(srm_po_list); moSrm_po_list.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid;item.create_time = DateTime.Now; }); await MongoHelper.InsertManyAsync(moSrm_po_list); } //采购订单明细占用详情 var srm_po_occupy = _mysql_srm_po_occupy.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && srm_po_list.Select(c => c.Id).Contains(x.polist_id.GetValueOrDefault())).Result; if (srm_po_occupy.Count > 0) { var moSrm_po_occupy = ObjectMapper.Map, List>(srm_po_occupy); moSrm_po_occupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; item.create_time = DateTime.Now; }); await MongoHelper.InsertManyAsync(moSrm_po_occupy); } } //pr var srm_pr_main = new List(); if (string.IsNullOrEmpty(analogCalcVersion)) { //周计划屏蔽年度产生的PR srm_pr_main = _mysql_srm_pr_main.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && x.state != 0 && string.IsNullOrEmpty(x.analogcalcversion) && itemIds.Contains(x.icitem_id.GetValueOrDefault())).Result; } else { srm_pr_main = _mysql_srm_pr_main.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && x.state != 0 && itemIds.Contains(x.icitem_id.GetValueOrDefault())).Result; } if (srm_pr_main.Count > 0) { var moSrm_pr_main = ObjectMapper.Map, List>(srm_pr_main); moSrm_pr_main.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; item.create_time = DateTime.Now; }); await MongoHelper.InsertManyAsync(moSrm_pr_main); List occupylist = new List(); if (string.IsNullOrEmpty(analogCalcVersion)) { var occupyListLINQ = _businessDbContext.srm_po_occupy.Where(x => x.company_id == companyId && x.factory_id == factoryId && !x.IsDeleted).Join(_businessDbContext.srm_pr_main.Where(x => x.company_id == companyId && x.factory_id == factoryId && x.state != 0 && string.IsNullOrEmpty(x.analogcalcversion) && itemIds.Contains(x.icitem_id.GetValueOrDefault())), p => p.polist_id, pr => pr.Id, (p, pr) => new { p, pr }).ToList(); for (int i = 0; i < occupyListLINQ.Count; i++) { occupylist.Add(occupyListLINQ[i].p); } }else { var occupyListLINQ = _businessDbContext.srm_po_occupy.Where(x => x.company_id == companyId && x.factory_id == factoryId && !x.IsDeleted).Join(_businessDbContext.srm_pr_main.Where(x => x.company_id == companyId && x.factory_id == factoryId && x.state != 0 && itemIds.Contains(x.icitem_id.GetValueOrDefault())), p => p.polist_id, pr => pr.Id, (p, pr) => new { p, pr }).ToList(); for (int i = 0; i < occupyListLINQ.Count; i++) { occupylist.Add(occupyListLINQ[i].p); } } //采购申请占用详情 //var srm_pr_occupy = _mysql_srm_po_occupy.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && srm_pr_main.Select(c => c.Id).Contains(x.polist_id.GetValueOrDefault())).Result; if (occupylist.Count > 0) { var moSrm_pr_occupy = ObjectMapper.Map, List>(occupylist); moSrm_pr_occupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; item.create_time = DateTime.Now; }); await MongoHelper.InsertManyAsync(moSrm_pr_occupy); } } var sysSet = _generalizedCodeMaster.Select(s => s.FldName == "SystemConfig" && s.Val == "ScheduleAgreement" && s.Domain == factoryId.ToString()).ToList(); int ScheduleAgreement = 0;//计划协议 if (sysSet.Any()) { if (!string.IsNullOrEmpty(sysSet[0].Ufld1)) { int.TryParse(sysSet[0].Ufld1, out ScheduleAgreement); } } _CalcBomViewAppService.ScheduleAgreement = ScheduleAgreement == 1; } /// /// 清处数据库快照 /// /// public async Task ClearSnapShot(long bangid) { //清除物料库存数据 await MongoHelper.DeleteManyAsync(p => p.bang_id == bangid); //清除工单占用记录表 //await _mes_mooccupy.DeleteAsync(p => p.bang_id == bangid); //清除工单主表 //await _mes_morder.Delete(p => p.bang_id == bangid); //清除工单子表 //await _mes_moentry.Delete(p => p.bang_id == bangid); //清除采购订单 await MongoHelper.DeleteManyAsync(p => p.bang_id == bangid); //清除采购订单明细 await MongoHelper.DeleteManyAsync(p => p.bang_id == bangid); //清除采购订单占用详情 //await _srm_po_occupy.DeleteAsync(p => p.bang_id == bangid); //清除PR await MongoHelper.DeleteManyAsync(p => p.bang_id == bangid); } /// /// 物料数据计算前准备 /// /// /// /// /// /// /// /// /// /// /// /// /// public void DataInitialization(List boms, long bangid, List icitemlist, List stocklist, List pretreatments, List sklist) { List itemIds = pretreatments.Select(p => p.item_id.GetValueOrDefault()).Distinct().ToList(); icitemlist.AddRange(_ic_item.GetListAsync(p => itemIds.Contains(p.mysql_id) && !p.IsDeleted).Result); #region 1、数据准备 //1.1、获取产能检查相关数据 //产品物料编码 List itemnums = pretreatments.Where(p => p.level == 1).Select(p => p.item_number).Distinct().ToList(); //产线明细 prodLines = _prodLineDetail.Select(p => itemnums.Contains(p.Part)).ToList(); //标准工序 routingOps = _routingOpDetail.Select(p =>p.Domain== param.factoryId.ToString()).ToList(); List lines = prodLines.Select(p => p.Line).Distinct().ToList(); //工作日历 calendarWorks = _shopCalendarWorkCtr.Select(p => lines.Contains(p.ProdLine)).ToList(); //休息日 qualityLineWorks = _qualityLineWorkDetail.Select(p => lines.Contains(p.ProdLine)).ToList(); //节假日 holidays = _holidayMaster.Select(p => p.Dated >= DateTime.Now.Date); //主工单 var ordlist = _workOrdMaster.Select(x => x.Domain == param.factoryId.ToString() && string.IsNullOrEmpty(x.Typed) == true && !string.IsNullOrEmpty(x.Status) && x.Status.ToUpper() != "C" && x.Status.ToUpper() != "P").ToList(); List mo_Mes_Morders = _mes_morder.GetListAsync(x => ordlist.Select(c => c.WorkOrd).Contains(x.morder_no) && x.company_id == param.company_id && x.factory_id == param.factoryId && x.bang_id == bangid).Result; List moids = mo_Mes_Morders.Select(p => p.mysql_id).ToList(); List mo_Mes_Moentry = _mes_moentry.GetListAsync(x => moids.Contains(x.moentry_moid)).Result; //工单占用表 List mes_mooccupyList = _mes_mooccupy.GetListAsync(x => x.moo_state == 1 && !x.IsDeleted && x.company_id == param.company_id && boms.Select(p => p.item_number).Contains(x.fitem_number) && x.bang_id == bangid).Result; List occoupyRefId = new List(); //物料采购订单明细 var poDetailList = _srm_po_list.GetListAsync(x => icitemlist.Select(p => p.mysql_id).ToList().Contains(x.icitem_id.Value) && x.bang_id == bangid && x.state == 1 && !x.IsDeleted).Result; occoupyRefId.AddRange(poDetailList.Select(p => p.mysql_id).ToList()); var srm_pr_mains = _srm_pr_main.GetListAsync(x => icitemlist.Select(p => p.mysql_id).ToList().Contains(x.icitem_id.Value) && x.bang_id == bangid && x.state != 0 && x.state != 4 && !x.IsDeleted).Result; occoupyRefId.AddRange(srm_pr_mains.Select(p => p.mysql_id).ToList()); //采购订单或采购申请占用数据 var poOccupys = _srm_po_occupy.GetListAsync(x => occoupyRefId.Contains(x.polist_id) && x.bang_id == bangid && !x.IsDeleted).Result; #endregion //物料库存 stocklist.AddRange(_ic_item_stock.GetListAsync(p => p.factory_id == param.factoryId && p.bang_id == bangid && itemIds.Contains(p.icitem_id)).Result); //物料库存占用表 sklist.AddRange(_ic_item_stockoccupy.GetListAsync(x => x.bang_id == bangid && !x.IsDeleted).Result); //物料提前期 leadTimeList = GetLeadTime(icitemlist, param.company_id, param.factoryId);//提前期列表 supplierList = GetSupplier(itemIds, param.company_id, param.factoryId);//供应商列表 _CalcBomViewAppService.leadTimeList = leadTimeList; _CalcBomViewAppService.supplierList = supplierList; //资源检查添加产线工序等数据 _CalcBomViewAppService.prodLines = prodLines; _CalcBomViewAppService.routingOps = routingOps; _CalcBomViewAppService.calendarWorks = calendarWorks; _CalcBomViewAppService.qualityLineWorks = qualityLineWorks; _CalcBomViewAppService.holidays = holidays; _CalcBomViewAppService.mordersList = mo_Mes_Morders;//工单 _CalcBomViewAppService.moentriesList = mo_Mes_Moentry;//工单子表 _CalcBomViewAppService.mooccupyAllList = mes_mooccupyList;//工单占用表 _CalcBomViewAppService.srm_Po_Lists = poDetailList; //采购明细 _CalcBomViewAppService.srm_Po_Occupies = poOccupys; //采购占用表 _CalcBomViewAppService.ic_item_List = icitemlist; //物料表 _CalcBomViewAppService.srm_Pr_Mains = srm_pr_mains;//PR } public void GenerateSort(List returnlist) { int level = returnlist.Max(s => s.level); returnlist.ForEach(s => { int num = level - s.level; if (num > 0) { s.num_order = long.Parse((s.num_order * Math.Pow(1000, num)).ToString()); } }); } /// /// 根据物料id获取物料4个提前期 /// /// 物料id /// 企业id /// 工厂id /// private List GetLeadTime(List icItemIds, long? companyId, long factoryid) { return icItemIds.Where(p => p.factory_id == factoryid && p.company_id == companyId && !p.IsDeleted). Select(x => new ICItemLeadTimeDto { item_id = x.mysql_id, transportation_leadtime = x.transportation_leadtime, stock_leadtime = x.stock_leadtime, production_leadtime = x.production_leadtime, order_leadtime = x.order_leadtime, minorderqty = x.minorderqty, put_integer = x.put_integer, minpackqty = x.minpackqty, ordissu_days = x.ordissu_days }).AsQueryable().ToList(); } //根据物料id获取物料供应商 private List GetSupplier(List icItemIds, long? companyId, long factoryid) { return _srm_purchase.GetListAsync(p => icItemIds.Contains(p.icitem_id) && p.company_id == companyId && p.factory_id == factoryid && !p.IsDeleted).Result; } /// /// 物料和BOM前置数据准备 /// /// /// /// /// /// /// /// public void IcItemPretreatment(bool flag, List boms, List bomlist, List bomchildlist, List icitemlist, List sublist, List suballlist, List subdtllist) { //获取物料bom,物料bom明细 GetIcBomData(boms, bomlist, bomchildlist, flag); //根据明细集合查出所有得替代关系表数据集合 List codeList = bomchildlist.Select(c => c.substitute_code).Distinct().ToList(); sublist.AddRange(_ic_substitute.GetListAsync(p => codeList.Contains(p.substitute_code) && !p.IsDeleted).Result); List subidlist = sublist.Select(c => c.mysql_id).Distinct().ToList(); suballlist.AddRange(_ic_substitute_group.GetListAsync(p => subidlist.Contains(p.substitute_group_id) && !p.IsDeleted).Result); List suballidlist = suballlist.Select(c => c.mysql_id).Distinct().ToList(); subdtllist.AddRange(_ic_substitute_group_detail.GetListAsync(p => suballidlist.Contains(p.substitute_group_id) && !p.IsDeleted).Result); //获取物料数据 List itemIds = bomlist.Select(p => p.icitem_id).ToList(); itemIds.AddRange(bomchildlist.Select(p => p.icitem_id).ToList()); itemIds.AddRange(subdtllist.Select(p => p.icitem_id).ToList()); icitemlist.AddRange(_ic_item.GetListAsync(p => itemIds.Contains(p.mysql_id) && !p.IsDeleted).Result); } /// /// 递归:获取icbom,icbomchild数据 /// /// /// /// public void GetIcBomData(List icBoms, List bomlist, List bomchildlist, bool flag) { if (icBoms.Count == 0) { return; } //添加物料bom数据 foreach (var ib in icBoms) { if (!bomlist.Exists(s => s.mysql_id == ib.mysql_id)) { bomlist.Add(ib); } } List icBomIds = icBoms.Select(m => m.mysql_id).ToList(); int page = 1; page = (int)Math.Ceiling(icBomIds.Count() / (decimal)1500); List childList = new List(); for (int i = 0; i < page; i++) { var pageBomsIds = icBomIds.Skip(i * 1500).Take(1500).ToList(); childList.AddRange(_ic_bom_child.GetListAsync(p => pageBomsIds.Contains(p.bom_id) && p.company_id == param.company_id && !p.IsDeleted).Result); } //没有明细数据,终止 if (childList.Count == 0) { return; } foreach (var bchild in childList) { if (!bomchildlist.Exists(s => s.mysql_id == bchild.mysql_id)) { bomchildlist.Add(bchild); } } if (flag) { return; } //通过物料bom明细数据反查物料bom数据 var boms = _ic_bom.GetListAsync(p => childList.Select(m => m.icitem_id).ToList().Contains(p.icitem_id) && p.use_status == 1 && p.company_id == param.company_id && !p.IsDeleted).Result.ToList(); foreach (var chd in childList) { var curBoms = boms.Where(p => p.icitem_id == chd.icitem_id).ToList(); GetIcBomData(curBoms, bomlist, bomchildlist, flag); } } /// /// 自动生成BOM预处理清单 /// public void AutoCreateBomBill(string companyid, List ic_Boms = null) { try { bool flag = false; if (ic_Boms == null) { flag = true; ic_Boms = _ic_bom.GetListAsync(p => p.company_id.ToString() == companyid && !p.IsDeleted).Result.ToList(); } var pretreatment = _mysql_b_bom_pretreatment.GetListAsync(s => ic_Boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; param.company_id = long.Parse(companyid); //物料bom List bomlist = new List(); List bomchildlist = new List(); //物料信息 List icitemlist = new List(); //替代关系 List sublist = new List(); List suballlist = new List(); List subdtllist = new List(); IcItemPretreatment(flag, ic_Boms, bomlist, bomchildlist, icitemlist, sublist, suballlist, subdtllist); List deleteList = new List(); List addList = new List(); foreach (var bom in ic_Boms) { var pret = pretreatment.Where(s => s.sourceid == bom.mysql_id).ToList(); if (pret.Any()) { //版本不同则重新生成 deleteList.AddRange(pret); } //bom层级组装 var getBomList = _pretreatmentAppService.BomPretreatment(bom.mysql_id, bomlist, bomchildlist, icitemlist); //bom替代关系组装 _pretreatmentAppService.BomSubstitute(getBomList, bomlist, bomchildlist, icitemlist, sublist, suballlist, subdtllist); //GenerateSort(getBomList); var list = ObjectMapper.Map, List>(getBomList); list.ForEach(s => { s.sourceid = bom.mysql_id; s.company_id = bom.company_id; s.tenant_id = bom.tenant_id; s.factory_id = bom.factory_id; }); addList.AddRange(list); } if (deleteList.Any()) { _businessDbContext.BulkDelete(deleteList); } if (addList.Any()) { _businessDbContext.BulkInsert(addList); } } catch (Exception e) { new NLogHelper("ResourceExamineAppService").WriteLog("AutoCreateBomBill", "自动生成BOM预处理清单:" + e.Message, _currentTenant.Id.ToString()); } } /// /// 生产长周期物料PR /// /// 需要传入工厂编码 /// public async Task CalcLongPeriodItemPR(InputDto input) { //来自定时任务的请求 if (input.year == 0 && input.month == 0) { input.year = DateTime.Now.Year; input.month = DateTime.Now.Month; } if (DateTime.Now.Month >= 10) { input.year = DateTime.Now.AddYears(1).Year; input.month = DateTime.Now.Month; } var ropParam = GetROPParam(input.factory_id.ToString()); //获取滚动未来六个月数据 var monthlist = GetYearPlanMonth(input.year); var productList = _replenishmentAnnualProduction.GetListAsync(a => monthlist.Contains(a.PlanMonth) && !a.IsDeleted && a.factory_id == input.factory_id).Result.OrderBy(s=>s.PlanMonth).ThenBy(s=>s.OrderNum).ToList(); var itemList= productList.Select(a=>a.SAPItemNumber).Distinct().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; var planItemList = planList.Select(a => a.number).Distinct().ToList(); var expectedList = itemList.Except(planItemList).ToList(); if (expectedList.Count > 0) { throw new NotImplementedException("年度销售预测物料" + string.Join(",", expectedList) + "在DOP物料表找不到!"); } var mesItemList = mesItem.Select(a => a.ItemNum).Distinct().ToList(); var expectedMesList = itemList.Except(mesItemList).ToList(); if (expectedMesList.Count > 0) { throw new NotImplementedException("年度销售预测物料" + string.Join(",", expectedMesList) + "在MES物料表找不到!"); } var bomItemList = bomList.Select(a => a.item_number).Distinct().ToList(); var expectedBOMList = itemList.Except(bomItemList).ToList(); if (expectedBOMList.Count > 0) { throw new NotImplementedException("年度销售预测物料" + string.Join(",", expectedBOMList) + "在BOM没有维护!"); } List moList=new List(); List moentryList = new List(); var list = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", productList.Count(), "", 1); long bangid = help.NextId(); for (int i = 0;i< productList.Count();i++) { if (productList[i].Qty<=0) continue; var ic_item = mesItem.Find(x => x.ItemNum == 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.JhMorder; mes_Morder.work_order_type = MorderEnum.CgMorder; mes_Morder.morder_state =""; mes_Morder.morder_no = list[i].NbrResult.ToString(); mes_Morder.fms_number = ""; mes_Morder.bom_number = bom.bom_number; 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.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.moentry_prd = null; mes_Morder.moentry_prdname = null; mes_Morder.moentry_wrkc = null; mes_Morder.moentry_wrkcname = null; mes_Morder.picking_qty = 0; 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; 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.UM; mes_Moentry.morder_production_number = productList[i].Qty; mes_Moentry.need_number = productList[i].Qty; 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; moList.Add(mes_Morder); moentryList.Add(mes_Moentry); } var safeItemQty = _itemMaster.Select(a => a.PurMfg == "L" && a.SafetyStk > 0 && a.IsActive); if (safeItemQty.Count > 0) { var itemStock = CalcStock(safeItemQty.Select(m => m.ItemNum).Distinct().ToList(), input); var safelist = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", safeItemQty.Count, "", 1); for (int i = 0; i < safeItemQty.Count; i++) { mes_morder mes_Morder = new mes_morder(); mes_Morder.GenerateNewId(help.NextId()); mes_Morder.morder_type = MorderEnum.JhMorder; mes_Morder.work_order_type = MorderEnum.CgMorder; mes_Morder.morder_state = ""; mes_Morder.morder_no = safelist[i].NbrResult.ToString(); mes_Morder.fms_number = ""; mes_Morder.bom_number = safeItemQty[i].ItemNum; mes_Morder.fmodel = safeItemQty[i].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 = safeItemQty[i].ItemNum; mes_Morder.product_name = safeItemQty[i].Descr; mes_Morder.morder_date = DateTime.Now.Date.AddDays(1); mes_Morder.moentry_sys_stime = Convert.ToDateTime(DateTime.Now.AddYears(1).Year + "-01-01"); 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; mes_Morder.unit = safeItemQty[i].UM; var itemStockQty = itemStock.Find(a => a.ItemNumber == safeItemQty[i].ItemNum); if (itemStockQty != null) { if (itemStockQty.Qty < safeItemQty[i].SafetyStk) { mes_Morder.morder_production_number = safeItemQty[i].SafetyStk - itemStockQty.Qty; mes_Morder.need_number = safeItemQty[i].SafetyStk - itemStockQty.Qty; } else { //超过安全库存不用考虑 continue; } } else { mes_Morder.morder_production_number = safeItemQty[i].SafetyStk; mes_Morder.need_number = safeItemQty[i].SafetyStk; } 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 = safeItemQty[i].UM; mes_Moentry.morder_production_number = safeItemQty[i].SafetyStk; mes_Moentry.need_number = safeItemQty[i].SafetyStk; 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; moList.Add(mes_Morder); moentryList.Add(mes_Moentry); } } //长周期物料只产生PR不生成实际工单 //await _mysql_mes_morder.InsertManyAsync(moList); //await _mysql_mes_moentry.InsertManyAsync(moentryList); moList = moList.OrderBy(a => a.moentry_sys_stime).ToList(); await PlanOrderResourceCheck(moList,moentryList, bangid, $"V{DateTime.Now.ToString("yyyyMMddHHmm")}",false,false); return "OK"; } public ReplenishmentDto GetROPParam(string domain) { //select [Domain],Val,Ufld1,UDeci1 from GeneralizedCodeMaster where [Domain] = '1001' AND FldName ='SystemConfig' // AND Val IN('ReplenishmentCalcPeriod', 'HistoryOutStockMonth', 'SaleFcstMonth', 'SaleFcstEntryDate', 'UpdateWeeks', 'WeekPlanUpdateDay', 'LongPeriodDay') List list = new List(); list.Add("ReplenishmentCalcPeriod"); list.Add("HistoryOutStockMonth"); list.Add("SaleFcstMonth"); list.Add("SaleFcstEntryDate"); list.Add("UpdateWeeks"); list.Add("WeekPlanUpdateDay"); list.Add("LongPeriodDay"); list.Add("IsUseROP"); var configList = _generalizedCodeMaster.Select(a => a.Domain == domain && a.FldName == "SystemConfig" && list.Contains(a.Val)); ReplenishmentDto replenishmentDto = new ReplenishmentDto(); replenishmentDto.HistoryOutStockMonth = 3; replenishmentDto.ReplenishmentCalcPeriod = "W"; replenishmentDto.HistoryOutStockMonth = 2; replenishmentDto.SaleFcstMonth = 2; replenishmentDto.SaleFcstEntryDate = 27; replenishmentDto.UpdateWeeks = 12; replenishmentDto.WeekPlanUpdateDay = 7;//每周日更新 replenishmentDto.LongPeriodDay = 60; replenishmentDto.IsUseROP = "否"; if (configList?.Find(a => a.Val == "HistoryOutStockMonth") != null) { replenishmentDto.HistoryOutStockMonth = (int)configList?.Find(a => a.Val == "HistoryOutStockMonth").UDeci1; } if (configList?.Find(a => a.Val == "ReplenishmentCalcPeriod") != null) { switch (configList?.Find(a => a.Val == "ReplenishmentCalcPeriod").Ufld1) { case "月": replenishmentDto.ReplenishmentCalcPeriod = "M"; break; case "周": replenishmentDto.ReplenishmentCalcPeriod = "W"; break; case "": replenishmentDto.ReplenishmentCalcPeriod = "D"; break; default: replenishmentDto.ReplenishmentCalcPeriod = "W"; break; } } if (configList?.Find(a => a.Val == "SaleFcstMonth") != null) { replenishmentDto.SaleFcstMonth = (int)configList?.Find(a => a.Val == "SaleFcstMonth").UDeci1; } if (configList?.Find(a => a.Val == "SaleFcstEntryDate") != null) { replenishmentDto.SaleFcstEntryDate = (int)configList?.Find(a => a.Val == "SaleFcstEntryDate").UDeci1; } if (configList?.Find(a => a.Val == "UpdateWeeks") != null) { replenishmentDto.UpdateWeeks = (int)configList?.Find(a => a.Val == "UpdateWeeks").UDeci1; } if (configList?.Find(a => a.Val == "WeekPlanUpdateDay") != null) { switch (configList?.Find(a => a.Val == "WeekPlanUpdateDay").Ufld1) { case "周一": replenishmentDto.WeekPlanUpdateDay = 1; break; case "周二": replenishmentDto.WeekPlanUpdateDay = 2; break; case "周三": replenishmentDto.WeekPlanUpdateDay = 3; break; case "周四": replenishmentDto.WeekPlanUpdateDay = 4; break; case "周五": replenishmentDto.WeekPlanUpdateDay = 5; break; case "周六": replenishmentDto.WeekPlanUpdateDay = 6; break; case "周日": replenishmentDto.WeekPlanUpdateDay = 7; break; default: replenishmentDto.WeekPlanUpdateDay = 7; break; } } if (configList?.Find(a => a.Val == "LongPeriodDay") != null) { replenishmentDto.LongPeriodDay = (int)configList?.Find(a => a.Val == "LongPeriodDay").UDeci1; } if (configList?.Find(a => a.Val == "IsUseROP") != null) { replenishmentDto.IsUseROP =configList?.Find(a => a.Val == "IsUseROP").Ufld1; } return replenishmentDto; } /// /// 计算ABC分类和FMR分类 /// /// public List GetRopAmount(List itemList, List supplierStatementDtos, List invTransHists, InputDto input) { List replenishmentROPWeekPlanDtos = new List(); var total_outstock_amout = 0m; foreach (var item in itemList) { var entry = supplierStatementDtos.FirstOrDefault(p => p.ItemNum == item); decimal NETPR = 0m; if (entry != null) { NETPR = entry.NETPR; } else { NETPR = 1; } //出库总数 var OutStockQty = invTransHists.Where(a => a.ItemNum == item).Sum(b => b.QtyChange); ReplenishmentROPWeekPlanDto replenishmentROPWeekPlanDto = new ReplenishmentROPWeekPlanDto(); //出库总金额 replenishmentROPWeekPlanDto.outstock_amout = Math.Abs(OutStockQty.GetValueOrDefault()) * NETPR; replenishmentROPWeekPlanDto.number = item; total_outstock_amout += Math.Abs(OutStockQty.GetValueOrDefault()) * NETPR; replenishmentROPWeekPlanDtos.Add(replenishmentROPWeekPlanDto); } replenishmentROPWeekPlanDtos = replenishmentROPWeekPlanDtos.OrderByDescending(a => a.outstock_amout).ToList(); var scale = 0m; if (total_outstock_amout <= 0) { return null; } replenishmentROPWeekPlanDtos.ForEach(a => { a.amout_scale = Math.Ceiling((a.outstock_amout / total_outstock_amout)*100); scale += a.amout_scale; if (scale <= 80) { a.ABC = "A"; } else if (scale >= 90) { a.ABC = "C"; } else { a.ABC = "B"; } }); return replenishmentROPWeekPlanDtos; } /// /// 计算ABC分类和FMR分类 /// /// public void CalcFMRAndABC(ReplenishmentROPWeekPlan replenishmentModel, ReplenishmentDto replenishmentDto, List shipList, List pickbilllist, List replenishmentROPWeekPlanDtos, InputDto input) { //总的移库次数 int totalCount = shipList.Count() + pickbilllist.Count(); var items = shipList.Select(s => s.ContainerItem).Distinct().ToList(); items.AddRange(pickbilllist.Select(s => s.ItemNum).Distinct().ToList()); items = items.Distinct().ToList(); //平均出库次数 decimal avgOutStock = totalCount / replenishmentDto.HistoryOutStockMonth / items.Count(); //瑞奇不提供价格敏感信息,ABC类都默认为B,全部当做无出库金额的物料 //无出库金额的物料 FMR分类 F 96 % M 90 % R 80 % //有出库金额的物料 ABC/ FMR分类 AF 96 % AM 90 % AR 80 % BF 96 % BM 90 % BR 80 % CF 96 % CM 90 % CR 80 % replenishmentModel.abc = replenishmentROPWeekPlanDtos.Where(a=>a.number== replenishmentModel.number).First().ABC;//原材料默认为B int itemMoveCount = shipList.Count(a => a.ContainerItem == replenishmentModel.number) + pickbilllist.Count(a => a.ItemNum == replenishmentModel.number); if (itemMoveCount > avgOutStock) { replenishmentModel.fmr = "F"; } else if (itemMoveCount >= avgOutStock / 2 && itemMoveCount < avgOutStock || itemMoveCount == 0) { replenishmentModel.fmr = "M";//没有出库移库记录的默认为M } else if (itemMoveCount < avgOutStock / 2) { replenishmentModel.fmr = "R"; } if (replenishmentModel.fmr == "F") { replenishmentModel.service_level_pct = (decimal?)0.96; } if (replenishmentModel.fmr == "M") { replenishmentModel.service_level_pct = (decimal?)0.9; } if (replenishmentModel.fmr == "R") { replenishmentModel.service_level_pct = (decimal?)0.8; } } /// /// 算平均月需求数量 /// /// 发货计划 /// /// /// /// public decimal CalcAvgDemand(List list, string itemNum,int? erp_cls, List pickbilllist=null) { if(erp_cls!=3) { if(list.Where(i => i.SAPItemNumber == itemNum && i.DistributionChannel=="瑞奇").Count()>0) { return list.Where(i => i.SAPItemNumber == itemNum && i.DistributionChannel == "瑞奇").Average(a => a.Qty); } return 0; }else { var pickItemList = pickbilllist.Select(a => a.ItemNum).Distinct(); var sumQty = pickbilllist.Where(a => a.ItemNum == itemNum)?.Sum(a => a.QtyChange); var month = pickbilllist.Where(a => a.ItemNum == itemNum)?.Select(a => a.CreateTime.Value.Month).Distinct().Count(); if (month == 0) return sumQty.Value; else return sumQty.GetValueOrDefault()/month.Value; } } public double CalcVariance(List list, string itemNum, int? erp_cls,decimal? monthl_avg_demand, List pickbilllist = null) { if (erp_cls != 3) { var nums = list.Where(i => i.SAPItemNumber == itemNum).Select(a => a.Qty); if (nums.Count() <= 1) return 0; return Math.Sqrt(nums.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(monthl_avg_demand), 2)) / (nums.Count() - 1)); } else { var nums = pickbilllist.Where(i => i.ItemNum == itemNum).Select(a =>a.QtyChange); if (nums.Count() <= 1) return 0; return Math.Sqrt(nums.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(monthl_avg_demand), 2)) / (nums.Count() - 1)); } } /// /// 获取指定日期在为一年中为第几周 /// /// 指定时间 /// 返回第几周 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; } //获取上周开始时间 public static DateTime getPreWeekStartTime() { var weekday = (int)DateTime.Now.DayOfWeek; return Convert.ToDateTime(DateTime.Now.AddDays(-7 - weekday + 1).ToString("yyyy-MM-dd 00:00:00.000")); } //获取上周结束时间 public static DateTime getPreWeekEndTime() { int weekday = (int)DateTime.Now.DayOfWeek; return Convert.ToDateTime(DateTime.Now.AddDays(weekday - 7 + 1).ToString("yyyy-MM-dd 23:59:59.000")); } /// /// 获取上个月开始时间 /// /// /// public static DateTime getPreMonthStartTime() { return Convert.ToDateTime(DateTime.Now.AddMonths(-1).AddDays(1 - DateTime.Now.Day).ToString("yyyy-MM-dd 00:00:00.000")); } /// /// 获取上月结束时间 /// /// /// public static DateTime getPreMonthEndTime() { return Convert.ToDateTime(DateTime.Now.AddDays(-DateTime.Now.Day).ToString("yyyy-MM-dd 23:59:59.000")); } /// /// 获取前后某个,整数月开始时间 /// /// 正数表示后多少个月的第一天,负数为前多少个月第一天 /// public static DateTime getMonthStartTime(int months) { return getPreMonthStartTime().AddMonths(months + 1); } /// /// 获取前后某个,整数月结束时间 /// /// 正数表示后多少个月的第一天,负数为前多少个月第一天 /// public static DateTime getMonthEndTime(int months) { return getPreMonthEndTime().AddMonths(months + 1); } /// /// 获取未来几个月PlanMonth /// /// /// public List GetPlanMonth(int monthCount) { List result=new List(); for(int i=0;i< monthCount; i++) { var months = DateTime.Now.AddMonths(i); result.Add($"{months.Year}-{months.Month.ToString("00")}"); } return result; } public List GetYearPlanMonth(int year) { List result = new List(); for (int i = 0; i < 12; i++) { var months = Convert.ToDateTime($"{year}-01-01"); months = months.AddMonths(i); result.Add($"{months.Year}-{months.Month.ToString("00")}"); } return result; } /// /// 获取前面几个月PlanMonth /// /// /// public List GetPrePlanMonth(int monthCount) { List result = new List(); for (int i = 0; i < monthCount; i++) { var months = DateTime.Now.AddMonths(-i); result.Add($"{months.Year}-{months.Month.ToString("00")}"); } return result; } public async Task AsyncItemStockFromWMS(List itemList,string analogCalcVersion) { //释放库存占用记录 await _systemJobAppService.SyncItemStockOccupyClear(); //产品编码 //var itemList = bom_Pretreatments.Select(a => a.item_number).Distinct().ToList(); List itemChildList = new List(); itemChildList.AddRange(itemList.Distinct()); if (!itemChildList.Any()) { return; } //List locationList = new List { "1000", "1001", "5008", "8000", "8001" }; var locationRange = _configurationItem.Select(x => x.FldName == "MRPLocationRange" && x.Domain == param.factoryId.ToString()).FirstOrDefault(); List locationList = new List { "1000", "1001", "5008", "8000", "8001" }; if (locationRange != null && locationRange.Val != null) { locationList = locationRange.Val.SplitToArray(",").ToList(); } if (!param.checkPlan) { if (locationList.Contains("1000")) { locationList.Remove("1000"); } } var locStock = _invMaster.Select(a => itemChildList.Contains(a.ItemNum) && a.IsActive && a.Domain == param.factoryId.ToString() && locationList.Contains(a.Location)); var sapInvList = _SAPInv.Select(a => a.WERKS == param.factoryId.ToString() && itemChildList.Contains(a.MATNR) && (a.SOBKZ.ToUpper() == "O" || locationList.Contains(a.LGORT))); //根据WMS物料,取出DOP物料数据 var items = _mysql_ic_item.GetListAsync(a => itemChildList.Contains(a.number) && a.factory_id == param.factoryId).Result; var itemIds = items.Select(b => b.Id).ToList();//需要处理的dop物料id集合 List mysqlStock = _mysql_ic_item_stock.GetListAsync(a => itemIds.Contains(a.icitem_id) && a.factory_id == param.factoryId).Result; List needAddList = new List(); List needupdList = new List(); foreach (var stockWMS in itemChildList) { var num = items.Find(x => x.number == stockWMS); if (num != null) { var item = mysqlStock.Find(a => a.icitem_id == num.Id); if (item != null) { needupdList.Add(item); } else { item = new ic_item_stock(); item.GenerateNewId(help.NextId()); item.tenant_id = param.company_id; item.factory_id = param.factoryId; item.company_id = param.company_id; item.icitem_id = num.Id; item.icitem_number = num.number; item.icitem_name = num.name; needAddList.Add(item); } item.sqty = 0; foreach (var lct in locationList) { var lctQty = locStock.Where(s => s.ItemNum == item.icitem_number && s.Location == lct).Sum(p => p.AvailStatusQty.GetValueOrDefault() + p.Assay.GetValueOrDefault()); if (lctQty == 0) { lctQty = sapInvList.Where(x => x.MATNR == item.icitem_number && x.LGORT == lct).Sum(p => p.LABST + p.INSME); } item.sqty += lctQty; } if (!string.IsNullOrEmpty(analogCalcVersion)) { item.sqty += sapInvList.Where(x => x.MATNR == item.icitem_number && x.SOBKZ.ToUpper() == "O").Sum(p => p.LABST + p.INSME); } } } if (needAddList.Count > 0) { _businessDbContext.BulkInsert(needAddList); } _businessDbContext.BulkUpdate(needupdList); } public async Task DeleteWeekPlan(long weekplanid, string productorder, long factory_id) { //2023/12/16 所有工单类型都能删除,中间件由业务人员自行处理 var weekplan = _replenishmentWeekPlan.GetListAsync(a => a.Id == weekplanid && a.ProductionOrder == productorder && a.factory_id == factory_id && a.IsReplenishmentModel == "N").Result; var workords = _workOrdMaster.Select(a => a.RecID == weekplanid && a.WorkOrd == productorder && a.Domain == factory_id.ToString()); var morders =_mysql_mes_morder.GetListAsync(a => a.Id == weekplanid && a.morder_no == productorder && a.factory_id == factory_id).Result; if (weekplan.Count == 0 && workords.Count == 0 && morders.Count==0) return "Fail|周计划或工单不存在"; if (string.IsNullOrEmpty(productorder)) { //未同步生产周计划工单,只需要删除导入的周计划 await _replenishmentWeekPlan.HardDeleteAsync(a => a.Id == weekplanid && a.ProductionOrder == productorder && a.factory_id == factory_id && a.IsReplenishmentModel == "N"); return "OK|删除成功"; } else { //判断是否下达 var workord = _workOrdMaster.Select(a => a.WorkOrd == productorder && a.Domain == factory_id.ToString()); if (workord.Count > 0) { //未下达的工单才可以删除,也就是初始或者已发布的工单 if (string.IsNullOrEmpty(workord[0].Status) || workord[0].Status.ToLower() == "p") { if (morders.Any()) { //如果是订单类型执行的删除,则将订单表更新成删除。 var melist = _mysql_mes_moentry.GetListAsync(x => x.moentry_moid == weekplanid).Result; var entry_id = melist.Select(x => x.soentry_id.GetValueOrDefault()).ToList(); List selist = _mysql_crm_seorderentry.GetListAsync(x => entry_id.Contains(x.Id)).Result; await _mysql_crm_seorderentry.HardDeleteAsync(selist); List solist = _mysql_crm_seorder.GetListAsync(x => selist.Select(c => c.seorder_id.GetValueOrDefault()).Contains(x.Id)).Result; List allseList = _mysql_crm_seorderentry.GetListAsync(x => solist.Select(c => c.Id).Contains(x.seorder_id.GetValueOrDefault()) && !entry_id.Contains(x.Id)).Result; List delsoList = new List(); foreach (var so in solist) { if (!allseList.Where(x => x.seorder_id == so.Id).Any()) { delsoList.Add(so); } } if (delsoList.Any()) { await _mysql_crm_seorder.HardDeleteAsync(delsoList); } } new NLogHelper("DeleteWeekPlan").WriteLog("DeleteWeekPlan", "删除工单:" + productorder + "__" + workord[0].Status, _currentTenant.Id.ToString()); await _replenishmentWeekPlan.HardDeleteAsync(a => a.ProductionOrder == productorder && a.factory_id == factory_id); await _mysql_mes_morder.HardDeleteAsync(a => a.morder_no == productorder && a.factory_id == factory_id); await _mysql_mes_moentry.HardDeleteAsync(a => a.moentry_mono == productorder && a.factory_id == factory_id); _workOrdMaster.Delete(a => a.WorkOrd == productorder && a.Domain == factory_id.ToString()); _workOrdDetail.Delete(a => a.WorkOrd == productorder && a.Domain == factory_id.ToString()); _workOrdRouting.Delete(a => a.WorkOrd == productorder && a.Domain == factory_id.ToString()); _scheduleResultOpMaster.Delete(a => a.WorkOrd == productorder && a.Domain == factory_id.ToString()); _periodSequenceDet.Delete(a => a.WorkOrds == productorder && a.Domain == factory_id.ToString()); await _mysql_ic_item_stockoccupy.HardDeleteAsync(a => a.morder_mo == productorder && a.factory_id == factory_id); await _mysql_srm_po_occupy.HardDeleteAsync(a => a.morder_mo == productorder && a.factory_id == factory_id); await _mysql_mes_mooccupy.HardDeleteAsync(a => a.moo_mo == productorder && a.factory_id == factory_id); return "OK|删除成功"; } else { return "Fail|该工单非下达,请走工单关闭。"; } } else { return "Fail|工单不存在"; } } } /// /// 生成交货单 /// /// /// /// public async Task CreateDeliverySchedule(string domain,string user) { string Msg = "OK|交货单生成成功"; //获取已发布且净需求数量大于0的交货计划数据 var demandplans = _icdemandschedule.GetListAsync(p => p.factory_id.ToString() == domain && p.status.ToUpper() == "P" && p.tosechedqty > 0 && !p.IsDeleted && string.IsNullOrEmpty(p.ishistoryversion)).Result.OrderBy(p => p.arrivaldate).ToList(); //获取已以生成交货单的交货计划 var alreadys = _srmpolistds.Select(p => p.domain == domain && demandplans.Select(m => m.Id).Contains(p.icdsid) && p.isactive == 1).ToList(); List newPlans = new List(); if (alreadys.Any()) { //交货计划存在已发布或者已关闭状态的交货单 List yfbIds = alreadys.Where(p => p.status.ToUpper() == "P" || p.status.ToUpper() == "C").Select(p => p.icdsid).Distinct().ToList(); //交货计划生成过交货单,但都是未发布状态 var wfbDs = alreadys.Where(p => !yfbIds.Contains(p.icdsid)).ToList(); if (wfbDs.Any()) { wfbDs.ForEach(p => p.isactive = 0); //删除未发布的交货单 _srmpolistds.Update(wfbDs); } //未发布交货单的交货计划 var wfbPlans = demandplans.Where(p => !yfbIds.Contains(p.Id)).ToList(); if (wfbPlans.Any()) { newPlans.AddRange(wfbPlans); } //如果已生成交货单的数量小于交货计划的净需求数量,则需要重新生成交货单 var yfbJhds = alreadys.Where(p => yfbIds.Contains(p.icdsid)).ToList(); var yfbPlans = demandplans.Where(p => yfbIds.Contains(p.Id)).ToList(); //净需求数量 ic_demandschedule newInsert = new ic_demandschedule(); foreach (var item in yfbPlans) { var curJhds = yfbJhds.Where(p=>p.icdsid == item.Id).ToList(); decimal sumQty = curJhds.Where(p => p.status.ToUpper() == "C").Sum(p => p.sentqty) + curJhds.Where(p => p.status.ToUpper() != "C").Sum(p => p.schedqty); if (item.tosechedqty <= sumQty) { continue; } //tosechedqty = item.tosechedqty - sumQty; newInsert = new ic_demandschedule(); newInsert.GenerateNewId(item.Id); newInsert.itemnum = item.itemnum; newInsert.tosechedqty = item.tosechedqty - sumQty; newInsert.fversion = item.fversion; newInsert.drawing = item.drawing; newInsert.requestdate = item.requestdate; newInsert.arrivaldate= item.arrivaldate; newInsert.shortqty = item.shortqty; newInsert.mesqty = item.mesqty; newInsert.locqty = item.locqty; newInsert.sechedqty = item.sechedqty; newInsert.status = item.status; newInsert.remarks = item.remarks; newInsert.ishistoryversion = item.ishistoryversion; newInsert.historyversionTime = item.historyversionTime; newPlans.Add(newInsert); } demandplans = newPlans; } //根据交货计划物料编码,获取物料属性为采购件的物料主数据 List itemMasters = _itemMaster.Select(p => demandplans.Select(m => m.itemnum).Contains(p.ItemNum) && p.Domain == domain && (p.PurMfg == "P" || p.PurMfg == "p")).ToList(); if (!itemMasters.Any()) { Msg = "OK|物料需求计划中没有采购件,不需要生成交货单"; return Msg; } //过滤掉物料属性不为采购件的交货计划 demandplans = demandplans.Where(p => itemMasters.Select(m => m.ItemNum).Contains(p.itemnum)).ToList(); if (!demandplans.Any()) { Msg = "OK|物料需求计划中没有采购件,不需要生成交货单"; return Msg; } List itemnums = demandplans.Select(p => p.itemnum).ToList(); //获取物料主数据 var icitems = _mysql_ic_item.GetListAsync(a => itemnums.Contains(a.number) && a.factory_id.ToString() == domain && !a.IsDeleted).Result.ToList(); //获取货源清单数据 var purchases = _srmPurchase.GetListAsync(p => p.factory_id.ToString() == domain && p.is_active == "否" && itemnums.Contains(p.number) && !p.IsDeleted).Result; if (!purchases.Any()) { Msg = "NO|没有可用的货源清单"; return Msg; } //获取采购明细数据:未关闭,且未交货数量(需求数量-已收数量)>0 List purOrdDetails = _PurOrdDetail.Select(p => p.Domain == domain && itemnums.Contains(p.ItemNum) && p.Status.ToUpper() != "C" && (p.QtyOrded - p.RctQty) > 0).OrderBy(p => p.DueDate).ToList(); List purOrds = purOrdDetails.Select(p => p.PurOrd).Distinct().ToList(); //获取送货单子表数据 List shdzbs = _scm_shdzb.Select(p=> purOrds.Contains(p.po_bill) && itemnums.Contains(p.sh_material_code) && string.IsNullOrEmpty(p.jhdbh)).ToList(); //获取采购单数据 List purOrdMasters = _PurOrdMaster.Select(p => p.Domain == domain && purOrds.Contains(p.PurOrd)).ToList(); //获取占用可用PO明细的交货单 List dbPolistds = _srmpolistds.Select(p => purOrds.Contains(p.ponumber) && p.isactive == 1).ToList(); //获取已完成的送货单子表数据 var purOrdNos = purOrds.JoinAsString("','"); var itemnumNos = itemnums.JoinAsString("','"); string sql = $"select b.id,[po_billline],[jhdbh],isnull([shzt],'待收') shzt,[jhdhh] ,b.sh_material_code,b.sh_material_name,b.po_bill,b.sh_delivery_quantity from scm_shd a left join scm_shdzb b on a.id=b.glid where po_bill in ('{purOrdNos}') and sh_material_code in ('{itemnumNos}') and jhdbh!='' and shzt='完成'"; var Endshdzbs = _businessDbContext.scm_shdzbDto.FromSqlRaw(sql).ToList(); //过滤PO、DO: //1、PO只有采购组为110,160的采购订单能使用 //2、DO只有供应类别为"标准"或"VMI"的才能使用 List newPurMasters = new List(); var kyPoList = purOrdMasters.Where(p => !p.PurOrd.StartsWith("DO") && (p.Buyer == "110" || p.Buyer == "160")).ToList(); if (kyPoList.Any()) { newPurMasters.AddRange(kyPoList); } var kyDoList = purOrdMasters.Where(p => p.PurOrd.StartsWith("DO") && (p.USAGE == "标准" || p.USAGE == "VMI")).ToList(); if (kyDoList.Any()) { newPurMasters.AddRange(kyDoList); } purOrdMasters = newPurMasters; //过滤采购单明细 purOrdDetails = purOrdDetails.Where(p => purOrdMasters.Select(m => m.PurOrd).Contains(p.PurOrd)).ToList(); //获取系统级参数:是否启用计划协议(0不启用,1启用) var sysSet = _generalizedCodeMaster.Select(s => s.FldName == "SystemConfig" && s.Val == "ScheduleAgreement" && s.Domain == param.factoryId.ToString()).ToList(); int ScheduleAgreement = 0; if (sysSet.Any()) { if (!string.IsNullOrEmpty(sysSet[0].Ufld1)) { int.TryParse(sysSet[0].Ufld1, out ScheduleAgreement); } } //生成交货单 srm_polist_ds entity; List inserts = new List(); //新生成的PR srm_pr_main srm_Pr = new srm_pr_main(); List prInserts = new List(); //交货单异常记录 List exceptions = new List(); DeliveryExceptionMaster info = new DeliveryExceptionMaster(); //操作时间 string optime = DateTime.Now.ToString("yyyyMMddHHmmss"); //采购明细剩余未交数量 decimal sumRestQty = 0m; //交货单占用数量 decimal sumDbOccupy = 0m; //本次计算占用数量 decimal sumCurOccupy = 0m; //剩余可用数量 decimal restQty = 0m; demandplans = demandplans.OrderBy(p => p.requestdate).ToList(); for (int i = 0; i < demandplans.Count; i++) { //物料数据 var curItem = icitems.FirstOrDefault(p=>p.number == demandplans[i].itemnum); if (curItem == null) { //添加异常记录 info = new DeliveryExceptionMaster(); info.Domain = domain; info.Icdsid = demandplans[i].Id; info.ItemNum = demandplans[i].itemnum; info.CreateTime = DateTime.Now; info.Remark = "物料需求计划[" + demandplans[i].itemnum + ":" + demandplans[i].requestdate.ToString("yyyy-MM-dd") + "]物料尚未同步到ic_item表,请同步后再生成交货单"; info.NeedQty = 0; info.OptTime = optime; exceptions.Add(info); continue; } //获取当前交货计划物料对应的货源清单 var curChaes = purchases.Where(p => p.number == demandplans[i].itemnum).OrderByDescending(p => p.quota_rate).ToList(); //校验1:如果当前物料没有维护货源清单,则跳过 if (!curChaes.Any()) { info = new DeliveryExceptionMaster(); info.Domain = domain; info.Icdsid = demandplans[i].Id; info.ItemNum = demandplans[i].itemnum; info.CreateTime = DateTime.Now; info.Remark = "物料需求计划[" + demandplans[i].itemnum + ":" + demandplans[i].requestdate.ToString("yyyy-MM-dd") + "]没有维护货源清单,无法转交货单"; info.OptTime = optime; exceptions.Add(info); continue; } //校验2:如果当前物料对应货源清单的供应商配额之和不为100%,则跳过 if (curChaes.Sum(p => p.quota_rate.GetValueOrDefault()) != 100) { info = new DeliveryExceptionMaster(); info.Domain = domain; info.Icdsid = demandplans[i].Id; info.ItemNum = demandplans[i].itemnum; info.CreateTime = DateTime.Now; info.Remark = "物料需求计划[" + demandplans[i].itemnum + ":" + demandplans[i].requestdate.ToString("yyyy-MM-dd") + "]的货源清单供应商配额之和不为100%,无法转交货单"; info.OptTime = optime; exceptions.Add(info); continue; } //获取当前交货计划物料对应的可用采购单明细数据 var curPurDtls = purOrdDetails.Where(p => p.ItemNum == demandplans[i].itemnum).OrderBy(p => p.CreateTime).ToList(); //当前采购明细对应的采购单 var curPurMsts = purOrdMasters.Where(p => curPurDtls.Select(m => m.PurOrd).Distinct().Contains(p.PurOrd)).ToList(); //当前采购明细对应的送货单 var curShds = shdzbs.Where(p => p.sh_material_code == demandplans[i].itemnum && curPurDtls.Select(m => m.PurOrd).Contains(p.po_bill)).ToList(); //数据库中当前采购单明细被交货单占用情况 var curDbOccupys = dbPolistds.Where(p => curPurDtls.Select(m => m.PurOrd).Contains(p.ponumber) && p.itemnum == demandplans[i].itemnum).ToList(); //本次计算中采购单明细被交货单占用情况 var curCalcOccupys = inserts.Where(p => curPurDtls.Select(m => m.PurOrd).Contains(p.ponumber) && p.itemnum == demandplans[i].itemnum).ToList(); //当前交货计划已分配数量 decimal allQty = 0m; //当前供应商分配数量 decimal needQty = 0m; //当前供应商已分配数量合计 decimal sumNeedQty = 0m; //当前供应商剩余需要分配数量 decimal remainQty = 0m; //存在货源清单,采购单明细可用数量满足当前交货计划,则先计算供应商配额,计算当前供应商对应的采购明细是否满足配额,若满足则占用采购单明细可用数量 curChaes = curChaes.OrderByDescending(p => p.quota_rate.GetValueOrDefault()).ToList(); for (int j = 0; j < curChaes.Count; j++) { if (curChaes[j].quota_rate.GetValueOrDefault() == 0) { continue; } //如果交货计划已分配数量>=交货计划净需求数量,则终止 if (allQty >= demandplans[i].tosechedqty) { break; } //供应商占用数量置0 sumNeedQty = 0m; //计算当前供应商分配数量 needQty = Math.Ceiling(demandplans[i].tosechedqty * curChaes[j].quota_rate.GetValueOrDefault() / 100.00m); //如果交货计划剩余数量小于按照供应商配额计算的数量,则当前供应商需分配数量为交货计划剩余数量 if (demandplans[i].tosechedqty - allQty < needQty) { needQty = demandplans[i].tosechedqty - allQty; } //获取当前供应商对应的采购单明细数据,按照交货日期从小到大开始占用 var pchPurMsts = curPurMsts.Where(p => p.Supp == curChaes[j].supplier_number).ToList(); var pchPurDtls = curPurDtls.Where(p => pchPurMsts.Select(m => m.PurOrd).Contains(p.PurOrd)).ToList(); //送货单占用数量 var pchShds = curShds.Where(p => pchPurMsts.Select(m => m.PurOrd).Contains(p.po_bill)).ToList(); //校验当前供应商的采购明细剩余可用数量是否满足供应商的配额 //采购单明细剩余可用数量 sumRestQty = pchPurDtls.Sum(p => p.QtyOrded) - pchShds.Sum(p=>p.sh_delivery_quantity); //交货单占用数量:交货单的剩余需要采购数量 var pchDbOccupys = curDbOccupys.Where(p => pchPurDtls.Select(m => m.PurOrd).Contains(p.ponumber)).ToList(); //未关闭交货单需求数量和交货数量两者取最大值,避免交货单需求数量小于送货数量 sumDbOccupy = pchDbOccupys.Where(p=>p.status.ToUpper() == "C").Sum(p=>p.sentqty) + pchDbOccupys.Where(p => p.status.ToUpper() != "C").Sum(p => (p.schedqty>= p.sentqty? p.schedqty: p.sentqty)); //本次计算交货单占用数量:本次计算交货单的需求数量 sumCurOccupy = curCalcOccupys.Where(p => pchPurDtls.Select(m => m.PurOrd).Contains(p.ponumber)).Sum(p => p.schedqty); //交货单已关闭,但已交数量和送货单送货数量不一致 var shTotal= Endshdzbs.Where(p => pchDbOccupys.Where(m=>m.status.ToUpper() == "C" && m.sentqty==0).Select(m => m.dsnum).Contains(p.jhdbh)).Sum(p => p.sh_delivery_quantity); //剩余可用数量 restQty = sumRestQty - sumDbOccupy - sumCurOccupy- shTotal; restQty = restQty < 0 ? 0 : restQty; if (restQty < needQty) { //当前供应商可用采购单明细不足,生成新的pr,记录异常日志 srm_Pr = new srm_pr_main(); srm_Pr.GenerateNewId(help.NextId()); srm_Pr.pr_order_type = curItem.erp_cls == 2 ? "L" : "";//单据类型 srm_Pr.supplier_type = curChaes[j].supplier_type; srm_Pr.IsRequireGoods = curChaes[j].IsRequireGoods; if (curChaes[j].supplier_type == "VMI") { srm_Pr.IsRequireGoods = 1; srm_Pr.pr_order_type = "K"; } srm_Pr.pr_purchaseid = curChaes[j].supplier_id;//供应商id srm_Pr.pr_purchasenumber = curChaes[j].supplier_number;//供应商编码 srm_Pr.pr_purchasename = curChaes[j].supplier_name;//供应商名称 srm_Pr.pr_purchaser = curChaes[j].order_rector_name;//采购员 srm_Pr.pr_purchaser_num = curChaes[j].order_rector_num;//采购员工号(采购信息表) srm_Pr.pr_rqty = needQty - restQty;//需求数量 srm_Pr.pr_aqty = srm_Pr.pr_rqty;//申请数量 srm_Pr.pr_sqty = srm_Pr.pr_rqty;//建议数量 srm_Pr.icitem_id = curItem.Id;//物料id srm_Pr.icitem_name = curItem.name;//物料名称 if (ScheduleAgreement == 1) { srm_Pr.pr_ssend_date = demandplans[i].arrivaldate.AddDays((double)(-7));//系统建议下单日期 srm_Pr.pr_sarrive_date = demandplans[i].arrivaldate;//系统建议到达日期(建议到货日期) } else { srm_Pr.pr_ssend_date = demandplans[i].arrivaldate.AddDays((double)(-1 * curChaes[j].lead_time.GetValueOrDefault()));//系统建议下单日期 srm_Pr.pr_sarrive_date = demandplans[i].arrivaldate; } srm_Pr.pr_sysprice = curChaes[j].order_price;//系统价格(含税) srm_Pr.pr_orderprice = srm_Pr.pr_rqty * curChaes[j].order_price;//订单价格(含税) srm_Pr.pr_price = curChaes[j].netpurchase_price;//采购净价(不含税) srm_Pr.pr_rate = curChaes[j].taxrate;//税率 srm_Pr.pr_unit = curItem.unit;//单位 srm_Pr.state = 1;//状态 srm_Pr.old_apply_aqty = 0;//已申请数量 srm_Pr.pr_type = curItem.erp_cls == 2 ? 2 : 3;//申请类型 srm_Pr.currencytype = curChaes[j].currency_type == null ? 1 : curChaes[j].currency_type.Value;//币种 srm_Pr.secInv_ratio = curItem.secinv_ratio;//安全库存触发采购比例 srm_Pr.tenant_id = curItem.company_id; srm_Pr.company_id = curItem.company_id; srm_Pr.factory_id = curItem.factory_id; srm_Pr.create_time = DateTime.Now; srm_Pr.create_by_name = user; srm_Pr.update_time = DateTime.Now; srm_Pr.update_by_name = user; srm_Pr.remark = "物料需求计划ID[" + demandplans[i].Id + "]生成交货单采购单不足,自动创建的Pr"; prInserts.Add(srm_Pr); //处理总数量,需求数量 allQty += needQty - restQty; needQty -= restQty; //添加异常记录 info = new DeliveryExceptionMaster(); info.Domain = domain; info.Icdsid = demandplans[i].Id; info.ItemNum = demandplans[i].itemnum; info.CreateTime = DateTime.Now; info.Remark = "物料需求计划[" + demandplans[i].itemnum + ":" + demandplans[i].requestdate.ToString("yyyy-MM-dd") + "]对应供应商[" + curChaes[j].supplier_name + "]" + (curChaes[j].IsRequireGoods == 0 ? "采购订单不足,已生成采购申请并推送SAP,请转采购订单后再生成交货单" : "要货令不足,已生成采购申请并自动转要货令,请重新生成交货单"); info.NeedQty = needQty - restQty; info.OptTime = optime; exceptions.Add(info); } //采购单明细优先级:先PO,按照交货日期从早到晚占用;再DO,按照交货日期从早到晚占用 //2024-03-05调整:按照采购订单创建日期从早到晚占用 pchPurDtls = CalcPurDetailPriority(pchPurDtls); for (int k = 0; k < pchPurDtls.Count; k++) { if (sumNeedQty >= needQty) { //当前供应商配额以满足,循环下一个供应商 break; } //当前采购明细剩余数量=订单数量-送货单数量(不是由交货单转的送货单) decimal syQty = pchPurDtls[k].QtyOrded - pchShds.Where(p => p.po_bill == pchPurDtls[k].PurOrd && p.po_billline == pchPurDtls[k].Line.ToString()).Sum(p => p.sh_delivery_quantity); //当前采购明细被占用数量(已占用数量) var occupy = pchDbOccupys.Where(p => p.ponumber == pchPurDtls[k].PurOrd && p.itemnum == pchPurDtls[k].ItemNum && p.poline == pchPurDtls[k].Line).ToList(); decimal yzyQty = occupy.Where(p=>p.status.ToUpper() == "C").Sum(p=>p.sentqty) + occupy.Where(p=>p.status.ToUpper() != "C").Sum(p=>p.schedqty); //当前计算中采购明细被占用数量(本次计算占用数量) var calcs = inserts.Where(p => p.ponumber == pchPurDtls[k].PurOrd && p.itemnum == pchPurDtls[k].ItemNum && p.poline == pchPurDtls[k].Line).ToList(); decimal bzyQty = calcs.Sum(p => p.schedqty); //当前采购明细可用数量 decimal kyQty = syQty - yzyQty - bzyQty; //剩余需要分配数量 remainQty = needQty - sumNeedQty; //当前采购明细已被全部占用,循环下一条采购明细 if (kyQty <= 0) { continue; } decimal xqQty = 0m; //当前采购明细的可用数量不满足交货单剩余需要分配数量 if (kyQty < remainQty) { //占用当前采购明细剩余可用数量 xqQty = kyQty; } else { xqQty = remainQty; //按照最小包装量圆整:最小包装量为0,则不需要圆整 decimal yzQty = curChaes[j].packaging_qty.GetValueOrDefault() == 0 ? remainQty : Math.Ceiling(remainQty / curChaes[j].packaging_qty.GetValueOrDefault()) * curChaes[j].packaging_qty.GetValueOrDefault(); //如果可用数量大于圆整数量 if (kyQty >= yzQty) { xqQty = yzQty; } } //生成实体 entity = new srm_polist_ds(); entity.Id = help.NextId(); entity.domain = domain; entity.icdsid = demandplans[i].Id; //交货单号最后一次性生成 entity.dsnum = ""; entity.status = "N"; entity.itemnum = demandplans[i].itemnum; entity.um = ""; entity.purgroup = ""; entity.suppliercode = curChaes[j].supplier_number; entity.supplier = string.IsNullOrEmpty(curChaes[j].supplier_name) ? "" : curChaes[j].supplier_name; entity.requestdate = demandplans[i].arrivaldate; entity.needdate = demandplans[i].requestdate; entity.ponumber = pchPurDtls[k].PurOrd; entity.poline = pchPurDtls[k].Line; entity.schedqty = xqQty; entity.lastsentqty = 0m; entity.sentqty = 0m; entity.restqty = xqQty; entity.createtime = DateTime.Now; entity.createuser = user; entity.remarks = ""; entity.isactive = 1; inserts.Add(entity); //当前交货计划已分配数量累加 allQty += xqQty; //当前供应商已分配数量累加 sumNeedQty += xqQty; } } } if (inserts.Any()) { //获取交货单号 var nbrlist = _serialNumberAppService.GetBillNo(domain, "M8", inserts.Count, "", 1); if (!nbrlist.Any() || nbrlist.Count != inserts.Count) { Msg = "NO|交货单号生成失败"; return Msg; } inserts = inserts.OrderBy(p => p.createtime).ToList(); for (int i = 0; i < inserts.Count; i++) { if (string.IsNullOrEmpty(nbrlist[i].NbrResult)) { Msg = "NO|交货单号生成失败"; return Msg; } inserts[i].dsnum = nbrlist[i].NbrResult; } } if (prInserts.Any()) { //获取Pr单号 var prlist = _serialNumberAppService.GetBillNo(domain, "PR", prInserts.Count, "", 1); if (!prlist.Any() || prlist.Count != prInserts.Count) { Msg = "NO|采购申请单号生成失败"; return Msg; } prInserts = prInserts.OrderBy(p => p.create_time).ToList(); for (int i = 0; i < prInserts.Count; i++) { if (string.IsNullOrEmpty(prlist[i].NbrResult)) { Msg = "NO|采购申请单号生成失败"; return Msg; } prInserts[i].pr_billno = prlist[i].NbrResult; } } //数据插入 using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { //插入交货单数据 if (inserts.Any()) { _srmpolistds.Insert(inserts); } //插入Pr if (prInserts.Any()) { _businessDbContext.BulkInsert(prInserts); } //插入异常记录 if (exceptions.Any()) { _DeliveryExceptionMaster.Insert(exceptions); } await unitOfWork.CompleteAsync(); } catch (Exception e) { unitOfWork.Dispose(); new NLogHelper("ReplenishmentAppService").WriteLog("CreateDeliverySchedule", "交货计划生成交货单失败:" + e.Message, _currentTenant.Id.ToString()); Msg = "NO|交货单保存失败:" + e.Message; }; } return Msg; } /// /// 计算采购单明细的占用优先级 /// /// /// public List CalcPurDetailPriority(List details) { List newDetails = new List(); //获取DO var doLists = details.Where(p => p.PurOrd.StartsWith("DO")).OrderBy(p=>p.CreateTime).ToList(); //获取PO var poLists = details.Where(p => !doLists.Select(m => m.PurOrd).Contains(p.PurOrd)).OrderBy(p => p.CreateTime).ToList(); for (int i = 0; i < poLists.Count; i++) { newDetails.Add(poLists[i]); } for (int i = 0; i < doLists.Count; i++) { newDetails.Add(doLists[i]); } return newDetails; } } }