using Business.Core.Enum; using Business.Core.MongoDBHelper; using Business.Core.Utilities; using Business.Dto; using Business.EntityFrameworkCore; using Business.EntityFrameworkCore.SqlRepositories; using Business.Model.Bang; using Business.Model.MES.IC; using Business.Model.Production; using Business.Model.Sale; using Business.Model.SRM; using Business.Model.Tech; using Business.MongoModel.MES.IC; using Business.MongoModel.Production; using Business.MongoModel.SRM; using Business.MongoModel.Tech; using Business.PriorityManagement; using Business.ResourceExamineManagement.Dto; using EFCore.BulkExtensions; using Microsoft.EntityFrameworkCore; using MongoDB.Driver; using MongoDB.Driver.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Dynamic.Core; using System.Threading.Tasks; using Volo.Abp.Application.Services; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; namespace Business.ResourceExamineManagement { /// /// 资源检查 /// //[Authorize(BusinessPermissions.ResourceExamine.Default)] public class ResourceExamineAppService : ApplicationService, IResourceExamineAppService, ITransientDependency { #region 服务 SnowFlake help = new SnowFlake(); private readonly ICurrentTenant _currentTenant; /// /// 工艺路径 /// private readonly IMongoDB _mes_technique; /// /// 工序 /// private readonly IMongoDB _mes_process; /// /// 工艺关联工序 /// private readonly IMongoDB _mes_tech_process; /// /// 工艺工序关联工位 /// private readonly IMongoDB _mes_tech_proc_workshop; /// /// 物料占用记录 /// private readonly IMongoDB _ic_item_stockoccupy; private IRepository _mysql_ic_item_stockoccupy; /// /// 物料详情 /// private readonly IMongoDB _ic_item; private IRepository _mysql_ic_item; /// /// 物料BOM /// private readonly IMongoDB _ic_bom; private IRepository _mysql_ic_bom; /// /// 物料BOM明细 /// private readonly IMongoDB _ic_bom_child; private IRepository _mysql_ic_bom_child; /// /// 物料库存表 /// private readonly IMongoDB _ic_item_stock; private IRepository _mysql_ic_item_stock; /// /// 物料采购报价单 /// private readonly IMongoDB _srm_purchase; private IRepository _mysql_srm_purchase; /// /// 采购申请单 /// private readonly IMongoDB _srm_pr_main; private IRepository _mysql_srm_pr_main; /// /// 采购订单表 /// private readonly IMongoDB _srm_po_main; private IRepository _mysql_srm_po_main; /// /// 采购订单明细表 /// private readonly IMongoDB _srm_po_list; private IRepository _mysql_srm_po_list; /// /// 采购订单占用详情 /// private readonly IMongoDB _srm_po_occupy; private IRepository _mysql_srm_po_occupy; /// /// 供应商 /// private readonly IMongoDB _srm_supplier; private IRepository _mysql_srm_supplier; /// /// 委外工单 /// private readonly IMongoDB _mes_oorder; private IRepository _mysql_mes_oorder; private IRepository _mysql_b_bom_pretreatment; private IRepository _mysql_examine_result; private IRepository _mysql_bom_child_examine; private IRepository _mysql_mo_occupy; private IRepository _mysql_mo_order; private IRepository _mysql_ooder; private IRepository _mysql_purchase; private IRepository _mysql_purchase_occupy; /// /// 替代群组 /// private readonly IMongoDB _ic_substitute; /// /// 替代群组 /// private readonly IMongoDB _ic_substitute_group; /// /// 替代群组 /// private readonly IMongoDB _ic_substitute_group_detail; /// /// 生产工单主表 /// private readonly IMongoDB _mes_morder; /// /// 生产工单子表 /// private readonly IMongoDB _mes_moentry; /// /// 在制工单占用记录表 /// private readonly IMongoDB _mes_mooccupy; /// /// mysql在制工单占用表 /// private readonly IRepository _mysql_mes_mooccupy; /// /// 销售订单 /// private readonly IRepository _mysql_crm_seorder; /// /// 销售订单明细 /// private readonly IRepository _mysql_crm_seorderentry; /// /// 生产工单主表 /// private readonly IRepository _mysql_mes_morder; /// /// 生产工单子表 /// private readonly IRepository _mysql_mes_moentry; /// /// 工艺路线表 /// private readonly ISqlRepository _routingOpDetail; /// /// 生产线明细 /// private readonly ISqlRepository _prodLineDetail; /// /// 排产记录表 /// private readonly ISqlRepository _periodSequenceDet; /// /// 排产结果明细 /// private ISqlRepository _scheduleResultOpMaster; /// /// 工作日历 /// private readonly ISqlRepository _shopCalendarWorkCtr; /// /// 休息时间段 /// private readonly ISqlRepository _qualityLineWorkDetail; /// /// 节假日 /// private readonly ISqlRepository _holidayMaster; /// /// 标准BOM表 /// private readonly ISqlRepository _productStructureMaster; /// /// 工单工序表 /// private ISqlRepository _workOrdRouting; /// /// 工单主表 /// private ISqlRepository _workOrdMaster; /// /// 工单物料明细 /// private ISqlRepository _workOrdDetail; private readonly ISqlRepository _rf_serialnumber; private readonly ISqlRepository _locationDetail; /// /// 资源检查入参 /// private readonly SeorderentryDto param = new SeorderentryDto(); /// /// 预处理 /// private readonly PretreatmentAppService _pretreatmentAppService; /// /// 在途检查 /// private readonly PurchaseOrderAppService _purchaseOrderAppService; /// /// 工单App /// private readonly MorderAppService _morderAppService; /// /// 计算BOM平铺物料情况 /// private readonly CalcBomViewAppService _CalcBomViewAppService; private List leadTimeList; private List supplierList; private readonly BusinessBangDbContext _businessBangDbContext; private readonly BusinessDbContext _businessDbContext; private readonly ISqlRepository _tagMasterRepository; /// /// 生产线维护表 /// private ISqlRepository _lineMaster; private ISqlRepository _itemMaster; private ISqlRepository _nbrMaster; private ISqlRepository _nbrDetail; private ISqlRepository _purOrdMaster; private ISqlRepository _purOrdDetail; private ISqlRepository _itemPackMaster; private ISqlRepository _generalizedCodeMaster; /// /// 生产排产 /// private readonly ProductionScheduleAppService _productionScheduleAppService; /// /// 优先级 /// private readonly PriorityAppService _priorityAppService; /// /// 产能检查 /// private readonly ProductExamineAppService _productExamineAppService; /// /// 生产线明细表 /// 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(); /// /// 节假日 /// public List holidays = new List(); private readonly IUnitOfWorkManager _unitOfWorkManager; #endregion #region 构造函数 /// /// 构造函数 /// /// /// public ResourceExamineAppService( IMongoDB mes_technique, IMongoDB mes_process, IMongoDB mes_tech_process, IMongoDB mes_tech_proc_workshop, IMongoDB ic_item, IMongoDB ic_bom, IMongoDB ic_bom_child, IMongoDB ic_item_stock, IMongoDB mes_oorder, IMongoDB srm_pr_main, IMongoDB srm_po_main, IMongoDB srm_po_list, IMongoDB srm_po_occupy, IMongoDB srm_purchase, IMongoDB ic_substitute, IMongoDB ic_substitute_group, IMongoDB ic_substitute_group_detail, IMongoDB mes_morder, IMongoDB mes_moentry, IMongoDB mes_mooccupy, IMongoDB ic_item_stockoccupy, IMongoDB srm_supplier, IRepository mysql_ic_item, IRepository mysql_ic_bom, IRepository mysql_ic_bom_child, IRepository mysql_mes_technique, IRepository mysql_crm_seorder, IRepository mysql_crm_seorderentry, IRepository mysql_ic_item_stock, IRepository mysql_ic_item_stockoccupy, IRepository mysql_mes_oorder, IRepository mysql_srm_pr_main, IRepository mysql_mes_mooccupy, IRepository mysql_mes_morder, IRepository mysql_mes_moentry, IRepository mysql_mes_process, IRepository mysql_mes_tech_process, IRepository mysql_srm_po_main, IRepository mysql_srm_po_list, IRepository mysql_srm_po_occupy, IRepository mysql_srm_purchase, IRepository mysql_examine_result, IRepository mysql_bom_child_examine, IRepository mysql_mo_occupy, IRepository mysql_mo_order, IRepository mysql_ooder, IRepository mysql_purchase, IRepository mysql_purchase_occupy, IRepository mysql_b_bom_pretreatment, IRepository mysql_srm_supplier, ISqlRepository tagMasterRepository, ISqlRepository periodSequenceDet, ISqlRepository lineMaster, ISqlRepository itemMaster, PretreatmentAppService pretreatmentAppService, CalcBomViewAppService calcbomviewAppService, PurchaseOrderAppService purchaseOrderAppService, ICurrentTenant currentTenant, MorderAppService morderAppService, BusinessBangDbContext businessBangDbContext, BusinessDbContext businessDbContext, ProductionScheduleAppService productionScheduleAppService, ISqlRepository routingOpDetail, ISqlRepository productStructureMaster, ISqlRepository workOrdRouting, ISqlRepository workOrdMaster, ISqlRepository workOrdDetail, ISqlRepository nbrMaster, ISqlRepository nbrDetail, ISqlRepository purOrdMaster, ISqlRepository purOrdDetail, PriorityAppService priorityAppService, ISqlRepository prodLineDetail, ISqlRepository shopCalendarWorkCtr, ISqlRepository qualityLineWorkDetail, ISqlRepository holidayMaster, ProductExamineAppService productExamineAppService, ISqlRepository rf_serialnumber, ISqlRepository locationDetail, ISqlRepository itemPackMaster, ISqlRepository generalizedCodeMaster, ISqlRepository scheduleResultOpMaster, IUnitOfWorkManager unitOfWorkManager ) { _mes_technique = mes_technique; _mes_process = mes_process; _mes_tech_process = mes_tech_process; _mes_tech_proc_workshop = mes_tech_proc_workshop; _ic_item = ic_item; _ic_bom = ic_bom; _ic_bom_child = ic_bom_child; _ic_item_stock = ic_item_stock; _mes_oorder = mes_oorder; _srm_pr_main = srm_pr_main; _srm_po_main = srm_po_main; _srm_po_list = srm_po_list; _srm_po_occupy = srm_po_occupy; _srm_purchase = srm_purchase; _ic_substitute = ic_substitute; _ic_substitute_group = ic_substitute_group; _ic_substitute_group_detail = ic_substitute_group_detail; _mes_morder = mes_morder; _mes_moentry = mes_moentry; _mes_mooccupy = mes_mooccupy; _ic_item_stockoccupy = ic_item_stockoccupy; _srm_supplier = srm_supplier; _mysql_ic_item = mysql_ic_item; _mysql_ic_bom = mysql_ic_bom; _mysql_ic_bom_child = mysql_ic_bom_child; _mysql_crm_seorder = mysql_crm_seorder; _mysql_crm_seorderentry = mysql_crm_seorderentry; _mysql_ic_item_stock = mysql_ic_item_stock; _mysql_ic_item_stockoccupy = mysql_ic_item_stockoccupy; _mysql_mes_oorder = mysql_mes_oorder; _mysql_srm_pr_main = mysql_srm_pr_main; _mysql_mes_mooccupy = mysql_mes_mooccupy; _mysql_mes_morder = mysql_mes_morder; _mysql_mes_moentry = mysql_mes_moentry; _mysql_srm_po_main = mysql_srm_po_main; _mysql_srm_po_list = mysql_srm_po_list; _mysql_srm_po_occupy = mysql_srm_po_occupy; _mysql_srm_purchase = mysql_srm_purchase; _mysql_examine_result = mysql_examine_result; _mysql_bom_child_examine = mysql_bom_child_examine; _mysql_mo_occupy = mysql_mo_occupy; _mysql_mo_order = mysql_mo_order; _mysql_ooder = mysql_ooder; _mysql_purchase = mysql_purchase; _mysql_purchase_occupy = mysql_purchase_occupy; _mysql_b_bom_pretreatment = mysql_b_bom_pretreatment; _mysql_srm_supplier = mysql_srm_supplier; _tagMasterRepository = tagMasterRepository; _periodSequenceDet = periodSequenceDet; _pretreatmentAppService = pretreatmentAppService; _CalcBomViewAppService = calcbomviewAppService; _purchaseOrderAppService = purchaseOrderAppService; _currentTenant = currentTenant; _morderAppService = morderAppService; _businessBangDbContext = businessBangDbContext; _businessDbContext = businessDbContext; _productionScheduleAppService = productionScheduleAppService; _routingOpDetail = routingOpDetail; _productStructureMaster = productStructureMaster; _workOrdRouting = workOrdRouting; _workOrdMaster = workOrdMaster; _workOrdDetail = workOrdDetail; _lineMaster = lineMaster; _itemMaster = itemMaster; _nbrMaster = nbrMaster; _nbrDetail = nbrDetail; _purOrdMaster = purOrdMaster; _purOrdDetail= purOrdDetail; _priorityAppService = priorityAppService; _rf_serialnumber = rf_serialnumber; _prodLineDetail = prodLineDetail; _shopCalendarWorkCtr = shopCalendarWorkCtr; _qualityLineWorkDetail = qualityLineWorkDetail; _holidayMaster = holidayMaster; _productExamineAppService = productExamineAppService; _locationDetail = locationDetail; _itemPackMaster = itemPackMaster; _generalizedCodeMaster = generalizedCodeMaster; _unitOfWorkManager = unitOfWorkManager; _scheduleResultOpMaster = scheduleResultOpMaster; } #endregion /// /// 资源检查 -- TODO:根据客户的不同标准交货期(假如客户设定10天),如果检查交期小于标准交货期(10天),则默认把建议交期调整为10天。 /// /// /// 类型(0,销售订单 1,销售订单行) /// /// public async Task ReceiveResult(string ids,int type) { if (string.IsNullOrEmpty(ids)) { throw new NotImplementedException("请输入正确的订单号!"); } ResourceCheckInputDto input = new ResourceCheckInputDto(); input.sorderId = AnalysisIdList(ids); //资源检查结果 PschedDto rtn = new PschedDto(); List sorders = new List(); List sentrys = new List(); //生成当前计算bangid long bangid = help.NextId(); if (type == 0) { //获取订单数据 sorders = _mysql_crm_seorder.GetListAsync(p => input.sorderId.Contains(p.Id) && !p.IsDeleted).Result; if (!sorders.Any()) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "订单数据不存在", _currentTenant.Id.ToString()); //throw new NotImplementedException("订单数据不存在!"); return "订单数据不存在"; } //获取订单行数据 sentrys = await _mysql_crm_seorderentry.GetListAsync(p => input.sorderId.Contains(p.seorder_id.GetValueOrDefault()) && (p.progress=="1" || p.progress == "2") && !p.IsDeleted); if (!sentrys.Any()) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "订单行数据不存在", _currentTenant.Id.ToString()); //throw new NotImplementedException("订单行数据不存在!"); return "订单行数据不存在"; } } else { //获取订单行数据 sentrys = await _mysql_crm_seorderentry.GetListAsync(p => input.sorderId.Contains(p.Id) && (p.progress == "1" || p.progress == "2") && !p.IsDeleted); if (!sentrys.Any()) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "订单行数据不存在", _currentTenant.Id.ToString()); //throw new NotImplementedException("订单行数据不存在!"); return "订单行数据不存在"; } sorders = _mysql_crm_seorder.GetListAsync(p => sentrys.Select(s => s.seorder_id).Contains(p.Id) && !p.IsDeleted).Result; if (!sorders.Any()) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "订单数据不存在", _currentTenant.Id.ToString()); //throw new NotImplementedException("订单数据不存在!"); return "订单数据不存在"; } } input.tenantId = sorders[0].tenant_id; input.factoryId = sorders[0].factory_id.GetValueOrDefault(); //资源检查入参全局变量赋值 param.tenantId = input.tenantId; param.factoryId = input.factoryId; param.checkflag = true; rtn.sorderid = input.sorderId; //资源检查明细list List examines = new List(); ExamineResult dtl; //处理销售订单优先级 sorders = _priorityAppService.CalcOrderPriority(sorders, sentrys); AsyncItemStockFromWMS(sentrys); //处理订单行优先级 sentrys = _priorityAppService.CalcOrderEntryPriority(sorders, sentrys); //删除同步Mysql后旧数据 await DeleteMySqlOldData(sentrys); //通过订单行的产品代码获取物料BOM数据 List boms = _ic_bom.Find(p => sentrys.Select(m => m.item_number).Contains(p.item_number) && p.factory_id == input.factoryId && p.tenant_id == input.tenantId && !p.IsDeleted).Result.ToList(); //物料信息 List icitemlist = new List(); //物料库存表 List stocklist = new List(); //物料占用记录 List sklist = new List(); 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(autoCreates); pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; } //数据库快照-同步mysql库数据到mongoDB中 await DbSnapShot(input.tenantId, input.factoryId, bangid, pretreatments); //记录订单行的物料齐套时间 List kittingTimes = new List(); DataInitialization(boms, bangid, icitemlist, stocklist, pretreatments); foreach (var sorder in sorders) { param.sorderId = sorder.Id; param.tenantId = input.tenantId; param.factoryId = input.factoryId; //param.checkflag = true; _morderAppService.param = param; _purchaseOrderAppService.param = param; _CalcBomViewAppService.param = param; _CalcBomViewAppService.seorder = sorder;//销售订单 var orderSentrys = sentrys.Where(s => s.seorder_id == sorder.Id).ToList(); foreach (var item in orderSentrys) { //获取销售订单“是否加急”字段 int urgent = sorder.urgent; //工单资源检查信息 dtl = new ExamineResult(); dtl.sorderid = sorder.Id; dtl.bill_no = sorder.bill_no; dtl.sentry_id = item.Id; dtl.entry_seq = item.entry_seq; dtl.need_qty = item.qty.GetValueOrDefault(); dtl.need_time = item.plan_date; dtl.bangid = bangid; //获取当前物料bom数据 var childBom = boms.Where(p => p.item_number == item.item_number).FirstOrDefault(); dtl.bom_number = childBom.bom_number; var itemPrelist = pretreatments.Where(s => s.sourceid == childBom.mysql_id).ToList(); if (!itemPrelist.Any()) { continue; } var getBomList = ObjectMapper.Map, List>(itemPrelist); getBomList.ForEach(s => s.sentry_id = item.Id); //库存初始化 _CalcBomViewAppService.BomStock(getBomList, stocklist, bangid); _CalcBomViewAppService.newStockOccList = new List(); //计算 _CalcBomViewAppService.CalcView(getBomList, bangid, item.qty.GetValueOrDefault(), item.plan_date, sklist, item, urgent, icitemlist); //TODO:最晚开始时间 var curFacDtl = leadTimeList.FirstOrDefault(p => p.item_id == childBom.icitem_id); //最晚开工时间=订单行客户要求交期-运输提前期-库存提前期-生产提前期-下单提前期-生产时间 dtl.latest_times = item.plan_date.GetValueOrDefault().AddDays(-Convert.ToDouble(curFacDtl?.transportation_leadtime.GetValueOrDefault() + curFacDtl?.stock_leadtime.GetValueOrDefault() + curFacDtl?.production_leadtime.GetValueOrDefault() + curFacDtl?.order_leadtime.GetValueOrDefault() + _CalcBomViewAppService.ProductionTimeDay)); //物料齐套时间 dtl.kitting_times = getBomList.Where(p => p.is_use).OrderByDescending(m => m.kitting_time).First().kitting_time.GetValueOrDefault(); //TODO:最早开始时间默认3天后(后期调整,因为要计算排产,计算产能这一类,才能得到开工时间) dtl.earliest_times = dtl.kitting_times.AddDays(1); item.progress = "2"; //替代关系展开list dtl.BomChildExamineList = getBomList; //添加订单行开工信息 examines.Add(dtl); //记录订单行的建议交期 KittingTimeDto dto = new KittingTimeDto(); dto.sentry_id = item.Id; dto.ItemNum = item.item_number; dto.LackQty = getBomList.First(p => p.level == 1).lack_qty; dto.kitting_time = dtl.kitting_times; kittingTimes.Add(dto); } } //计算订单行的建议交期(产能/物料) CalcSuggestDate(sentrys, kittingTimes, icitemlist); examines.ForEach(p => { var sent = sentrys.Find(s => s.Id == p.sentry_id); if (sent != null) { p.sys_material_date = sent.sys_material_date; p.sys_capacity_date = sent.sys_capacity_date; } }); rtn.mordersList = _CalcBomViewAppService.mordersInsertList; List prmainlist = new List(); if (_CalcBomViewAppService.SRMPRDtoList.Any()) { List> prlist = _CalcBomViewAppService.SRMPRDtoList.Where(f => f.srm_Pr_Main != null).Select(s => s.srm_Pr_Main).ToList(); foreach (var pr in prlist) { foreach (var item in pr) { prmainlist.Add(item); } } rtn.srm_pr_list = _CalcBomViewAppService.SRMPRDtoList; } using (var unitOfWork = _unitOfWorkManager.Begin(false,true)) { try { await _mysql_crm_seorderentry.UpdateManyAsync(sentrys); /*//批量保存 后期考虑子工单 if (moderlist.Any()) { await _mes_morder.InsertMany(_CalcBomViewAppService.mordersInsertList); _businessDbContext.BulkInsert(moderlist); if (workOrds.Any()) { _workOrdMaster.Insert(workOrds); } if (workOrdRoutings.Any()) { _workOrdRouting.Insert(workOrdRoutings); } if (workOrdDetails.Any()) { _workOrdDetail.Insert(workOrdDetails); } }*/ if (_CalcBomViewAppService.mordersInsertList.Any()) { await _mes_morder.InsertMany(_CalcBomViewAppService.mordersInsertList); } if (prmainlist.Any()) { await _srm_pr_main.InsertMany(prmainlist); } if (_CalcBomViewAppService.mooccupyAllInsertList.Any()) { _CalcBomViewAppService.mooccupyAllInsertList.ForEach(s => { s.tenant_id = param.tenantId; s.factory_id = param.factoryId; }); await _mes_mooccupy.InsertMany(_CalcBomViewAppService.mooccupyAllInsertList); /*var moOccupy = ObjectMapper.Map, List>(_CalcBomViewAppService.mooccupyAllInsertList); _businessDbContext.BulkInsert(moOccupy);*/ rtn.mooccupyAllList = _CalcBomViewAppService.mooccupyAllInsertList; } if (_CalcBomViewAppService.moentriesInsertList.Any()) { _CalcBomViewAppService.moentriesInsertList.ForEach(s => { s.tenant_id = param.tenantId; s.factory_id = param.factoryId; }); await _mes_moentry.InsertMany(_CalcBomViewAppService.moentriesInsertList); /*var mesmoentrys = ObjectMapper.Map, List>(_CalcBomViewAppService.moentriesInsertList); _businessDbContext.BulkInsert(mesmoentrys);*/ } if (_CalcBomViewAppService.orderList.Any()) { _CalcBomViewAppService.orderList.ForEach(s => { s.tenant_id = param.tenantId; s.factory_id = param.factoryId; }); await _mes_oorder.InsertMany(_CalcBomViewAppService.orderList); /*var ooders = ObjectMapper.Map, List>(_CalcBomViewAppService.orderList); _businessDbContext.BulkInsert(ooders);*/ rtn.order_list = _CalcBomViewAppService.orderList; } if (_CalcBomViewAppService.newStockOccList.Any()) { _CalcBomViewAppService.newStockOccList.ForEach(s => { s.id = help.NextId(); s.tenant_id = param.tenantId; s.factory_id = param.factoryId; }); await _ic_item_stockoccupy.InsertMany(_CalcBomViewAppService.newStockOccList); } if (_CalcBomViewAppService.srm_Po_OccupiesInsert.Any()) { _CalcBomViewAppService.srm_Po_OccupiesInsert.ForEach(s => { s.tenant_id = param.tenantId; s.factory_id = param.factoryId; }); await _srm_po_occupy.InsertMany(_CalcBomViewAppService.srm_Po_OccupiesInsert); /*var poOccupies = ObjectMapper.Map, List>(_CalcBomViewAppService.srm_Po_OccupiesInsert); _businessDbContext.BulkInsert(poOccupies);*/ } await unitOfWork.CompleteAsync(); } catch (Exception e) { unitOfWork.Dispose(); new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "资源检查工单相关数据更新失败:" + e.Message, _currentTenant.Id.ToString()); return e.Message; }; } rtn.examines = examines; rtn.item_stockoccupy_list = sklist; //检查结果写入数据库 var b_Examine_Results = ObjectMapper.Map, List>(rtn.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 rtn.examines) { var b_ex = ObjectMapper.Map(ex); b_ex.GenerateNewId(help.NextId());// = help.NextId(); if (_CalcBomViewAppService.mordersInsertList.Any()) { var moentry = _CalcBomViewAppService.moentriesInsertList.Where(s => s.soentry_id == b_ex.sentry_id).FirstOrDefault(); if (moentry != null) { var sentryMo = _CalcBomViewAppService.mordersInsertList.Where(s => s.mysql_id == moentry.moentry_moid).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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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(); return e.Message; } } //清空快照数据 await ClearSnapShot(bangid); return JsonConvert.SerializeObject("ok"); } //PR手动合并 public async Task PrMerge(string ids) { //物料、供应商为相同才允许合并。 var idList = AnalysisIdList(ids); List prlist = _mysql_srm_pr_main.GetListAsync(s => idList.Contains(s.Id)).Result; if (prlist.Where(s => s.state == 0).Count() > 0) { return JsonConvert.SerializeObject("所选包含已关闭采购申请,请重新选择。"); } if (prlist.Where(s => s.state == 2).Count() > 0) { return JsonConvert.SerializeObject("所选包含已提交评审采购申请,请重新选择。"); } if (prlist.Where(s => s.state == 4).Count() > 0) { return JsonConvert.SerializeObject("所选包含已评审通过采购申请,请重新选择。"); } if (prlist.Any()) { var list = prlist.GroupBy(s => new { s.icitem_id, s.pr_purchaseid }); if (list.Count() > 1) { return JsonConvert.SerializeObject("所选行的物料编码,供应商名称必须相同"); } } else { return JsonConvert.SerializeObject("所选采购申请单未找到,请刷新界面重新操作。"); } srm_pr_main srm_Pr = help.DeepCopy(prlist[0]); srm_Pr.GenerateNewId(help.NextId()); srm_Pr.pr_billno = prlist[0].pr_type == 2 ? _CalcBomViewAppService.getOrderNum("WWPR") : _CalcBomViewAppService.getOrderNum("PR");//pr单号 srm_Pr.state = 1; /*if (mes_morder != null) { srm_Pr.pr_mono = mes_morder.morder_no;//关联工单号 srm_Pr.entity_id = 1;//工单行号 }*/ srm_Pr.pr_purchaseid = prlist[0].pr_purchaseid;//供应商id srm_Pr.pr_purchasenumber = prlist[0].pr_purchasenumber;//供应商编码 srm_Pr.pr_purchasename = prlist[0].pr_purchasename;//供应商名称 srm_Pr.pr_purchaser = prlist[0].pr_purchaser;//采购员 srm_Pr.pr_purchaser_num = "";//采购员工号(采购信息表)*//* srm_Pr.pr_rqty = prlist.Sum(s => s.pr_rqty);//需求数量 srm_Pr.pr_aqty = prlist.Sum(s => s.pr_aqty);//申请数量 srm_Pr.pr_sqty = prlist.Sum(s => s.pr_sqty);//建议数量 srm_Pr.pr_ssend_date= prlist.Min(s => s.pr_ssend_date);//系统建议下单日期 srm_Pr.pr_sarrive_date = prlist.Min(s => s.pr_sarrive_date);//系统建议到达日期(建议到货日期) srm_Pr.pr_psend_date = prlist.Min(s => s.pr_psend_date);//计划下单日期 srm_Pr.pr_parrive_date = prlist.Min(s => s.pr_parrive_date);//计划到达日期 srm_Pr.pr_rarrive_date = prlist.Min(s => s.pr_rarrive_date);//需求到货日期 srm_Pr.pr_sysprice = prlist.Sum(s => s.pr_rqty) * prlist[0].pr_price * (1 + prlist[0].pr_rate);//系统价格(含税) srm_Pr.pr_orderprice = prlist.Sum(s => s.pr_rqty) * prlist[0].pr_price * (1 + prlist[0].pr_rate);//订单价格(含税) /*srm_Pr.icitem_id = returnlist.item_id;//物料id srm_Pr.icitem_name = returnlist.item_name;//物料名称 srm_Pr.pr_order_type = 1;//单据类型 srm_Pr.pr_ssend_date = DateTime.Now;//系统建议下单日期 srm_Pr.pr_price = prlist[0].pr_price;//采购净价(不含税) srm_Pr.pr_rate = prlist[0].pr_rate;//税率 srm_Pr.pr_unit = prlist[0].pr_unit;//单位 srm_Pr.state = prlist[0].state;//状态 srm_Pr.old_apply_aqty = prlist[0].old_apply_aqty;//已申请数量 srm_Pr.pr_type = prlist[0].pr_type;//申请类型 srm_Pr.currencytype = prlist[0].currencytype;//币种 srm_Pr.secInv_ratio = prlist[0].secInv_ratio;//安全库存触发采购比例 srm_Pr.tenant_id = prlist[0].tenant_id; srm_Pr.factory_id = prlist[0].factory_id;*/ prlist.ForEach(s => { s.state = 0; s.refer_pr_billno = srm_Pr.pr_billno; }); using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { _businessDbContext.BulkUpdate(prlist); _businessDbContext.BulkInsert(new List { srm_Pr }); await unitOfWork.CompleteAsync(); } catch (Exception e) { new NLogHelper("ResourceExamineAppService").WriteLog("PrMerge", "采购申请单合并数据更新失败:" + e.Message, _currentTenant.Id.ToString()); unitOfWork.Dispose(); return JsonConvert.SerializeObject(e.Message); } } return JsonConvert.SerializeObject("ok"); } //PR自动合并 public void PrAutoMerge() { //TODO:先按每周四调度任务循环,周五下单处理 //拉取所有,然后根据送货周期来合并第一次得合并数据 //List prlist = _mysql_srm_pr_main.GetListAsync(s => s.state == 1 || s.state == 2).Result; //直接按间隔多少天一次来处理数据,定时任务按周四来考虑。 DateTime toTime = new DateTime(2023, 7, 6); DateTime starttime = toTime.Date.AddDays(8); DateTime endtime = toTime.Date.AddDays(14); List prlist = _mysql_srm_pr_main.GetListAsync(s => s.pr_rarrive_date >= starttime && s.pr_rarrive_date <= endtime && (s.state == 1 || s.state == 3)).Result; //List prlist = _mysql_srm_pr_main.GetListAsync(s => s.icitem_id == 1949).Result; //List purchaselist = _mysql_srm_purchase.GetListAsync(s => prlist.Select(c => c.icitem_id).Contains(s.icitem_id) && prlist.Select(c => c.pr_purchaseid).Contains(s.supplier_id)).Result; List ic_Items = _mysql_ic_item.GetListAsync(s => prlist.Select(c => c.icitem_id).Contains(s.Id)).Result; List prWeekDtos = new List(); List insetPrList = new List(); List updatePrList = new List(); var moPrlist = ObjectMapper.Map, List>(prlist); foreach (var pr in prlist) { bool bl = pr.sentry_id == null ? true : false; //找到是否生成了新的PR //var newPr = insetPrList.Find(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id && (s.sentry_id == null) == bl); var newPr = insetPrList.Find(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id); if (newPr == null) { //有多条才进行合并 //var ilist = prlist.Where(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id && (s.sentry_id == null) == bl).ToList(); var ilist = prlist.Where(s => s.pr_purchaseid == pr.pr_purchaseid && s.icitem_id == pr.icitem_id).ToList(); if (ilist.Count > 1) { var icitem = ic_Items.Find(s => s.Id == pr.icitem_id); newPr = help.DeepCopy(pr); newPr.GenerateNewId(help.NextId()); newPr.pr_billno = pr.pr_type == 2 ? _CalcBomViewAppService.getOrderNum("WWPR") : _CalcBomViewAppService.getOrderNum("PR");//pr单号 newPr.state = pr.state; newPr.pr_rqty = ilist.Sum(s => s.pr_rqty);//需求数量 newPr.pr_aqty = ilist.Sum(s => s.pr_aqty);//申请数量 newPr.pr_sqty = ilist.Sum(s => s.pr_sqty);//建议数量 decimal day = 0; if (icitem != null) { //目前只加入了下单前置(天) day += icitem.order_leadtime.GetValueOrDefault(); } newPr.pr_rarrive_date = starttime;//需求到货日期 newPr.pr_ssend_date = newPr.pr_rarrive_date.Value.AddDays(-double.Parse(day.ToString()));//系统建议下单日期 newPr.pr_psend_date = newPr.pr_ssend_date;//计划下单日期 newPr.pr_sarrive_date = newPr.pr_rarrive_date;//系统建议到达日期(建议到货日期) newPr.pr_parrive_date = newPr.pr_rarrive_date;//计划到达日期 newPr.pr_sysprice = newPr.pr_rqty * pr.pr_price * (1 + pr.pr_rate);//系统价格(含税) newPr.pr_orderprice = newPr.pr_rqty * pr.pr_price * (1 + pr.pr_rate);//订单价格(含税) ilist.ForEach(s => { s.refer_pr_billno = newPr.pr_billno; }); insetPrList.Add(newPr); ilist.ForEach(s => { s.state = 0; }); updatePrList.AddRange(ilist); } } } #region 此逻辑是处理按每周几送货实现,先屏蔽 /*foreach (var pr in moPrlist) { var pur = purchaselist.Find(s => s.icitem_id == pr.icitem_id && s.supplier_id == pr.pr_purchaseid); if (pur != null) { if (pur.is_week) { var prDtos = prWeekDtos.Where(s => s.icitem_id == pr.icitem_id && s.pr_purchaseid == pr.pr_purchaseid).ToList(); if (!prDtos.Any()) { prDtos = AnalysisIntervalData(pur.is_days, pr); prWeekDtos.AddRange(prDtos); } //判断当前PR属于哪个区间 if (prDtos.Any()) { foreach (var dto in prDtos) { int wk = (int)pr.pr_rarrive_date.GetValueOrDefault().DayOfWeek; wk = wk == 0 ? 7 : wk; if (dto.weekList.Contains(wk)) { if (wk >= dto.week) { pr.pr_rarrive_date = pr.pr_rarrive_date.GetValueOrDefault().Date.AddDays(dto.week - wk); } else { //wk 2 week 5 pr.pr_rarrive_date = pr.pr_rarrive_date.GetValueOrDefault().Date.AddDays(0 - wk - (7 - dto.week)); } break; } } } else { //如果没有则还是需要处理 } } else { //如果此物料没有设置周期送货,则所有数据合并为一个PR,转成一个PO } } }*/ #endregion using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { if (insetPrList.Any()) { _businessDbContext.BulkInsert(insetPrList); } if (updatePrList.Any()) { _businessDbContext.BulkUpdate(updatePrList); } unitOfWork.CompleteAsync(); } catch (Exception e) { unitOfWork.Dispose(); new NLogHelper("ResourceExamineAppService").WriteLog("PrAutoMerge", "采购申请单自动合并更新失败:" + e.Message, _currentTenant.Id.ToString()); }; } } /// /// 解析按周频率送货方式 /// /// /// /// private List AnalysisIntervalData(string is_days,mo_srm_pr_main pr) { List prWeekDtos = new List(); //周期送货,需要对数据进行按周期区分 if (!string.IsNullOrEmpty(is_days)) { string[] days = JsonConvert.DeserializeObject(is_days); List weekInt = new List(); foreach (var d in days) { if (!string.IsNullOrEmpty(d)) { weekInt.Add(int.Parse(d)); } } weekInt.Sort(); //解析区间值 for (int idx = 0; idx < weekInt.Count; idx++) { PrWeekDto dto = new PrWeekDto(); dto.week = weekInt[idx]; dto.weekList = new List(); dto.icitem_id = pr.icitem_id.Value; dto.pr_purchaseid = pr.pr_purchaseid.Value; //判断如果还有送货日期,则需要设定区间范围包含本次和下次之前的周期 if (idx + 1 < weekInt.Count) { int end = weekInt[idx + 1]; for (int start = dto.week; start < end; start++) { dto.weekList.Add(start); } } else { //假设 就定了周一 int count = 7 - dto.week + weekInt[0]; for (int start = 0; start < count; start++) { if (dto.week + start > 7) { dto.weekList.Add(dto.week + start - 7); } else { dto.weekList.Add(dto.week + start); } } } prWeekDtos.Add(dto); } } return prWeekDtos; } /* int getDateWeekRang(DateTime tmpDate) { var startDateStr = tmpDate.Date.AddDays(-(int)(tmpDate.DayOfWeek) + 1).ToString("yyyy-MM-dd");//当前周的开始日期 var endDateStr = tmpDate.Date.AddDays(7 - (int)(tmpDate.DayOfWeek)).ToString("yyyy-MM-dd");//当前周的结束日期 GregorianCalendar gc = new System.Globalization.GregorianCalendar(); int weekOfYear = gc.GetWeekOfYear(tmpDate, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday); return weekOfYear; }*/ //PR自动审核 public async Task PrAutoApprove() { //直接按间隔多少天一次来处理数据,定时任务按周四来考虑。 DateTime toTime = new DateTime(2023, 7, 6); DateTime starttime = toTime.AddDays(1); DateTime endtime = toTime.AddDays(8); List prlist = _mysql_srm_pr_main.GetListAsync(s => s.pr_rarrive_date >= starttime && s.pr_rarrive_date <= endtime && (s.state == 1|| s.state == 2 || s.state == 3)).Result; if (prlist.Any()) { List purchaselist = _mysql_srm_purchase.GetListAsync(s => prlist.Select(c => c.icitem_id).Contains(s.icitem_id) && prlist.Select(c => c.pr_purchaseid).Contains(s.supplier_id)).Result; List itemsupplierList = _mysql_srm_supplier.GetListAsync(s => prlist.Select(c => c.pr_purchaseid).Contains(s.Id)).Result; List ic_Items = _mysql_ic_item.GetListAsync(s => prlist.Select(c => c.icitem_id).Contains(s.Id)).Result; PoActionListDto poaction = new PoActionListDto(); param.tenantId = prlist[0].tenant_id; param.factoryId = prlist[0].factory_id.GetValueOrDefault(); AutoCreatePOFromPR(prlist, ic_Items, itemsupplierList, purchaselist, poaction); using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { if (poaction.poMain.Any()) { _businessDbContext.BulkUpdate(prlist); _businessDbContext.BulkInsert(poaction.poMain); } if (poaction.polist.Any()) { _businessDbContext.BulkInsert(poaction.polist); } if (poaction.poOccupiesList.Any()) { _businessDbContext.BulkInsert(poaction.poOccupiesList); } if (poaction.poMasterList.Any()) { _purOrdMaster.Insert(poaction.poMasterList); //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值 List nbrs = poaction.poMasterList.Select(a => a.PurOrd).ToList(); var nbrList = _purOrdMaster.Select(a => a.Domain == "1001" && nbrs.Contains(a.PurOrd)); poaction.poDetailList.ForEach(c => { c.PurOrdRecID = nbrList.Where(a => a.PurOrd == c.PurOrd).First().RecID; }); _purOrdDetail.Insert(poaction.poDetailList); } await unitOfWork.CompleteAsync(); } catch (Exception e) { unitOfWork.Dispose(); new NLogHelper("ResourceExamineAppService").WriteLog("PrApprove", "采购申请单合并失败:" + e.Message, _currentTenant.Id.ToString()); return JsonConvert.SerializeObject("合并失败,请联系管理员。"); } } return JsonConvert.SerializeObject("ok"); } else { return JsonConvert.SerializeObject("没有需要审核的采购申请单。"); } } /// /// //PR手动审核 /// /// /// public async Task PrApprove(string ids) { //物料、供应商为相同才允许合并。 var idList = AnalysisIdList(ids); List prlist = _mysql_srm_pr_main.GetListAsync(s => idList.Contains(s.Id)).Result; if (!prlist.Any()) { return JsonConvert.SerializeObject("所选采购申请单未找到,请刷新界面重新操作。"); } if (prlist.Where(s => s.state == 0).Count() > 0) { return JsonConvert.SerializeObject("所选包含已关闭采购申请,请重新选择。"); } if (prlist.Where(s => s.state == 3).Count() > 0) { return JsonConvert.SerializeObject("所选包含评审未通过采购申请,请重新选择。"); } List purchaselist = _mysql_srm_purchase.GetListAsync(s => prlist.Select(c => c.icitem_id).Contains(s.icitem_id) && prlist.Select(c => c.pr_purchaseid).Contains(s.supplier_id)).Result; List itemsupplierList = _mysql_srm_supplier.GetListAsync(s => prlist.Select(c => c.pr_purchaseid).Contains(s.Id)).Result; var purclist = purchaselist.GroupBy(s => new { s.supplier_type, s.supplier_id }); if (purclist.Count() > 1) { return JsonConvert.SerializeObject("采购申请单的采购类别必须相同。"); } List ic_Items = _mysql_ic_item.GetListAsync(s => prlist.Select(c => c.icitem_id).Contains(s.Id)).Result; PoActionListDto poaction = new PoActionListDto(); param.tenantId = prlist[0].tenant_id; param.factoryId = prlist[0].factory_id.GetValueOrDefault(); AutoCreatePOFromPR(prlist, ic_Items, itemsupplierList, purchaselist, poaction); using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { if (poaction.poMain.Any()) { _businessDbContext.BulkUpdate(prlist); _businessDbContext.BulkInsert(poaction.poMain); } if (poaction.polist.Any()) { _businessDbContext.BulkInsert(poaction.polist); } if (poaction.poOccupiesList.Any()) { _businessDbContext.BulkInsert(poaction.poOccupiesList); } if (poaction.poMasterList.Any()) { _purOrdMaster.Insert(poaction.poMasterList); //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值 List nbrs = poaction.poMasterList.Select(a => a.PurOrd).ToList(); var nbrList = _purOrdMaster.Select(a => a.Domain == "1001" && nbrs.Contains(a.PurOrd)); poaction.poDetailList.ForEach(c => { c.PurOrdRecID = nbrList.Where(a => a.PurOrd == c.PurOrd).First().RecID; }); _purOrdDetail.Insert(poaction.poDetailList); } await unitOfWork.CompleteAsync(); } catch (Exception e) { unitOfWork.Dispose(); new NLogHelper("ResourceExamineAppService").WriteLog("PrApprove", "采购申请单合并失败:" + e.Message, _currentTenant.Id.ToString()); return JsonConvert.SerializeObject("合并失败,请联系管理员。"); } } return JsonConvert.SerializeObject("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; } /// /// 资源检查结果评审 /// /// /// 类型(0,销售订单 1,销售订单行) public async Task ReviewExamineResult(string ids, int type) { if (string.IsNullOrEmpty(ids)) { throw new NotImplementedException("订单号错误,请联系管理员!"); } Array alist = ids.Split(','); List sorderId = new List(); foreach (string longid in alist) { sorderId.Add(long.Parse(longid)); } List sorders = new List(); List sentrys = new List(); if (type == 0) { //获取订单数据 sorders = _mysql_crm_seorder.GetListAsync(p => sorderId.Contains(p.Id) && !p.IsDeleted).Result; if (!sorders.Any()) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "订单数据不存在", _currentTenant.Id.ToString()); //throw new NotImplementedException("订单数据不存在!"); return "订单数据不存在"; } //获取订单行数据 sentrys = await _mysql_crm_seorderentry.GetListAsync(p => sorderId.Contains(p.seorder_id.GetValueOrDefault()) && !p.IsDeleted); if (!sentrys.Any()) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "订单行数据不存在", _currentTenant.Id.ToString()); //throw new NotImplementedException("订单行数据不存在!"); return "订单行数据不存在"; } } else { //获取订单行数据 sentrys = await _mysql_crm_seorderentry.GetListAsync(p => sorderId.Contains(p.Id) && !p.IsDeleted); if (!sentrys.Any()) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "订单行数据不存在", _currentTenant.Id.ToString()); //throw new NotImplementedException("订单行数据不存在!"); return "订单行数据不存在"; } sorders = _mysql_crm_seorder.GetListAsync(p => sentrys.Select(s => s.seorder_id).Contains(p.Id) && !p.IsDeleted).Result; if (!sorders.Any()) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "订单数据不存在", _currentTenant.Id.ToString()); //throw new NotImplementedException("订单数据不存在!"); return "订单数据不存在"; } } //获取订单行数据 progress == "2"已做检查但是未评审的订单行 sentrys = sentrys.Where(s => s.progress == "2").ToList(); if (!sentrys.Any()) { new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "订单行数据不存在", _currentTenant.Id.ToString()); //throw new NotImplementedException("订单行数据不存在!"); return "没有需要评审的订单行数据"; } List seIds = sentrys.Select(s => s.Id).ToList(); //找到当前计算周期里工单 List moentry = _mes_moentry.GetManyByCondition(x => seIds.Contains(x.soentry_id.Value)).Result; List mordersList = _mes_morder.GetManyByCondition(x => moentry.Select(p => p.moentry_moid).ToList().Contains(x.mysql_id)).Result; List WriteMoentry = new List(); List WriteMorder = new List(); //找最新计算结果 List exmlist = _mysql_examine_result.GetListAsync(s => seIds.Contains(s.sentry_id.GetValueOrDefault())).Result; List exmResult = new List(); List bangidList = new List(); #region 回写工单 foreach (var se in sentrys) { var newExm = exmlist.Where(s => s.sentry_id == se.Id).OrderByDescending(p => p.create_time).FirstOrDefault(); if (newExm != null) { se.progress = "3"; se.sys_material_date = newExm.sys_material_date; se.sys_capacity_date = newExm.sys_capacity_date; //如果计算记录有工单id,则代表有生成工单,而不是占用计划工单 if (newExm.morder_id.GetValueOrDefault() != 0) { var me = moentry.Find(s => s.soentry_id == se.Id && s.bang_id == newExm.bangid); if (me == null) { //补救场景,假设mongdb数据丢失,从一个json格式中获取数据 } var mo = mordersList.Find(s => s.mysql_id == me.moentry_moid && s.bang_id == newExm.bangid); if (mo == null) { //补救场景,假设mongdb数据丢失,从一个json格式中获取数据 } WriteMoentry.Add(me); WriteMorder.Add(mo); } exmResult.Add(newExm); bangidList.Add(newExm.bangid.GetValueOrDefault()); } } //如果已经回写,则不需要回写 List dborders = _mysql_mes_morder.GetListAsync(x => WriteMorder.Select(c => c.mysql_id).Contains(x.Id)).Result; //过滤掉已经回写的数据 WriteMorder = WriteMorder.Where(x => !dborders.Select(c => c.Id).Contains(x.mysql_id)).ToList(); #endregion //批量保存 后期考虑子工单 List moderlist = new List(); List workOrds = new List(); List workOrdRoutings = new List(); List workOrdDetails = new List(); if (WriteMorder.Any()) { WriteMorder.ForEach(s => { s.create_time = DateTime.Now; }); moderlist = ObjectMapper.Map, List>(WriteMorder); List allRoutings = _routingOpDetail.Select(p => moderlist.Select(m => m.product_code).Contains(p.RoutingCode)); //同步工单 CreateWorkOrdDates(moderlist, allRoutings, workOrds, workOrdRoutings, workOrdDetails); } //当前订单号所关联的最新计算结果里的占用记录 List mooccupyList = await _mes_mooccupy.GetManyByCondition(s => seIds.Contains(s.moo_id_billid.Value) && bangidList.Contains(s.bang_id.Value)); //委外工单计算记录 List oorderList = await _mes_oorder.GetManyByCondition(s => seIds.Contains(s.sentry_id.Value) && bangidList.Contains(s.bang_id.Value)); //PO占用记录 List po_occupy = await _srm_po_occupy.GetManyByCondition(s => seIds.Contains(s.eid.Value) && bangidList.Contains(s.bang_id.Value)); List prmainlist = await _srm_pr_main.GetManyByCondition(s => seIds.Contains(s.sentry_id.Value) && bangidList.Contains(s.bang_id.Value)); using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { await _mysql_crm_seorderentry.UpdateManyAsync(sentrys); //批量保存 后期考虑子工单 if (moderlist.Any()) { _businessDbContext.BulkInsert(moderlist); if (workOrds.Any()) { _workOrdMaster.Insert(workOrds); } if (workOrdRoutings.Any()) { _workOrdRouting.Insert(workOrdRoutings); } if (workOrdDetails.Any()) { _workOrdDetail.Insert(workOrdDetails); } if (WriteMoentry.Any()) { var mesmoentrys = ObjectMapper.Map, List>(WriteMoentry); _businessDbContext.BulkInsert(mesmoentrys); } } if (mooccupyList.Any()) { mooccupyList.ForEach(s => { s.create_time = DateTime.Now; }); var moOccupy = ObjectMapper.Map, List>(mooccupyList); _businessDbContext.BulkInsert(moOccupy); } if (oorderList.Any()) { oorderList.ForEach(s => { s.create_time = DateTime.Now; }); var ooders = ObjectMapper.Map, List>(oorderList); _businessDbContext.BulkInsert(ooders); } //沟通方老师与何腾,库存与库存占用,使用方老师得locationDetail和workorddetital 做需求数量和已发数量来实现库存占用和已扣减库存? /*if (sklist.Any()) { sklist.ForEach(s => { s.id = help.NextId(); s.tenant_id = param.tenantId; s.factory_id = param.factoryId; }); await _ic_item_stockoccupy.InsertMany(sklist); }*/ if (po_occupy.Any()) { po_occupy.ForEach(s => { s.create_time = DateTime.Now; }); var poOccupies = ObjectMapper.Map, List>(po_occupy); _businessDbContext.BulkInsert(poOccupies); } if (prmainlist.Any()) { var pr_mainlist = ObjectMapper.Map, List>(prmainlist); _businessDbContext.BulkInsert(pr_mainlist); } await unitOfWork.CompleteAsync(); } catch (Exception e) { unitOfWork.Dispose(); new NLogHelper("ResourceExamineAppService").WriteLog("ReviewExamineResult", "资源检查评审数据更新失败:" + e.Message, _currentTenant.Id.ToString()); return e.Message; }; } return "ok"; } /// /// 通过ic_bom获取工艺路径数据 /// /// /// public List GetMesTechniques(List ic_Boms) { List techniques = new List(); var builder = Builders.Filter; var filters = new List>(); ic_Boms?.ForEach(item => { var filter = builder.Eq(x => x.bom, item.bom_number) & builder.Eq(x => x.bomver, item.version) & builder.Eq(x => x.tenant_id, param.tenantId) & builder.Eq(x => x.factory_id, param.factoryId) & builder.Eq(x => x.IsDeleted, false); filters.Add(filter); }); techniques = _mes_technique.Find(builder.Or(filters)).Result; return techniques; } /// /// 递归:获取icbom,icbomchild数据 /// /// /// /// public void GetIcBomData(List icBoms, List bomlist, List bomchildlist) { if (icBoms.Count == 0) { return; } //添加物料bom数据 foreach (var ib in icBoms) { if (!bomlist.Exists(s => s.mysql_id == ib.mysql_id)) { bomlist.Add(ib); } } //获取物料bom明细数据 //List childList = _ic_bom_child.GetManyByCondition(p => icBoms.Select(m => m.mysql_id).Contains(p.bom_id) && p.use_status == 1 && p.tenant_id == param.tenantId && p.factory_id == param.factoryId && !p.IsDeleted).Result.ToList(); List childList = _ic_bom_child.GetManyByCondition(p => icBoms.Select(m => m.mysql_id).Contains(p.bom_id) && p.tenant_id == param.tenantId && p.factory_id == param.factoryId && !p.IsDeleted).Result.ToList(); //没有明细数据,终止 if (childList.Count == 0) { return; } foreach (var bchild in childList) { if (!bomchildlist.Exists(s => s.mysql_id == bchild.mysql_id)) { bomchildlist.Add(bchild); } } //通过物料bom明细数据反查物料bom数据 var boms = _ic_bom.GetManyByCondition(p => childList.Select(m => m.icitem_id).ToList().Contains(p.icitem_id) && p.use_status == 1 && p.tenant_id == param.tenantId && p.factory_id == param.factoryId && !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); } } /// /// 删除旧订单行数据 /// /// /// /// /// 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 _mysql_mes_mooccupy.DeleteManyAsync(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 tenantId, long factoryId, long bangid,List pretreatments) { //TODO:申老师明确后续需要调整 根据需要使用的字段,来同步表数据。 //同步物料库存数据 根据预处理,来只找出部分数据同步。 List itemIds = pretreatments.Select(s => s.item_id.GetValueOrDefault()).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)).Result; if (icitemStokc.Count > 0) { List numbers = pretreatments.Select(s => s.item_number).ToList(); var locStock = _locationDetail.Select(a => numbers.Contains(a.ItemNum) && a.IsActive && a.Domain == factoryId.ToString()); //设置当前计算bangid icitemStokc.ForEach(item => { item.bang_id = bangid; var pret = pretreatments.Find(s => s.item_id == item.icitem_id); if(pret != null) { item.sqty = locStock.Where(s => s.ItemNum == pret.item_number).Sum(p => p.QtyOnHand.GetValueOrDefault()); } }); var moIcitemStokc = ObjectMapper.Map, List>(icitemStokc); moIcitemStokc.ForEach(item => { item.id = help.NextId(); }); //插入数据 await _ic_item_stock.InsertMany(moIcitemStokc); } //在制工单占用记录表 var mes_mooccupy = _mysql_mes_mooccupy.GetListAsync(x => x.tenant_id == tenantId && x.factory_id == factoryId).Result; if (mes_mooccupy.Count > 0) { mes_mooccupy.ForEach(item => { item.bang_id = bangid; }); var moMes_mooccupy = ObjectMapper.Map, List>(mes_mooccupy); moMes_mooccupy.ForEach(item => { item.id = help.NextId(); }); await _mes_mooccupy.InsertMany(moMes_mooccupy); } //工单主表 var mes_morder = _mysql_mes_morder.GetListAsync(x => x.tenant_id == tenantId && x.factory_id == factoryId).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.id = help.NextId(); }); await _mes_morder.InsertMany(moMes_morder); } //工单子表 var mes_moentry = _mysql_mes_moentry.GetListAsync(x => x.tenant_id == tenantId && 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.id = help.NextId(); }); await _mes_moentry.InsertMany(moMes_moentry); } //TODO:要不要根据某些条件只同步有效的数据 //采购订单 var srm_po_main = _mysql_srm_po_main.GetListAsync(x => x.tenant_id == tenantId && x.factory_id == factoryId).Result; if (srm_po_main.Count > 0) { srm_po_main.ForEach(item => { item.bang_id = bangid; }); var moSrm_po_main = ObjectMapper.Map, List>(srm_po_main); moSrm_po_main.ForEach(item => { item.id = help.NextId(); }); await _srm_po_main.InsertMany(moSrm_po_main); } //采购订单明细 var srm_po_list = _mysql_srm_po_list.GetListAsync(x => x.tenant_id == tenantId && x.factory_id == factoryId).Result; if (srm_po_list.Count > 0) { srm_po_list.ForEach(item => { item.bang_id = bangid; }); var moSrm_po_list = ObjectMapper.Map, List>(srm_po_list); moSrm_po_list.ForEach(item => { item.id = help.NextId(); }); await _srm_po_list.InsertMany(moSrm_po_list); } //采购订单占用详情 var srm_po_occupy = _mysql_srm_po_occupy.GetListAsync(x => x.tenant_id == tenantId && x.factory_id == factoryId).Result; if (srm_po_occupy.Count > 0) { srm_po_occupy.ForEach(item => { item.bang_id = bangid; }); var moSrm_po_occupy = ObjectMapper.Map, List>(srm_po_occupy); moSrm_po_occupy.ForEach(item => { item.id = help.NextId(); }); await _srm_po_occupy.InsertMany(moSrm_po_occupy); } } /// /// 清处数据库快照 /// /// public async Task ClearSnapShot(long bangid) { //清除物料库存数据 await _ic_item_stock.Delete(p => p.bang_id == bangid); //清除工单占用记录表 await _mes_mooccupy.Delete(p => p.bang_id == bangid); //清除工单主表 //await _mes_morder.Delete(p => p.bang_id == bangid); //清除工单子表 //await _mes_moentry.Delete(p => p.bang_id == bangid); //清除采购订单 await _srm_po_main.Delete(p => p.bang_id == bangid); //清除采购订单明细 await _srm_po_list.Delete(p => p.bang_id == bangid); //清除采购订单占用详情 await _srm_po_occupy.Delete(p => p.bang_id == bangid); } /// /// 根据物料id获取物料4个提前期 /// /// 物料id /// 企业id /// 工厂id /// private List GetLeadTime(List icItemIds, long tenantId, long factoryid) { return icItemIds.Where(p => p.factory_id == factoryid && p.tenant_id == tenantId && !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 tenantId, long factoryid) { return _srm_purchase.Find(p => icItemIds.Contains(p.icitem_id) && p.tenant_id == tenantId && p.factory_id == factoryid && !p.IsDeleted).Result; } /// /// 同一周以周五为合并采购申请单截点判断是否为同一周 /// /// 基准订单时间 /// 目标订单时间 /// private bool IsSameWeek(DateTime orderTime1, DateTime orderTime2) { int week = (int)orderTime1.DayOfWeek; bool isSameWeek = false; DateTime dateTime = orderTime1; switch (week) { case 0: //星期天 dateTime = dateTime.AddDays(0); dateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59); isSameWeek = orderTime2 < dateTime; break; case 1: //星期一 dateTime = dateTime.AddDays(4); dateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59); isSameWeek = orderTime2 < dateTime; break; case 2: //星期二 dateTime = dateTime.AddDays(3); dateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59); isSameWeek = orderTime2 < dateTime; break; case 3: //星期三 dateTime = dateTime.AddDays(2); dateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59); isSameWeek = orderTime2 < dateTime; break; case 4: //星期四 dateTime = dateTime.AddDays(1); dateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59); isSameWeek = orderTime2 < dateTime; break; case 5: //星期五 dateTime = dateTime.AddDays(0); dateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59); isSameWeek = orderTime2 < dateTime; break; case 6: //星期六 dateTime = dateTime.AddDays(0); dateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59); isSameWeek = orderTime2 < dateTime; break; } return isSameWeek; } private void AutoCreatePOFromPR(List list , List icitemlist, List itemsupplierList, List purchaselist, PoActionListDto poaction) { var zcPr = list.Where(a => a.pr_billno.StartsWith("PR")).ToList(); if (zcPr.Any()) { AutoCreatePOFromPRByType(zcPr, icitemlist, itemsupplierList, purchaselist, poaction,1); } var wwPr = list.Where(a => a.pr_billno.StartsWith("WWPR")).ToList(); if (wwPr.Any()) { AutoCreatePOFromPRByType(wwPr, icitemlist, itemsupplierList, purchaselist, poaction,2); } } /// /// 根据PR生成PO /// /// /// /// /// /// /// 1正常PO,2是委外 private void AutoCreatePOFromPRByType(List list, List itemList, List itemsupplierList, List purchaselist, PoActionListDto poaction,int poType) { List polist = new List(); List podetaillist = new List(); List pOGroupDtos = new List(); //合并条件:目前传入的数据是一周的数据,暂时不考虑多周数据合并。 //标准类 1.销售订单产生 2.计划工单产生 //物料属性 委外 外购 //供应商类别 标准类 外协类 VMI类 费用类 资产类 //此逻辑已经在PR按周合并了。这一块直接转PO_list,然后根据此类型,再生成PO foreach (var item in list) { var pur = purchaselist.Find(s => s.supplier_id == item.pr_purchaseid && s.icitem_id == item.icitem_id); if (pur == null) { //无货源清单的PR不处理 continue; } POGroupDto poDto = pOGroupDtos.Find(s => s.supplier_type == pur.supplier_type && s.supplier_id == item.pr_purchaseid); if (poDto == null) { poDto = new POGroupDto(); poDto.supplier_id = item.pr_purchaseid.GetValueOrDefault(); poDto.supplier_type = pur.supplier_type; poDto.polist = new List(); pOGroupDtos.Add(poDto); } item.state = 0; srm_po_list podetail = new srm_po_list(); podetail.GenerateNewId(help.NextId()); podetail.pr_id = item.Id; podetail.pr_billno = item.pr_billno; podetail.icitem_id = item.icitem_id; podetail.ItemNum = itemList.First(a => a.Id == item.icitem_id).number; podetail.icitem_name = item.icitem_name; podetail.qty = item.pr_aqty; podetail.netprice = item.pr_price; podetail.rate = item.pr_rate; podetail.price = item.pr_orderprice / item.pr_aqty; podetail.total_price = item.pr_orderprice; podetail.plan_qty = item.pr_aqty; podetail.unit = item.pr_unit; podetail.state = item.state; podetail.rarrdate = item.pr_rarrive_date; podetail.rnumber = 0; podetail.currencytype = item.currencytype; podetail.create_time = DateTime.Now; podetail.factory_id = param.factoryId; podetail.tenant_id = param.tenantId; podetail.stock_id = 1; podetaillist.Add(podetail); poDto.polist.Add(podetail); } List referlist = new List(); RecursionGetDbPr(list, referlist); //组合PO foreach (var dto in pOGroupDtos) { srm_po_main po_Main = new srm_po_main(); po_Main.GenerateNewId(help.NextId()); po_Main.po_billno = poType == 1 ? GetMaxSerialNumber(416188684804165) : GetMaxSerialNumber(416555323363397); var pr = list.Find(s => s.Id == dto.polist[0].pr_id); var itemsupplier = itemsupplierList.Find(a => a.Id == pr.pr_purchaseid); po_Main.po_purchaser = pr.pr_purchaser; po_Main.po_purchaser_no = pr.pr_purchaser_num; po_Main.po_ssend_date = DateTime.Now; po_Main.po_tax_rate = pr.pr_rate; po_Main.po_express = 1; po_Main.state = 0; po_Main.po_note = ""; po_Main.po_order_type = 1; po_Main.po_total = 0; po_Main.currency = pr.currencytype; po_Main.bill_type = poType; po_Main.supplier_id = pr.pr_purchaseid; po_Main.supplier_name = pr.pr_purchasename; po_Main.supplier_no = pr.pr_purchasenumber; po_Main.contact = itemsupplier is null ? "" : itemsupplier.contact; po_Main.suppliertelephone = itemsupplier is null ? "" : itemsupplier.telephone; po_Main.deliveryaddress = ""; po_Main.supplierdddress = itemsupplier is null ? "" : itemsupplier.supplier_address; po_Main.confirmstate = 1; po_Main.logisticsstate = 0; po_Main.financialstate = 0; po_Main.create_time = DateTime.Now; po_Main.factory_id = param.factoryId; po_Main.tenant_id = param.tenantId; po_Main.po_delivery = 1; polist.Add(po_Main); int row = 1; dto.polist.ForEach(p => { var toPr = list.Find(s => s.Id == p.pr_id); List clist = new List(); RecursionPr(toPr, referlist, clist); if (clist.Any()) { clist.ForEach(c => { if (!string.IsNullOrEmpty(c.pr_mono)) { srm_po_occupy srm_Po_Occupy = new srm_po_occupy(); srm_Po_Occupy.GenerateNewId(help.NextId()); //srm_Po_Occupy.bang_id = bangid; srm_Po_Occupy.morder_mo = c.pr_mono; srm_Po_Occupy.qty = c.pr_aqty; srm_Po_Occupy.eid = c.sentry_id; srm_Po_Occupy.polist_id = p.Id; srm_Po_Occupy.polist_row = p.polist_row; srm_Po_Occupy.type = MorderEnum.Zyjc_Type;//TODO:类型未知 srm_Po_Occupy.stime = p.create_time; srm_Po_Occupy.etime = p.rarrdate; srm_Po_Occupy.state = 1; srm_Po_Occupy.tenant_id = param.tenantId;//取销售子表企业ID srm_Po_Occupy.factory_id = param.factoryId; srm_Po_Occupy.create_time = DateTime.Now; srm_Po_Occupy.create_by_name = "admin"; srm_Po_Occupy.update_time = DateTime.Now; srm_Po_Occupy.update_by_name = "admin"; poaction.poOccupiesList.Add(srm_Po_Occupy); } }); } po_Main.po_total += p.total_price; p.po_id = po_Main.Id; p.po_billno = po_Main.po_billno; p.polist_row = row; p.pr_purchase_id = po_Main.supplier_id; p.pr_purchase_name = po_Main.supplier_name; row++; }); } poaction.poMain.AddRange(polist); poaction.polist.AddRange(podetaillist); List purOrdMasters = new List(); polist.ForEach(a => { purOrdMasters.Add(new PurOrdMaster { Domain = "1001", Potype = poType==1?"po":"pw", PurOrd = a.po_billno, Buyer = a.po_purchaser, OrdDate = a.po_ssend_date, Curr = "CNY", Supp = a.supplier_no, Tax1 = a.po_tax_rate, Department = a.purchasing_orgname, CustPhone = a.suppliertelephone, CustAddress = a.supplierdddress, IsActive = true, CreateTime = a.create_time, UpdateTime = a.update_time }); }); poaction.poMasterList.AddRange(purOrdMasters); List purOrdDetails = new List(); podetaillist.ForEach(a => { purOrdDetails.Add(new PurOrdDetail { Domain = "1001", Potype = poType == 1 ? "po" : "pw", PurOrd = a.po_billno, IsActive = true, CreateTime = a.create_time, UpdateTime = a.update_time, Line = a.polist_row, ItemNum = a.ItemNum, QtyOrded = a.qty.GetValueOrDefault(), QtyReceived = a.rqty.GetValueOrDefault(), PurCost = a.price, StdCost = a.price / (1 + a.rate), TaxRate = a.rate, DueDate = a.rarrdate }); }); poaction.poDetailList.AddRange(purOrdDetails); } /// /// 递归寻找PR,找到最末级数据,生成占用关系 /// public void RecursionGetDbPr(List list, List referlist) { List prlist = _mysql_srm_pr_main.GetListAsync(s => list.Select(c => c.pr_billno).Contains(s.refer_pr_billno)).Result; if (prlist.Any()) { referlist.AddRange(prlist); RecursionGetDbPr(prlist, referlist); } } /// /// 递归寻找当前PR所关联的真实工单生成的PR,需要形成占用关系。 /// /// /// public void RecursionPr(srm_pr_main pr, List referlist, List clist) { var list = referlist.Where(s => s.refer_pr_billno == pr.pr_billno).ToList(); if (list.Any()) { foreach (var child in list) { RecursionPr(child, referlist, clist); } } else { clist.Add(pr); } } /// /// 计划工单齐套检查 /// /// /// public async Task PlanOrderResourceCheck() { /*List workOrds = workOrd.Split(",").ToList(); if (workOrds.Count == 0) { return ""; }*/ List Mes_Morders = _mysql_mes_morder.GetListAsync(x => x.morder_type == "计划工单").Result; //先排除锁定期内的工单 //优先级排序 DateTime lookTime = DateTime.Now.Date.AddDays((double)8); Mes_Morders = Mes_Morders.Where(s => s.moentry_sys_stime > lookTime).OrderBy(s => s.moentry_sys_stime).ToList(); if (Mes_Morders.Any()) { List monolist = Mes_Morders.Select(c => c.morder_no).ToList(); //清理PR的占用。 List occupy = await _mysql_srm_po_occupy.GetListAsync(s => monolist.Contains(s.morder_mo)); _businessDbContext.BulkDelete(occupy); //清理锁定期外的排程数据 _periodSequenceDet.Delete(s => monolist.Contains(s.WorkOrds)); _scheduleResultOpMaster.Delete(s => monolist.Contains(s.WorkOrd)); //只走计划工单 await OrderKittingCheck(Mes_Morders, true); } else { return JsonConvert.SerializeObject("未查找到对应的计划工单,请联系管理员。"); } return JsonConvert.SerializeObject("ok"); } /// /// 按未来N天工单齐套检查 /// /// /// public async Task OrderResourceCheck(int day, string workOrd) { List mo_Mes_Morders = new List(); if (day == 0) { List workOrds = workOrd.Split(",").ToList(); if (workOrds.Count == 0) { return ""; } mo_Mes_Morders = _mysql_mes_morder.GetListAsync(x => workOrds.Contains(x.morder_no)).Result; } else { mo_Mes_Morders = _mysql_mes_morder.GetListAsync(x => x.start_time > DateTime.Now.Date.AddDays(1) && x.start_time < DateTime.Now.Date.AddDays(day) && x.morder_state == MorderEnum.Xd_state && !x.IsDeleted).Result; } //只做库存是否齐套检查 if (mo_Mes_Morders.Any()) { var rtn = await OrderKittingCheck(mo_Mes_Morders); OrderResourceViewDto result = DataPackage(rtn); result.DayBulletinBoardList = result.DayBulletinBoardList.OrderByDescending(d => d.day).ToList(); //保存检查结果 SaveExamineResult(result.KittingCheckResultList, result.DayBulletinBoardList, 1); return JsonConvert.SerializeObject("ok"); } else { return JsonConvert.SerializeObject("没有需要检查的工单"); } } /// /// 工单齐套检查/替代料齐套检查结果保存 /// /// /// public async void SaveExamineResult(List KittingCheckResultList, List DayBulletinBoardList, int type) { //检查结果写入数据库 List examineList = new List(); List orderDetails = new List(); List daybulletinboards = new List(); foreach (var ex in KittingCheckResultList) { var examine = ObjectMapper.Map(ex); examine.GenerateNewId(help.NextId()); examine.type = type; examine.create_time = DateTime.Now; examine.tenant_id = param.tenantId; examine.factory_id = param.factoryId; examine.create_time = DateTime.Now; examineList.Add(examine); ex.order_item_list.ForEach(s => { var detail = ObjectMapper.Map(s); detail.GenerateNewId(help.NextId()); detail.order_examine_id = examine.Id; detail.tenant_id = param.tenantId; detail.factory_id = param.factoryId; detail.create_time = DateTime.Now; orderDetails.Add(detail); }); } foreach (var item in DayBulletinBoardList) { var detail = ObjectMapper.Map(item); detail.GenerateNewId(help.NextId()); detail.type = type; detail.create_time = DateTime.Now; detail.tenant_id = param.tenantId; detail.factory_id = param.factoryId; daybulletinboards.Add(detail); } if (examineList.Any()) { _businessBangDbContext.BulkInsert(examineList); } if (daybulletinboards.Any()) { _businessBangDbContext.BulkInsert(daybulletinboards); } if (orderDetails.Any()) { _businessBangDbContext.BulkInsert(orderDetails); } } /// /// 替代关系检查 /// /// /// public async Task SubstituteResourceCheck(int day, string workOrd) { List mo_Mes_Morders = new List(); if (day == 0) { List workOrds = workOrd.Split(",").ToList(); if (workOrds.Count == 0) { return ""; } mo_Mes_Morders = _mysql_mes_morder.GetListAsync(x => workOrds.Contains(x.morder_no)).Result; } else { mo_Mes_Morders = _mysql_mes_morder.GetListAsync(x => x.start_time > DateTime.Now.Date.AddDays(1) && x.start_time < DateTime.Now.Date.AddDays(day) && x.morder_state != MorderEnum.Accomplish_state && !x.IsDeleted).Result; } if (mo_Mes_Morders.Any()) { var result = await OrderKittingCheck(mo_Mes_Morders); OrderResourceViewDto rtn = DataPackage(result, true); rtn.DayBulletinBoardList = rtn.DayBulletinBoardList.OrderByDescending(d => d.day).ToList(); //保存检查结果 替代关系不计算每日物料情况 SaveExamineResult(rtn.KittingCheckResultList, new List(), 2); return JsonConvert.SerializeObject(rtn); } else { return JsonConvert.SerializeObject("没有需要检查的工单"); } } /// /// 检查结果组装 /// /// /// /// public OrderResourceViewDto DataPackage(PschedDto result, bool flag = false) { OrderResourceViewDto rtn = new OrderResourceViewDto(); rtn.KittingCheckResultList = new List(); rtn.DayBulletinBoardList = new List(); result.examines.ForEach(examine => { OrderResourceDto dto = new OrderResourceDto(); dto.orderId = examine.morder_id.GetValueOrDefault(); dto.order_no = examine.morder_no; dto.time = examine.order_statr_time.GetValueOrDefault(); dto.ketting_time = examine.kitting_times; dto.need_qty = examine.need_qty; dto.bom_number = examine.bom_number; dto.order_item_list = new List(); var list = examine.BomChildExamineList; if (flag) { list = list.Where(s => s.type == 1 || s.haveicsubs == 1).ToList(); } list.ForEach(subitem => { var cdto = ObjectMapper.Map(subitem); /*OrderItemDto cdto = new OrderItemDto(); cdto.fid = subitem.fid; cdto.parent_id = subitem.parent_id; cdto.bom_number = subitem.bom_number; cdto.item_id = subitem.item_id; cdto.item_name = subitem.item_name; cdto.item_number = subitem.item_number; cdto.num = subitem.num; cdto.num_order = subitem.num_order; cdto.qty = subitem.qty; cdto.self_lack_qty = subitem.self_lack_qty; cdto.sqty = subitem.sqty; cdto.use_qty = subitem.use_qty; cdto.mo_qty = subitem.mo_qty; cdto.mo_occupy_list = subitem.mo_occupy_list; cdto.make_qty = subitem.make_qty; cdto.make_list = subitem.make_list; cdto.purchase_qty = subitem.purchase_qty; cdto.purchase_list = subitem.purchase_list; cdto.purchase_occupy_qty = subitem.purchase_occupy_qty; cdto.purchase_occupy_list = subitem.purchase_occupy_list; cdto.subcontracting_qty = subitem.subcontracting_qty; cdto.subcontracting_list = subitem.subcontracting_list; cdto.kitting_time = subitem.kitting_time; cdto.substitute_code = subitem.substitute_code; cdto.substitute_strategy = subitem.substitute_strategy; cdto.substitute_mode = subitem.substitute_mode; cdto.is_use = subitem.is_use;*/ dto.order_item_list.Add(cdto); string day = dto.time.ToString("yyyy-MM-dd HH:mm"); if (subitem.is_use && subitem.level != 1) { //每日每物料使用情况 DayBulletinBoard dbb = rtn.DayBulletinBoardList.Find(s => s.day == day && s.item_number == cdto.item_number); if (dbb == null) { dbb = new DayBulletinBoard(); dbb.day = day; dbb.item_name = cdto.item_name; dbb.item_number = cdto.item_number; rtn.DayBulletinBoardList.Add(dbb); } dbb.self_lack_qty += subitem.lack_qty; dbb.use_qty += subitem.use_qty; dbb.make_qty += cdto.make_qty; dbb.mo_qty += subitem.mo_qty; dbb.purchase_occupy_qty += subitem.purchase_occupy_qty; } }); rtn.KittingCheckResultList.Add(dto); }); return rtn; } /// /// 工单检查物料齐套 /// /// public async Task OrderKittingCheck(List mo_Mes_Morders, bool planCheck = false) { //资源检查结果 PschedDto rtn = new PschedDto(); //资源检查明细list List examines = new List(); OrderCheckDto input = new OrderCheckDto(); if (mo_Mes_Morders.Any()) { input.tenantId = mo_Mes_Morders[0].tenant_id; input.factoryId = mo_Mes_Morders[0].factory_id.GetValueOrDefault(); } //资源检查入参全局变量赋值 param.tenantId = input.tenantId; param.factoryId = input.factoryId; param.checkflag = false; param.checkPlan = planCheck; //生成当前计算bangid long bangid = help.NextId(); /*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;*/ List mo_Mes_Moentries = _mysql_mes_moentry.GetListAsync(x => mo_Mes_Morders.Select(s => s.Id).Contains(x.moentry_moid.Value)).Result; //获取订单行数据 List sentrys = _mysql_crm_seorderentry.GetListAsync(p => p.tenant_id == input.tenantId && 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.Find(p => mo_Mes_Morders.Select(m => m.bom_number).Contains(p.bom_number) && p.factory_id == input.factoryId && p.tenant_id == input.tenantId && !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).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(autoCreates); pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; } //数据库快照-同步mysql库数据到mongoDB中 await DbSnapShot(input.tenantId, input.factoryId, bangid, pretreatments); DataInitialization(boms, bangid, icitemlist, stocklist, pretreatments); _morderAppService.param = param; _purchaseOrderAppService.param = param; _CalcBomViewAppService.param = param; 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.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(); var itemPrelist = pretreatments.Where(s => s.sourceid == childBom.mysql_id).ToList(); 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.newStockOccList = new List(); _CalcBomViewAppService.mes_morder = item; //库存初始化 _CalcBomViewAppService.BomStock(getBomList, stocklist, bangid); //计算 _CalcBomViewAppService.CalcView(getBomList, bangid, item.need_number.GetValueOrDefault(), item.start_time, sklist, sentry, item.urgent, icitemlist); //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(); 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; } //获取工单数据 var workOrdMasters = _workOrdMaster.Select(p => mo_Mes_Morders.Select(c=>c.morder_no).Contains(p.WorkOrd)); workOrdMasters.ForEach(s => { s.OrdDate = DateTime.Now.Date.AddDays(7);//锁定期 s.DueDate = DateTime.Now.Date.AddDays(7); }); //优先级排序 workOrdMasters = workOrdMasters.OrderBy(s => s.OrdDate).ToList(); //排产 await _productionScheduleAppService.DoProductShcedule(workOrdMasters); foreach (var wod in workOrdMasters) { var morder = mo_Mes_Morders.Find(s => s.morder_no == wod.WorkOrd); morder.moentry_sys_stime = wod.OrdDate; morder.moentry_sys_etime = wod.DueDate; var exa = rtn.examines.Find(s => s.morder_no == wod.WorkOrd); //根据排产后得日期,反推PR。 var wkordPrList = prmainlist.Where(s => s.pr_mono == wod.WorkOrd).ToList(); //反算所有的PR,根据时间减去提前期 wkordPrList.ForEach(pr => { var ts = pr.pr_parrive_date - pr.pr_psend_date; var icitem = icitemlist.Find(s => s.mysql_id == pr.icitem_id); if (icitem != null) { var bce = exa.BomChildExamineList.Find(s => s.item_id == pr.icitem_id && s.num == pr.num); pr.pr_sarrive_date = morder.moentry_sys_stime.Value.AddDays((double)(0 - bce.pre_time.GetValueOrDefault() - 1 - icitem.clean_leadtime.GetValueOrDefault()));//到货还需要向前推 物料的预处理时间。到货日期必须提前一天到 pr.pr_ssend_date = pr.pr_sarrive_date.GetValueOrDefault().AddDays(0 - ts.Value.Days); if (pr.pr_ssend_date > DateTime.Now) { pr.pr_ssend_date = DateTime.Now; } } }); } using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { _businessDbContext.BulkUpdate(mo_Mes_Morders); if (prmainlist.Any()) { var pr_mainlist = ObjectMapper.Map, List>(prmainlist); _businessDbContext.BulkInsert(pr_mainlist); } if (_CalcBomViewAppService.srm_Po_OccupiesInsert.Any()) { _CalcBomViewAppService.srm_Po_OccupiesInsert.ForEach(s => { s.tenant_id = param.tenantId; s.factory_id = param.factoryId; }); await _srm_po_occupy.InsertMany(_CalcBomViewAppService.srm_Po_OccupiesInsert); } await unitOfWork.CompleteAsync(); } catch (Exception e) { unitOfWork.Dispose(); new NLogHelper("ResourceExamineAppService").WriteLog("OrderKittingCheck", "工单检查数据更新失败:" + e.Message, _currentTenant.Id.ToString()); } } //检查结果写入数据库 var b_Examine_Results = ObjectMapper.Map, List>(rtn.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 rtn.examines) { var b_ex = ObjectMapper.Map(ex); b_ex.GenerateNewId(help.NextId());// = help.NextId(); if (_CalcBomViewAppService.mordersInsertList.Any()) { var moentry = _CalcBomViewAppService.moentriesInsertList.Where(s => s.soentry_id == b_ex.sentry_id).FirstOrDefault(); if (moentry != null) { var sentryMo = _CalcBomViewAppService.mordersInsertList.Where(s => s.mysql_id == moentry.moentry_moid).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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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.tenant_id = param.tenantId; 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("OrderKittingCheck", "工单检查资源检查计算结果数据更新失败:" + e.Message, _currentTenant.Id.ToString()); unitOfWork.Dispose(); } } } //清空快照数据 await ClearSnapShot(bangid); return rtn; } /// /// 物料数据计算前准备 /// /// /// /// /// /// /// /// /// /// /// /// /// public void DataInitialization(List boms, long bangid, List icitemlist, List stocklist, List pretreatments) { List itemIds = pretreatments.Select(p => p.item_id.GetValueOrDefault()).ToList(); icitemlist.AddRange(_ic_item.GetManyByCondition(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 => itemnums.Contains(p.RoutingCode)).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); //主工单 List mo_Mes_Morders = _mes_morder.GetManyByCondition(x => boms.Select(p => p.bom_number).Contains(x.bom_number) && (x.morder_state != MorderEnum.Accomplish_state || x.morder_state != MorderEnum.Close_state && x.morder_icitem_type != MorderEnum.XgwyMorder) && x.tenant_id == param.tenantId && x.bang_id == bangid).Result; List moids = mo_Mes_Morders.Select(p => p.mysql_id).ToList(); List mo_Mes_Moentry = _mes_moentry.GetManyByCondition(x => moids.Contains(x.moentry_moid)).Result; //工单占用表 List mes_mooccupyList = _mes_mooccupy.GetManyByCondition(x => x.moo_state == 1 && !x.IsDeleted && x.tenant_id == param.tenantId && boms.Select(p => p.item_number).Contains(x.fitem_number) && x.bang_id == bangid).Result; //物料采购订单明细 var poDetailList = _srm_po_list.GetManyByCondition(x => icitemlist.Select(p => p.mysql_id).ToList().Contains(x.icitem_id.Value) && x.bang_id == bangid && x.state == 1 && x.rstate == 1 && !x.IsDeleted).Result; //采购订单占用数据 var poOccupys = _srm_po_occupy.GetManyByCondition(x => poDetailList.Select(p => p.id).ToList().Contains(x.polist_id) && x.bang_id == bangid && !x.IsDeleted).Result; #endregion //处理一下已经插入得占用记录 //物料库存 stocklist.AddRange(_ic_item_stock.GetManyByCondition(p => p.factory_id == param.factoryId && p.bang_id == bangid && itemIds.Contains(p.icitem_id)).Result); //物料提前期 leadTimeList = GetLeadTime(icitemlist, param.tenantId, param.factoryId);//提前期列表 supplierList = GetSupplier(itemIds, param.tenantId, 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; //物料表 } 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()); } }); } /// /// 物料和BOM前置数据准备 /// /// /// /// /// /// /// /// public void IcItemPretreatment(List boms, List bomlist, List bomchildlist, List icitemlist, List sublist, List suballlist, List subdtllist) { //获取物料bom,物料bom明细 GetIcBomData(boms, bomlist, bomchildlist); //根据明细集合查出所有得替代关系表数据集合 List codeList = bomchildlist.Select(c => c.substitute_code).ToList(); sublist.AddRange(_ic_substitute.GetManyByCondition(p => codeList.Contains(p.substitute_code) && !p.IsDeleted).Result); List subidlist = sublist.Select(c => c.mysql_id).ToList(); suballlist.AddRange(_ic_substitute_group.GetManyByCondition(p => subidlist.Contains(p.substitute_group_id) && !p.IsDeleted).Result); List suballidlist = suballlist.Select(c => c.mysql_id).ToList(); subdtllist.AddRange(_ic_substitute_group_detail.GetManyByCondition(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.GetManyByCondition(p => itemIds.Contains(p.mysql_id) && !p.IsDeleted).Result); } /// /// 自动生成BOM预处理清单 /// public void AutoCreateBomBill(List ic_Boms = null) { ic_Boms ??= _ic_bom.Find(p => p.factory_id == 10101 && p.tenant_id == 101 && !p.IsDeleted).Result.ToList(); var pretreatment = _mysql_b_bom_pretreatment.GetListAsync(s => ic_Boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result; //物料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(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.Find(s => s.sourceid == bom.mysql_id && s.bom_id == bom.mysql_id); if (pret != null) { if (pret.version == bom.version) { //如果存在,且版本相同,则不需要处理 continue; } //版本不同则重新生成 deleteList.Add(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; }); addList.AddRange(list); } if (deleteList.Any()) { _businessDbContext.BulkDelete(deleteList); } if (addList.Any()) { _businessDbContext.BulkInsert(addList); //await _mysql_b_bom_pretreatment.InsertManyAsync(addList); } } /// /// BOM清单批量预处理 /// public void AutoCreateBomBillInterface() { AutoCreateBomBill(); } public async Task AutoCreatePickBill(List workOrds, List dbPeriodSequences, List nbrMasterList, List nbrDetailList) { if (dbPeriodSequences.Any()) { //按照工单领料,一个工单一个领料单,之前是按照排产日期和产线分别领料 foreach (var workord in workOrds) { Dictionary dictItemQty = new Dictionary(); List lines = dbPeriodSequences.Where(a => a.WorkOrds == workord).Select(a => a.Line).Distinct().ToList(); List lineMasters = _lineMaster.Select(p => lines.Contains(p.Line) && p.Domain == "1001" && p.IsActive); List itemList = GetProductStructure(dbPeriodSequences.First(a => a.WorkOrds == workord).ItemNum); var childrenList = itemList.Select(a => a.ComponentItem).Distinct().ToList(); List itemLocList = _itemMaster.Select(p => childrenList.Contains(p.ItemNum) && p.Domain == "1001" && p.IsActive).Distinct().ToList(); List itemPackList = _itemPackMaster.Select(p => childrenList.Contains(p.ItemNum) && p.Domain == "1001" && p.IsActive).Distinct().ToList(); var Nbr = GetMaxSerialNumber(417416915624005); //根据某一产线汇总即该工单的总数 decimal QtyOrdSum = dbPeriodSequences.Where(a => a.WorkOrds == workord && a.Line == lines[0]).Sum(a => a.OrdQty.GetValueOrDefault()); string LocationTo= lineMasters.FirstOrDefault()?.Location; nbrMasterList.Add(new NbrMaster { Domain = "1001", Type = "SM", Nbr = Nbr, Remark = "下达自动领料", Date = dbPeriodSequences.Where(a => a.WorkOrds == workord).Min(a => a.PlanDate), //ProdLine = item.Line, Status = "", WorkOrd = workord, QtyOrd = QtyOrdSum, IsActive = true, IsChanged = true, Name = "1001", Department = "101", CreateTime = DateTime.Now, UpdateTime = DateTime.Now, CreateUser = "1001", UpdateUser = "1001" }); int i = 1; itemList?.ForEach(a => { var find = itemLocList?.Find(c => c.ItemNum == a.ComponentItem); string LocationFrom = ""; if (find != null) { LocationFrom = find.Location; } //相同物料汇总 var itemComponent = nbrDetailList.Find(b => b.Nbr == Nbr && b.ItemNum == a.ComponentItem); if (itemComponent == null) { nbrDetailList.Add(new NbrDetail { Domain = "1001", Type = "SM", Nbr = Nbr, ItemNum = a.ComponentItem, QtyFrom = 0, QtyTo = 0, LocationFrom = LocationFrom, LocationTo = LocationTo,//现在这几条线是同一线边仓,暂时不考虑多个线边仓 WorkOrd = workord, QtyOrd = QtyOrdSum * a.Qty, CurrQtyOpened = QtyOrdSum * a.Qty, Line = i, IsActive = true, CreateTime = DateTime.Now, UpdateTime = DateTime.Now, CreateUser = "1001", UpdateUser = "1001", UM = a.UM }); i++; } else { nbrDetailList.First(b => b.Nbr == Nbr && b.ItemNum == a.ComponentItem).QtyOrd = itemComponent.QtyOrd + QtyOrdSum * a.Qty; nbrDetailList.First(b => b.Nbr == Nbr && b.ItemNum == a.ComponentItem).CurrQtyOpened = itemComponent.CurrQtyOpened + QtyOrdSum * a.Qty; } }); nbrDetailList.ForEach(a => { if (a.Nbr == Nbr) { var find = itemLocList?.Find(c => c.ItemNum == a.ItemNum); var packfind = itemPackList?.Find(c => c.ItemNum == a.ItemNum); if (find != null && !find.TraceDetail && packfind != null && packfind.PackingQty > 0) { a.CurrQtyOpened = Math.Ceiling(a.CurrQtyOpened.GetValueOrDefault() / packfind.PackingQty.GetValueOrDefault()) * packfind.PackingQty; dictItemQty.Add(a.ItemNum, QtyOrdSum * itemList.First(b => b.ComponentItem == a.ItemNum).Qty); } else { dictItemQty.Add(a.ItemNum, QtyOrdSum * itemList.First(b => b.ComponentItem == a.ItemNum).Qty); } } }); List itemKeys = dictItemQty.Keys.ToList(); //var items = _mysql_ic_item.GetListAsync(a => itemKeys.Contains(a.number) && a.factory_id == 1001 && a.tenant_id == 1000).Result; //var itemIds = items.Select(b => b.Id).ToList(); //var leadTimes = GetLeadTime(itemIds, 1000, 1001).Max(a=>a.ordissu_days.GetValueOrDefault()); decimal leadTimes = itemLocList.Select(a => a.MFGMTTR).Max(); //没有维护备料提前期,默认取7天 if (leadTimes > 0) { nbrMasterList.First(a => a.Nbr == Nbr).Date = dbPeriodSequences.Where(a => a.WorkOrds == workord).Min(a => a.PlanDate).GetValueOrDefault().AddDays(-1 * Convert.ToDouble(leadTimes)); } else { nbrMasterList.First(a => a.Nbr == Nbr).Date = dbPeriodSequences.Where(a => a.WorkOrds == workord).Min(a => a.PlanDate).GetValueOrDefault().AddDays(-7); } //TODO: //因为我们并没有模拟发料的过程,在自动生成领料单的时候就要扣减库存,实际业务不能这么做。 //在有上料和追溯的系统,可以在扫码上料或报工时(从线边仓)扣减。或者在实际发料出库时扣减。 var locStock = _locationDetail.Select(a => itemKeys.Contains(a.ItemNum) && a.IsActive && a.Domain == "1001"); locStock?.ForEach(a => { nbrDetailList.ForEach(b => { if (a.ItemNum == b.ItemNum && a.Location == b.LocationFrom && a.QtyOnHand - dictItemQty[a.ItemNum] > 0) { a.QtyOnHand -= dictItemQty[a.ItemNum]; } }); }); _locationDetail.Update(locStock); } } } public void AsyncItemStockFromWMS(List sentrys) { //产品编码 var itemList = sentrys.Select(a => a.item_number).Distinct().ToList(); List itemChildList = new List(); itemList.ForEach(a => { itemChildList.AddRange(GetChildItemNumber(a, new List())); }); var stockList = _locationDetail.Select(a => a.Domain == "1001" && a.IsActive && itemChildList.Distinct().Contains(a.ItemNum)); var groupList = stockList. GroupBy(m => new { m.ItemNum }). Select(a => new { ItemNum = a.Key.ItemNum, Qty = a.Sum(c => c.QtyOnHand) }).ToList(); var itemNums = groupList.Select(b => b.ItemNum).ToList();//需要处理的dop物料编码集合 var items = _mysql_ic_item.GetListAsync(a => itemNums.Contains(a.number) && a.factory_id == 1001 && a.tenant_id == 1000).Result; var itemIds = items.Select(b => b.Id).ToList();//需要处理的dop物料id集合 List mysqlStock = _mysql_ic_item_stock.GetListAsync(a => itemIds.Contains(a.Id) && a.factory_id == 1001 && a.tenant_id == 1000).Result; List needAddList = new List(); foreach (var stockWMS in groupList) { foreach (var num in items) { if (stockWMS.ItemNum == num.number) { var item = mysqlStock.Find(a => a.Id == num.Id); if (item != null) { item.sqty = groupList.First(a => a.ItemNum == num.number).Qty; } else { ic_item_stock stock = new ic_item_stock(); stock.GenerateNewId(help.NextId()); stock.factory_id = 1001; stock.tenant_id = 1000; stock.icitem_id = num.Id; stock.icitem_name = num.name; stock.sqty = groupList.First(a => a.ItemNum == num.number).Qty; } break; } }; } if (needAddList.Count > 0) { _businessDbContext.BulkInsert(needAddList); } _businessDbContext.BulkUpdate(mysqlStock); } //循环获取子级物料编码,包括产品本身,有重复的结果去重即可 public List GetChildItemNumber(string itemNum, List list) { list.Add(itemNum); var productStructures = _productStructureMaster.Select(p => p.ParentItem == itemNum && p.Domain == "1001" && p.IsActive); list.AddRange(productStructures.Select(a => a.ComponentItem)); foreach (var item in productStructures) { if (item.StructureType.ToUpper() == "X") { GetChildItemNumber(item.ComponentItem, list); } } return list; } /// /// 得到一个流水号的最大流水号 /// /// 流水号id /// json数据,可以用json中的某个字段值作为通配符字替换流水号格式。 /// public string GetMaxSerialNumber(long id, JObject? formData = null) { var modelList = _rf_serialnumber.Select(s => s.Id == id); if (modelList == null && modelList.Count < 1) { return string.Empty; } var model = modelList[0]; int max = model.CurrentNumber + 1; var date = DateTime.Now; var lastDate = model.LastTime; switch (model.NumberType) { case 1: //年流水 if (date.Year > lastDate.Year) { max = 1; } break; case 2: //月流水 if (date.Year > lastDate.Year || date.Month > lastDate.Month) { max = 1; } break; case 3: //日流水 if (date.Year > lastDate.Year || date.Month > lastDate.Month || date.Day > lastDate.Day) { max = 1; } break; } string number = max.ToString().PadLeft(model.NumberSize, '0'); string serialNumber = string.IsNullOrWhiteSpace(model.Format) ? number : model.Format.ContainsIgnoreCase("{number}") ? model.Format.ReplaceIgnoreCase("{number}", number) : model.Format + number; //更新当前编号和最后时间 model.LastTime = date; model.CurrentNumber = max; _rf_serialnumber.Update(model); return Wildcard.Replace(serialNumber, formData); } /// /// 生产排产 /// /// /// /// public async Task ProductionSchedule(string workOrd) { List workOrds = workOrd.Split(",").ToList(); if (workOrds.Count == 0) { return ""; } //获取工单数据 var workOrdMasters = _workOrdMaster.Select(p => workOrds.Contains(p.WorkOrd)); //获取已排产的工单 List dbWorkOrds = _periodSequenceDet.Select(p => workOrds.Contains(p.WorkOrds)).Select(p => p.WorkOrds).Distinct().ToList(); //过滤掉已排产的工单 workOrdMasters = workOrdMasters.Where(p => !dbWorkOrds.Contains(p.WorkOrd)).ToList(); if (workOrdMasters.Count == 0) { return JsonConvert.SerializeObject("ok"); } //排产 await _productionScheduleAppService.DoProductShcedule(workOrdMasters); //AutoCreatePickBill(workOrdMasters.Select(p => p.WorkOrd).ToList()); return JsonConvert.SerializeObject("ok"); } /// /// 生成领料单 /// /// public async Task CreatePickBill(string workOrd) { List workOrds = new List(); List workOrdMasters = new List(); if (string.IsNullOrEmpty(workOrd)) { //获取工单数据 workOrdMasters = _workOrdMaster.Select(p => p.OrdDate >= DateTime.Now.Date.AddDays(1) && p.OrdDate < DateTime.Now.Date.AddDays(4) && p.Status != "r" && p.Status != "c"); } else { workOrds = workOrd.Split(",").ToList(); if (workOrds.Count == 0) { return JsonConvert.SerializeObject("没有需要下达的工单。"); } workOrdMasters = _workOrdMaster.Select(p => workOrds.Contains(p.WorkOrd) && p.Status != "r" && p.Status != "c"); } if (workOrdMasters.Count == 0) { return "没有需要下达的工单。"; } //获取已排产的工单 List dbPeriodSequences = _periodSequenceDet.Select(p => workOrds.Contains(p.WorkOrds) && p.Domain == "1001" && p.IsActive); List dbWorkOrds = dbPeriodSequences.Select(p => p.WorkOrds).Distinct().ToList(); //查出已排产的工单 workOrdMasters = workOrdMasters.Where(p => dbWorkOrds.Contains(p.WorkOrd)).ToList(); //查出已产生领料单、过滤掉,取出未领料的工单 var nbrList = _nbrMaster.Select(a => a.Domain == "1001" && a.Type == "SM" && dbWorkOrds.Contains(a.WorkOrd)); var noNbrlist = nbrList.Select(p => p.WorkOrd).ToList(); workOrdMasters = workOrdMasters.Where(p => !noNbrlist.Contains(p.WorkOrd)).ToList(); if (workOrdMasters.Count == 0) { return "当前选择的工单已领料或未排产。"; } List nbrMasterList = new List();//需要生成领料单列表 List nbrDetailList = new List();//需要生成领料单明细列表 var ords = workOrdMasters.Select(p => p.WorkOrd).ToList(); dbPeriodSequences = dbPeriodSequences.Where(p => ords.Contains(p.WorkOrds)).ToList(); await AutoCreatePickBill(ords, dbPeriodSequences, nbrMasterList, nbrDetailList); if (nbrMasterList.Any()) { dbPeriodSequences.ForEach(p => { p.Status = "r"; }); workOrdMasters.ForEach(p => { p.Status = "r"; }); //获取工单工艺路径数据 List workOrdRoutings = _workOrdRouting.Select(p => ords.Contains(p.WorkOrd) && p.MilestoneOp && p.Domain == "1001" && p.Status != "C" && p.IsActive); workOrdRoutings.ForEach(p => { p.Status = "r"; }); using (var unitOfWork = _unitOfWorkManager.Begin(false, true)) { try { _nbrMaster.Insert(nbrMasterList); nbrMasterList.ForEach(a => { string sql = string.Format("exec pr_WMS_BPM_AddMobileTask @TaskID='{0}',@PlanDate='{1}',@ExecuterTypeID=2,@CreateUser='{2}'",a.Nbr,a.Date.Value.ToString("yyyy-MM-dd"),a.CreateUser); _businessDbContext.Database.ExecuteSqlRaw(sql); }); //快开平台用自增列RecId关联,所以需要插入后再查给明细表赋相应的值 List nbrs = nbrMasterList.Select(a => a.Nbr).ToList(); var DBnbrList = _nbrMaster.Select(a => a.Domain == "1001" && a.Type == "SM" && nbrs.Contains(a.Nbr)); nbrDetailList.ForEach(c => { c.NbrRecID = DBnbrList.Where(a => a.Nbr == c.Nbr).First().RecID; }); _nbrDetail.Insert(nbrDetailList); _workOrdMaster.Update(workOrdMasters); _periodSequenceDet.Update(dbPeriodSequences); _workOrdRouting.Update(workOrdRoutings); await unitOfWork.CompleteAsync(); } catch (Exception e) { unitOfWork.Dispose(); new NLogHelper("ResourceExamineAppService").WriteLog("CreatePickBill", "生成领料单相关数据更新失败:" + e.Message, _currentTenant.Id.ToString()); return e.Message; } } } return ""; } /// /// 同步工单等相关数据 /// /// /// 工艺路线数据 public void CreateWorkOrdDates(List morders, List allRoutings, List workOrds, List workOrdRoutings, List workOrdDetails) { //工单主表 WorkOrdMaster workOrd; //工单工艺路线表 WorkOrdRouting woRouting; //工单物料表 WorkOrdDetail woDetail; foreach (var item in morders) { //添加工单数据 workOrd = new WorkOrdMaster(); workOrd.Domain = "1001"; workOrd.OrdDate = item.moentry_sys_stime; workOrd.ReleaseDate = Convert.ToDateTime(item.moentry_sys_stime.GetValueOrDefault().ToString("u")); workOrd.WorkOrd = item.morder_no; workOrd.ItemNum = item.product_code;//物料编码 workOrd.QtyOrded = item.need_number.GetValueOrDefault(); workOrd.RoutingCode = item.product_code; workOrd.Period = 1; workOrd.Priority = item.urgent; workOrd.Status = " "; workOrd.IsActive = true; workOrd.IsConfirm = true; workOrd.CreateTime = DateTime.Now; workOrd.Batch = item.morder_no; workOrd.Typed = "s"; workOrds.Add(workOrd); //添加工单工艺路线数据 var curRoutings = allRoutings.Where(p => p.RoutingCode == item.product_code).ToList(); foreach (var dtl in curRoutings) { woRouting = new WorkOrdRouting(); woRouting.Domain = "1001"; 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; workOrdRoutings.Add(woRouting); } List curStructures = GetProductStructure(item.product_code); foreach (var structure in curStructures) { //添加工单的物料信息 woDetail = new WorkOrdDetail(); woDetail.Domain = "1001"; woDetail.WorkOrd = item.morder_no; woDetail.Op = structure.Op; woDetail.ItemNum = structure.ComponentItem; woDetail.QtyRequired = item.need_number.GetValueOrDefault() * structure.Qty; woDetail.QtyPosted = 0m; woDetail.QtyReturned = 0m; woDetail.FrozenBOMQty = structure.Qty; woDetail.Status = ""; woDetail.IsActive = true; woDetail.CreateTime = DateTime.Now; workOrdDetails.Add(woDetail); } } } /// /// 获取标准Bom数据--TODO:存在循环查询数据库问题,后续调整 /// /// 产品物料编码 /// public List GetProductStructure(string itenNum) { List rtnStructures = new List(); //根据itemNum获取bom数据 var productStructures = _productStructureMaster.Select(p => itenNum == p.ParentItem && p.Domain == "1001" && p.IsActive); //添加非虚拟件 rtnStructures.AddRange(productStructures.Where(p => p.StructureType.ToUpper() != "X").ToList()); //获取当前产品的虚拟件 var curPhantoms = productStructures.Where(p => p.StructureType.ToUpper() == "X").ToList(); if (curPhantoms.Count == 0) { return rtnStructures; } //递归获取所有虚拟件对应的子物料 RecursionProductStructure(itenNum, curPhantoms, rtnStructures); return rtnStructures; } /// /// 递归获取虚拟件的子物料 /// /// 产品的物料编码 /// 当前产品的虚拟件 /// public void RecursionProductStructure(string parentItem, List structures, List rtnStructures) { //获取虚拟件的子物料 List chdStructures = _productStructureMaster.Select(p => structures.Select(m => m.ComponentItem).Contains(p.ParentItem) && p.Domain == "1001" && p.IsActive); //非虚拟件 var notPhantoms = chdStructures.Where(p => p.StructureType.ToUpper() != "X").ToList(); //存在非虚拟件 foreach (var item in notPhantoms) { item.ParentItem = parentItem; } rtnStructures.AddRange(notPhantoms); //虚拟件 var phantoms = chdStructures.Where(p => p.StructureType.ToUpper() == "X").ToList(); if (phantoms.Count > 0) { //递归 RecursionProductStructure(parentItem, phantoms, rtnStructures); } } /// /// 计算订单行的系统建议交期 /// /// /// public void CalcSuggestDate(List sentrys, List kittingTimes, List icitemlist) { //获取排产记录 List itemNums = sentrys.Select(p => p.item_number).Distinct().ToList(); DateTime eralist = kittingTimes.Min(p => p.kitting_time).Date; List periodSequences = _periodSequenceDet.Select(p => itemNums.Contains(p.ItemNum) && p.PlanDate >= eralist).ToList(); //资源检查添加产线工序等数据 _productExamineAppService.prodLines = prodLines; _productExamineAppService.routingOps = routingOps; _productExamineAppService.calendarWorks = calendarWorks; _productExamineAppService.qualityLineWorks = qualityLineWorks; _productExamineAppService.holidays = holidays; _productExamineAppService.periodSequences = periodSequences; if (sentrys.Count == 0) { return; } _productExamineAppService.CalcSuggestTime(sentrys, kittingTimes, icitemlist); } } }